Sublime Forum

Plugin idea - Removing Python's >>>

#1

Hi all,

this is PyBen reporting in.
I discovered Sublime Text just three weeks ago and I am still amazed how lightning fast it runs.
Still I use PyCharm as my main IDE but try to adapt Sublime to my needs.
I particularly like that Sublime Text allows me to write plugins in python.

So, here is my first plugin idea, which could making coding python even more joyful:

A standard task is to copy code snippets found on the web into your editor.

In case of python, those often are preceded by the prompt characters: >>>
I am sure I am not the only one who finds it annoying to manually remove those, especially when more than one line of code is involved.
A plugin which automagically removes those annoying chars before pasting would be therefore really helpful!

I have two questions to you fellow Sublime lovers:
1) Would such plugin be useful to you? (I need to know whether it is worthwhile publishing it.)
2) Is writing a new plugin really the best approach to the respective end or is there already a good builtin method (like a macro / or some search and replace magic) / or existing plugin I am not aware of?

  • PyBen
0 Likes

#2

Welcome to ST.

You mean code snippets like that?

>>> my_dict = {'a' : 'one', 'b' : 'two'}
>>> 'a' in my_dict
True
>>> 'b' in my_dict
True
>>> 'c' in my_dict
False

I don’t remember a plugin which automatically strips >>> characters.

Answer 1)

I can’t answer this question as I was not faced to such a task too often.

Answer 2)

The biggest advantage of ST is you can automate nearly everything you need easily using python and adapt ST to your needs. But this is also one of the most tricky things with ST. There are thousands of packages out there to provide more or less useful and more or less general/personal functionality. It is quite hard to find a correct set of plugins required for efficient every day work. This is besides a question which depends on personal tastes and the tasks you are faced to.

like a macro

ST supports JSON based macros, but I never felt comfortable with that syntax as JSON is too noisy with all its terrible brackets, braces and quotations. The idea behind them is simple - just chain the available commands after each other and put it into a *.sublime-macro file. A macro can than be bound to a key or added to menu/command pallet.

some search and replace magic

I use RegReplace to do automated text replacements like that. You can setup predefined rules which include anything you need to do comprehensive find and replace operations and recall them easily in macros, by key bindings or create menu/command pallet entries for them.

Example:

I have the following entry in the reg_replace_rules.sublime-settings (created with a easy to use “Wizard”)

"strip_python_command_line":
{
	"find": "^>>>\\s*",
	"name": "strip_python_command_line",
	"replace": ""
}

This rule can be used by other python packages as follows:

view.run_command("reg_replace", {"replacements": ["strip_python_command_line"]})

You can create a key binding

{
	"keys": ["f9"],
	"command": "reg_replace",
	"args": {
		"replacements": ["strip_python_command_line"]
	},
}

or add the following entry to a Packages/User/Default.sublime-commands file to have it available in the command pallet:

{
    "caption": "Reg Replace: Strip python command line chars (>>>)",
    "command": "reg_replace",
    "args": {"replacements": ["strip_python_command_line"]}
},

You can even chain several replacement rules.

This way the text is not automatically replaced on paste but with only little more effort. I honestly don’t feel happy with automated paste replacements as there always might be situations you don’t want such special automatism.

2 Likes

#3

You’d probably want to strip multiline inputs as well which are preceded by ....

0 Likes

#4

@ deathaxe,

thanks for your in depth reply and your warm welcome. I am really looking forward to learn and contribute to the sublime community here!

Yes, indeed I meant code snippets like the one you mentioned (I should have included one in the first place). It is interesting how different people endow different workflows. I struggle with “>>>” and “…” contaminated snippets all the time, while you don’t. I guess it would be a boring world If we were all the same.

Thanks for pointing out a better alternative than writing Json based macros. I have just put your lines of code into my snippet collection and will certainly make use of them at some point in the future.

@facelessuser
I just reimagined the plugin I have in mind to allow replacement of a multitude of patterns. Thereby its usefulness would be maximized. Then the thought struck me that probably someone else must have already coded a plugin to perform exactly that task. Indeed I found a nice one called RegReplace.
Guess who is the author? :slight_smile:

I think this renders my own plans for a plugin obsolete.

Still I am not sure how to trigger RegReplace. Can the commands be bound to a key combination?
Would it be possible and useful to modify clipboard contents before pasting - maybe as a means to exclude the whole of the text from the replacement scope? Or just restricting it to a selected region?

  • PyBen
1 Like

#5

That does sound like a niffty plugin :slight_smile:.

Yup. You can create command palette commands, or key binding commands, or menu commands, or call them from other plugins if you feel so inclined.

I’m not exactly sure what you are asking. You can enable RegReplace to only search a selection, it should be covered in the documentation. As I recall it’s generally a global setting. So when a you have a selection it will replace in the selection, and if not it will find and replace in the whole file.

As for manipulating the replace, RegReplace allows you to use a replace plugin where you provide a python method that can do more advanced logic and replacements. Not sure what you mean with the clipboard.

1 Like

#6

This section has some command examples (keybinding as well): http://facelessuser.github.io/RegReplace/usage/#create-find-and-replace-sequences.

Selections is in the settings file. I don’t seem to specifically cover it in the documentation except in passing…I should fix that: https://github.com/facelessuser/RegReplace/blob/master/reg_replace.sublime-settings#L51

Replacement plugins: http://facelessuser.github.io/RegReplace/usage/#custom-replace-plugins.

0 Likes

#7

Maybe I did not express myself clearly enough. Let me fix that. :slight_smile:

The usage scenario I outlined in my initial post was that of copy from web and pasting into sublime.
So I am wondering whether your plugin could (and should) be extended to manipulate contents of the clipboard
(the place your text is stored in after you hit Ctrl + c ;-)) before those are actually pasted into sublime.

An advantage would be that this method provides additional compartmentalization, sparing the already in the editor from potential collateral damage, caused by gone-rogue string replacement.

Instead of manipulating the clipboard contents, the string replacement might be limited to a selected portion of the text only. I wonder whether your truly nifty plugin has such operation mode?

-Ben

0 Likes

#8

Depending how it’s setup, it can run on just selections, that is how I’d recommend it was approached as it could be achieved now. Auto operating on clipboard wouldn’t be so great as I have no way to determine there is actual Python code in the clipboard (it could be some other language), and I’d have to override the paste command. Or it could be string or comment content, who knows.

Ideally you would create a new command that would either paste, ensure selection of pasted content, and apply regex to the paste content (which RegReplace could do if applying to only selections is enabled).

The other option is to pull the clipboard content into a buffer apply the regex, copy it back to the clipboard and then paste (which RegReplace doesn’t currently support). This would require new feature support as RegReplace is geared towards operating on a view. And it would probably not have syntax scope awareness as it is not content from a view.
.

0 Likes

#9

Still I am not sure how to trigger RegReplace.

@facelessuser: How do you think about the following enhancement to make user’s life a bit easier:

  1. Dynamically create a Default.sublime-command file with all the rules defined in reg_replace_rules.sublime-settings to make them available in the command pallet without further configuration.
  2. Create a command “RegReplace: Find and Replace” which displays a dedicated list of defined rules to run.

I don’t need keybindings for each replacement and creating commands by hand feels a bit inconvenient - especially for simple stand alone rules.

0 Likes

#10

You can easily write a plugin to do it automatically and overwrite ctrl+v if this is the case. Just select Tools >> Developer >> New Plugin… and paste:
This will just left strip >>> from each line in the clipboard and run paste afterwards. In addition it provides a context to limit it only to the cases where your clipboard starts with >>>, so it will only mess with other keybindings in such cases.

import re

import sublime
import sublime_plugin


class StripArrowQuotesAndPasteCommand(sublime_plugin.TextCommand):
    def run(self, edit):
        content = sublime.get_clipboard()
        subre = re.compile(r"^>>>\s?")
        content = "\n".join(subre.sub("", l) for l in content.split("\n"))
        sublime.set_clipboard(content)
        self.view.run_command("paste")


class StripArrowQuotesPasteContext(sublime_plugin.EventListener):
    def on_query_context(self, view, key, operator, operand, match_all):
        if key != "clipboard_startswith":
            return
        result = sublime.get_clipboard().startswith(operand)
        if operator == sublime.OP_NOT_EQUAL:
            result = not result
        return result

Then add this keybindings:

    {
        "keys": ["ctrl+v"],
        "command": "strip_arrow_quotes_and_paste",
        "context":
        [
            { "key": "clipboard_startswith", "operand": ">>>" },
            // additional limitations
        ],
    },
1 Like

#11

This doesn’t make sense to me. The rules you define are just rules. RegReplace allows you to chain rules together in a command. Generating commands for the rules isn’t helpful for me as some rules are not meant to be run on their own.

So then I’d have to provide a setting option where you define rule chains and provide a caption for them…sounds a lot like creating a command.

0 Likes

#12

I think it’s probably not good to override ctrl+v unless all you ever do is work with Python code, but even then, maybe you are pasting Python output into a comment and want the >>>. It would make more sense to have a separate paste command specifically for when you know you have content that needs to be parsed. This is why to me it makes more sense to just have have a command where you can select some content and then strip it. Even if content starts with >>> doesn’t mean it needs to be stripped.

1 Like

#13

After some thought and reflection about my own coding behavior I now second that. I no longer think that manipulating the clipboard before pasting is a good idea. Especially if one could limit the scope of effect to a selected portion of the code.

@r-stein
Nonetheless, thanks for the code snippets. I have put them into my collection. Maybe they find their way into different plugin I can delight the Sublime community with.

0 Likes

#14

You can add a command to the command palette and call it when you need to fix and paste the code.

0 Likes

#15

I know about the features of chaining, but I have a set of simple rule, which I needed to create commands for by hand. I chained them in rare cases only. I wouldn’t expect a feature to automate command creation for chained commands. Maybe just an additional caption entry in your RegReplace: Edit Regular Expression Rule panel. If it is not none, a command with that title is created, if none, it is ignored. This way one could decide whether to automatically add the rule to command pallet or just create a template to be chained with others by hand later.

0 Likes

#16

@deathaxe. But what would the auto generated command do? Does it mark the content, fold the content, replace the content with no prompt, replace with prompt, just highlight the find, select the find?

RegReplace allows you to configure not only the find and replace, but what it does when you execute the command. There would be a lot of assumptions to be be made to auto-gen a command.

On the one hand I understand where you are coming from. You have very specific work flow with it, and this would help. But on the other hand, not everyone shares this workflow. A little one time setup for a command that saves you from ever having to to type all that in ever again isn’t that bad.

With all of that said, you could easily write a plugin that piggy backs off RegReplace and scans the rules, and does what you want. I just feel like what you are requesting is for an ultra specific kind of workflow. If I added such a feature, it would only be natural that people would then request, “Can you add a configurable action option into the rule?”, etc.

2 Likes

#17

Note that str.strip (and lstrip) work on characters provided as the parameter and not on sequences. Thus this would be equivalent to str.lstrip(" >") and the second call is redundant.

4 Likes

#18

Thanks for the hint, I have updated the code.

1 Like

#19

As a bottom line of this thread:
It is worthwhile reaching a bit deeper into the treasure chest of PackageControl.io.
In my case RegReplace is a package which already provides the function I require.

0 Likes