expansions.hx
Resolve Helix command line expansions like %{file_path_absolute} from Steel plugins
- Stars: 3
- Last commit:
- Created:
Resolve Helix command line expansions like %{file_path_absolute} from Steel plugins
Helix command line expansions (%{cursor_line}, %{file_path_absolute}, etc.),
resolved from Steel.
Helix expands these for its own typable commands only. execute_command_line
splits the rest of the line on whitespace and hands the raw strings to the
scripting engine, so a Steel command receives %{file_path_absolute} as
literal text. This library resolves them for plugins that want the same
convenience.
This is not a plugin: there is nothing to require from init.scm, you use this
from your own plugins.
Depend on it in your own cog.scm:
(define dependencies
'((#:name "expansions.hx"
#:git-url "https://github.com/waddie/expansions.hx")))
Then:
(require "expansions.hx/expansions.scm")
(expand "wc -l %{file_path_absolute}")
;; => #hash('ok #t 'text "wc -l /home/you/notes.md")
(expand "echo %{nope}")
;; => #hash('ok #f 'error "unknown variable 'nope'")
| function | returns |
|---|---|
(expand text) | result hash: 'ok #t and 'text, or 'ok #f and 'error |
(expand-variable name) | the same, for one variable name without its %{} |
(variable-names) | the variable names this resolves |
(shell-quote text) | text single-quoted for /bin/sh |
Errors are returned as data, never thrown, including errors raised inside the editor accessors: a variable that cannot be read reports rather than aborting the calling command.
Values are inserted raw, exactly as Helix inserts them, so a caller building a
shell command has to quote what it interpolates. shell-quote is there for
that, and matters more here than upstream: a path with a space in it will
otherwise word-split.
parse.scm is separately requirable if you want the parse without the editor:
(parse-expansions text) returns literal and expansion segments, and has no
Helix dependency.
As upstream: %{variable}, %u{25CF} (Unicode codepoint), %sh{echo hi}
(shell command) and %reg{a} (register), with %% for a literal percent.
Contents of %sh{} are themselves expanded first.
Seven delimiter pairs are accepted: (), [], {}, <>, '', "" and
||. The bracket pairs nest; the three same-character pairs end at the next
occurrence.
A bare % is an error, as it is in Helix, so a printf format string needs
its percents doubled.
| variable | value |
|---|---|
cursor_line | one-indexed line of the primary cursor |
cursor_column | one-indexed column of the primary cursor |
buffer_name | path relative to the working directory, or [scratch] |
file_path_absolute | absolute path of the document, or the working directory |
line_ending | \n or \r\n |
current_working_directory | Helix’s working directory |
workspace_directory | nearest ancestor containing .git, .jj, .svn, .helix |
language | language id, or text |
selection | the primary selection |
selection_line_start | one-indexed first line of the primary selection |
selection_line_end | one-indexed last line of the primary selection |
%reg{} reads through Steel’s register->value, which does not see Helix’s
implicit registers.
%sh{} runs under /bin/sh. The configured editor.shell has a setter and
no getter in Steel, so it cannot be read.
line_ending is read off the first few thousand characters of the document
rather than from Document::line_ending, which no accessor exposes. A
document with no line ending in that stretch is reported as \n.
The parser is tested headlessly. Requires steel-test.
steel test/parse-test.scm
The expansion layer needs a running Helix, so it is not covered.
Copyright © 2026 Tom Waddington
Distributed under the MIT License. See LICENSE file for details.