duskos

dusk os fork
git clone git://git.alexwennerberg.com/duskos
Log | Files | Refs | README | LICENSE

commit e7e499917bb8be7a4d4d46eb3af7274d41a7eb99
parent 76a286150c13da717f49710aab216b4de89edc28
Author: Virgil Dupras <hsoft@hardcoded.net>
Date:   Mon, 26 Jun 2023 07:06:25 -0400

text/pager: stop relying on Pipe filters

I'm getting rid of "chain" (and Pipe probably) and the pager is the only user
of this mechanism. More details in following commits.

Diffstat:
Mfs/doc/text/pager.txt | 47+++++++++++++++++++++++------------------------
Mfs/text/pager.fs | 29+++++++++++++++++------------
Mfs/xcomp/init.fs | 1-
3 files changed, 40 insertions(+), 37 deletions(-)

diff --git a/fs/doc/text/pager.txt b/fs/doc/text/pager.txt @@ -1,36 +1,35 @@ # Pager -Prerequisites: sys/io, sys/grid +Prerequisites: sys/io, sys/grid, sys/loop Pagers are a way to interactively control an IO stream. For now, there is only -one page implementation, the "spager" (for Serial Pager), that is, the lowest -common denominator, paging-wise. It doesn't require a Grid and simply inserts a -"Next page..." line at regular intervals, waiting for user input before -continuing. Pressing any key shows the next page, pressing ESC calls "quit" -(this generally returns to prompt). +one page implementation in text/pager. It's a "serial pager", that is, the +lowest common denominator, paging-wise. It doesn't require a Grid and simply +inserts a "Next page..." line at regular intervals, waiting for user input +before continuing. Pressing any key shows the next page, pressing ESC calls +"abort" (this generally returns to prompt). -The pager is implemented as a set of Pipe filters and can be hooked to any Pipe -but will generally be hooked to the Console, with its "input" companion on the -"in" side of it. What this companion does is to reset the pager threshold any -time a key is requested. This way, the pager will only be activated when there's -a lot of contents to spit *at once*. It will not be activated for commands with -small outputs. +The page works through the "page" word. For example: -For now, the pager counter is global. + page console :self file :spit + +This will spit the currently active file to the console while paging. This works +by temporarily overriding "console writeio" with a line counter. + +The trick is to know when to remove that override: we only want "page" to affect +the command we're about to run, not to begin paging the console forever. + +To do this, we use the Idle loop (sys/loop). That is, we add a pager removal +word in the the idle loop, which will be called as soon as we return to +interactive prompt. + +This means that the pager will not play well with any word that calls the idle +loop. When that becomes a real problem, we'll think of something... ## API pagerthreshold Value holding the number of lines the pager accepts before showing its "Next page..." prompt. Default is 20. -spagerwrite ( a n hdl -- a n hdl ) - Filters :writebuf so that writes happen line by line (LF-separated). At each - line, increase the line counter. If it reaches pagerthreshold, print "Next - page..." and wait for a keypress. If that key is ESC, quits, otherwise, reset - the line counter and continue. - -spagerread ( n hdl -- n hdl ) - Resets the line counter. - -spager$ ( -- ) - Install Serial pager filters on the Console +page ( -- ) + Make the console page until the next idle loop runs. diff --git a/fs/text/pager.fs b/fs/text/pager.fs @@ -1,19 +1,24 @@ require /sys/kbd.fs +require /sys/loop.fs 0 value _cnt 20 value pagerthreshold +0 value baseio -: spagerread ( n hdl -- n hdl ) 0 to _cnt ; +: err abort" pager error" ; -create _nextpage ," Next Page...\n" -: spagerwrite ( a n hdl -- a n hdl ) - [ CELLSZ neg [rcnt] ! ] >r ( a n ) \ V1=nextword V2=hdl - _cnt pagerthreshold = if - 0 to _cnt - _nextpage 13 V2 V1 execute 13 <> if abort" pager error" then - key ESC = if quit then then - 2dup LF rot> cidx if ( a n idx ) - to1+ _cnt nip 1+ ( a n ) then r> ; +: _reset baseio if 0 to@! baseio to console writeio then ; +' _reset loopadd -: spager$ - ['] spagerread console :addrfilter ['] spagerwrite console :addwfilter ; +: waitkey 0 to@! baseio key swap to baseio ; +: _writebuf ( a n hdl -- written-n ) + drop _cnt pagerthreshold = if + 0 to _cnt S" Next Page...\n" baseio IO :puts + waitkey ESC = if abort then then + 2dup LF rot> cidx if ( a n idx ) to1+ _cnt nip 1+ then ( a n ) + baseio IO :writebuf ; +: _flush drop baseio IO :flush ; + +create WriteIO 0 , ' err , ' _writebuf , ' _flush , ' err , + +: page 0 to _cnt WriteIO to@! console writeio to baseio ; diff --git a/fs/xcomp/init.fs b/fs/xcomp/init.fs @@ -5,5 +5,4 @@ f<< /lib/fmt.fs f<< /lib/diag.fs f<< /sys/rdln.fs f<< /text/pager.fs -\ we don't automatically call spager$ in init because of automated tests, : init S" Dusk OS\n" stype .free rdln$ stdio$ quit ;