// VSCODE-VIML — ENGINEERING REPORT

VS Code / VSCodium support for VimL · standalone TextMate grammar (source.viml) · LSP via vimlrs --lsp · DAP via vimlrs --dap · verified with vscode-textmate

>_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.

94
Built-in functions scoped
29
Ex commands scoped
33
Statement keywords
18
Special v: variables
1
TextMate grammar
3
Detection paths (ext + filenames + shebang)
12
Tokenizer assertions
2
Runtime channels (LSP + DAP)

~COMPONENTS

FileResponsibility
package.jsonExtension 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.jsonLine comment ", brackets, auto-closing / surrounding pairs (both quote styles), word pattern, and block-keyword indentationRules.
extension.jsActivates 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.jsPure (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.jsonTextMate 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.jsLoads the grammar under vscode-textmate + vscode-oniguruma (the engine VS Code itself uses) and asserts the scope of 12 sample tokens.

$SCOPE MAP

Token groupTextMate scopeSample
Statement keywordskeyword.control.vimlif function let try return echo throw
Ex commandskeyword.other.command.vimlset autocmd augroup nnoremap highlight syntax
Special v: variablesconstant.language.vimlv:true v:false v:version v:val v:lnum v:shell_error
Built-in functionssupport.function.vimlsubstitute printf has split matchstr json_encode
Scope-sigil variablesvariable.other.vimlg:foo s:bar b:baz l:tmp a:000
Optionsvariable.other.option.viml&number &l:shiftwidth
Registers / environmentvariable.other.register.viml / variable.other.environment.viml@a @+ $HOME
Function introentity.name.function.vimlfunction! s:Trim
Literalsstring.* / constant.numericsingle / 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 tokenAsserted scope
letkeyword.control.viml
g:countervariable.other.viml
function! / s:Trimkeyword.control.viml / entity.name.function.viml
substitutesupport.function.viml
v:versionconstant.language.viml
setkeyword.other.command.viml