在 PlainNotes 包中为 Sublime Text 添加额外的注释语法

Add additional comment syntax in the PlainNotes package for Sublime Text

我使用的是 PlainNotes 包,它的语法不是纯文本。我想为注释添加一些额外的语法,例如 JS 注释(由 // 触发)。我正在尝试使用演示中建议的代码编辑 this file(工具 > 开发人员 > 新语法):

...
contexts:
  main:
    ......
    # Comments begin with a '//' and finish at the end of the line
    - match: '//'
      scope: punctuation.definition.comment.example-c
      push: line_comment

  line_comment:
    - meta_scope: comment.line.example-c
    - match: $
      pop: true

其中一个可能的问题是我不知道如何设置范围。当我 select HTML 评论时,我尝试使用 Ctrl+Alt+Shift+P 快捷键的范围,我也查看了 tmLanguage 文件,但我仍然卡住

出于此答案的目的,我们将假设我们要应用于语法的匹配规则如下:

- match: '//'
  scope: punctuation.definition.comment.begin.html
  push:
    - meta_scope: comment.line.double-slash.html
    - match: $\n?
      pop: true

这是示例语法模板中版本的更紧凑版本,因为它使用 anonymous context 而不是 push 的命名 context。范围已略微调整(请参阅 standard scope names 用于此类内容),我们还可以选择匹配注释行末尾的换行符,以确保光标位于注释中时不应该发生的事情当光标位于注释行末尾时不会发生。

我们还假设我们要测试的示例 note 文件包含以下文本:

This is a single line

This is a paragraph of
text that is spread over
several lines.

除此之外,您可能会 运行 陷入一些潜在的陷阱;其中一些一般适用于语法,其中一些特定于 PlainNotes 包:

陷阱 1:匹配规则放置很重要

match 语句在 context 中的顺序指定了它们在语法中匹配的优先级。一般来说,匹配文本的 context 中的第一个匹配项是选定的。

如果您将 match 规则作为最后一条规则注入到 main 上下文中,则无论您尝试注释掉什么,都不会发生任何事情。相反,所有文本行的范围将保持为 text.html.markdown.note meta.paragraph.markdown.

这是因为检测一段文本的句法规则比评论match更靠近main上下文的顶部,所以在评论规则可以匹配段落规则之前有已经匹配并使用了该文本。

match 规则作为 main 中的第一项显示了一个稍微不同的问题。如果你这样做,你会看到如果你试图注释掉单行,范围将改变说那里有一条注释(尽管在视觉上你无法分辨;更多内容见下文)。同样,如果您尝试注释掉段落的第一行,它的范围也会发生变化。

但是,试图注释掉段落中的第二行或第三行没有任何效果;范围保持不变。这样做的原因直接进入陷阱 #2。

陷阱 2:语法上下文不同

在一个语法中,存在一个或多个 contexts 语法规则。总是有一个名为 main 的上下文,这是语法 "starts" 与其匹配的地方。对于我们的评论规则,还有第二个 anonymous 上下文,其中包含一个表示评论结束的匹配规则。

每个上下文都是不同的;他们有匹配的规则,但只考虑活动上下文中的规则,而忽略所有其他规则;上下文是 distinct.

我们这里的问题是 main 上下文中的最后一条规则检测到它认为是段落的开头,当发生这种情况时,它会 push 进入匿名上下文就像我们的评论规则一样。

一旦发生这种情况,语法就会认为它在一段文本中,并且应用了另一套完整的规则,其中一个规则与评论不匹配。这让我们可以对第一行进行注释,因为它还不是一个段落,但是一旦段落开始,注释就不会出现,直到该段落退出。

要解决此问题,您还需要在段落规则中包含注释规则,以便它也适用于段落。

为此,我们可以定义一个我们自己的上下文,其中仅包含我们的匹配评论规则:

  comments:
    - match: '//'
      scope: punctuation.definition.comment.begin.html
      push:
        - meta_scope: comment.line.double-slash.html
        - match: $\n?
          pop: true

现在,作为 main 中的第一个匹配项,我们可以包含 comments 上下文中的规则,以便它们应用到那里:

  main:
    - include: comments
    ...

然后我们还搜索语法以找到应用 meta.paragraph.markdown 范围的位置以找到匹配段落的位置并在其中执行 include 以注入我们的评论规则那里也一样。牢记第一个陷阱,我们将其作为匿名 context 中的第一条规则,以便它可以在其他任何事情之前使用评论:

    - match: '^(?=\S|[ ]{1,3})(?![=-]{3,}(?=$))'
      push:
        - meta_scope: meta.paragraph.markdown
        - include: comments
        ...

有了它,我们现在可以对段落行进行注释,并且范围将表明它是我们想要的注释。

然而,我们仍然没有看到任何视觉指示表明存在评论,这将我们引向第三个陷阱。

陷阱 3:语法和配色方案协同工作

使用中的语法和使用中的配色方案需要协同工作才能提供我们期望看到的语法高亮显示。语法将范围应用于文本,配色方案具有将颜色应用于范围的规则。

如果语法没有使用配色方案匹配的规则来限定某些内容,则无法应用任何样式;这就是这里发生的事情。

从技术上讲,我们的规则应用的范围是正确的和标准的link 如上所述。在这种特殊情况下,手头的问题是 PlainNotes 包不仅包括它自己的语法,还包括它自己的配色方案。

它应用的配色方案与我们正在使用的标准化范围不匹配,因为根据包作者的定义,语法不会生成该范围。

PlainNotes 提供的配色方案具有注释规则,但仅适用于块注释,而不适用于我们在此处使用的行注释。您可以通过在注释文件中使用 HTML 评论并看到它在视觉上发生变化来看到这一点。

最方便的解决方法是修改注释规则应用的范围,以便它们应用 PlainNotes 期望的范围:

  comments:
    - match: '//'
      scope: punctuation.definition.comment.begin.html
      push:
        - meta_scope: comment.block.html
        - match: $\n?
          pop: true

有了它,我们可以注释段落中的单行或内部行,并获得我们期望的语法高亮显示:

根据您的用例,这可能不足以允许在您想要的所有地方发表评论。

例如,无法在标题中进行评论,因为有一个 match 规则将标题匹配为一个完整的行,它会在任何内容匹配之前消耗评论标记。

修复需要修改标题的匹配规则以类似于评论(即推送 context 以便您可以 include 评论),这可能值得也可能不值得。