Sublime Text 3 macro to delete x lines from caret - macros

I'm wanting to create a Sublime Text 3 macro to select 111 lines from the cursor and delete them. I tried recording this, but all it did was delete one character backwards, which I'm still confused by. I then looked into writing the macro manually, and the relevant commands here, but I've still not been able to figure out from that page whether what I want is possible, and if it is, how. Would really appreciate some help with this.

There is no internal Sublime Text command that will do multiple moves at once, unfortunately. However it is possible to define your own movement command via plugin code, which allows you to work around that.
To go this route, select Tools > Developer > New Plugin... from the menu and replace the default code with the following, then save the file as a python file (e.g. move_repeat.py). By using the menu entry to do this, Sublime will ensure that your plugin is stored in your User package.
import sublime
import sublime_plugin
class MoveRepeatCommand(sublime_plugin.TextCommand):
def run(self, edit, repeat=1, **kwargs):
for num in range(repeat):
self.view.run_command("move", kwargs)
This implements a new command named move_repeat which is a drop in replacement for the move command, providing an extra argument of repeat that specifies how many times to perform the movement that you provide.
As a drop in replacement, this can be used for any cursor movement (lines, words, etc).
Using this, your macro becomes the following:
[
{
"command": "move_repeat",
"args":
{
"by": "lines",
"extend": true,
"forward": true,
"repeat": 111
}
},
{
"command": "left_delete"
}
]
Here I just created the macro by hand-coding it. If you wanted to do this with an actual macro recording you would need to go about that another way.
For example, you could record the macro going down only one line and deleting, then manually add the extra value after the fact, or you could bind a key binding to the repeated command first and then do a macro recording.

The Messy Way
I've since managed to figure out a way to record macros. For some reason, the recorder doesn't register text selection by mouse, so I had to select the text via keyboard shortcut while recording the macro. This does the job in that it creates the macro I describe, although it also results in a script that I'm guessing is far less elegant than it would be if written by someone in the know.
Here's a shortened version of the script I ended up with:
[
{
"args":
{
"by": "lines",
"extend": true,
"forward": true
},
"command": "move"
},
{
"args":
{
"by": "lines",
"extend": true,
"forward": true
},
"command": "move"
},
{
"args":
{
"by": "lines",
"extend": true,
"forward": true
},
"command": "move"
},
{
"args":
{
"by": "lines",
"extend": true,
"forward": true
},
"command": "move"
},
{
"args":
{
"by": "lines",
"extend": true,
"forward": true
},
"command": "move"
},
{
"args": null,
"command": "left_delete"
}
]
It's as crude as it gets. It works by using the move command to select one line at a time. This means that this command block needs to be repeated for each line that you want to select for deletion. In my case, I needed 111 of them. Hopefully someone will come along and offer a nicer solution, but until then, this does the job.

Related

how to put increased number for multiline selection in visual studio code

I want to add increased number for multi selected caret in visual studio code.
now, When I type it write same words.
But I would like to add increased number by some shortkey so that I don't need to update each one manually.
Preferred result should be like this.
I want to know if this is possible in vs code.
Thanks
You do not need an extension for your use case, although that may make it easier. Here is how to do it without an extension.
Find: (?<=index:\s*)\d+ : this selects only the digits following index: .
Alt+Enter will select all those digits.
Now you can run a simple snippet to replace those digits with an increasing number that could be 0-based or 1-based. Make this keybinding to insert the snippet (in your keybindings.json):
{
"key": "alt+m", // whatever keybinding you want
"command": "editor.action.insertSnippet",
"args": {
"snippet": "$CURSOR_NUMBER" // this will increment and is 1-based
}
}
Trigger the above keybinding. Demo:
Here is an extension approach, using an extension I wrote, Find and Transform, that makes this easy. Make this keybinding:
{
"key": "alt+m", // whatever keybinding you want
"command": "findInCurrentFile",
"args": {
"find": "(?<=index:\\s*)\\d+", // same find regex
"replace": "${matchNumber}", // this variable will increase, 1-based
"isRegex": true
}
}
That combines the find and replace in one step.
Here is another method so you do not need to hardcode the starting point.
{
"key": "alt+m", // whatever keybinding you want
"command": "findInCurrentFile",
"args": {
"preCommands": [
"editor.action.addSelectionToNextFindMatch",
"editor.action.clipboardCopyAction"
],
"find": "(?<=index:\\s*)\\d+",
"replace": [
"$${",
// whatever math you want to do here
"return Number(${CLIPBOARD}) + ${matchIndex};",
"}$$",
],
"isRegex": true,
"postCommands": "cancelSelection"
}
}
Put the cursor next to or select the number you want as the starting point. The number could be anywhere in the document actually.
You can use the extension Regex Text Generator
Define the following key binding
{
"key": "ctrl+shift+f9", // or any other key combo
"when": "editorTextFocus",
"command": "regexTextGen.generateText",
"args": {
"generatorRegex" : "{{=i+1}}"
}
}
place the multi cursors after index:
press the key combo
accept or modify the inputs
look at the preview, press Enter if you like it, Esc to abort
You can do it with Increment Selection or Text Pastry

Change comment symbol location when using VSCode "Toggle Line Comment" command

Is it possible to customize the location of the comment symbol ('#' when using Python) in VSCode?
For example, if my code is:
def my_func():
value = 1
and I press CMD-/ on line 2, I get:
def my_func():
# value = 1
I would prefer to get:
def my_func():
# value = 1
Is there a way to modify the default behavior?
VSCode: 1.67.1
MacOS: 12.3.1
There is no built-in way to do that. You will need an extension. See https://stackoverflow.com/a/59448448/836330 for a previous answer using a different extension. Here is a better answer using an extension I made in the meantime, Find and Transform. But there are restrictions as noted below.
Make this keybinding (in your keybindings.json):
{
"key": "alt+/", // unfortunately, this cannot be ctrl+/
"command": "findInCurrentFile",
"args": {
{
"key": "alt+r",
"command": "findInCurrentFile",
"args": {
"preCommands": [
"cursorEnd",
"cursorHomeSelect",
"cursorHomeSelect"
],
"replace": "${LINE_COMMENT}${TM_CURRENT_LINE}",
"restrictFind": "line" // works on multiple lines, see the demo
},
"when": "editorLangId == python" // if you want to limit it to a language
},
}
You can use whatever keybinding you want, but not Ctrl+/ because then toggle off will not work.
Ctrl+/ will work to toggle off comments if you do not use it in the keybinding above to add comments.
Note: For this to work well you need to disable the following setting (which I have shown disabled for a particular language, python):
"[python]": {
"editor.comments.insertSpace": false
}
That goes into your settings.json.

How to make VSCode cursor macro instantanious?

I'm using the multi-command extension, and after pasting some text in a macro, I move the cursor around a few times, like the following:
{
"command": "multiCommand.test",
"interval": 0,
"sequence":[
{
"command": "editor.action.insertSnippet",
"args": {"snippet": "some text\n\n"}
},
{"command" : "cursorUp"},
{"command" : "cursorUp"},
{"command" : "cursorEnd"},
]
}
Everything ends up correct, but there's a noticeable delay in the cursor executing these commands that I'd like to be instantaneous (e.g. i'd like to not see it go through every step but just end up at the right spot.) Is there some setting I can change, or other command I can use to just instruct the cursor to move to a certain coordinate in the text?
Add the field $0 in your snippet
"snippet": "some text$0\n\n"
And remove the cursor commands

how to create sublime text macro with selected line of code?

I'm trying to do an other sublime text macro.
I will simplify what i would like :
I select a line of code, press the macro key and the macro will add 1 line of text above and 2 more below the selected line.
Ex:
My line of code
I select the line, press macro key and the code may be like :
echo('init');
My line of code
echo('After line');
echo('again after');
I already try the record macro tools but it's not working for the text selected and for go to the line after the selected.
I know how to use key binding it's just for the macro file...
Thanks for your help :)
You don't need a macro for that, you can directly create a keybinding (obviously you can also move it to a macro):
{
"keys": ["ctrl+alt+a"],
"command": "insert_snippet",
"args": {
"contents": "echo('init');\n$SELECTION\necho('After line');\necho('again after');"
},
"context":
[
{ "key": "selection_empty", "operator": "equal", "operand": false }
]
},
Aside: if you only write you macros to trigger them from keybindings you might be interested in the ChainOfCommand package.

Sublime Text autocomplete window closes when scrolling off the list

When scrolling the autocomplete list with up or down, if you go too far in either direction (e.g. there are no more suggestions), the list will close.
The behavior I want is to have the list wrap when reaching the end instead of close.
This is easy to fix with downward scrolling by assigning this hotkey:
{ "keys": ["down"], "command": "auto_complete", "context":
[ { "key": "auto_complete_visible" } ]
},
That's because the auto_complete command has built-in functionality to scroll downward each time it's invoked, which is why the hotkey works.
...But upward scrolling is different. I've tried about 20 different hotkey and macro combinations with no success.
I'm almost certain the only way to achieve this behavior is with a plugin, but unfortunately my Python skill level is nil.
If it matters, I'm manually invoking autocomplete with ctrl+space (the automatic popup is disabled).
I'm using Sublime Text 2.
Best solution: use auto_complete_cycle settings (added 26 March 2015):
Please use this new simple solution and not the python plugin
Sublime Text new version relased on 24 March 2015 has a new setting called auto_complete_cycle that implement this behaviour. Set it to true to iterate through the autocomplete results.
"auto_complete_cycle": true
Worst old solution: this custom plugin
I have just made this plugin that works well on Sublime Text 3 in Linux Mint. I have not tested it in Sublime Text 2 but think the plugin system it's the same, so, it should work on that version too. The workaround used it's not too pretty but works.
import sublime, sublime_plugin
class UpArrowInAutoCompleteCommand(sublime_plugin.TextCommand):
def run(self, edit):
self.view.settings().set('autoCompleteFlag',True)
self.view.settings().set('initialPoint', self.view.sel()[0].begin())
""" Move one line up """
self.view.run_command('move', {"by": "lines", "forward": False});
""" Auto-complete was opened and up arrow was pressed, so if the cursor changes
(on_selection_modified will be triggered) we have gone outside the list.
If we were not in the first element on_selection_modified will not be triggered, so
we turn of the flag"""
sublime.set_timeout(lambda: self.view.settings().set('autoCompleteFlag', False),300)
class AutoCompleteSelectionModifiedTriggerCommand(sublime_plugin.EventListener):
def on_selection_modified(self, view):
if view.settings().get('autoCompleteFlag'):
""" If the up arrow was pressed and on_selection_modified
has been triggered, then we know that we were in the first element
of the list and we hitted the up arrow"""
view.settings().set('autoCompleteFlag', False)
initialPoint = view.settings().get('initialPoint')
""" We don't know how many words the auto_complete has, so,
in order to calculate that number, we move down in the list
till we get outside the list. After that we make the list appear
again and move down n-1 times to go (and stay) to the last line """
view.sel().clear()
view.sel().add(initialPoint)
view.run_command('auto_complete')
numLines = 0
while view.sel()[0].begin() == initialPoint:
view.run_command('move', {"by": "lines", "forward": True})
numLines += 1
if numLines == 401:
return
if numLines == 0:
return
view.sel().clear()
view.sel().add(initialPoint)
view.run_command('auto_complete')
numLine = 0
while numLine < (numLines-1):
view.run_command('move', {"by": "lines", "forward": True})
numLine += 1
To make the plugin use Tools>new Plugin and paste the code. Then save it in Packages/User folder. You can use Preferences>Browse Packages to find the Packages floder, inside which the User folder is located.
To make it work I added to my user key-bindings file this bindings (the second it's your own binding):
{
"keys": ["up"],
"command": "up_arrow_in_auto_complete",
"context": [{
"key": "auto_complete_visible",
"operator": "equal",
"operand": true
}]
}, {
"keys": ["down"],
"command": "auto_complete",
"context": [{
"key": "auto_complete_visible"
}]
}
Edit: this is an example result: