ls says in green what the shell will start

Directories were already blue. Something the shell will run is green now,
and it is asked by LOOKING rather than looked up.

This was priced once as needing a runnable bit in the directory entry,
set by the filesystem from a list of magic numbers it would have to be
taught - declined twice, for putting format knowledge in the filesystem
and giving two implementations a registry to keep in step.

It costs nothing of the sort any more. The shell decides what to run by
reading a file's first block, so "will this run" is a question with an
answer already, and this asks the same one the shell would: SBEX for a
program, "#!" for a script. Nothing is written down and nothing has to
agree about anything.

The price is a block read per file, which is exactly what the bit existed
to avoid: a listing of thirty seven files went from 260,593 cycles to
635,321. It is paid in ls and not in dir on purpose - dir is the listing
you audit and is built into the shell, this is the one you read and was
loaded off the disk anyway. The fast one stays fast.

plain.script is the proof on the test disk: it sits among a dozen scripts
that are green and is not one, because it is the fixture with no shebang
and the shell will not start it. The extension is decoration and the
colour is the truth, which is the whole of what running by content means,
finally visible.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
This commit is contained in:
Anachronaut
2026-09-06 19:53:33 -04:00
co-authored by Claude Opus 5
parent afda6ca83b
commit eaeb473176
15 changed files with 124 additions and 23 deletions
+91 -1
View File
@@ -199,7 +199,8 @@ lsColour:
; ---- What it is, said in colour ----
;
; The attribute reaches a terminal as well as the screen now, so this is one mechanism and
; not two. A directory in blue and an unfinished save in red; everything else plain.
; not two. A directory in blue, something that will run in green, an unfinished save in red,
; and everything else plain.
SETD.0 Kind
LDA.0
BRA lsFileInk
@@ -212,6 +213,27 @@ lsBlue:
BRI lsInk
lsFileInk:
; ---- Whether it will run, asked by looking ----
;
; This was priced once as needing a RUNNABLE BIT in the directory entry, set by the
; filesystem from a list of magic numbers it would have to be taught - which was declined,
; twice, for putting format knowledge in the filesystem and giving two implementations a
; registry to keep in step.
;
; It costs nothing of the sort now. The shell decides what to run by READING the first block
; of a file, so "will this run" is a question with an answer already, and asking it is the
; same question the shell would ask. Nothing new is written down and nothing has to agree
; about anything: if the shell learns a third kind of runnable file, this is wrong until
; somebody adds two lines, and wrong in the direction of a listing that is less colourful.
;
; The price is a block read per file, which is what the bit existed to avoid. It is paid
; here rather than in dir on purpose: dir is the listing you audit and is built into the
; shell, and this is the one you read and is a program that was loaded off the disk anyway.
CALL runnable
BNQ lsPlain
INIA 0d2
BRI lsInk
lsPlain:
RSTA
lsInk:
OUTA 0x06
@@ -300,6 +322,67 @@ lengthDone:
ADD
RET
; ---- Will the shell start this? ----
;
; Q is zero if it will. The same two things the shell itself looks for in a first block: SBEX
; for a program, "#!" for a script. A file too short to have a first block at all cannot be
; either, and osFileBlock saying no is that answer arriving for free.
runnable:
SETD.0 Name
SETD.1 Block
RSTA
RSTB
SWI osFileBlock
BNQ runnableNo
; The shebang first, because two bytes settle it.
SETD.0 Block
LDA.0
INIB 0d35 ; '#'
CCF
SUB
BNQ runnableExec
INCD.0
LDA.0
INIB 0d33 ; '!'
CCF
SUB
BRQ runnableYes
runnableExec:
SETD.0 Block
SETD.1 ExecText
INIA 0d4
SETD.2 Left
STA.2
runnableSame:
LDA.0
LDB.1
CCF
SUB
BNQ runnableNo
INCD.0
INCD.1
SETD.2 Left
LDA.2
DECA
STA.2
BNA runnableSame
runnableYes:
RSTA
RSTB
CCF
ADD
RET
runnableNo:
INIA 0x01
RSTB
CCF
ADD
RET
; A is how much of the cell the name took. Fills the rest of it with spaces.
padOut:
; The cell less what the name took, and IN THAT ORDER. Written the other way round first,
@@ -337,6 +420,8 @@ newLine:
#Base 0x3000
ExecText:
"SBEX"
Slash:
"/"
Space:
@@ -362,7 +447,12 @@ Seen:
0x00
Used:
0x00
Left:
0x00
Name:
#Reserve 0d24
Given:
#Reserve 0d64
; A whole block, because osFileBlock writes one whether the file fills it or not.
Block:
#Reserve 0d256
+11
View File
@@ -724,6 +724,17 @@ sorting. Nothing here sorts; entries come back in the order the directory holds
order arbitrary, down-and-across buys nothing and costs a division on a machine that cannot
divide. If sorting ever arrives, that is the moment to change it.
**Something that will run is green**, and that is asked by looking rather than looked up. The
shell decides what to run by reading a file's first block, so "will this run" already has an
answer and this asks the same question the shell would: `SBEX` for a program, `#!` for a
script. It costs a block read per file, which is exactly the price a *runnable bit* in the
directory entry was proposed to avoid - and that bit was declined twice for putting format
knowledge in the filesystem and giving two implementations a registry to keep in step. Paying
the price here instead buys the same listing and writes nothing down.
It is paid in `ls` and not in `dir` on purpose. Reading every file roughly doubles what a
listing costs; `dir` stays the fast one, and this one was loaded off the disk anyway.
**The width comes from the screen**, port `0x32`, which is 80 while CosmOS is running because
CosmOS asks for the wide mode as it starts.
+1 -1
View File
@@ -49,7 +49,7 @@ pass.script 20
holds.script 87
crossed.txt 560
36 files, 2 directories
48 of 64 entries, 1887 blocks free
48 of 64 entries, 1886 blocks free
> exit
halted
Execution halted.
+1 -1
View File
@@ -40,7 +40,7 @@ args.script 64
pass.script 20
holds.script 87
35 files, 2 directories
47 of 64 entries, 1890 blocks free
47 of 64 entries, 1889 blocks free
> drive 1
> dir
other.txt 28
+1 -1
View File
@@ -56,7 +56,7 @@ args.script 64
pass.script 20
holds.script 87
35 files, 2 directories
47 of 64 entries, 1890 blocks free
47 of 64 entries, 1889 blocks free
> exit
halted
Execution halted.
+1 -1
View File
@@ -44,7 +44,7 @@ args.script 64
pass.script 20
holds.script 87
35 files, 2 directories
47 of 64 entries, 1890 blocks free
47 of 64 entries, 1889 blocks free
> exit
halted
Execution halted.
+1 -1
View File
@@ -44,7 +44,7 @@ args.script 64
pass.script 20
holds.script 87
35 files, 2 directories
47 of 64 entries, 1890 blocks free
47 of 64 entries, 1889 blocks free
> exit
halted
Execution halted.
+10 -10
View File
@@ -1,19 +1,19 @@
CosmOS
> ls
greet.sbx hello.sbx Life.sbx Snake.sbx Keys.sbx
Say.sbx Where.sbx Break.sbx Grid.sbx Press.sbx
Mode.sbx Flip.sbx Sprite.sbx Depth.sbx Packages/
Pad.sbx Crash.sbx vars.script blocks.script loops.script
tune.sbx Play.sbx notes.txt Apps/ hi.script
bad.script plain.script cross.script nonl.script outer.script
inner.script loop.script hush.script aloud.script args.script
pass.script holds.script
greet.sbx hello.sbx Life.sbx Snake.sbx Keys.sbx
Say.sbx Where.sbx Break.sbx Grid.sbx Press.sbx
Mode.sbx Flip.sbx Sprite.sbx Depth.sbx Packages/
Pad.sbx Crash.sbx vars.script blocks.script loops.script
tune.sbx Play.sbx notes.txt Apps/ hi.script
bad.script plain.script cross.script nonl.script outer.script
inner.script loop.script hush.script aloud.script args.script
pass.script holds.script
> cd /Apps
/Apps> ls
Copy.sbx Say.sbx Where.sbx Walk.sbx ls.sbx Lander where.sh
Copy.sbx Say.sbx Where.sbx Walk.sbx ls.sbx Lander where.sh
/Apps> cd /
> ls /Packages/app.Lander
Lander.sbx splash.tune
Lander.sbx splash.tune
> mkdir /empty
made
> cd /empty
+1 -1
View File
@@ -132,7 +132,7 @@ args.script 64
pass.script 20
holds.script 87
35 files, 2 directories
47 of 64 entries, 1890 blocks free
47 of 64 entries, 1889 blocks free
> exit
halted
Execution halted.
+1 -1
View File
@@ -51,7 +51,7 @@ args.script 64
pass.script 20
holds.script 87
35 files, 2 directories
47 of 64 entries, 1890 blocks free
47 of 64 entries, 1889 blocks free
> exit
halted
Execution halted.
+1 -1
View File
@@ -40,7 +40,7 @@ args.script 64
pass.script 20
holds.script 87
35 files, 2 directories
47 of 64 entries, 1890 blocks free
47 of 64 entries, 1889 blocks free
> load
load what?
> load nosuch.sbx
+1 -1
View File
@@ -38,7 +38,7 @@ args.script 64
pass.script 20
holds.script 87
35 files, 2 directories
47 of 64 entries, 1890 blocks free
47 of 64 entries, 1889 blocks free
> load Say.sbx
loaded, starting at 5000
> run the disk took its time
+1 -1
View File
@@ -38,7 +38,7 @@ args.script 64
pass.script 20
holds.script 87
35 files, 2 directories
47 of 64 entries, 1890 blocks free
47 of 64 entries, 1889 blocks free
> drive 1
> dir
f1.txt 1500
+1 -1
View File
@@ -44,7 +44,7 @@ args.script 64
pass.script 20
holds.script 87
35 files, 2 directories
47 of 64 entries, 1890 blocks free
47 of 64 entries, 1889 blocks free
> exit
halted
Execution halted.
+1 -1
View File
@@ -43,7 +43,7 @@ f Copy.sbx 7
f Say.sbx 1
f Where.sbx 4
f Walk.sbx 1
f ls.sbx 3
f ls.sbx 4
f Lander 4
f where.sh 3
/Apps> cd /