如何在指定文件类型不在括号中时将 space 添加到等号的两端?

How to add space to both ends of a equal-sign when not in parentheses with specified file types?

可能吗?例如,当在 .py.lua 文件中,而不是在 () 中并且我键入 = 时,st3 会自动在两端添加一个 space。比如赋值语句:

a = 1

但如果处于 () 状态则禁用:

func(a=1) 
func(a=1,func(b=1))

您可以通过在 = 键上创建键绑定来执行此操作,以插入 space,然后是 = 和另一个 space,将检查:

  • 插入符号处的语法对应于 Python 或 Lua
  • 行首和文本插入符号之间的文本不包含不平衡的括号

如果不满足条件,则不使用键绑定,并且=将正常插入而不包围白色space。 (假设 = 键上的其他键绑定,如果有的话,被 evaluated 发现不适用。)


步骤

  1. 在 Sublime Text 中,打开 Preferences 菜单和 select Keybindings - User

  2. 如果文档不为空,将文本插入符号移至文档开头的第一个 [ 字符之后。

  3. 粘贴以下内容:

    { "keys": ["="], "command": "insert", "args": { "characters": " = " }, "context":
        [
            { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true },
            { "key": "selector", "operator": "equal", "operand": "source.python, source.lua", "match_all": true },
            { "key": "preceding_text", "operator": "regex_match", "operand": "^(([^()]*+)(\((?:(?2)|(?3))*\))?+)(?1)*+$", "match_all": true }
        ]
    },
    
  4. 如果文档以前是空的,请在文档开头键入 [,在文档末尾键入 ]。这是为了确保它是一个有效的 JSON 数组。

  5. 保存文件。

  6. 在Python或Lua文档中按=键,看到会自动插入space 不在不平衡括号内时围绕它。


正则表达式的解释:

Sublime Text这方面使用了PCRE regex flavor provided by the Boost library,它支持递归,这样我们就不用再重复判断括号是否平衡了。

  • ^ 行首
  • ( 开始捕获组 1
    • ([^()]*+) - 将所有连续的非括号字符捕获到捕获组 2
    • ( 开始捕获组 3
      • \( 匹配文字 ( 个字符
      • (?:(?2)|(?3))* 递归匹配对应于捕获组 2 或 3(即递归)的相同正则表达式模式,零次或无限次
      • \) 匹配文字 ) 字符
    • ) 结束捕获组 3
    • ?+ 使前一组可选但占有欲
  • ) 结束捕获组 1
  • (?1)*+ 零次或无限次所有格递归匹配对应于捕获组 1 的相同正则表达式模式
  • $ 要匹配的文本结尾 - 在本例中,文本插入符所在的位置,因为使用了 preceding_text 上下文。

总体效果是,在文本插入符所在的行中,插入符位置之前满足以下任何条件的情况下,它将匹配:

  • 没有使用括号
  • 非嵌套双括号打开和关闭
  • 嵌套的括号全部关闭
  • 没有闭括号没有对应的开括号

因为正则表达式存储在 JSON 中,\ 字符需要使用额外的 \ 进行转义,这就是为什么 operand 字符串包含 \( 但我只在正则表达式解释中提到 \(

范围选择器

为确保键绑定仅在 Python 和 lua 上有效,使用范围 selector 上下文,参数为 source.python, source.lua。 selector 匹配 source.pythonsource.lua,或者如果可以将一种语言嵌入另一种语言,则实际上两者都匹配。

在 Sublime Text 中查找语言的基本范围的一种方法是转到设置相关语法的文档的最开头,然后转到 Tools 菜单 -> Developer -> Show Scope Name。它甚至可以处理空文件。

Scope selector 是从 TextMate 借来的,有关它们的更多文档可以在这里找到:

键绑定文档

可以在此处找到有关键绑定的更多信息:http://docs.sublimetext.info/en/latest/reference/key_bindings.html#structure-of-a-key-binding

我个人认为查看默认键绑定以获取灵感很有用。