10

我有一个仅包含一行的 html 源文件,如下所示:

<html><head>test</head><body>wow</body></html>

,我想将其格式化如下:

<html>
    <head>
        test
    </head>
    <body>
        wow
    </body>
</html>

,我使用了命令:Edit-> Line-> Reindent 但它不起作用。

4

3 回答 3

8

在 Sublime Text 中试试这个:

  1. 突出显示第一个标签中的最后一个字符:“ >
  2. 使用Find> Quick Add Next(Mac上的Command+或PC上的+ )DCtrlD

您现在将在多个选择中突出显示所有出现,将插入符号移动到标签的末尾并按回车键插入您需要的所有新行。

祝你好运

于 2013-02-28T12:51:52.377 回答
3

我的印象是 Sublime 也提供了这种能力。当我发现它不是时,我有了使用正则表达式的想法。尽管 regex 通常被认为不适合解析 XML/HTML,但我发现这种方法在这种情况下是可以接受的。据说 Sublime 也可以通过插件高度定制,所以我认为这将是一种方式。

崇高的插件

老实说,我本可以想到tidy或至少怀疑肯定有插件可以解决您的问题。相反,我最终编写了我的第一个 sublime 插件。我只用你的输入和预期的输出对它进行了测试,它满足了,但它肯定离可靠地工作还很远。但是,我在这里发布它以分享我学到的东西,它仍然是问题的答案。

打开一个Ctrl+n的缓冲区示例插件(作为 Python 模块),它为实现子类提供了一个很好的模板。TextCommand 提供对活动缓冲区/当前打开文件的访问。像它的亲戚和一样,它需要覆盖运行方法。sublime_plugin.TextCommandWindowCommandApplicationCommand

官方 API 参考建议通过阅读随 Sublime 构建分发并位于Packages/Default相对于 Sublime 配置路径的示例源来学习。更多示例可在网站上找到。互联网还有更多内容。

处理选定的文本

要为您的问题找到解决方案,我们主要需要访问View表示活动文本缓冲区的对象。幸运的是,TextCommand我们即将实现的子类有一个,我们可以方便地向它询问当前选择的区域及其选择内容,处理符合我们需要的选择文本,然后将选择的文本替换为我们的偏好。

总结一下字符串操作:有四个正则表达式,每个都匹配元素类<start-tag><empty-tag/>和。假设我们所有的标记文本都被这些覆盖,我们将选择中的每一行都放入匹配的子字符串中。然后每行重新对齐这些。完成此操作后,我们通过记住缩进其前身包含开始标记的每一行来应用简单的缩进。包含结束标记的行立即取消缩进。 </close-tag>text-node

使用 Python 正则表达式的组寻址功能,我们可以确定每一行的缩进并相应地对齐下一行​​。事不宜迟,这将导致内部一致的缩进标记,但不考虑选择之外的行。通过将选择扩展到封闭元素,或者至少符合相邻行的缩进级别,可以轻松改善结果。它总是可以使用默认命令

另一件需要注意的事情是将键绑定到插件命令和贡献菜单条目。可能以某种方式可能,并且默认值.sublime-menu.sublime-commands文件Packages/Default至少给出了一个想法。无论如何,这里有一些代码。它必须保存在Packages/User/whatever.pySublime Python 控制台 ( ) 中,并且可以像这样调用:.Ctrl+`view.run_command('guess_indentation')

代码

import sublime
import sublime_plugin
import re

class GuessIndentationCommand(sublime_plugin.TextCommand):
    def run(self, edit):
        view = self.view
        #view.begin_edit()
        # patterns
        start_tag = '<\w+(?:\s+[^>\/]+)*\s*>'       # tag_start
        node_patterns = [start_tag, 
                        start_tag[:-1]+'\/\s*>',    # tag_empty
                        '<\/\s?\w+\s?>',            # tag_close
                        '[^>\s][^<>]*[^<\s]']       # text_node
        patterns = '(?:{0})'.format('|'.join(node_patterns))
        indentors = re.compile('[ \t]*({0})'.format('|'.join(node_patterns[:1])))
        unindentors=re.compile('[ \t]*({0})'.format(node_patterns[2]))
        # process selected text
        for region in view.sel():
            # if selection contains text:
            if not region.empty():
                selection = view.substr(region)
                expanded = []
                # divide selected lines into XML elements, if it contains more than one
                for line in selection.split('\n'):
                    elements = re.findall(patterns, line)
                    if len(elements)>0:
                        expanded += elements
                    else:
                        expanded.append(line)
                # indent output
                indent=0
                indented = []
                for line in expanded:
                    match = unindentors.match(line)
                    if match:
                        indent = max(0, indent-1)
                    # append line to output, unindented if closing tag
                    indented.append('\t'*indent+line)
                    if match:
                        continue
                    # test for possible indentation candidate
                    # indentation applies to the NEXT line
                    match = indentors.match(line)
                    if match:
                        indent+=1
                # replace selection with aligned output
                view.replace(edit, region, '\n'.join(indented))
于 2013-02-28T13:16:05.677 回答
0

如果它是为了简单的事情,我能够记录一个缩进标签的宏(工具->记录宏),然后保存它并重用这个宏。不确定这是否有帮助。

于 2013-02-28T09:00:17.857 回答