commit 08a37e59b842ffd9f80b9aaab6e6e0cefeaf8168
parent 3e6f4fbd3c0e9017ba8ed76216bcf2970fcc02c0
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Fri, 27 Jan 2023 22:43:47 -0500
sys/rdln: make ESC flush line without interpreting
Diffstat:
3 files changed, 32 insertions(+), 19 deletions(-)
diff --git a/fs/doc/sys/rdln.txt b/fs/doc/sys/rdln.txt
@@ -6,9 +6,19 @@ Dusk's main loop endlessly consumes text coming from "console". If you plug your
input (for example the keyboard device) directly on it, words will be executed
as soon as you type a whitespace. This behavior is generally uncomfortable
because we expect the system to consume what we type in a line-by-line manner.
-We also want to have the opportunity to correct mistakes on that line before we
-send it for interpretation. We also usually want to have some kind of prompt
-(the "ok" prompt). That's what sys/rdln does.
+
+sys/rdln makes the console input have the following behavior:
+
+1. Buffer input without interpreting it immediately.
+2. When we begin buffering a line, prompt with "ok\n".
+3. Echo every character received.
+4. When backspace (ASCII $08) is received, go back one character in the buffer
+ and emit backspace+space (unless of course we're at the beginning of the
+ buffer).
+5. Replace CR (ASII $0d) keys with LF (ASCII $0a).
+6. If ESC is pressed (ASCII $1b), flush the line and don't interpret it.
+7. If any other ASCII control character is received (< $20), flush the line and
+ interpret it.
It defines a Rdln structure as well as a re-implementation of the "main" routine
(the routine that endlessly consumes words).
@@ -37,11 +47,10 @@ so that EOF condition is never actually reached.
Methods:
-:readline ( self -- )
- Clear the buffer and type into it through sys/kbd's "key". When BS is
- received and if we're not at the beginning of the buffer, we go back one
- character emit SPC+BS. If we receive any other ASCII control char, typing
- ends. After a :readline, "ptr" = "buf(".
+:typeline ( self -- f )
+ Clear the buffer and type into it through sys/kbd's "key", applying buffering
+ rules outlined above. f=1 if resulting line should be interpreted. f=0 if not
+ (ESC was pressed). After a :readline, "ptr" = "buf(".
:reset ( self -- )
Set "ptr" to ")buf" so that the next "readbuf" call triggers :readline.
diff --git a/fs/sys/rdln.fs b/fs/sys/rdln.fs
@@ -6,21 +6,24 @@ create in( LNSZ allot
here const in)
: bs? BS over = swap $7f = or ;
+: cr>lf dup CR = if drop LF then ;
\ only emit c if it's within the visible ascii range
: emitv ( c -- ) dup SPC - $5f < if emit else drop then ;
-: lntype ( ptr c -- ptr+1 f )
- dup bs? if ( ptr c )
- drop dup in( > if 1- BS emit then spc> BS emit 0
- else ( ptr c ) \ non-BS
- dup emitv dup rot c!+ ( c ptr+1 ) dup in) = rot SPC < or ( ptr+1 f )
- then ;
extends MemIO struct[ Rdln
- : :readline ( self -- ) >r \ V1=self
- in( begin key lntype until ( a )
- dup V1 to )buf 1- LF swap c! in( r> to ptr ;
+ : :lntype ( c self -- f ) >r \ V1=self
+ dup bs? if ( c )
+ drop V1 ptr V1 buf( > if -1 V1 to+ ptr BS emit then spc> BS emit 0
+ else ( c ) \ non-BS
+ cr>lf V1 )buf V1 ptr - 1 = if drop LF then
+ dup emitv dup V1 :putc SPC <
+ then rdrop ( f ) ;
+ : :typeline ( self -- f ) >r \ V1=self
+ V1 buf( LNSZ + V1 to )buf V1 :rewind
+ begin key V1 :lntype until
+ V1 ptr V1 to )buf V1 :rewind r> )buf 1- c@ ESC <> ;
: _readbuf2 ( n hdl -- a? read-n )
- dup :eof? if ." ok\n" dup :readline nl> then _readbuf ;
+ dup :eof? if begin ." ok\n" dup :typeline until nl> then _readbuf ;
: :reset ['] _readbuf2 over ['] :readbuf sfield! dup )buf swap to ptr ;
: :interpret
['] _readbuf over ['] :readbuf sfield!
diff --git a/fs/text/ged.fs b/fs/text/ged.fs
@@ -43,7 +43,8 @@ KEYS c@ wordtbl handlers
:w $ffff edbuf :goright ;
:w pagesz edbuf :goup ;
:w pagesz edbuf :godown ;
-:w _statusline rdln :readline _statusline rdln :interpret _top _top! ;
+:w _statusline rdln :typeline _statusline
+ if rdln :interpret then _top _top! ;
: ged 0 to _top begin
_refresh key KEYS c@+ [c]? ( idx )