# coderunner-extension — JavaScript-style highlighting for `.coderunner` files

A VS Code language extension that colours the Code Runner scripts in
[`codeRunner scripts/`](../../codeRunner%20scripts/). It contributes a `coderunner` language bound
to the `.coderunner` file extension, and a grammar that does nothing but `include: source.js` —
so a script is painted with the editor's built-in JavaScript theme colours.

**Highlighting only.** There is no language server, no linter and no diagnostics, deliberately:
the DSL is not JavaScript, so anything that tried to *check* the file would be wrong more often
than useful. Correctness checking belongs to the `businessmap-code-runner` skill's `crlint.py`.

Nothing here is read by the application. It is tracked so the whole team gets the same editor
setup from a checkout instead of each person recreating it.

## Install

Grab the packaged `local.coderunner-language-0.0.1.vsix` from this folder and install it. Either
route works; they do the same thing.

**From the command line**

```bash
code --install-extension deploy/coderunner-extension/local.coderunner-language-0.0.1.vsix
```

**From the UI** — Extensions view → `...` menu in its title bar → *Install from VSIX…* → pick the
file.

Then run **Developer: Reload Window** (`Ctrl+Shift+P`). A running window loaded its extension list
at startup and will not notice the new one until it reloads.

To confirm it took: open a `.coderunner` file and check the language indicator in the status bar
reads **CodeRunner**. `code --list-extensions | grep coderunner` should print
`local.coderunner-language`.

### Other editors and setups

| Setup | Command |
|---|---|
| Cursor | `cursor --install-extension <path to .vsix>` |
| VSCodium | `codium --install-extension <path to .vsix>` |
| Remote-SSH / Dev Container / WSL | Install it **on the remote**. A grammar runs in the UI process, but the extension has to be present where the workspace is. From the Extensions view, use *Install in SSH: hostname*, or run the CLI inside the remote's integrated terminal. |

### Do not copy the folder into `~/.vscode/extensions`

That used to work and no longer does, which is how this folder came to exist. Two reasons it
fails silently — no error, no entry in the Extensions view, files just left uncoloured:

1. **VS Code ignores unregistered folders.** Since roughly 1.74 the user-extensions directory is
   driven by the `extensions.json` manifest that sits beside the extension folders. A folder
   nobody added to that manifest is not scanned. `--install-extension` is what writes the entry.
2. **A sandboxed install reads a different directory.** The Flatpak build
   (`/app/bin/code`, visible as `bwrap` in `ps`) keeps its extensions in
   `~/.var/app/com.visualstudio.code/data/vscode/extensions`, and Snap likewise has its own path.
   On such a box `~/.vscode/extensions` may exist, full of leftovers from an earlier native
   install, and be read by nothing. Use the CLI and it lands wherever that build actually looks.

If highlighting still does not appear, `Developer: Inspect Editor Tokens and Scopes` on a
`.coderunner` file shows which grammar, if any, claimed the token.

## Rebuild after changing the source

The extension source is in [`src/`](src/) — that is the copy to edit, and it is what
`build.sh` packages:

```
src/package.json                       language + grammar contributions, and the version
src/language-configuration.json        brackets, auto-closing pairs, block comments
src/syntaxes/coderunner.tmLanguage.json  the grammar (currently: include source.js)
```

```bash
bash deploy/coderunner-extension/build.sh
```

It writes `local.coderunner-language-<version>.vsix` next to itself. **Bump `version` in
`src/package.json` first** — VS Code keys an installed extension by id and version, so
reinstalling the same version over itself needs `--force` and, on some builds, quietly keeps the
old copy.

`build.sh` needs only bash, `python3` and `zip`; it does not use `vsce`, so it works offline and
pulls no `node_modules`. It refuses to package a manifest that is missing a required field,
references a file that is not there, contains JSON that does not parse, or declares a `scopeName`
in `package.json` that disagrees with the grammar file — each of which produces an extension that
installs cleanly and then does nothing.

Commit the rebuilt `.vsix` alongside the `src/` change, so a checkout stays installable without a
build step.

## Extending the grammar

The grammar is a single `include` of the JavaScript grammar. Most of the DSL's keywords happen to
be JavaScript keywords too and colour for free; the ones that are not — `elseif`, `then`, `as` —
land as plain identifiers. To colour those, add patterns *before* the include, since TextMate takes
the first match:

```json
"patterns": [
  { "match": "\\b(elseif|then|as)\\b", "name": "keyword.control.coderunner" },
  { "include": "source.js" }
]
```

The authoritative keyword list is the lexer in
[`app/Libraries/Businessmap/CodeRunner/`](../../app/Libraries/Businessmap/CodeRunner/), and the
built-in functions are in its `Functions` class. Both also feed the
`businessmap-code-runner` skill, which `php scripts/check-skill-sync.php` keeps in step with the
source — **this extension is not covered by that check**, so a keyword added to the lexer will not
fail any gate for being missing here.
