Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to duplicate selection with Sublime Text snippet

The quest

Turn this (with currHour being the current selection):

var currHour = now.getHours();

into this:

var currHour = now.getHours();
console.log('currHour=' + currHour);

Should work also for these cases:

currHour = now.getHours();

-->

currHour = now.getHours();
console.log('currHour=' + currHour);

and (where b is selected):

a = b;

-->

a = b;
console.log('b=' + b);

etc.


The Situation

Now, by following this answer I was able to produce the second line, with this:

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

NB: my snippet code ommits <scope> because the scope is implied by the location of the snippet file (under language-specific dir -- JavaScript).

NB2: the <tabTrigger> setting in the snippet was ommited intentionally, because I will use a keyboard shortcut:

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

OK, that brings me half way there...


The problem

The current "solution" requires of me to manually duplicate the selection before I can invoke the snippet. That is an inconvenient step I'd like to skip if I can. So, are there ways to make snippet duplicate the selection into new line?

like image 631
Saran Avatar asked Jan 27 '26 11:01

Saran


1 Answers

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)

like image 186
skuroda Avatar answered Jan 29 '26 13:01

skuroda



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!