#vim #modal-editor #ex #editor #vim-editor #ex-command

hjkl-ex

Ex-command registry and dispatch layer for the hjkl editor stack

37 releases (22 breaking)

Uses new Rust 2024

new 0.41.2 Aug 6, 2026
0.40.0 Aug 1, 2026
0.39.1 Jul 30, 2026

#842 in Text editors

Download history 17/week @ 2026-05-15 50/week @ 2026-06-26 25/week @ 2026-07-03 18/week @ 2026-07-10 22/week @ 2026-07-17

115 downloads per month
Used in 3 crates (2 directly)

MIT license

3MB
49K SLoC

hjkl-ex

Ex-command registry and dispatch layer for the hjkl editor stack.

CI crates.io docs.rs MSRV License: MIT

Part of the hjkl monorepo — a vim-modal editor in Rust.

Provides a typed Registry for ex commands, range parsing, Tab-completion, and the full :set option table. Host applications register commands and call try_dispatch to let hjkl-ex handle them; unrecognised commands fall back to the host's own handling.

What lives here

  • Registry<H> / HostRegistry<Ctx> — extensible command registries with canonical names, aliases, and ArgKind metadata used by the completer.
  • try_dispatch — resolves a command string against the editor registry and returns an ExEffect (save, quit, info, error, …), or None when no match.
  • complete / complete_arg — Phase 6 Tab-completion engine. Resolves the command token, then dispatches to path, setting, buffer, register, or mark completion based on the command's declared ArgKind.
  • all_setting_names — flat list of all :set option names and aliases, consumed by the host's completion ArgSources.
  • parse_range — Vim-compatible line-range parser (%, ., $, 'a, …).

Usage

cargo add hjkl-ex
use hjkl_ex::{Registry, try_dispatch, all_setting_names, ArgSources, complete};

// Register commands (or use the built-in default_registry).
let reg = hjkl_ex::default_registry::<MyHost>();
let host_reg = hjkl_ex::HostRegistry::<()>::new();

// Dispatch a command string (without the leading ':').
if let Some(effect) = try_dispatch(&reg, &mut editor, "w") {
    // handle ExEffect::Save / ExEffect::Quit / …
}

// Tab-completion for the prompt.
let settings: Vec<String> = all_setting_names();
let sources = ArgSources {
    settings: &settings,
    ..Default::default()
};
let completions = complete("set nu", 6, &reg, &host_reg, &sources);
// completions.candidates == ["nu", "number", "numberwidth", …]

Documentation

docs.rs/hjkl-ex

Contributing

See the monorepo CONTRIBUTING guide.

License

MIT — see LICENSE.

Dependencies

~14–21MB
~305K SLoC