skrift
skrift is moonshot's text editor. it runs inside a
kakel window and reads and writes
files through jakel. type
edit (filename) from
skalman to open a file. the
editor takes over the keyboard. no shell prompt, no echo, just a buffer and a
cursor.
modes
skrift has two modes. insert mode is home, you open a file and start typing. escape enters command mode, where single keys trigger actions. this is not vim-style modality. there is no normal mode, no composition language. just typing, and a small set of commands behind one key.
- insert mode (default)
-
typing inserts characters at the cursor. backspace deletes backward.
ctrl-d deletes the character under the cursor (forward delete,
same as command-mode
x). enter inserts a newline. tab advances to the next 4-column stop. arrow keys move in any direction, left and right within a line, up and down between lines (preserving the remembered column so vertical movement feels natural). escape enters command mode. - command mode
-
ireturns to insert mode.hshows a key reference in the status bar.qquits and saves the buffer back to jakel.xdeletes the character under the cursor.dd(pressdtwice) deletes the entire current line.cc(pressctwice) changes (deletes) the current line and enters insert mode.cw(cthenw) changes from the cursor to the end of the current word and enters insert mode.yy(pressytwice) copies (yanks) the current line. any ofdd,yy, orcccan be prefixed with a digit count, so3dddeletes three lines,5yyyanks five lines. the same digit accumulator that powers5G(go to line 5) now also feeds repeat counts.uundoes the last buffer modification, whether an insert, a deletion, a paste, or a change operation. undo is single-level, so pressinguagain does not redo. any new modification after undo saves a fresh undo state.gg(pressgtwice) jumps to the first line.Gjumps to the last line, or, with a digit prefix, to a specific line (5Ggoes to line 5).eevaluates the current line as a c0 expression through the repl and shows the result in the status bar.E(shift-e) does the same but inserts the result as a// => Ncomment on the next line.rruns every line in the buffer through the repl interpreter. output scrolls in the editor window, with aran N lnsummary afterward.escapealso returns to insert mode. arrow keys still move the cursor.
ctrl chords
ctrl chords work in both modes. ctrl-a jumps to the start of the
current line. ctrl-e jumps to the end. ctrl-k kills
(deletes) everything from the cursor to the end of the line, or, if the
cursor is already at the end, kills the newline to merge with the next line.
ctrl-d deletes the character under the cursor (forward delete).
the keyboard handler tracks the left ctrl key (scancode 0x1D) as
a held-state modifier, exactly like shift and alt.
how it works
the editor runs directly in the keyboard interrupt handler, the same context that echoes keystrokes to the screen when the shell is active. when skrift is active the keyboard handler routes every keypress to it instead of echoing and enqueuing for the shell. this is the same pattern skalman v1 used before it became a scheduled task.
the buffer is one flat, fixed-size heap allocation. inserting a character shifts every byte after the cursor right by one position and deleting shifts them left. this is the simplest possible buffer and it is fast enough for files of a few thousand lines. the use case is writing c0 source code for the repl's compile-and-execute mode, not editing a novel. a gap buffer or piece table can replace it later when the profile demands it.
rendering is a full redraw on every keystroke. it clears the window, walks the buffer line by line, draws each character into the visible viewport, draws a status bar at the bottom and draws an inverted-colour cell at the cursor position. the cursor is a full-cell invert (the character under the cursor is drawn in the window's background colour on a bright foreground background) rather than punkt's underline, because an editor cursor should be unambiguous.
file i/o is simple. skrift_start reads the file from jakel through
the normal path-resolution and read apis. skrift_quit writes the
buffer back, creating the file if it does not exist. saving does not call
jakel_sync, because disk i/o is too slow for interrupt context, so the
user runs sync from the shell after quitting, the same pattern as
the shell's own write builtin.
status bar
the bottom row of the editor window shows the current mode, the filename, a
* when the buffer has unsaved changes, the cursor's line and
column (1-indexed), and the available commands for the current mode. in insert
mode the right-hand hint reads esc:cmd and in command mode it
shows c:chg dd:del y:yank and so on. pressing h overlays a full key reference.
arrow keys
the ps/2 keyboard sends arrow keys as two-byte sequences, an
0xE0 prefix byte followed by the arrow's scancode. the keyboard
handler gained an e0_prefix flag that captures this. when
0xE0 arrives it sets the flag and returns from the interrupt after
acknowledging the pic. the next interrupt picks up the flag and passes it to the
active key consumer. the editor maps the four arrow make codes, up (72), left
(75), right (77), and down (80), to cursor movement.
visual selection
hold shift while pressing arrow keys to select text. the selection spans from the anchor (where shift was first held) to the cursor. selected characters are drawn with inverted colours, the same visual as the editor cursor, so the selection is immediately obvious. releasing shift and pressing an arrow key clears the selection. the selection survives mode switches (escape to toggle between insert and command mode) so you can select in insert mode and operate in command mode.
once a region is selected, operating on it works as you would expect.
din command mode- deletes the selection. if no selection is active,
dpends fordd(delete current line) as before. yin command mode- copies (yanks) the selection into the yank buffer. without a selection,
ypends foryy(yank current line). xin command mode- deletes the selection. without a selection, deletes the character under the cursor.
ein command mode- evaluates the selected text as a c0 expression through the repl and shows the result in the status bar. without a selection, evaluates the current line.
- typing in insert mode
- any printable character, enter, backspace, or tab deletes the selection first and then performs the normal action. this is type-to-replace, the way every modern editor works. ctrl-k and ctrl-d also delete the selection when one is active.
the status bar shows sel:N when a selection is active, where N is the
number of selected bytes. the keyboard handler passes the shift held-state to the
editor as a fifth argument alongside the make code, ascii, e0 flag, and ctrl flag
it was already passing.