Sublime Forum

Snippets with functions and multiple values - is that possible?

#1

Hello,

I am a ST newbie and I come from Emacs. There I used heavily YASnippet and it was possible to use functions in snippets.

Now I am wondering if I can do the same in a snippet in ST.

  1. I want to enter a value and later do a multiplication with 1.19 later in a mirror.
  2. I want to have the current date in a snippet field.
  3. I would like to offer different contents in a snippet field and would like to choose from 1 of them?

My main use case is a larger markdown snippet that works more than a template where I can tab through insert different stuff and where I would like to have a larger flexibility.

I hope my question is somewhat understandable? If there would be a better solution than snippets for that than I would be pointed in the right direction.

Best regards,

Daniel

0 Likes

#2

Sublime snippets use boost’s regular expression. So any logic which can be done with that, such as conditionals and substitutions, can be applied in snippets as well.

For a more advanced logic, it seems that the easiest way is to use a Sublime macro, which is capable of executing anything you’d like, including insertion of snippets and navigating its fields.

Here are some links to related topics which might give you the information you need:

Disclaimer, I’m not experienced with the above material, so I hope that I’m not misleading you.

1 Like

#3

To get current date into a snippet, I needed to write a helper command to go along with it. So for example, I had a comment header snippet. You can create your own fields in a snippet with ${CUSTOM_NAME} in the text. You invoke the snippet with your command instead of the snippet and when doing so, you can replace the custom field text.

A snippet of the header command:

        date = time.ctime(time.time())
        year = time.strftime("%Y", time.localtime())

        # Some irrelevant code snipped 

        # Inserting template/snippet
        self.view.run_command("insert_snippet",
            {
                "name"    : template,
                "FILENAME": filename,
                "AUTHOR"  : author,
                "COMPANY" : company,
                "CDATE"   : date,
                "MDATE"   : date,
                "YEAR"    : year
            })

Here you can see that I’ve filled a variable with current date (and a stripped down version for just the year) and then when insert_snippet is called, I’m filling my custom fields with the text.

As for the multi-selection in a snippet, I don’t know how to do that. The multiplication could be done with a command/snippet combo also.

3 Likes

#4

It’s been posted by @papadokolos earlier (second topic), but I’d like to reference it directly as well: https://github.com/FichteFoll/InsertDate#snippet-macros

Regarding your first point, this seems rather complicated and specific and at the same time vague. Maybe you can describe an actual use case so we can more easily think of the right solution?

Regardin the third, there are a couple solutions for this. The easiest would be to just include all possible values in the default text for that field and separate them with, for example, |. This way it’s quite clear that the user should be choosing one of the values displayed.

The other, more complex, solution is to write a plugin that provides completion values via the API and additionally have a plugin that automatically opens the autocomplete popup once that field is reached. However, this is rather advanced, so I won’t go into details.

And finally, the method that @Remi outlined: just writing a plugin to generate the snippet. You can use Window.show_quick_panel to prompt the user with options to select from and insert the choosen result into the snippet that you insert. This is a nice compromise between the other two options.

3 Likes

#5

Hello Fichte,

thanks for the reply and I saw the example from the InsertDate package already. As I pointed out I am still a ST newbie and I try to understand where to put it and how to call it. But somehow it seems to have worked.

The first example is a simple math sample. I would like to enter in one snippet field a currencie value and would like to have in a mirror field the currency value with value added tax added (value * 1.19). If possible rounded to two digits after the decimal point.

I will still go through the manual and see if I will come up with a solution. I am not a programmer but I have some hobby programming background that might help.

Regarding writing plugins I will even look into that as well.

Somehow I am still amazed that calling commands or have conditional logic in snippets is such a rare features. I looked into various Vim snippet solutions and there it was also not that common.

Regardin the third, there are a couple solutions for this. The easiest would be to just include all possible values in the default text for that field and separate them with, for example, |. This way it’s quite clear that the user should be choosing one of the values displayed.

Do you mean as an example:

Choose: A|B|C

And I would have to delete upon completion what I don’t need or later. But I would not get a dialog where I could choose a value and only that would be inserted.

0 Likes

#6

Thanks, @papadokolos. Next time I will search the forum better.

Both solutions seems to provide a solution. And I am still trying to implement them. :slight_smile:

1 Like

#7

Thanks, @remi.

I will try that approach as well. In what file would I put that code?

And the normal snippet templat would be where in that example?

Sorry for my questions but I am pretty new to ST3.

0 Likes

#8

Well the plugin command route is not difficult, but it does have some complexity to it. First you’ll want to brush up on Python as everything is written in that language. Fortunately it’s a very readable language and there is a vast amount of information you can search for and the documentation is very well done.

However once you’re ready to dip your toes in, you can go to your Sublime window, select Tools => Developer => New Plugin... and it’ll generate a file with a basic plugin that writes Hello, World! to the console (obtainable by Ctrl-<grave> (not sure how to type grave into Markdown’s fixed width font style because it’s the delimeter for the same.) That’s where you’d put your code that helps generate the specific snippet you want to inject.

Once you have your function ready, you can execute it via the console (easiest for checking, but least user friendly) or bind it to a key (need to edit your keybind and have it execute the command – probably best intermediate solution when you want to test a lot of iterations) or make it available via menu and Command Palette (finishing touches)

Hope that helps. If you’re interested, I’d go up to the main menu at the top and click on Support where there are some getting started articles for plugins.

1 Like

#9

Is the existing snippet system implemented in Python? If so, I wonder how difficult it would be to extend it with new functionality.

1 Like

#10

An extension of the snippet with those capabilities would be great. As it seems it isn’t directly and without coding (Macros, Plugins, Commands) to have snippets with commands in fields or fields with multiple values where the user can choose one.

With direct support snippets would be more powerful and easier to use. Especially for non programmers. :slight_smile: More powerful snippets would be an way to be more productive in ST3. Even programmers could easily find use cases for logic in snippets.

0 Likes

#11

snippets are built-in and not in python so they can’t be extended

To make things clear: Yasnippet fills each field when you are at the field and fills the other fields when you jump further. Sublime Text uses multiple-cursors for that purpose, which has advantages and disadvantages. However you can also use regular expression replacements instead of an additional cursor, e.g. you can use ${1/a/b/g} to replace all a's by b's in the field.

IMO the best extension would be programmable, because how could you have more power than writing programs?
My idea would be to add an annotation like ${1@mult(3)}, which calls the corresponding function and inserts the resulting value (the function should accept and return strings and would be globally registered as commands).

def mult(field, multiplier="2"):
    return str(int(field) * int(multiplier))

So packages could provide that replace functions and even non-programmers could profit from it =)

Bonus: The replacement system is quite powerful, so you can emulate to choose value, e.g.:

My Snippet: ${2:${1:1:Hello,2:World,3:Test}}${1/^(?:(1)|(2)|(3)|.*)$/(?1:Hello)(?2:World)(?3:Test)/g}
$3

3 Likes

#12

@r-stein

Richard, your replacement snippet is pretty cool. Unfortunately it doesn’t contain the text content in the mirror field and only the number.

Anyway, I will explore plugin creation next and I will see what I can do.

0 Likes

#13

@fichtefoll, regarding your older post that @papadokolos linked to you mentioned the quoted variant. I looked at the documentation but I am not sure how to implement that.

I couldn’t figure out how such a tmPreferences file would look like nor how to fill in it the current date. Could you please provide a longer example or point to one?

0 Likes