Take a look at this code:
<p>This is nice text!</p>
What i want to achieve is to select This is nice text!
and make it like this:
<p>{{ __('This is nice text!') }}</p>
This is a basic example of laravel language helper. It has more implementations tho.
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:
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 \$
insteadtabTrigger
is a phrase you can use to expand the snippet manually; it's optionaldescription
is a textual description of what the snippet is for; it's optionalscope
indicates where the snippet applies; it's optionalThe 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:
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.
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 localize
Tab 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:
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" },
]
},