sublimetext3 - 如何使用 Sublime Text 对具有相同标签的段落进行分组或显示?
问题描述
我在 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 中寻找一种方便的方法,以便能够快速浏览带有标签组织的注释/段落的巨大文本文档。
解决方案
没有简单的内置方法来做这样的事情。正如您所提到的,您可以搜索有问题的标签并在结果之间跳过。您还可以尝试制作一个仅匹配您感兴趣的标签(及其内容)的正则表达式,然后执行 aFind 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 中工作(因为您已对其进行了标记),尽管这仅对我进行了轻度测试。
该示例演示了如何查找文件中代表标签的部分,以便可以将它们从文件中删除并重新添加到顶部。对于非破坏性选项,这可以改为确定与标签不匹配的区域并将它们折叠起来,这样只会在缓冲区中立即显示您感兴趣的标签。
推荐阅读
- r - 将括号/括号内的数字增加指定数量的函数
- algorithm - 不规则间隔 - 在哪里画线?
- html - 使用css选择选择菜单的一个选项后如何更改文本颜色?
- c++ - 在 C++ 中使用 0 初始化 2d c-array 不正确
- wordpress - 如何在自定义 WordPress 主题中生成标题图像替代文本?
- android - 如何为底部导航选项卡使用喷气背包导航组件/导航图?
- python - 如何有效地向前/向后一半填充数据帧中的空白?
- javascript - 在不知道项目名称的情况下循环遍历 javascript 对象
- python - 如何在 Python 中读取 txt 文件的特定部分?
- javascript - 未定义的属性“播放”