当前位置:  开发笔记 > 开发工具 > 正文

触发每个字母数字按键的动作

如何解决《触发每个字母数字按键的动作》经验,为你挑选了1个好方法。

我在插件的Default (Windows).sublime-keymap文件中有以下几行:

...
{ "keys": ["ctrl+shift+a"], "command": "table_editor_align", "context":
    [
        { "key": "setting.enable_table_editor", "operator": "equal", "operand": true, "match_all": true },
        { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*\\|", "match_all": true },
        { "key": "following_text", "operator": "regex_contains", "operand": "$", "match_all": true }
    ]
},
...

相反,触发该命令只当ctrl+ shift+ a,我想触发此命令每次字母数字按键后(包括AZ,az,0-9,为什么不也口音E,A,C等,我们使用即所有字符写作时)?

"keys": ["[a-zA-Z0-9_]"]

似乎不起作用.

注意:插件当前是sublime_plugin.TextCommand的子类,我认为保持这个是必须的.我试图修改的插件是https://github.com/vkocubinsky/SublimeTableEditor,我希望在每次按键后自动重新对齐,而不是在每个CTRL + SHIFT + A之后:

在此输入图像描述



1> OdatNurd..:

我不知道一次将键绑定到一大类键,所以为了做你想做的事,你必须一次为每个键创建一个单独的映射,这是相当笨拙,很可能不是一个好主意.


[编辑]实际上有一种方法可以做到这一点; 我在答案结尾处添加了更多信息[/ edit]


从一些简单的测试中可以看出,您感兴趣的键(输入文本)直接由Sublime核心处理,除非您为它们提供映射.也就是说,它们颠覆了正常的命令机制,这意味着无论何时插入文本并重新格式化都无法捕获.

正如MattDMO所建议的那样,一种方法是使用on_modified处理程序来跟踪缓冲区何时被修改,然后以这种方式触发重新排列.

可以执行类似操作的示例插件如下:

import sublime
import sublime_plugin
import re

class TableFormatEventListener(sublime_plugin.EventListener):
    def __init__(self):
        self._views = dict()
        self.regex = re.compile(r"\s*\|")

    def on_modified(self, view):
        # Only for views with table editing enabled that are not already being
        # modified
        if (view.settings().get("enable_table_editor", False) and
                self._views.get(view.id(), False) is False):

            for s in view.sel():
                line = view.substr(view.line(s.begin()))
                prior = view.substr(s.begin() - 1) if s.begin() > 0 else ""

                # Only if all cursors are inside of a table row and the
                # character prior to the cursor is not a space
                if self.regex.match(line) is None or prior == " ":
                    return

            # Perform the realignment
            self._views[view.id()] = True
            view.run_command("table_editor_align")
            self._views[view.id()] = False

    def on_text_command(self, view, cmd, args):
        # Don't trigger reformatting while an undo is happening
        if cmd == "undo":
            self._views[view.id()] = True

    def on_post_text_command(self, view, cmd, args):
        # Undo is complete; resume reformat handling
        if cmd == "undo":
            self._views[view.id()] = False

这实现了一个事件侦听器,每次修改视图时都会触发该事件侦听器.这意味着文本被添加删除,并且还包括诸如粘贴之类的东西(字面意思是任何修改缓冲区的东西;更多内容在一秒钟内).

该插件执行与键绑定相同的上下文检查,以确保所有可用的插入符当前位于表行内,就像调用该命令重新对齐表一样,否则会引发错误.

此外,还会检查添加的最后一个字符是否为空格.这是因为重新格式化似乎删除了尾随空格,这有效地阻止了您无法在表格中的任何位置输入空格.

假设所有游标都在表行中并且不只是插入空格,则在当前视图上执行重新对齐表的命令.

这里要注意的是重新调整表会导致缓冲区的内容被修改,然后再次触发插件监听器,它会在循环中反复重新调整表,直到插件主机崩溃.

为了阻止这种情况发生,我们会跟踪应该on_modified忽略其事件的视图,在修改表之前将当前视图添加到列表中,然后在完成后将其删除.

插件所做的一个副作用是你在一个表内做出的任何改变都会导致两个修改; 您所做的更改以及重新对齐表的更改(即使它没有更改).这意味着,为了撤消表格中的更改,有时您必须按下撤消次数比您想象的更多次.

这会导致潜在的问题.例如,如果您要在表行的开头退格,则该行和前一行将位于同一行.修改调用重新调整函数,正式使两行成为一行.

现在你有点蠢,因为你无法撤消变化; 当您按下撤消一次时,它会撤消重新调整,但这样做会修改缓冲区,从而触发重新调整以立即再次发生.

为了解决该问题,事件侦听器还侦听undo命令即将发生的时间,并确保在撤消发生时,修改处理程序不会重新对齐表.

由于我没有使用这个特定的插件,因此需要以这种方式处理的其他场景可能存在类似的边缘情况.

根据您正在编辑的表的大小,性能可能会受到影响,也可能不受影响.在我的(非常简单的)测试中,小型桌子上的性能在我的机器上可以忽略不计.您的里程可能会有所不同,因此在代码中进行额外检查可能是一个好主意,如果当前文件超过某个线路阈值或沿着这些线路,则可能会停止触发.


[编辑]

实际上,实际上有一种方法可以做一些类似于你最初问的方法.虽然你仍然需要一些胶水插件代码来将所有内容组合在一起(并且有一些可用性问题仍与表插件如何进行重新格式化有关),但可以为一个插入的字符分配一个触发任何插入字符的键绑定.

所需的插件代码是一个接受字符并按正常方式插入文本的命令,但随后也会触发表格对齐命令.

import sublime
import sublime_plugin

class TextAndAlignTableCommand(sublime_plugin.TextCommand):
    def run(self, edit, character):
        self.view.run_command("insert", {"characters": character})
        if character != " ":
            self.view.run_command("table_editor_align")

这定义了一个带有单个参数的命令,它将以character通常输入字符的方式插入缓冲区.然后,如果角色不是空格,它还会调用命令重新对齐表格.

有了这个,创建的键绑定是:

{ "keys": [""], "command": "text_and_align_table", "context":
    [
        { "key": "setting.enable_table_editor", "operator": "equal", "operand": true, "match_all": true },
        { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*\\|", "match_all": true },
        { "key": "following_text", "operator": "regex_match", "operand": "\\s*\\|.*$", "match_all": true }
    ]
},

这基本上是您在上面提到的键绑定(这是触发重新格式化的基础表插件的默认值),稍作修改.

首先,密钥绑定到密钥,这使得它可能触发任何否则将插入缓冲区的字符.

其次,它使用上面的自定义命令,首先插入文本,然后重新格式化表格.

第三,following_text修改上下文,使其仅在表格中列的末尾处触发,以便可以将文本插入列的中间而不将光标位置跳转到列的末尾.

当以这种方式绑定时,绑定将触发任何单个字符,并将调用带有参数的命令,该参数告诉您该字符是什么.绑定本身不能有一个修饰符(例如ctrl,shift等),但你得到的字符是否则会被键入的字符.

这是一个更清晰,并且与上面的代码没有相同的问题,因为所有采取的操作都是同一编辑操作的一部分.

此外,在列体内部不会触发绑定会消除由于表重新调整移动光标位置而能够在列的中间插入文本的问题.这确实使表格不对齐,但在这种情况下可以使用现有的键绑定来纠正问题.

另一方面,在列值的末尾(重新格式化之后)仍然不可能有空格,因为表格重新格式化要删除它们.为了阻止这种情况发生,底层插件必须被修改为不这样做,但这似乎会在一定程度上损害表格式.

推荐阅读
sx-March23
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有