commit 13e9a5643e2d0f9a108a15ef395d07e6c42bf27e
parent 02923e7c0072ad2415a6666d4f64dd1e1149499a
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Fri, 27 Jan 2023 10:00:24 -0500
sys/rdln: allow Rdln struct to interpret outside the main loop
Diffstat:
2 files changed, 45 insertions(+), 10 deletions(-)
diff --git a/fs/doc/sys/rdln.txt b/fs/doc/sys/rdln.txt
@@ -1,5 +1,7 @@
# Readline subsystem
+Prerequisites: sys/io
+
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
@@ -8,8 +10,8 @@ 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.
-It defines a read-only RdlnIn IO structure as well as a re-implementation of the
-"main" routine (the routine that endlessly consumes words).
+It defines a Rdln structure as well as a re-implementation of the "main" routine
+(the routine that endlessly consumes words).
To install it, you only have to call "rdln$", which installs itself at the
appropriate places:
@@ -20,7 +22,37 @@ appropriate places:
2. Change "main" to its own implementation, which resets the rdln buffer before
starting the endless loop. This way, when we run "quit", the rest of the rdln
buffer will not be ran.
-3. Set "console readio" the RdlnIn.
+3. Set "console readio" to the "rdln" structbind
After the "rdln$" call, the readline subsystem is active and you'll be prompted
for the first time.
+
+## Rdln API
+
+The Rdln structure extends MemIO to wrap the realine buffer. The sys/rdln unit
+also defines a "rdln" structbind to it.
+
+This structure overrides :readbuf so that when it's at EOF, it calls :readline
+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(".
+
+:reset ( self -- )
+ Set "ptr" to ")buf" so that the next "readbuf" call triggers :readline.
+ Also, ensure that :readbuf is properly set (:interpret changes :readbuf
+ binding temporarily, we want to change it back afterwards, or if an abort
+ occurred during :interpret).
+
+:interpret ( self -- )
+ This is an override of IO :interpret. It temporarily changes :readbuf to
+ MemIO's _readbuf so that we don't trigger :readline at EOF and thus allow
+ :interpret to end at some point. This override also changes the
+ ( self -- self ) signature to ( self -- ) because it's unlikely that "self"
+ is still needed after a call to this version of :interpret, so we don't need
+ that weirdness to propagate.
diff --git a/fs/sys/rdln.fs b/fs/sys/rdln.fs
@@ -17,16 +17,19 @@ here const in)
extends MemIO struct[ Rdln
: :readline ( self -- ) >r \ V1=self
- in( begin key lntype until ( a ) dup r> to )buf 1- LF swap c! ;
- : _readbuf ( n hdl -- a? read-n )
- dup :eof? if ." ok\n" dup :readline nl> in( over to ptr then
- MemIO _readbuf ;
- : :empty dup )buf swap to ptr ;
- : :new MemIO :new ['] _readbuf over ['] :readbuf sfield! ;
+ in( begin key lntype until ( a )
+ dup V1 to )buf 1- LF swap c! in( r> to ptr ;
+ : _readbuf2 ( n hdl -- a? read-n )
+ dup :eof? if ." ok\n" dup :readline nl> then _readbuf ;
+ : :reset ['] _readbuf2 over ['] :readbuf sfield! dup )buf swap to ptr ;
+ : :interpret
+ ['] _readbuf over ['] :readbuf sfield!
+ MemIO :interpret :reset ;
+ : :new MemIO :new dup :reset ;
]struct
in( LNSZ Rdln :new structbind Rdln rdln
-: rdlnreset rdln :self to console readio rdln :empty ;
+: rdlnreset rdln :self to console readio rdln :reset ;
: rdlnmain rdlnreset begin word runword again ;
: rdln$
\ we have a read loop, we can have regular abort.