Files
lush/issues/25-envvar-expansion-in-commands.md
Cormac Shannon 42baabde34 Implement $VAR expansion in commands (issue #25)
Extend read_command_body() to detect $NAME and trigger interpolation
using the same fragment-split mechanism as ${expr}. The lexer collects
the identifier into cmd_envvar; the parser's unified parseinterp()
branches on it to emit tostring(getenv(NAME)).
2026-03-18 08:35:46 +00:00

1.6 KiB

25 — Environment variable expansion in commands

Status: done

Problem

$VAR syntax works in Lua expressions but not inside commands:

print($PATH)        -- works: $PATH is lexed as TK_ENVVAR, expanded via getenv()
!echo $PATH         -- broken: $PATH is kept as literal text, passed unexpanded

The same applies to backtick commands:

local r = `echo $HOME`   -- $HOME is literal, not expanded

Why it happens

The lexer has two separate paths for $:

  1. In Lua code (llex.c:667): $NAMETK_ENVVAR token → compiled to getenv("NAME") call
  2. In command mode (llex.c:518): $ without { is saved as a literal character in the command string buffer

Only ${expr} interpolation works in commands — it enters a Lua expression context and returns the result inline. Bare $NAME is passed through verbatim.

Since commands are executed via fork/exec (not through /bin/sh), there is no shell to expand $PATH at runtime either.

Expected behavior

$VAR should expand in commands the same way it does in Lua expressions:

!echo $HOME          -- should print /Users/nik
!echo $PATH          -- should print the PATH value
local r = `echo $HOME`  -- r.stdout should contain /Users/nik

Workaround

Use ${expr} interpolation:

!echo ${$HOME}

Possible fix

In read_command_body() (llex.c:518), when $ is followed by an identifier, emit the current command fragment and produce a TK_ENVVAR-equivalent expansion inline — similar to how ${expr} already splits the command string to insert interpolated values.