Пользовательское автоматическое закрытие скобок в Sublime Text

Я пытаюсь автоматически закрыть звездочку (*) символ в файлах Markdown.
Я просматривал все файлы языковых настроек и ничего не могу использовать в качестве примера. Я также попытался написать фрагмент, но нашел его неэффективным (он не влияет на выбор).

Я искал вокруг и нашел BracketHighlighter (который утверждает, что разрешает настраиваемые пары автоматического закрытия), но безуспешно (установлен через Package Control, также перезапущен).

Любые идеи о том, где я должен начать или что я делаю не так?


Решение (спасибо @skuroda)

Ответ Скуроды будет в порядке - однако я сделал несколько изменений, которые я хотел бы добавить к их ответу:

{ "keys": ["*"], "command": "insert_snippet", "args": {"contents": "$0**"}, "context":
    [
        { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true },
        { "key": "preceding_text", "operator": "regex_contains", "operand": "\\*\\*", "match_all": true },
        { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }

    ]
}

Который добавляет два ** если звездочка нажата рядом с двумя предыдущими звездочками (например, **| затем ***| становится **|** где | это курсор. Это очень помогает в подбадривании текста.

3 ответа

Решение

Возможно, вам придется немного изменить контекст, но это должно быть началом. Это основано на привязках клавиш для автопары для встроенных скобок.

{ "keys": ["*"], "command": "insert_snippet", "args": {"contents": "*$0*"}, "context":
    [
        { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true },
        { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|;|\\}|$)", "match_all": true },
        { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }

    ]
},
{ "keys": ["*"], "command": "insert_snippet", "args": {"contents": "*${0:$SELECTION}*"}, "context":
    [
        { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true },
        { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }
    ]
},
{ "keys": ["*"], "command": "move", "args": {"by": "characters", "forward": true}, "context":
    [
        { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true },
        { "key": "following_text", "operator": "regex_contains", "operand": "^\\*", "match_all": true },
        { "key": "selector", "operator": "equal", "operand": "text.html.markdown", "match_all": true }
    ]
}

Использовать этот

{ "keys": ["*"], "command": "insert_snippet", "args": {"name": "Packages/User/my-snippet.sublime-snippet" }}

Теперь перейдите в "Настройки"> "Обзор пакетов", а затем в "Папку пользователя". Создать файл.

мой-snippet.sublime-сниппет

и используйте следующий код внутри

<snippet><content><![CDATA[
*${0:$SELECTION}*
]]></content></snippet>

Удачи

Вот моя версия. Он также основан на встроенных привязках клавиш для автоматической пары, но с некоторыми изменениями.

[
    { "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": "following_text", "operator": "regex_contains", "operand": "^(?:\\s|\\.|,|:|;|!|\\?|'|\"|‐|-|—|\\)|]|\\}|⟩|>|›|»|$)", "match_all": true },
            { "key": "preceding_text", "operator": "not_regex_contains", "operand": "\\S$", "match_all": true },
            { "key": "selector", "operator": "equal", "operand": "text.plain, text.html.markdown", "match_all": true },
        ]
    },
    { "keys": ["*"], "command": "insert_snippet", "args": {"contents": "*${0:$SELECTION}*"}, "context":
        [
            { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true },
            { "key": "selection_empty", "operator": "equal", "operand": false, "match_all": true },
            { "key": "selector", "operator": "equal", "operand": "text.plain, text.html.markdown", "match_all": true },
        ]
    },
    { "keys": ["*"], "command": "move", "args": {"by": "characters", "forward": true}, "context":
        [
            { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true },
            { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true },
            { "key": "following_text", "operator": "regex_contains", "operand": "^\\*", "match_all": true },
            { "key": "selector", "operator": "equal", "operand": "text.plain, text.html.markdown", "match_all": true },
        ]
    },
    { "keys": ["backspace"], "command": "run_macro_file", "args": {"file": "res://Packages/Default/Delete Left Right.sublime-macro"}, "context":
        [
            { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true },
            { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true },
            { "key": "preceding_text", "operator": "regex_contains", "operand": "\\*$", "match_all": true },
            { "key": "following_text", "operator": "regex_contains", "operand": "^\\*", "match_all": true },
            { "key": "selector", "operator": "equal", "operand": "text.plain, text.html.markdown", "match_all": true },
        ]
    },
]

В отличие от версии по умолчанию, эта версия будет:

  • создавать пары символов, только если перед кареткой стоит символ пробела или начало строки (например, по умолчанию не разрешается автосопряжение после o, но делает после ö или же $ - эта версия исключает все)
  • создавать пары, когда за кареткой следуют различные символы (., :, !, " и более - по умолчанию разрешено создавать пары только перед пробелом, табуляцией и некоторыми скобками)
  • работать только в текстовых файлах Markdown (.txt и.md)

Я также использую эту версию для кавычек, заменив значение по умолчанию (конечно, разрешив кавычки глобально).

Двойные символы

Моя версия двухсимвольной функциональности (аналогично OP / по умолчанию, но с некоторыми изменениями):

[
    { "keys": ["*"], "command": "insert_snippet", "args": {"contents": "$0**"}, "context":
        [
            { "key": "preceding_text", "operator": "regex_contains", "operand": "\\*\\*", "match_all": true },
            { "key": "following_text", "operator": "not_regex_contains", "operand": "\\*", "match_all": true },
            { "key": "selector", "operator": "equal", "operand": "text.plain, text.html.markdown", "match_all": true },
        ]
    },
]

Это сделает двойные символы, в этом случае звездочки (*), если в строке, предшествующей каретке, уже есть две последовательные звездочки.

Твик позволяет пропускать звездочки (по одному за раз), когда за кареткой следует любая звездочка.

Версия OP всегда добавляет две новые звездочки, если в строке, предшествующей каретке, уже есть две последовательные звездочки, даже если за кареткой следует звездочка, что является нежелательным поведением (например, сразу после добавления второй двойной звездочки, нажав клавишу звездочки добавил бы еще два вместо пропуска новых звездочек).

Пояснения

Из привязок клавиш Sublime Text по умолчанию:

Одно из правил гласит, что для создания пары перед кареткой должны стоять строчные буквы, заглавные буквы, цифры, тот же символ или подчеркивание:

{ "key": "preceding_text", "operator": ^"not_regex_contains", "operand": "[\"a-zA-Z0-9_]$"^, "match_all": true },

Тем не менее, он по-прежнему разрешает пару, если перед кареткой стоят другие буквы или символы (ö, ž, đ, ç, , Ψ, ?, ~, [, , $и т. д.) Так не должно быть, поэтому я его подправил. Следующее требует, чтобы перед кареткой предшествовал символ пробела или начало строки (исключая все другие символы, а не только основные буквы и цифры):

"not_regex_contains", "operand": "\\S$"

Это двойной минус, чтобы включить начало строк. Следующее будет работать только после пробельных символов (пробел, табуляция, другое), но НЕ в начале строк:

"regex_contains", "operand": "\\s$"

Другое правило гласит, что для создания пары за кареткой также должны следовать определенные символы: tab, space,), ], }, >, end of line:

{ "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\)|]|\\}|>|$)", "match_all": true },

Я подумал, что сопряжение символов также должно быть разрешено, если за символом следуют другие символы, а именно знаки препинания и другие пробельные символы, не включенные в значение по умолчанию.

Следующее включает в себя больше знаков препинания (., ,, :, ;, !, ?, ', ", , -, , , , ") и все пробельные символы:

"^(?:\\s|\\.|,|:|;|!|\\?|'|\"|‐|-|—|\\)|]|\\}|⟩|>|›|»|$)"

Обратите внимание, что символ пробела, предшествующий каретке, является обязательным. Это означает, что пара не будет создана, если она не нужна.

Это помогло бы в ситуации, когда кто-то хочет начать писать форматированный текст в конце предложения, но до пунктуации в конце этого предложения, например (| представляет карету):

"Это предложение |"

"Это предложение |" // user types a space

"Это предложение *|*" // User types a character and it gets a pair instead of staying single

"Это предложение *с большим количеством слов |*"

Этот вопрос задавался несколько лет назад, но, надеюсь, мой ответ в будущем будет полезен всем, кто заинтересован.

Другие вопросы по тегам