>_EXECUTIVE SUMMARY
vscode-viml is the VS Code / VSCodium extension for VimL (Vimscript), backed by the vimlrs interpreter — a standalone Vimscript engine written in Rust (a port of Neovim's eval engine on fusevm). It ships a declarative language contribution (filetype, grammar, editor config), an LSP client that launches vimlrs --lsp, a debug adapter that launches vimlrs --dap, and a TextMate grammar (source.viml) covering the VimL surface.
Design principle: mirror the proven vscode-stryke runtime wiring. The LSP transport is omitted so the client spawns bare vimlrs --lsp and never appends --stdio (the arg-rejection / “connection got disposed” failure mode learned from vscode-stryke). The binary is resolved to an absolute path through $PATH plus common install dirs (~/.cargo/bin, /opt/homebrew/bin, …), so it works even when the editor is launched from the macOS Dock and doesn’t inherit the shell $PATH.
~COMPONENTS
| File | Responsibility |
|---|---|
package.json | Extension manifest — contributes.languages (id vim, *.vim, config filenames, shebang firstLine), contributes.grammars (source.viml), contributes.configuration (LSP settings), contributes.commands (run / debug), contributes.debuggers (type vim), and the vscode-languageclient dependency. |
language-configuration.json | Line comment ", brackets, auto-closing / surrounding pairs (both quote styles), word pattern, and block-keyword indentationRules. |
extension.js | Activates on onLanguage:vim. Starts a LanguageClient running vimlrs --lsp over stdio, registers the run command (terminal vimlrs <file>), and registers a DebugAdapterDescriptorFactory launching vimlrs --dap. Missing binary → one non-fatal warning; highlighting still works. |
lib/resolveBinary.js | Pure (vscode-free) resolver that turns the vim.path setting into an absolute, executable path — searching $PATH then the GUI-missed fallback dirs. Unit-tested in CI. |
syntaxes/vim.tmLanguage.json | TextMate grammar — comments, shebang, single + double strings, numbers, special v: vars, function definitions, built-in functions, statement keywords, ex commands, scope variables, options, environment, registers, and operators. |
scripts/tokenize_test.js | Loads the grammar under vscode-textmate + vscode-oniguruma (the engine VS Code itself uses) and asserts the scope of 12 sample tokens. |
$SCOPE MAP
| Token group | TextMate scope | Sample |
|---|---|---|
| Statement keywords | keyword.control.viml | if function let try return echo throw |
| Ex commands | keyword.other.command.viml | set autocmd augroup nnoremap highlight syntax |
Special v: variables | constant.language.viml | v:true v:false v:version v:val v:lnum v:shell_error |
| Built-in functions | support.function.viml | substitute printf has split matchstr json_encode |
| Scope-sigil variables | variable.other.viml | g:foo s:bar b:baz l:tmp a:000 |
| Options | variable.other.option.viml | &number &l:shiftwidth |
| Registers / environment | variable.other.register.viml / variable.other.environment.viml | @a @+ $HOME |
| Function intro | entity.name.function.viml | function! s:Trim |
| Literals | string.* / constant.numeric | single / double strings, numbers |
#VERIFICATION
The grammar is loaded under the exact engine VS Code uses at runtime — vscode-textmate driving vscode-oniguruma — and a sample is tokenized with the resulting scopes asserted. This proves the grammar compiles under oniguruma and classifies VimL tokens correctly, including the tricky cases: a function! definition with its name capture, a scope-sigil variable such as g:counter against the v:version special, and a built-in call like substitute(...) distinguished by its trailing paren.
| Sample token | Asserted scope |
|---|---|
let | keyword.control.viml |
g:counter | variable.other.viml |
function! / s:Trim | keyword.control.viml / entity.name.function.viml |
substitute | support.function.viml |
v:version | constant.language.viml |
set | keyword.other.command.viml |