没有简单的内置方法来做这样的事情。正如您所提到的,您可以搜索有问题的标签并在结果之间跳过。您还可以尝试制作一个仅匹配您感兴趣的标签(及其内容)的正则表达式,然后执行 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 中工作(因为您已对其进行了标记),尽管这仅对我进行了轻度测试。
该示例演示了如何查找文件中代表标签的部分,以便可以将它们从文件中删除并重新添加到顶部。对于非破坏性选项,这可以改为确定与标签不匹配的区域并将它们折叠起来,这样只会在缓冲区中立即显示您感兴趣的标签。