Sublime Forum

Sublime snippet question

#1

I am writing markdown with sublime and want to type math equations faster. Is there anyway to achieve the following functionality in sublime snippet?

Type any character followed by a number, press tab and it will become character_number. For example, if I type ‘a1’ and press tab it will become ‘a_1’.

If this cannot be achieved by snippet, what about packages?

0 Likes

#2

Snippets and completions are more for expanding a predefined piece of text into something more expansive, but the expansion text is predefined and not based on the text that triggered it. So, it may be technically possible to do this via a snippet, but to do so you would need to create a snippet for every possible combination of text and number that you might run across.

There may be a package that would allow for this, but a simple plugin is also possible, such as this one:

import sublime
import sublime_plugin

import re


class MarkdownExpandCommand(sublime_plugin.TextCommand):
    """
    Assumes that every caret in the view is trailing a word that has at least
    one digit following, and inserts an underscore between the word and the
    trailing number.
    """
    re = re.compile(r"^.*?(\d+)$")

    def run(self, edit):
        # Iterate over all cursors from the bottom up
        for sel in reversed(self.view.sel()):
            # Get the content of the line up to the caret
            span = sublime.Region(self.view.line(sel.b).a, sel.b)
            text = self.view.substr(span)

            # Determine how many digits there are prior to the cursor, then
            # insert an underscore that many characters back.
            num_len = len(self.re.match(text).group(1))
            self.view.insert(edit, span.b - num_len, "_")

This creates a command that assumes that the text prior to the cursor is some number of digits, and it looks backwards from the cursor to the first non-digit and then inserts an underscore there. It operates over all of the carets in the buffer.

In order to finish the setup, you need a key binding that will apply it to the Tab key, but only when required. An example of that would be:

{
    "keys": ["tab"],
    "command": "markdown_expand",
    "context": [
        { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true },
        { "key": "selection_empty", "operator": "equal", "operand": "true", "match_all": true },
        { "key": "preceding_text", "operator": "regex_match", "operand": ".*[^\\d\\s]\\d+", "match_all": true },
    ]
},

This triggers the command, but only in markdown files where there is no selection and the text prior to the cursor ends in a number not preceeded by whitespace (so 9 will not trigger it, but a9 will).

2 Likes