Rewrite issue #10 for scripts+REPL, add issue #12, add interactive command tests

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.
This commit is contained in:
Cormac Shannon
2026-03-01 19:35:09 +00:00
parent af8300aa40
commit 41b2095ed9
3 changed files with 610 additions and 16 deletions

View File

@@ -0,0 +1,77 @@
# Issue #12 — Path-based command execution
**Status:** open
**Related:** #10 (interactive command execution)
## Problem
Issue #10's parser heuristic detects bare-word commands when an **identifier** at statement position is followed by a non-exception-list token. This covers `ls -la`, `git status`, etc. — but not commands invoked by path, because the first token isn't an identifier:
```
./script/update -- first token is .
../lua -- first token is .
/bin/ls -- first token is /
~/bin/deploy -- first token is ~
```
In standard Lua, none of these are valid statement starts, so claiming them for shell commands doesn't steal any Lua syntax.
## Proposed heuristic
Add parser rules for path-prefixed commands. When the parser sees one of these tokens at statement position, treat the rest of the line as a shell command:
| First token(s) | Pattern | Example |
|----------------|---------|---------|
| `.` `/` | dot-slash | `./script.sh` |
| `.` `.` `/` | dot-dot-slash | `../other/build` |
| `/` | absolute path | `/bin/ls -la` |
| `~` `/` | home-relative path | `~/bin/deploy` |
### Detection
- `.` at statement position → peek next token:
- `/` on same line → path command (`./ ...`)
- `.` on same line → peek again: `/` → path command (`../ ...`)
- anything else → parse as Lua (`.` could be a concat operator fragment, though this isn't valid at statement start anyway)
- `/` at statement position → path command (not valid Lua statement start)
- `~` at statement position → peek next token:
- `/` on same line → path command (`~/ ...`)
- anything else → parse as Lua (`~` is bitwise NOT in Lua 5.4, though `~expr` as a bare statement is already a syntax error)
### Argument capture
Same as issue #10: once detected, extract the raw text of the entire line from the source buffer. Emit bytecode equivalent to `_ = __interactive("raw line text")`.
## Examples
```lua
-- all of these run as shell commands
./configure --prefix=/usr/local
../build/lush test.lua
/usr/bin/env python3 -c "print('hello')"
~/bin/deploy staging
-- check exit code like any other interactive command
./run-tests
if _.code ~= 0 then
print("tests failed")
end
```
## Non-conflicts with Lua
- `/` at statement start: not valid Lua (`/` is division, needs a left operand)
- `./` at statement start: `.` is concat, `/` is division — `./foo` as Lua would be `. / foo` (concat divided by foo), which needs a left operand. Not valid at statement start.
- `../` at statement start: same reasoning, not valid
- `~/` at statement start: `~` is bitwise NOT, `/` is division — `~/foo` as Lua would be `(~()) / foo`, which isn't valid at statement start as a bare expression statement
## Open questions
- Should `~` without `/` be supported? (e.g., `~user/bin/script` — tilde expansion for other users). Probably not initially.
- Should bare `.` or `..` (without `/`) be treated as commands? In shells, `source` is sometimes aliased to `.`. Probably not — too ambiguous.
## Files touched
| File | Description |
|------|-------------|
| `lparser.c` | Add path-prefix detection alongside the identifier heuristic in statement parsing |