Use cmd_mode (already on LexState) to signal whether interpolation
follows, instead of separate *_INTERP token variants. This eliminates
duplicate simple/interpolated code paths in the parser — commandexp()
and interactivestat() now each use a single unified loop that checks
cmd_mode != 0. A shared parseinterp() helper handles each ${expr}
interpolation cycle.
Add a dedicated OP_LUSH A B instruction that loads shell C functions
directly from the registry, eliminating the need for upvalue allocation
in mainfunc(), upvalue population in lua_load(), and the fragile
LUSH_NUM_UPVALS heuristic. Every chunk no longer carries 4 extra
upvalues.
Store __command, __interactive, __getenv, __setenv as upvalues
populated by lua_load() from the registry, keeping them invisible
to user code while accessible to the parser's codegen.
Unquoted tokens are now expanded through a tilde → brace → glob pipeline
in parse_argv. Quoted tokens (single, double, or backslash) suppress all
expansion. Uses glob(3) with GLOB_NOCHECK for wildcard matching and manual
implementations for tilde (~→$HOME) and brace ({a,b,c}) expansion.
Save and restore cmd_mode across interpolation parsing so that
luaX_readcommandcont resumes in the correct mode after a nested
backtick command inside ${...}.
Revert the bespoke __prompt()/__prompt2() function mechanism from issue
#09 and return to stock Lua's _PROMPT/_PROMPT2 globals (which already
support dynamic prompts via __tostring metatables). Set default
_PROMPT = "lush> " in doREPL if not already defined by config.
Replace static _PROMPT/_PROMPT2 with dynamic __prompt(exitcode)/__prompt2(exitcode)
functions. Fallback chain: __prompt() → _PROMPT → "> ". Install a default __prompt
that shows the current directory with ~ abbreviation. Track last exit code from the
REPL loop and pass it to the prompt function.
Add !command syntax that runs commands with inherited terminal (no
capture). The lexer treats ! as a statement-starting token, reading
to end-of-line with the same interpolation/escape/pipe support as
backtick commands. The C function sets _ = {code=N, stdout="", stderr=""}.
Add split_pipeline() to split command strings on unquoted | and
exec_pipeline() to fork N children connected by inter-stage pipes.
Only the last stage's stdout/stderr are captured; middle stages'
stderr is inherited. Exit code comes from the last stage.
Redesign issue #10: bare-word commands now work in both scripts and
the REPL via a parser-level heuristic (identifier + non-exception-list
token → shell command). Add runtime fallback for string-arg syntax
(echo "hello"), double-dash flag handling, and classification examples.
Add issue #12 for path-based command execution (./script, /bin/ls, ~/bin/deploy).
Add testes/lush/commands-interactive.lua as a design playground covering
result table structure, exit codes, commands inside Lua blocks, _ behaviour,
runtime fallback, Lua variable shadowing, and interleaved Lua/shell.
Use sigsetjmp/siglongjmp to catch SIGINT during readline/fgets input
and jump back to the REPL loop with a fresh prompt. Running Lua code
still gets interrupted via the existing laction/lstop mechanism.
Fixes#11.
Rewrite #10 with refined interactive command design: bare-word REPL
fallback instead of ! prefix, result table assigned to _, same shape
as captured commands. Add #11 for Ctrl-C clearing the current line
instead of exiting the REPL.
Use uname -s to select Linux vs macOS build flags instead of
hardcoding. Add -undefined dynamic_lookup for test shared libs
on macOS. Set _port=true automatically on non-Linux in ./all.
Add test suite under testes/lush/ covering backtick commands, argv
parsing, ${} interpolation, and $NAME environment variables. Wire
them into testes/all.lua so they run with the full Lua 5.5 suite.
Skip /dev/full test in files.lua when the device doesn't exist
(macOS has no /dev/full).
Mark issues #02 (backtick lexing/parsing), #03 (command execution
runtime), and #04 (argv parsing) as resolved. Add new issues for
configuration (#08), programmable prompt (#09), and interactive
command execution (#10).
Implements luaB_command: fork/execvp with pipe-captured stdout/stderr,
argv parsing with quoting/escaping, and non-blocking pipe reading via
select(). Backs the __command() calls emitted by the backtick parser.
Resolves#03 and #04.
Backtick expressions now compile as calls to a global __command()
function instead of being treated as plain strings. Interpolation
via ${expr} is supported, with each interpolated value wrapped in
tostring() for type safety. Commands are parsed in primaryexp so
suffix operations like `.stdout` work directly.
Adds a stub __command that returns {code, stdout, stderr} for testing
until the real implementation (issue #03).
- New macro l_strcoll to ease changing 'strcoll' to something else.
- MAXINDEXRK==1 in 'ltests.h' is enough to run test 'code.lua'.
- Removed unused '#include' in 'lutf8lib.c'.
When calling 'luaK_storevar', the 'expdesc' for the variable must be
created before the one for the expression, to satisfy the assumptions
for register allocation. So, in a statement like 'global a = exp', where
'a' is actually '_ENV.a', this variable must be handled before the
initializing expression 'exp'.
When dumping a string, adding 2 to its size may overflow a size_t for
external strings, which may not have a header. (Adding 1 is Ok, because
all strings end with a '\0' not included in their size.) The new method
for saving NULL strings code them as a repeated string, using the
reserved index 0.
The check for limit of local variables is made after generating code to
initialize them. If there are too many local variables not initialized,
the coding of instruction OP_LOADNIL could overflow an argument.
A vararg table can be virtual. If the vararg table is used only as
a base in indexing expressions, the code does not need to create an
actual table for it. Instead, it compiles the indexing expressions
into direct accesses to the internal vararg data.