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

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.

Related

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

VS Code: Shortcut to select or remove Block Comment with no text selected

I know there is a shortcut for comment and uncomment code block (SHIFT + ALT + A), but is there a way to quickly select (or even remove without select) block comment without using mouse or keyboard to select and press the delete/backspace button? For example:
/*
This is a large block of code with at least 50 lines of code!
:
:
*/
Is there a keyboard shortcut where I can place my cursor anywhere in the block comment and remove it in just a few keystrokes? Thanks!
You can set a macro to do this pretty easily.
First, use the excellent Select By extension (#rioV8) to select the text between and including the block comment markers /* and */. Put his into your settings:
"selectby.regexes": {
"BlockCommentSelect": {
"backward": "\/\\*",
"forward": "\\*\/",
"forwardInclude": true,
"backwardInclude": true,
"showSelection": true
}
},
You can use that with a keybinding like:
{
"key": "alt+s", // whatever keybinding you wish
"command": "selectby.regex",
"args": ["BlockCommentSelect"],
"when": "editorTextFocus"
},
You could stop here and use your keybinding to select the text and then Shift+Alt+A to toggle off the block comment.
Or you could add the selectby.regex1 to a macro and do it the selection and toggling off in one step. Here using the macro extension multi-command put this into your settings as well as the above selectby.regexes setting:
"multiCommand.commands": [
{
"command": "multiCommand.BlockCommentOff",
"sequence": [
{
"command": "selectby.regex",
"args": ["BlockCommentSelect"]
},
"editor.action.blockComment"
]
},
]
and then a keybinding to trigger that macro (in your keybindings.json):
{
"key": "shift+alt+A", // trigger the macro with whatever keybinding if you wish
"command": "extension.multiCommand.execute",
"args": { "command": "multiCommand.BlockCommentOff" },
"when": "editorTextFocus && !editorHasSelection"
},
Here I used Shift+Alt+A to trigger the macro. And I used the when clause !editorHasSelection because if you have a selection maybe you want to block comment only that selection (inside another block comment!!).
Demos: (1) Just the first method where selectby selects your text and you manually toggle it off, and then (2) using the macro version to do it in one step.

Sublime Text 3 macro to delete x lines from caret

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.

Using TM_SELECTED_TEXT in my custom snippets

With the November 2016 (version 1.8) release of VSCode Snippet Variables are now supported, specifically TM_SELECTED_TEXT.
This makes me happy as I have used these heavily in both Sublime Text and TextMate.
I can't figure out how to get it to work in VSCode. I've created the snippet they use as an example:
"in quotes": {
"prefix": "inq",
"body": "'${TM_SELECTED_TEXT:${1:type_here}}'"
}
I then enter some text, highlight it and that's where things start to break.
The idea is highlight some text, run the snippet and then ${TM_SELECTED_TEXT:${1:type_here}} is replaced with the highlighted text. The problem I'm having is that to run the snippet you need to type the prefix value (in this case inq) to run the snippet which over-writes your highlighted text which messes everything up.
In Sublime/Textmate I launched the snippet from a keyboard combination which left my text highlighted.
Is there a way, in VSCode, to either make this work as is or launch the snippet from a key combination like was available in Sublime?
Coming in 1.49 (it is in the Insiders' Build as of this edit) your example will finally work as you expected. See merged pull request.
Vscode will now "remember" your selected text if any, and when you type your snippet prefix, insert it into the TM_SELECTED_TEXT variable even though you seemingly over-typed that selected text.
As of v1.20 this has become easier as a new variable $CLIPBOARD has been added, see new snippet variables. So there is no need to assign and run a shortcut - but you must copy the selection to clipboard CTRL-C.
Your example could now be:
"in quotes": {
"prefix": "inq",
"body": "'$CLIPBOARD:${1:type_here}'"
}
Note: $CLIPBOARD works. There's no need for the extra curly brackets {$CLIPBOARD}.
With the word highlighted, press F1 and run the command "Insert Snippet", then select your snippet on the list.
Also you can edit your keybindings by going to File>Preferences>Keyboard Shortcuts and add some shortcut to the "editor.action.showSnippets" command, like this:
{
"key": "ctrl+alt+s",
"command": "editor.action.showSnippets",
"when": "editorTextFocus"
}
https://github.com/Microsoft/vscode/issues/17780
as per this thread you can assign exact snippet to keybinding by providing args.
keybinding example for bootstrap media queries
{
"key": "ctrl+alt+b",
"command": "editor.action.insertSnippet",
"when": "editorTextFocus",
"args": {
"name": "bsup"
}
},
{
"key": "ctrl+alt+shift+b",
"command": "editor.action.insertSnippet",
"when": "editorTextFocus",
"args": {
"name": "bsup_copy"
}
},
snippet example
"bsup": {
"prefix": "bsup",
"body": [
"#include media-breakpoint-up(md){",
"\t${TM_SELECTED_TEXT}",
"}"
],
"description": "Bootstrap media up"
},
"bsup_copy": {
"prefix": "bsup_copy",
"body": [
"${1:${TM_SELECTED_TEXT}}",
"#include media-breakpoint-up(md){",
"\t${2:${TM_SELECTED_TEXT}}",
"}"
],
"description": "Bootstrap media up + copy selected text"
},
UPD: moreover - you can define snippet directly in keybindings.json which seems to be even more convenient for me in some cases
{
"key": "cmd+shift+c",
"command": "editor.action.insertSnippet",
"when": "editorTextFocus",
"args": {
"snippet": "console.log('${TM_SELECTED_TEXT}', $TM_SELECTED_TEXT$1);"
}
}
using documentation from https://code.visualstudio.com/docs/editor/userdefinedsnippets i was able to customize snippets, i am using 'surround with' extension and can put my own snippet into settings.json as follows:
"html_h3-name": {
"label": "h3",
"description": "wrap by h3 with <a name=''>, top",
"snippet": "<h3><a name=\"${TM_SELECTED_TEXT/[\\s]/-/g}\"></a>$TM_SELECTED_TEXT\n\t<a class=\"small\" href=\"#top\">top</a>\n</h3>"
},
which takes highlighted code in VSCode and creates h3 header from it with a name link:
it converts 'aaa bbb ccc' to
<h3><a name="aaa-bbb-ccc"></a>aaa bbb ccc
<a class="small" href="#top">top</a>
</h3>

Sublime Text Select and Copy in one (macro and keybinding) not working, why?

I have a select-copy.sublime-macro files that contains this:
[
{ "command": "expand_selection_to_word" },
{ "command": "copy" }
]
I then have this in my sublime-keymap file:
{
"keys": ["ctrl+d"],
"command": "run_macro_file",
"args": {"file": "Packages/User/select-copy.sublime-macro" }
}
However, given a line like this:
property: val[|]ue;
Where [|] is the cursor, when I press my keybinding (ctrl+d), I would expect to get 'value' copied. However, when I paste, I actually get the whole line (property: value).
Any idea why?
That happens because expand_selection_to_word its not a command (the right command its expand_selection, and 'words' should be the value of the 'to' argument).
So, change your macro to this and it should work:
[
{
"command": "expand_selection",
"args": {"to": "word"}
},
{
"command": "copy"
}
]
Note: the macro was selecting the whole line because its the default behavior of the copy command if nothing its selected (you can try using ctrl+c when nothing its selected). In addition, if you open the console and execute the macro you should see a warning message saying Unknown macro command expand_selection_to_word.