如何使用Sublime Text分组或显示具有相同标签的段落?

问题描述 投票:2回答:1

我在Sublime Text中有这样的文本(通常是一个非常大的文本文件):

#tag3
Some notes here about this and that.

#tag1 #tag2
Hello world, here is some text

#tag4
Blah
Blah

#tag2 
Lorem ipsum dolor sit amet, consectetur adipiscing elit, 
sed do eiusmod tempor incididunt ut labore et dolore magna 

#foo
bar

如何使用Sublime Text分组或仅显示与#tag2相关的段落?是否可以使用“多个游标”或其他技术?

这是所需的输出:#tag2段落首先移动,然后其余部分移动到最后:

#tag1 #tag2
Hello world, here is some text

#tag2 
Lorem ipsum dolor sit amet, consectetur adipiscing elit, 
sed do eiusmod tempor incididunt ut labore et dolore magna 

#tag3
Something else

#tag4
Blah
Blah

#foo
bar

我到目前为止尝试过:CTRL + F和#tag2,然后浏览不同的匹配项以查找与此标记相关的所有内容。

注意:我不是在寻找命令行方法,而是在Sulbime Text中使用方便的方法来快速浏览带有由标签组织的注释/段落的巨大文本文档。

sublimetext3 sublimetext2 sublimetext text-editor multiple-cursor
1个回答
1
投票

做这样的事情没有简单的内置方式。正如您所提到的,您可以搜索有问题的标签并在结果之间跳过。您还可以尝试制作一个只与您感兴趣的标签(及其内容)匹配的正则表达式,然后执行Find All选择它们并将它们剪切并粘贴到顶部。但是,根据文件的内容,这可能是也可能不可行。

一种可能的方法是为您的笔记创建某种自定义语法,以便您可以利用内置符号列表功能。

%YAML 1.2
---
# See http://www.sublimetext.com/docs/3/syntax.html
scope: text.plain.notes
file_extensions:
  - notes
contexts:
  main:
    - match: '^\s*(#\w+)'
      captures:
        1: entity.name.type
      push:
        - match: '#\w+'
          scope: entity.name.type
        - match: $
          pop: true

如果将这个简单的示例语法(仅限ST3)应用于您的注释文件,则所有标记都将突出显示语法并显示在符号列表中,允许您使用Goto > Goto Symbol

在这种情况下,标记将按照它们在文件中出现的顺序出现在符号列表中,但您可以输入一些过滤文本来过滤列表并轻松地在它们之间跳过。您还可以通过Goto > Goto Anything直接在标签上打开文件。

此外,将光标放在标签上,Goto > Goto Defintion...将显示一个快速面板,为当前文件和其他文件提供该标签的其他位置(如果有),允许您跳转到适当的位置。

对于你在问题中提到的那些会改变文件内容的东西,你需要一个插件。

这样一个插件的一个例子如下,它假设标签总是单独出现在行上,并且跟随它们的所有内容直到下一行标记是正文(例如在示例文本中列出)。

import sublime
import sublime_plugin

import re

# Regular expressions that match a single tag as well as a line that contains
# one or more tags. Note that the code below presumes that lines with tags
# contain ONLY tags and nothing else.
_tag_regex = r"#\w+"
_tag_line_regex = r"^[ \t]*(?:(?:#\w+)\s*){1,}"

# Command palette input handlers are only supported in Sublime builds 3154 and
# later, so guard against using them in a previous version.
st_ver = int(sublime.version())
HandlerBase = sublime_plugin.ListInputHandler if st_ver >= 3154 else object


class TagInputHandler(HandlerBase):
    """
    Input handler for a command argument named "tag"; tries to provide a list
    of tags that appear in the current file, if any. The selected value becomes
    the value for the argument.
    """
    def __init__(self, view):
        self.view = view

    def placeholder(self):
        return "Tag to move"

    def list_items(self):
        tags = set()
        tag_lines = self.view.find_all(_tag_line_regex)

        for region in tag_lines:
            line = self.view.substr(region)
            tags.update(re.findall(_tag_regex, line))

        if not tags:
            sublime.status_message("File contains no tags")

        return list(sorted(tags))


class TagToTopCommand(sublime_plugin.TextCommand):
    def run(self, edit, tag=None):
        if tag is None:
            return self.prompt_tag()

        # Find all lines that contain tags; they are considered the start of
        # sections.
        lines = self.view.find_all(_tag_line_regex)
        matched = []
        eof = sublime.Region(self.view.size())

        # Keep any tag lines that contain the tag we were given. The found
        # regions are modified so that they start at the start of the tag line
        # and end at the start of the following tag section (or end of file)
        # so that the region entirely encompasses the data for these tags.
        for idx, line in enumerate(lines):
            end = lines[idx + 1] if idx + 1 < len(lines) else eof
            if tag in re.findall(_tag_regex, self.view.substr(line)):
                matched.append(sublime.Region(line.a, end.a))

        # Extract all of the sections that we matched above.
        text = []
        if matched:
            # Go bottom up so we don't disturb our offsets.
            for region in reversed(matched):
                text.append(self.view.substr(region))

                # Special handling if this region ends at the buffer end
                if region.b == eof.b:
                    # Move the start up the region upwards to skip over all
                    # blank lines, so that when we trim this section out there
                    # aren't extra blank lines left at the bottom of the view.
                    prev_line = self.view.line(region.a - 1)
                    while prev_line.a == prev_line.b:
                        prev_line = self.view.line(prev_line.a - 1)
                    region.a = prev_line.b + 1

                    # The region doesn't capture the last line of the buffer,
                    # so ensure that this item is separated from the other
                    # items when it moves.
                    text[-1] += "\n"

                self.view.replace(edit, region, '')

            # Add all of the text back at the beginning, but reverse the order
            # of the entries so they preserve the order they appeared in the
            # file.
            self.view.insert(edit, 0, ''.join(reversed(text)))
        else:
            sublime.status_message("'%s' not found in the current file" % tag)

    def input(self, args):
        # This is invoked by Sublime if the command is executed from the
        # command palette; we make the palette prompt us for the tag if one is
        # not given.
        if args.get("tag", None) is None:
            return TagInputHandler(self.view)

    def prompt_tag(self):
        # This is invoked in situations where the command is executed without a
        # "tag" parameter and it's not executing in the command palette; fall
        # back to prompting via a quick panel
        items = TagInputHandler(self.view).list_items()

        def pick(idx):
            if idx != -1:
                self.view.window().run_command("tag_to_top", {"tag": items[idx]})

        self.view.window().show_quick_panel(
            items,
            lambda idx: pick(idx))

这实现了一个tag_to_top命令,给定一个标记,它将找到提及该标记的所有部分,并以当前文件顺序将它们拉到文件的顶部。

tag参数是可选的;如果没有给出当前文件中所有唯一标签的列表,将显示在列表中供您选择。您也可以直接将标签传递给它,例如,如果您有经常查看的标签或其他标签。

{
    "keys": ["super+t"], "command": "tag_to_top",
    //"args": { "tag": "#something" }
},

如果需要,您还可以将以下内容添加到TagActions.sublime-commands包中名为User的文件中,将其添加到命令面板中:

[
    { "caption": "Bring Tag to Top", "command": "tag_to_top" }
]

如上所述,您可以提供标记作为参数,可能会多次使用不同的标记添加命令以轻松交换文件。

此外,如果您正在使用支持它的Sublime版本,则从命令选项板运行时,这将直接提示您输入标记,而不是打开快速面板。

请注意,上面的内容适用于Sublime Text 3,但它也适用于Sublime Text 2(因为你标记了它),尽管这只是我自己的温和测试。

该示例演示了如何查找表示标记的文件部分,以便可以从文件中删除它们并将其添加回顶部。对于非破坏性选项,这可以适用于确定与标记不匹配的区域,而是将它们折叠起来,这样只会让您感兴趣的标记立即在缓冲区中可见。

© www.soinside.com 2019 - 2024. All rights reserved.