Search code examples
sublimetext3

How to override Sublime Text 3 Package's (CSS3) completion syntax


I'm using the CSS3 package with Sublime Text 3.

I'm trying to override the behaviour when typing a CSS property. For example, given the following:

body {
  | <- insertion point
}

If I type background and press tab, the result will be background:, which I what I want.

If I type background:, the moment I type the colon, the line changes to background: ;, with the insertion point before the semi-colon. I don’t want this, as I always type a space after the colon myself, ending up with two spaces there. I don't want to retrain my muscle memory as all my other editing environments don't add the space automatically.

I would really like to figure out how to override this completion behaviour.

I've tried editing the completions/properties.py file inside the CSS3 package but that does not seem to be the source of this completion. Unfortunately I don't know enough about how ST packages are put together to figure this out.


Solution

  • The completions that are coming from completions/properties.py are used by the package's on_query_completions handler, which is what's used by Sublime to populate the autocompletion popup. As such, modifying the contents there (and restarting Sublime so the package reloads) would alter what gets offered in the autocomplete popup (or what can be automatically chosen as the best completion, in the correct circumstances).

        ("background", "background: ${1};"),
    

    This specifies that the autocomplete trigger of background should expand out to the name of the property followed by a colon and a space, and the cursor is left at ${1}, so something like backTab expands out to background: |;; this is the place to modify if you want to add to or modify these kinds of completions.

    On the other hand, the issue you're having is that pressing : is what triggers the space to be inserted. This isn't actually something that's autocomplete related at all, though that's not entirely obvious from looking at it.

    If you turn on command logging (View > Show Console, sublime.log_commands(True)) and follow your steps above, when you press : you see this in the console:

    command: insert_snippet {"contents": ": $0;"}
    

    That's an indication that there's a key binding in place that's doing this for you. Using View Package File from the command palette and filtering with css3 keymap will let you open CSS3/Default.sublime-keymap, where the first key binding is what's doing this:

        { "keys": [":"], "command": "insert_snippet", "args": {"contents": ": $0;"}, "context":
            [
                { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true },
                { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true },
                { "key": "selector", "operator": "equal", "operand": "meta.declaration-list.css, meta.at-rule.color-profile.block.css, meta.at-rule.counter-style.block.css, meta.at-rule.font-face.block.css, meta.font-feature-type-block.css, meta.at-rule.font-palette-values.block.css, meta.at-rule.page.block.css -meta.page-margin-box.css, meta.at-rule.viewport.block.css", "match_all": true },
                { "key": "selector", "operator": "not_equal", "operand": "meta.selector.css", "match_all": true },
                { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\}|$)", "match_all": true }
            ]
        },
    

    The context applied to this binding ensures that it triggers in this particular situation, and it's manually triggering the insert_snippet command to insert the space and semicolon for you.

    In order to stop it from doing this, copy that binding from this file into your own key bindings file and change the contents to not include the space that you don't want.

    I don't use this package, but based on the scope selectors in the context this can trigger in a few different instances and not just in this one; in all cases it would cause the insertion of the space as well.

    If your muscle memory always inserts the space in response to entering a : then that's not a big deal; if it is then you would need to alter the copied binding to change the selector context lines so that they only match when you're editing a property. That would cause Sublime to select your key binding in that case but to fall back to the one in the package in other cases.