2 Commits
Author SHA1 Message Date
AnachronautandClaude Opus 5 fd962f0084 The shell runs what it reads, not what a name ends in
A typed word had ".sbx" pasted on the end of it before anything went
looking, which is why "notes.txt" sent the shell after a notes.txt.sbx
that was never going to exist, and why a script could only be started
with "do". The extension was what made a file reachable by name.

Now the word as typed is asked for first and the word with the extension
on it only after that misses. What comes back is dispatched on what is
inside it: SBEX loads and starts, "#!" is read as lines. The loader
already refuses anything that is not SBEX and the script reader already
refuses anything without the shebang, so the two kinds of runnable file
turn each other away and neither has to know the other exists.

The suffix can only ever be a second guess, so a file that is really
there always beats one that would have to be invented and every program
already on a disk still starts by the short name people type for it. It
costs a second walk of each directory when a word is not found in it.

Tab completion offers a file under the name it actually has, and the
suffix stripper is gone: a first word can now be any file at all, and
offering only the ones ending .sbx would hide the scripts.

The video capture windows moved out a hundred thousand cycles, because
starting Lander now walks four names where it walked two.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
2026-09-06 13:23:14 -04:00
AnachronautandClaude Opus 5 2b0aeeefd4 Start a program by typing its name
A word the shell has no command for is now looked for on the disk as
"<name>.sbx", and if it is there it is loaded and started exactly as load and
run would do it. Whatever followed the word reaches the program through
osArgument by the same route as whatever follows run, so "Say hello there"
and "Type notes.txt" work without either program knowing how it was started.

load and run are unchanged and both stay. load is how the monitor puts an
arbitrary file in front of itself, which typing a name deliberately cannot do:
the extension is added rather than assumed, so "notes.txt" looks for
notes.txt.sbx and a text file is unreachable by name whatever is inside it.

Three things this had to get right:

The built-ins are tried first and always win. The search hangs off the end of
the dispatch chain, so a file called dir.sbx cannot become dir, and the
commands worth trusting when the disk is what you are doubting stay
trustworthy. The invoke disk carries a working dir.sbx so that this is checked
rather than asserted.

A file that is found but is broken says so. "not a program" and "I do not
know" are different answers, and giving the second about a file sitting on the
disk would send somebody looking in the wrong place. loadProgram therefore
hands back a status as well as a message, since only "no file of that name"
can fairly be reported as anything other than a fault.

doLoad became that subroutine rather than being copied. It ends in RET instead
of a jump to the prompt, and each way of failing sets its number and its text
together so a new one cannot leave half of the answer behind.

cosmosBreak moves because Break prints the pointers it was handed and those
are the shell's leftovers, which a CALL now puts back.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
2026-08-24 17:25:50 -04:00