Ecko for VS Code
Language support for Ecko, a small language for work that is
not.
Diagnostics, completion, hover, go-to-definition and formatting come from
ecko lsp, which is the compiler itself, so your editor cannot disagree with a
build. Syntax highlighting and 37 snippets work with no server at all.
What Ecko looks like
Ecko is for work where a failure costs money: transaction streams, catalog
syncs, backfills that run for days, APIs that have to stay up. It is built
around what happens when something goes wrong.
A failure is a value you catch, with a kind that says what happened. This job
sets a malformed row aside, keeps going, and stops on anything it did not plan
for:
import std.json
rows = [r"""{"id": 1, "cents": 1250}""", r"""{"id": 2, "cents": """, r"""{"id": 3, "cents": 990}"""]
mut total = 0
mut rejected = []
for line in rows {
try {
row = json.decode(line)
total = total + row.cents
} catch (e) {
# A malformed row is set aside. Anything else stops the job, loudly.
match get(e, "kind") {
"parse" => {
rejected = push(rejected, line)
}
_ => error(e)
}
}
}
print("{total} cents, {len(rejected)} rejected")
2240 cents, 1 rejected
A mistake fails on the line that made it. Reading past the end of a list or
overflowing an integer is an error right there, not a null or a wrapped number
that turns into a wrong total three steps later:
xs = [1, 2, 3]
try { print(xs[9]) } catch (e) { print("caught: {e.message}") }
mut total = 9223372036854775807
try { total = total + 1 } catch (e) { print("caught: {e.message}") }
Contracts catch what types cannot:
# Boolean contracts catch what types cannot.
@requires(amount > 0)
@ensures(result >= 0)
fn fee(amount) = amount * 3 // 100
print(fee(1250))
print(fee(900))
You see most of this before anything runs. ecko check runs ahead of every
program and refuses undefined names, wrong arity and use before definition. That
same analysis is what this extension shows you as you type.
There is more: pattern matching over union types, pipelines, sql { ... }
blocks with real bind holes, share-nothing concurrency, and a standard library
that is already installed. import std.http is an HTTP server. import std.sql
is SQLite. ai[T] calls a model and checks the answer against your own types;
with no API key it runs in a deterministic offline mock mode, so code that uses a
model tests like any other code.
Try it
Paste any example into a file and run it:
ecko example.ecko
Or try the language in your browser first. The
playground is the real compiler built to WebAssembly,
running client-side with no backend.
What this extension gives you
From the language server (needs the ecko binary):
- Live diagnostics as you type - parse errors, undefined names with
did-you-mean, arity mismatches, use before definition, non-exhaustive matches,
unreachable code, unused imports and variables, shadowed builtins, and
unwrapped credentials
- Completion for keywords, builtins,
std modules, your own top-level
functions, types and variables, and a module's members after a .
- Hover showing signatures for your functions and labels for builtins
- Go to definition, document symbols for the outline and breadcrumbs, and
workspace symbol search
- Find All References and occurrence highlighting, scoped to the open file
and scope-aware - a name shadowed in an inner block resolves to its own
declaration, not to every occurrence of the spelling
- Quick fixes on five diagnostics: correct a misspelled name to the
suggestion the compiler already computed, remove an unused import, prefix an
unused binding with
_, declare a reassigned binding mut, or fill in the
missing arms of a non-exhaustive match
- Semantic highlighting, coloured by the compiler rather than the grammar,
so
std modules and types are told apart from ordinary names
- Format Document, the same result as
ecko fmt
Always, with no server:
- Syntax highlighting for
.ecko, covering string interpolation, raw and byte
strings, decimal literals, sql { ... } blocks, contract and tool
annotations, the ai clauses (using, with, on, -> stream), and ##
documentation comments
- 37 snippets -
match, try, @requires, @ensures, sql,
template, secret, ai[T] and the rest
- Auto-closing brackets and quotes, indentation rules, and folding via
# region / # endregion
Requirements
The editing intelligence is served by ecko lsp, so you need the binary. It is
a single file with nothing to configure:
curl -fsSL https://ecko.sh/install | sh
The extension looks for it in this order:
ecko.server.path in your settings
- the
ECKO_BINARY environment variable
ecko on your PATH
~/.local/bin/ecko, then ~/.ecko/bin/ecko, then /usr/local/bin/ecko
Those fallbacks matter because VS Code and Cursor started from a desktop
launcher often do not inherit a shell's PATH, and "the server won't start" is
almost always that. Set ecko.server.path to an absolute path if so.
Without the binary you still get highlighting and snippets, and a notice
explaining how to switch the rest on.
Learn more
Licence
Ecko is proprietary software, free for any use, personal or commercial. It is
not open source.
The extension and the language share these terms; the full text is in LICENSE.