Sublime Text Wrap Selection with Snippet

Sublime Text wrap selection with snippet

As can be seen here:

Tools -> New Snippet... -> save as darken.sublime-snippet in Data\Packages\User\

<snippet>
<content><![CDATA[darken($SELECTION, 5%);]]></content>
<!-- Optional: Tab trigger to activate the snippet -->
<tabTrigger>darken</tabTrigger>
<!-- Optional: Scope the tab trigger will be active in -->
<scope>source.css</scope>
<!-- Optional: Description to show in the menu -->
<description>Darken Snippet</description>
</snippet>

And keybind:

{ "keys": ["ctrl+shift+o"], 
"command": "insert_snippet",
"args": { "name": "Packages/User/darken.sublime-snippet" } },

EDIT:
It would be even better if you add $1 right after the $SELECTION, then the cursor will jump to the selected word or right in the place where it has to be written if it's not selected.

Change the above snippet's second line to this:

<content><![CDATA[darken($SELECTION$1, 5%);]]></content>

Sublime Text 2 wrapping selection in tag

Using Emmet, place the cursor in the tag you want to wrap and press ctrl + w (for MacOS) or Alt+Shift+W (for Windows), a box will pop up to enter the type of tag you want to wrap with.

Sublime text 3: How to wrap selected text in custom string/ tag/ function (laravel language helper example)

Generally speaking, the easiest way to wrap selected text with other text is to use a snippet to perform the job. Snippets allow you to insert arbitrary text into the buffer in a few different ways, and also allows for the inclusion of whatever the selected text happens to be at the time the expansion happens.

To see this in action, you can select Tools > Developer > New Snippet from the main menu, which will create a snippet template for you. Once that's done, replace the entire content of the file with the following text and save the snippet. Sublime will default to your User package as the location, and you can choose any name that you want; just make sure that the extension is sublime-snippet so that Sublime will recognize the file. In this example I have named the file localize.sublime-snippet.

<snippet>
<content><![CDATA[
{{ __('${0:${SELECTION}}') }}
]]></content>
<tabTrigger>localize</tabTrigger>
<description>Localize text</description>
<scope>text.blade</scope>
</snippet>

As seen here, snippets are XML files. The link above is to the unofficial documentation on snippets, so briefly we'll just say:

  • The content of the CDATA section is the snippet text that will expand
  • $ has a special meaning in the snippet body, so if you want to insert a literal $, you need to specify \$ instead
  • The tabTrigger is a phrase you can use to expand the snippet manually; it's optional
  • The description is a textual description of what the snippet is for; it's optional
  • The scope indicates where the snippet applies; it's optional

The snippet content can contain numbered fields like $0, $1 and so on, and when the snippet expands Sublime will position the cursor at $1 for you to enter text, then jump to $2 when you press Tab and so on until all fields are filled out, which makes the cursor jump to $0 (the "exit" of the snippet).

Also worth noting that the scope here assumes you are using the Laravel Blade Highlighter package for your syntax highlighting. If you're not, then while editing a blade file use Tools > Developer > Show Scope Name and replace text.blade with the first line in the popup instead.

Now with the snippet in place, we can do a few things automatically. First, while in a blade file, you can enter the tab trigger text and press Tab and the content of the snippet will expand, putting the cursor inside of the single quotes (where the $0 is in the snippet) so you can enter some text:

Sample snippet expansion

The list of snippets that apply to the current situation is also automatically added to the command palette as commands that are prefixed with Snippet:; you can use Tools > Snippets from the main menu or just open the command palette and do a command search to see the snippets that apply to the current situation. Here we can see our localize snippet being displayed; the description comes from the tag in the snippet, and Sublime also reminds us of how to trigger the snippet.

Snippet in command palette

So now cycling back to your original question of wrapping text, note that the body of the snippet contains this:

{{ __('${0:${SELECTION}}') }}

The ${0} is specifying where the cursor should go when the snippet is done expanding fields (of which there are none), and the :${SELECTION} part is saying that the default value of this field should be the selected text.

When you use the localizeTab method of expanding the snippet as above, there is no selected text, so the cursor just ends up sitting in the middle of the string. However, if you trigger the snippet from the command palette, it's possible to select text first. In that case the selected text is replaced by the snippet, but since the snippet captures the selection, you end up with text wrapping your selection:

Expansion via command palette

For things like this that you do frequently, you can also use the insert_snippet command to cause the snippet to expand; in such a case you would select text first to wrap it, but with no selection the snippet would expand with the cursor inside of the single quotes as if you did it manually.

For example, you could create a key binding such as the following:

{
"keys": ["ctrl+alt+l"],
"command": "insert_snippet",
"args": {
"name": "Packages/User/localize.sublime-snippet"
},
"context": [
{ "key": "selector", "operator": "equal", "operand": "text.blade" },
]
},

The context section here makes the binding active only in a blade file and not everywhere similar to how the scope in the snippet works; this is because the insert_snippet command directly inserts the snippet without doing any checks.

Similarly you could also add this to the right click context menu by creating a file named Context.sublime-menu in your User package (i.e. the same location as you saved the snippet to above) with the following content:

[
{ "caption": "-", "id": "end" },

{
"caption": "Localize Blade Text",
"command": "insert_snippet",
"args": {
"name": "Packages/User/localize.sublime-snippet"
},
},
]

Here the menu command will always be available regardless of what file you're editing because as mentioned above the insert_snippet command doesn't constrain the expansion of the snippet based on scope. You could solve that with a small simple plugin, though (not covered here since this answer is pretty massive as it is).

One last thing to mention is that in cases where you're using the insert_snippet command directly (that is, when you are not using the command palette or Tab expansion methods), you can skip some steps here.

The insert_snippet command can take a contents argument in place of the name argument; while the name argument specifies the snippet that should be expanded, the contents argument just contains the snippet content directly. That saves you the step of having to create the sublime-snippet file in the first place.

For your example here, this key binding will do the same as the above one will, but without requiring the snippet file to exist:

{
"keys": ["ctrl+alt+l"],
"command": "insert_snippet",
"args": {
"contents": "{{ __('${0:${SELECTION}}') }}"
},
"context": [
{ "key": "selector", "operator": "equal", "operand": "text.blade" },
]
},

Sublime Text 3 wrap selection with tag and HTML autocomplete do not work properly

You can use an emmet alternative shortcut: Ctrl+Shift+G

It asks you for a wrap abbreviation in the bottom of the frame, so just insert strong and click Enter. It will just wrap all the content highlighted.

How to wrap selection in curly brackets in sublime text 2 with correct indentation?

I've figured this out using a custom snippet:

<snippet>
<content><![CDATA[
{
$SELECTION$1
}
]]></content>
<!-- Optional: Set a tabTrigger to define how to trigger the snippet -->
<!-- <tabTrigger>hello</tabTrigger> -->
<!-- Optional: Set a scope to limit where the snippet will trigger -->
<scope>source.js, source.php</scope>
</snippet>

... and then binding that snippet to a key combination.
If you use the snippet you might want to change the scope (depending on the language you need), or just disable it entirely.

I'll leave the answer here just in case somebody needs it!

Is there a way in Sublime to wrap a selection of text in two separately defined strings?

You can try playing around with the Snippet functionality of Sublime Text. Here's a sample to get you started.

<snippet>
<content><![CDATA[
<?php echo ${0:my_function}("${SELECTION}"; ?>
]]></content>
<!-- Optional: Set a tabTrigger to define how to trigger the snippet -->
<!-- <tabTrigger>hello</tabTrigger> -->
<!-- Optional: Set a scope to limit where the snippet will trigger -->
<!-- <scope>source.python</scope> -->
</snippet>

Wrap selection in html tag suddenly stopped working in Sublime Text 3

  1. From Sublime Text, go to the Tools menu -> Browse Packages.
  2. Create a folder called XML.
  3. Create a folder called Snippets.
  4. Create a file called long-tag.sublime-snippet.
  5. Open it.
  6. Paste in the following (from https://github.com/sublimehq/Packages/blob/master/XML/Snippets/long-tag.sublime-snippet):

    <snippet>
    <content><![CDATA[<${1:p}>${2:$SELECTION}</${1/([^ ]+).*/$1/}>]]></content>
    <tabTrigger><</tabTrigger>
    <scope>text.xml</scope>
    <description>Long Tag</description>
    </snippet>
  7. Save it

  8. Copy it up one level, to the XML folder.

The keybinding will now work.

How to duplicate selection with Sublime Text snippet

I'm not great with snippets, so there may be another way. Anyways, you can do it with a plugin.

import re
import sublime
import sublime_plugin
class ConsoleLog(sublime_plugin.TextCommand):
def run(self, edit):
view = self.view
cursor = view.sel()[0]
line_region = view.line(cursor)
string = view.substr(line_region)
match = re.search(r"(\s*)(var\s+)?(\w+)\s*=", string)
if match:
if cursor.empty():
var_text = match.group(3)
else:
var_text = view.substr(cursor)
view.insert(edit, line_region.end(), "\n%sconsole.log('%s = ' + %s);" % (match.group(1), var_text, var_text))
end = view.line(line_region.end() + 1).end()
view.sel().clear()
view.sel().add(sublime.Region(end, end))

You just need to place the cursor on the line with your assignment operation. Bind your key binding to console_log. You can change the name as you see fit. Just be sure you change the name of the text command as well.

You could also modify your snippet so you don't have to type the text first. It seems unintuitive to type the variable name, select it, then hit your snippet key. Something like this may work better.

<snippet>
<content>
<![CDATA[console.log('$1 =' + $1);$2]]> </content>
<description>Print selection to console.log</description>
</snippet>

Edit:

I used the plugin to generate the console.logs with the cursor on the lines containing var foo = bar and foo = bar. That is, it's two invocations of the plugin command. Though you could modify it to handle multiple cursors also.

var foo = bar
console.log('foo = ' + foo)

foo = bar
console.log('foo = ' + foo)

I also modified the plugin so it should use a variable assignment automatically if nothing is selected. If something is selected, it will use the selected text in the console log. If you don't want the empty selection stuff, just remove the if statement under if match: and replace it with var_text = view.substr(cursor)



Related Topics



Leave a reply



Submit