Skip to content
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
1 task done
savetheclocktower opened this issue Feb 26, 2023 · 0 comments
Open
1 task done

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

savetheclocktower opened this issue Feb 26, 2023 · 0 comments
Labels
enhancement New feature or request

Comments

@savetheclocktower
Copy link

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

@savetheclocktower savetheclocktower added the enhancement New feature or request label Feb 26, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant