在反向 "Split into Lines" 命令上保留选择

Preserve selection on reverse "Split into Lines" command

如果您 select 几行文本并按 Ctrl-Shilf-L(或菜单 > 选择 > 拆分为行),您将看到每行末尾都有多光标。

这是试图完成类似任务的插件,但现在光标应该位于行的开头。

这个插件有效,但我想稍微改进它 - 它应该保留 selection,就像默认的 Ctrl-Shift-L 行为一样。

import sublime_plugin

class SplitIntoLinesReverseCommand(sublime_plugin.TextCommand):
    def run(self, edit):
        self.view.run_command("split_selection_into_lines")
        # Seems to be redundant:
        # self.view.run_command("expand_selection", {"to": "line"})
        self.view.run_command("move", {"by": "characters", "forward": False})
        # Already tried this:
        # self.view.run_command("move", {"by": "characters", "forward": False, "extend": True})

测试文本:

foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo foo
bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar bar
baz baz baz baz baz baz baz baz baz baz baz baz baz baz baz baz

听起来你想要这样的东西:

import sublime_plugin

class SplitIntoLinesReverseCommand(sublime_plugin.TextCommand):
    def run(self, edit):
        self.view.run_command("split_selection_into_lines")
        self.view.run_command("move", {"by": "characters", "forward": True})
        self.view.run_command("move_to", {"to": "bol", "extend": True})

这里的步骤是:

  1. 使用现有命令将选区拆分为多行
    • 这会使光标位于行尾的每一行都被选中
  2. 光标向前移动一个字符
    • 当有选中的文本时,将光标向前或向后移动字符将插入符号移动到选择的那一端并删除选择;这会将插入符号留在行尾并删除选择。
  3. 将光标移动到行首,扩展选择
    • 这会将光标放在您希望它所在的位置,然后将选择放回原处。

还有其他方法可以通过直接操作选择来完成相同的事情,但通常更容易、更快速地构建现有命令,就像这里所做的那样。


如果您启用了自动换行并且所选内容中的任何行都换行,则上述解决方案将无法按预期工作。这是因为当换行时,跳转到行首和行尾的移动命令将跳转到插入符号所在行的逻辑(视觉)末尾,而不是跳到行的物理开头和结尾。

为了在自动换行的情况下工作,您需要考虑到这一点。同样,这可以通过手动摆弄选择来实现,但更简单的方法是在命令执行期间暂时关闭自动换行,以便移动按预期工作:

import sublime_plugin

class SplitIntoLinesReverseCommand(sublime_plugin.TextCommand):
    def run(self, edit):
        # Save the state of word wrap and ensure that it's turned off
        word_wrap = self.view.settings().get("word_wrap", None)
        self.view.settings().set("word_wrap", False)

        self.view.run_command("split_selection_into_lines")
        self.view.run_command("move", {"by": "characters", "forward": True})
        self.view.run_command("move_to", {"to": "bol", "extend": True})

        # Replace the setting as long as it existed.
        if word_wrap is not None:
            self.view.settings().set("word_wrap", word_wrap)