MCPcopy Index your code
hub / github.com/bathos/Ecmascript-Sublime

github.com/bathos/Ecmascript-Sublime @2.5.1

Chat with this repo
repository ↗ · DeepWiki ↗ · release 2.5.1 ↗ · + Follow
37 symbols 73 edges 9 files 0 documented · 0%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

Gitter

Ecmascript Sublime Syntax

A sublime-syntax language definition for Ecmascript / Javascript / ES6 / ES2015 / Babel or what have you.

Sublime syntax is only available in Sublime Text 3.0.

New in 2.5

Added:

  • Logical assignment operators &&=, ??= (||= was already present)
  • Ergonomic private field brand checks (#foo in bar)
  • Class static blocks
  • Import assertions

Removed:

  • The old bind operator proposal (::) has been dead for too many years to justify keeping around. Goodbye old friend — you were actually pretty cool.
  • The scope keyword.operator.assignment.conditional.mallet was changed to align with the pattern established for other augmented assignment operators.

Fixed:

  • Private generator methods no longer cause the class body context to stick around past the end of the actual class body.

New in 1.6

  • Nested syntax highlighting

A common use of mutli-line template literals is to embed snippets of code. For instance, it could be snippets of HTML/CSS in the browser or SQL queries in node.js. For those longer template literals, it may be useful to enable nested syntax highlighting and make snippets of code easier to read. You can enable this by adding a block comment directive before a template literal. The complete syntax for the directive is as follows:

/* syntax: {SYNTAX_NAME} */ tag? `contents`

Where the tag identifier may appear before or after the syntax block comment directive.

One of the perks to using this directive is that nested syntax blocks will inherit their usual functionality from their syntax definition, such as keybindings, snippets, autocompletions, and commenting:

Nested Syntaxes

Supported Syntaxes: Here's the list of currently supported syntaxes. I just went with all the ones that I assume are reasonable to use in the browser / node.js. Feel free to open an issue if you think another syntax would be useful.

  • bash | shell
  • css
  • html
  • javascript | js
  • json
  • dot (Graphviz)
  • glsl (GLslang for WebGL)
  • lua
  • sql
  • xml
  • yaml

And here is a demonstration of all the currently supported syntaxes:

Nested Syntaxes

New in 1.3

  • Improvements to JSX scopes
  • JSX fragment support
  • Styled JSX support
  • Numeric separators support
  • BigInt support
  • Regexp features: dotall flag, property escapes, named captures, lookbehinds
  • Private instance fields

The Styled JSX additions merit some explanation. Earlier I half-assed this by delegating to the CSS syntax definition when a JSX element with a template child met the expected conditions for styled JSX. This doesn’t work well in practice because of the context sensitivity of the matches in the default CSS syntax definition — that is, in any position after interpolation, one was apt to get bad highlighting of the CSS since the it no longer knew if it was in a selector or a value, etc.

To address this, I added a deliberately forgiving and imprecise, simple ("flat") CSS matcher that is chiefly concerned with identifying lexical constructs for this context. It uses a subset of the same scope names as the pre-bundled sublime CSS definition, but some of the scopes needed to be conflated due to the lost context awareness. The end result is CSS highlighting for Styled JSX templates that should be consistent and helpful in the great majority of cases despite the lost distinctions.

Styled JSX example

Support for XML-style namespacing (ns colon) in JSX has been removed. It was in the official grammar, but afaict it is not used in practice and isn’t supported by Babel’s JSX transform. Instead, scoping for member expression style component names is improved, and html (lowercase / possible hyphens) names are scoped distinctly from component references (pascalcase / es identifier).

JSX fragments are a new way to indicate unkeyed groups of sibling nodes without the need for extraneous divs: <>stuff</>.

The numeric separators proposal, which permits underscores within numeric literals in most positions for improved readability of (mainly) hex and binary notated numbers recently advanced to stage 3.

The BigInt proposal did as well. This is a new numeric type which is represented syntactically by the suffixing "n" to a numeric literal.

The new RegExp features at stage 3 are the dotall ("s") flag, Unicode property character class escapes, named capture groups and named capture backreferences, and positive and negative lookbehind assertions.

Private instance fields (prefixed with '#') are included, with the caveat that for practical reasons our definition can’t recognize most situations where a reference to such a property would be illegal.

Although not very thorough, some color schemes have been updated a bit to take advantage of the new scopes. (Always looking to add better color schemes if anybody has stuff to contribute!)

New in 1.1

  • Most currently-stage-3 proposals (likely ES2018) and some stage 2 now covered.
  • Added new theme, Haydn

Haydn example

New in 1.0

  • Highlighting for merge conflict markers (cannot be perfect by its nature, but better than nothing)
  • New theme, Sibelius, which is probably the first tasteful one. Between that and the fact that this has been around for a year, bugs seem under control, and a fair number of people are using this, I figured I should do '1.0'.

Sibelius example

New in 0.3

  • JSX support
  • Adds source.js at root to increase compatibility with other packages

JSX example

New in 0.2

Remaining Work

  • I’d like to provide more themes with the definition package itself. The first of these is ‘Excelsior,’ a kind of tacky attempt to demonstrate what can be done that I’ve grown very fond of as it matured. It’s (mostly) complete now. Still, it’s probably a bit much for many users.
  • The chunk of comment-delimited code starting at assignmentExpression_NO_IN is actually possible to generate as a build step. Doing so will reduce the chances of accidentally editing assignmentExpression without making the corresponding change in assignmentExpression_NO_IN. I’m not sure if this is worthwhile yet but it’s rolling around in my head.
  • A lot of the redundant-looking contexts exist for good reasons -- but not all of them. There should be a clean-up and consolidation phase for contexts, but more importantly, for patterns (or more often, pattern components).

Why Bother

There are at least three tmLanguage syntax definitions available for Javascript right now, and two support ES6+: JSNext and Babel Sublime (which I think is a fork of the former). Since they’re actually great already, I should explain what the point of this fourth one is.

Sublime syntax is a brand new YAML syntax definition system that was introduced in Sublime Text dev build 3084 in April of 2015. Previously the only definition system Sublime supported was tmLanguage, originally from TextMate. In addition to cutting out the common build step of YAML -> heinous XML, Sublime syntax introduced a ‘context’ system for controlling what kinds of matches could take place at a given juncture.

Contexts exist in a FILO stack. They can be pushed, popped, or ‘set’ (pop-push). As in tmLanguage, matching cannot look past the current line, but using contexts bypasses some of the old consequences of that constraint, allowing more advanced and accurate scope assignment.

The number one reason why I made this is that it bothered me that many disparate elements of the grammar that just happened to look similar had to share generic scopes like meta.brace.curly. Thanks to Sublime syntax, Ecmascript Sublime doesn’t have to have scopes that describe what something looks like. In the case of braces, instead you will find scopes for block statements, object literals, object binding patterns, class and function bodies, namespace imports, etc -- the things that the braces mean.

It goes a bit beyond that, too. If you like, you can color if statements differently from loop statements for example. Generators, methods, and accessors are also individuated. In fact there are far more very specific scopes available than anyone would ever reasonably use, but the point is to allow the theme designer to choose exactly which elements share colors (most good themes seem to have relatively small palettes, really).

However there are good reasons one might prefer one of the other choices for syntax highlighting. For one, maybe you like a theme that plays better with one of the others. There are also differences with the approaches taken that may or may not suit your style. And finally, Ecmascript Sublime is a lot more rigid by nature, so invalid token sequences will not often pass unnoticed -- you may find this useful, or you may find it bothersome.

Here’s an early shot of Excelsior. I should add an updated one soon:

Early Excelsior example

And here’s an example I’m fond of, using background colors to indicate the depth of matching groups in a regular expression:

Excelsior regex example

Feature Coverage

ECMAScript Sublime tries to stay current with the editor’s draft ES spec and any stage 4 proposals that introduce new syntax.

Syntax-change proposals at earlier stages are supported in many cases. If a proposal gets withdrawn, we eventually remove it here too. To be included before stage 4, some combo of the following has to be true (but it’s not a science):

  • One or more engines have implemented it
  • The syntax is a reasonably settled aspect of the proposal
  • It’s specified clearly enough to not make us just guess
  • The proposal has high momentum/usage and the syntax is unlikely to change
  • The scope is small enough that it’s not costly to add or remove it

Some earlier-than-stage-4 proposals (as of mid 2021) which are supported are:

Non-JS extensions

Apart from the special handling for some tagged template strings, the only syntactic feature supported which isn’t either JS or proposed JS is JSX. This is due to its popularity, low complexity (esp. w/ regard to how “isolatable” it is), and the unlikelihood of collision with new grammar features of JS proper. It’s “safe.”

TypeScript isn’t supported. It’s a distinct language that merits a distinct syntax definition. TS syntactic extensions touch almost every production and many occur in “unsafe” places that would make preserving the signature feature of ES Sublime — its relatively high specificity — very difficult.

Also, despite its size, its grammar doesn’t seem to be specified! I thought that was pretty surprising when I first researched the viability here. I did find evidence of an early attempt at formalizing it, but it was pretty different from current TS (and it wasn’t a sound).

SublimeText Symbols

A Sublime syntax definition involves more than the definition proper. These other items use the tmPreferences format to describe how automatic indentation works, as well as how the "symbol list" is populated.

If you haven’t used Sublime symbol navigation before, I recommend checking it out. It’s a quick way to

Core symbols most depended-on inside this repo

yaml_load
called by 7
nested/src/modify-ecmascript.js
insert_rules
called by 7
nested/src/modify-ecmascript.js
clean_context
called by 6
nested/src/syntax.js
match_replace
called by 6
nested/src/modify-ecmascript.js
recurse_context
called by 6
nested/src/enhance-color-scheme.js
analyze
called by 4
nested/src/syntax.js
clone
called by 4
nested/src/modify-ecmascript.js
stack_top
called by 4
nested/src/modify-ecmascript.js

Shape

Function 22
Method 11
Class 4

Languages

TypeScript84%
Python16%

Modules by API surface

nested/src/syntax.js10 symbols
nested/src/modify-ecmascript.js10 symbols
commands.py6 symbols
nested/emk.js4 symbols
nested/src/test/interp.js3 symbols
nested/src/enhance-color-scheme.js3 symbols
nested/src/stack-filter.js1 symbols

For agents

$ claude mcp add Ecmascript-Sublime \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact