Skip to content
This repository was archived by the owner on Jan 8, 2025. It is now read-only.
This repository was archived by the owner on Jan 8, 2025. It is now read-only.

Supporting $BLOCK_COMMENT_(START|END) and $LINE_COMMENT  #12

Open
@savetheclocktower

Description

@savetheclocktower

Have you checked for existing feature requests?

  • Completed

Summary

I mentioned the problems in supporting these snippet variables in #11. Here’s the longer version.

Suppose someone wants to use this snippet in a JavaScript file:

$BLOCK_COMMENT_START
  Copyright $CURRENT_YEAR Conglom-O Corp.
$BLOCK_COMMENT_END

What are the comment delimiters for JavaScript? Let’s consult language-javascript/settings/language-javascript.cson:

'.source.js':
  'editor':
    'nonWordCharacters': '/\\()"\':,.;<>~!#@%^&*|+=[]{}`?-…'
    'commentStart': '// '
    'foldEndPattern': '^\\s*\\}|^\\s*\\]|^\\s*\\)'
    'increaseIndentPattern': '(?x)
        \\{ [^}"\']*(//.*)? $
      | \\[ [^\\]"\']*(//.*)? $
      | \\( [^)"\']*(//.*)? $
      '
    'decreaseIndentPattern': '(?x)
        ^ \\s* (\\s* /[*] .* [*]/ \\s*)* [}\\])]
      '

Ah. It only defines commentStart. Why? Because the only place I can see where this option is consumed in core is the Editor: Toggle Line Comments command. Why not commentEnd, then? Because that command usually doesn’t need commentEnd to be able to flip a selection or line between commented and not-commented. Looking through the grammars, the only ones for which commentEnd is defined are the ones that appear to have only a block-comment syntax and no line-comment syntax, like CSS.

But we need to know all three kinds of tokens — block-start, block-end, and line-start — or fall back to '' whenever one doesn’t exist.

When @Aerijo ran into this problem, they opened an RFC to propose the inclusion of this metadata in the grammar declaration itself. I’d argue that we should flesh out the information in the place where it’s already defined: a package’s scoped settings file, as in our language-javascript example.

Why in a different file? Why not the main grammar file?

One reason is that there’s no existing convention for this in a TM-style grammar document. But the main reason is this:

Say you’re in an HTML file and editing an inline script block. You insert a snippet that uses $BLOCK_COMMENT_START. To find out which token to use, the snippets package looks up the grammar from the root scope, which is text.html.basic. It finds that $BLOCK_COMMENT_START should be <!--, and dutifully inserts that string into the snippet. But it’s wrong, because the comment syntax is different inside of a script tag.

Instead, here’s how it should work: snippets should get the scope descriptor at the cursor, then ask atom.config for the right value:

function getBlockCommentStart (editor) {
  return atom.config.get('editor.blockCommentStart', {
    scope: editor.getLastCursor().getScopeDescriptor()
  });
}

It’s just this easy; Pulsar will understand that the source.js present in the scope descriptor means that it should return the setting for JavaScript instead of the one for HTML.

Proposal

Thus here’s what I think our earlier settings file should look like:

'.source.js':
  'editor':
    'nonWordCharacters': '/\\()"\':,.;<>~!#@%^&*|+=[]{}`?-…'
    'commentStart': '// '
    'blockCommentStart': '/* '
    'blockCommentEnd': ' */'
    'lineCommentStart': '// '
    'foldEndPattern': '^\\s*\\}|^\\s*\\]|^\\s*\\)'
    'increaseIndentPattern': '(?x)
        \\{ [^}"\']*(//.*)? $
      | \\[ [^\\]"\']*(//.*)? $
      | \\( [^)"\']*(//.*)? $
      '
    'decreaseIndentPattern': '(?x)
        ^ \\s* (\\s* /[*] .* [*]/ \\s*)* [}\\])]
      '

In the RFC it was suggested that they should be organized into a hierarchy, but I’m more interested in (a) abiding by existing conventions within settings files, (b) allowing for easy implementation by authors of language packages, and (c) allowing for easy overriding by users.

We’d keep commentStart for backward-compatibility, but in the medium term I’d want to change the Editor: Toggle Line Comments command to prefer the lineCommentStart config value, then fall back to blockCommentStart/blockCommentEnd, then fall back to previous behavior.

We’d add this metadata to all built-in language packages. Third-party language packages would not have these settings present, and wouldn’t add them unless someone was still maintaining them, but there’s nothing stopping users from defining them in their own config.cson:

'.source.applescript':
  'editor':
    'lineCommentStart': '-- '
    'blockCommentStart': '(* '
    'blockCommentEnd': ' *)'

You get the idea.

What benefits does this feature provide?

Three new snippet variables are supported, and people will be able to migrate away from VSCode more easily.

Any alternatives?

This information could still be stored in the grammar file, but I explain above why I think that's a bad idea. There may be good use cases for storing comment metadata in the grammar, but this isn't one of them.

Other examples:

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions