X-Git-Url: http://git.subgeniuskitty.com/pforth/.git/blobdiff_plain/2da0395e27e0cff42fb0a1a680ee6105f6e353e5..db35c5f457c413bd50cd79b0170cb295abb614d2:/fth/history.fth diff --git a/fth/history.fth b/fth/history.fth index 6299d1d..42c2696 100644 --- a/fth/history.fth +++ b/fth/history.fth @@ -1,513 +1,512 @@ -\ Command Line History -\ -\ Author: Phil Burk -\ Copyright 1988 Phil Burk -\ Revised 2001 for pForth - -0 [IF] - -Requires an ANSI compatible terminal. - -To get Windows computers to use ANSI mode in their DOS windows, -Add this line to "C:\CONFIG.SYS" then reboot. - - device=c:\windows\command\ansi.sys - -When command line history is on, you can use the UP and DOWN arrow to scroll -through previous commands. Use the LEFT and RIGHT arrows to edit within a line. - CONTROL-A moves to beginning of line. - CONTROL-E moves to end of line. - CONTROL-X erases entire line. - - -HISTORY# ( -- , dump history buffer with numbers) -HISTORY ( -- , dump history buffer ) -XX ( line# -- , execute line x of history ) -HISTORY.RESET ( -- , clear history tables ) -HISTORY.ON ( -- , install history vectors ) -HISTORY.OFF ( -- , uninstall history vectors ) - -[THEN] - -include? ESC[ termio.fth - -ANEW TASK-HISTORY.FTH -decimal - -private{ - -\ You can expand the history buffer by increasing this constant!!!!!!!!!! -2048 constant KH_HISTORY_SIZE - -create KH-HISTORY kh_history_size allot -KH-HISTORY kh_history_size erase - -\ An entry in the history buffer consists of -\ byte - Count byte = N, -\ chars - N chars, -\ short - line number in Big Endian format, -\ byte - another Count byte = N, for reverse scan -\ -\ The most recent entry is put at the beginning, -\ older entries are shifted up. - -4 constant KH_LINE_EXTRA_SIZE ( 2 count bytes plus 2 size bytes ) - -: KH-END ( -- addr , end of history buffer ) - kh-history kh_history_size + -; - -: LINENUM@ ( addr -- w , stores in BigEndian format ) - dup c@ 8 shift - swap 1+ c@ or -; - -: LINENUM! ( w addr -- ) - over -8 shift over c! - 1+ c! -; - -variable KH-LOOK ( cursor offset into history, point to 1st count byte of line ) -variable KH-MAX -variable KH-COUNTER ( 16 bit counter for line # ) -variable KH-SPAN ( total number of characters in line ) -variable KH-MATCH-SPAN ( span for matching on shift-up ) -variable KH-CURSOR ( points to next insertion point ) -variable KH-ADDRESS ( address to store chars ) -variable KH-INSIDE ( true if we are scrolling inside the history buffer ) - -: KH.MAKE.ROOM ( N -- , make room for N more bytes at beginning) - >r ( save N ) - kh-history dup r@ + ( source dest ) - kh_history_size r> - 0 max move -; - -: KH.NEWEST.LINE ( -- addr count , most recent line ) - kh-history count -; - -: KH.REWIND ( -- , move cursor to most recent line ) - 0 kh-look ! -; - -: KH.CURRENT.ADDR ( -- $addr , count byte of current line ) - kh-look @ kh-history + -; - -: KH.CURRENT.LINE ( -- addr count ) - kh.current.addr count -; - -: KH.COMPARE ( addr count -- flag , true if redundant ) - kh.newest.line compare 0= \ note: ANSI COMPARE is different than JForth days -; - -: KH.NUM.ADDR ( -- addr , address of current line's line count ) - kh.current.line + -; - -: KH.CURRENT.NUM ( -- # , number of current line ) - kh.num.addr LINENUM@ -; - -: KH.ADDR++ ( $addr -- $addr' , convert one kh to previous ) - count + 3 + -; -: KH.ADDR-- ( $addr -- $addr' , convert one kh to next ) - dup 1- c@ \ get next lines endcount - 4 + \ account for lineNum and two count bytes - - \ calc previous address -; - -: KH.ENDCOUNT.ADDR ( -- addr , address of current end count ) - kh.num.addr 2+ -; - -: KH.ADD.LINE ( addr count -- ) - dup 256 > - IF ." KH.ADD.LINE - Too big for history!" 2drop - ELSE ( add to end ) -\ Compare with most recent line. - 2dup kh.compare - IF 2drop - ELSE - >r ( save count ) -\ Set look pointer to point to first count byte of last string. - 0 kh-look ! -\ Make room for this line of text and line header. -\ PLB20100823 Was cell+ which broke on 64-bit code. - r@ KH_LINE_EXTRA_SIZE + kh.make.room -\ Set count bytes at beginning and end. - r@ kh-history c! ( start count ) - r@ kh.endcount.addr c! - kh-counter @ kh.num.addr LINENUM! ( line ) -\ Number lines modulo 1024 - kh-counter @ 1+ $ 3FF and kh-counter ! - kh-history 1+ ( calc destination ) - r> cmove ( copy chars into space ) - THEN - THEN -; - -: KH.BACKUP.LINE { | cantmove addr' -- cantmove , advance KH-LOOK if in bounds } - true -> cantmove ( default flag, at end of history ) -\ KH-LOOK points to count at start of current line - kh.current.addr c@ \ do we have any lines? - IF - kh.current.addr kh.addr++ -> addr' - addr' kh-end U< \ within bounds? - IF - addr' c@ \ older line has chars? - IF - addr' kh-history - kh-look ! - false -> cantmove - THEN - THEN - THEN - cantmove -; - -: KH.FORWARD.LINE ( -- cantmove? ) - kh-look @ 0= dup not - IF kh.current.addr kh.addr-- - kh-history - kh-look ! - THEN -; - -: KH.OLDEST.LINE ( -- addr count | 0, oldest in buffer ) - BEGIN kh.backup.line - UNTIL - kh.current.line dup 0= - IF - nip - THEN -; - -: KH.FIND.LINE ( line# -- $addr ) - kh.rewind - BEGIN kh.current.num over - - WHILE kh.backup.line - IF ." Line not in History Buffer!" cr drop 0 exit - THEN - REPEAT - drop kh.current.addr -; - - -: KH-BUFFER ( -- buffer ) - kh-address @ -; - -: KH.RETURN ( -- , move to beginning of line ) - 0 out ! - 13 emit -; - -: KH.REPLACE.LINE ( addr count -- , make this the current line of input ) - kh.return - tio.erase.eol - dup kh-span ! - dup kh-cursor ! - 2dup kh-buffer swap cmove - type -; - -: KH.GET.MATCH ( -- , search for line with same start ) - kh-match-span @ 0= ( keep length for multiple matches ) - IF kh-span @ kh-match-span ! - THEN - BEGIN - kh.backup.line not - WHILE - kh.current.line drop - kh-buffer kh-match-span @ text= - IF kh.current.line kh.replace.line - exit - THEN - REPEAT -; - -: KH.FAR.RIGHT - kh-span @ kh-cursor @ - dup 0> - IF - tio.forwards - kh-span @ kh-cursor ! - ELSE drop - THEN -; - -: KH.FAR.LEFT ( -- ) - kh.return - kh-cursor off -; - -: KH.GET.OLDER ( -- , goto previous line ) - kh-inside @ - IF kh.backup.line drop - THEN - kh.current.line kh.replace.line - kh-inside on -; - -: KH.GET.NEWER ( -- , next line ) - kh.forward.line - IF - kh-inside off - tib 0 - ELSE kh.current.line - THEN - kh.replace.line -; - -: KH.CLEAR.LINE ( -- , rewind history scrolling and clear line ) - kh.rewind - tib 0 kh.replace.line - kh-inside off -; - -: KH.GO.RIGHT ( -- ) - kh-cursor @ kh-span @ < - IF 1 kh-cursor +! - 1 tio.forwards - THEN -; - -: KH.GO.LEFT ( -- ) - kh-cursor @ ?dup - IF 1- kh-cursor ! - 1 tio.backwards - THEN -; - -: KH.REFRESH ( -- , redraw current line as is ) - kh.return - kh-buffer kh-span @ type - tio.erase.eol - - kh.return - kh-cursor @ ?dup - IF tio.forwards - THEN - - kh-span @ out ! -; - -: KH.BACKSPACE ( -- , backspace character from buffer and screen ) - kh-cursor @ ?dup ( past 0? ) - IF kh-span @ < - IF ( inside line ) - kh-buffer kh-cursor @ + ( -- source ) - dup 1- ( -- source dest ) - kh-span @ kh-cursor @ - cmove -\ ." Deleted!" cr - ELSE - backspace - THEN - -1 kh-span +! - -1 kh-cursor +! - ELSE bell - THEN - kh.refresh -; - -: KH.DELETE ( -- , forward delete ) - kh-cursor @ kh-span @ < ( before end ) - IF ( inside line ) - kh-buffer kh-cursor @ + 1+ ( -- source ) - dup 1- ( -- source dest ) - kh-span @ kh-cursor @ - 0 max cmove - -1 kh-span +! - kh.refresh - THEN -; - -: KH.HANDLE.WINDOWS.KEY ( char -- , handle fkeys or arrows used by Windows ANSI.SYS ) - CASE - $ 8D OF kh.get.match ENDOF - 0 kh-match-span ! ( reset if any other key ) - $ 48 OF kh.get.older ENDOF - $ 50 OF kh.get.newer ENDOF - $ 4D OF kh.go.right ENDOF - $ 4B OF kh.go.left ENDOF - $ 91 OF kh.clear.line ENDOF - $ 74 OF kh.far.right ENDOF - $ 73 OF kh.far.left ENDOF - $ 53 OF kh.delete ENDOF - ENDCASE -; - -: KH.HANDLE.ANSI.KEY ( char -- , handle fkeys or arrows used by ANSI terminal ) - CASE - $ 41 OF kh.get.older ENDOF - $ 42 OF kh.get.newer ENDOF - $ 43 OF kh.go.right ENDOF - $ 44 OF kh.go.left ENDOF - ENDCASE -; - - -: KH.SPECIAL.KEY ( char -- true | false , handle fkeys or arrows, true if handled ) - true >r - CASE - - $ E0 OF key kh.handle.windows.key - ENDOF - - ASCII_ESCAPE OF - key dup $ 4F = \ for TELNET - $ 5B = OR \ for regular ANSI terminals - IF - key kh.handle.ansi.key - ELSE - rdrop false >r - THEN - ENDOF - - ASCII_BACKSPACE OF kh.backspace ENDOF - ASCII_DELETE OF kh.backspace ENDOF - ASCII_CTRL_X OF kh.clear.line ENDOF - ASCII_CTRL_A OF kh.far.left ENDOF - ASCII_CTRL_E OF kh.far.right ENDOF - - rdrop false >r - - ENDCASE - r> -; - -: KH.SMART.KEY ( -- char ) - BEGIN - key dup kh.special.key - WHILE - drop - REPEAT -; - -: KH.INSCHAR { charc | repaint -- } - false -> repaint - kh-cursor @ kh-span @ < - IF -\ Move characters up - kh-buffer kh-cursor @ + ( -- source ) - dup 1+ ( -- source dest ) - kh-span @ kh-cursor @ - cmove> - true -> repaint - THEN -\ write character to buffer - charc kh-buffer kh-cursor @ + c! - 1 kh-cursor +! - 1 kh-span +! - repaint - IF kh.refresh - ELSE charc emit - THEN -; - -: EOL? ( char -- flag , true if an end of line character ) - dup 13 = - swap 10 = OR -; - -: KH.GETLINE ( max -- ) - kh-max ! - kh-span off - kh-cursor off - kh-inside off - kh.rewind - 0 kh-match-span ! - BEGIN - kh-max @ kh-span @ > - IF kh.smart.key - dup EOL? not ( ) - ELSE 0 false - THEN ( -- char flag ) - WHILE ( -- char ) - kh.inschar - REPEAT drop - kh-span @ kh-cursor @ - ?dup - IF tio.forwards ( move to end of line ) - THEN - space - flushemit -; - -: KH.ACCEPT ( addr max -- numChars ) - swap kh-address ! - kh.getline - kh-span @ 0> - IF kh-buffer kh-span @ kh.add.line - THEN - kh-span @ -; - -: TEST.HISTORY - 4 0 DO - pad 128 kh.accept - cr pad swap type cr - LOOP -; - -}private - - -: HISTORY# ( -- , dump history buffer with numbers) - cr kh.oldest.line ?dup - IF - BEGIN kh.current.num 3 .r ." ) " type ?pause cr - kh.forward.line 0= - WHILE kh.current.line - REPEAT - THEN -; - -: HISTORY ( -- , dump history buffer ) - cr kh.oldest.line ?dup - IF - BEGIN type ?pause cr - kh.forward.line 0= - WHILE kh.current.line - REPEAT - THEN -; - -: XX ( line# -- , execute line x of history ) - kh.find.line ?dup - IF count evaluate - THEN -; - - -: HISTORY.RESET ( -- , clear history tables ) - kh-history kh_history_size erase - kh-counter off -; - -: HISTORY.ON ( -- , install history vectors ) - history.reset - what's accept ['] (accept) = - IF ['] kh.accept is accept - THEN -; - -: HISTORY.OFF ( -- , uninstall history vectors ) - what's accept ['] kh.accept = - IF ['] (accept) is accept - THEN -; - - -: AUTO.INIT - auto.init - history.on -; -: AUTO.TERM - history.off - auto.term -; - -if.forgotten history.off - -0 [IF] -history.reset -history.on -[THEN] +\ Command Line History +\ +\ Author: Phil Burk +\ Copyright 1988 Phil Burk +\ Revised 2001 for pForth + +0 [IF] + +Requires an ANSI compatible terminal. + +To get Windows computers to use ANSI mode in their DOS windows, +Add this line to "C:\CONFIG.SYS" then reboot. + + device=c:\windows\command\ansi.sys + +When command line history is on, you can use the UP and DOWN arrow to scroll +through previous commands. Use the LEFT and RIGHT arrows to edit within a line. + CONTROL-A moves to beginning of line. + CONTROL-E moves to end of line. + CONTROL-X erases entire line. + + +HISTORY# ( -- , dump history buffer with numbers) +HISTORY ( -- , dump history buffer ) +XX ( line# -- , execute line x of history ) +HISTORY.RESET ( -- , clear history tables ) +HISTORY.ON ( -- , install history vectors ) +HISTORY.OFF ( -- , uninstall history vectors ) + +[THEN] + +include? ESC[ termio.fth + +ANEW TASK-HISTORY.FTH +decimal + +private{ + +\ You can expand the history buffer by increasing this constant!!!!!!!!!! +2048 constant KH_HISTORY_SIZE + +create KH-HISTORY kh_history_size allot +KH-HISTORY kh_history_size erase + +\ An entry in the history buffer consists of +\ byte - Count byte = N, +\ chars - N chars, +\ short - line number in Big Endian format, +\ byte - another Count byte = N, for reverse scan +\ +\ The most recent entry is put at the beginning, +\ older entries are shifted up. + +4 constant KH_LINE_EXTRA_SIZE ( 2 count bytes plus 2 line_number bytes ) + +: KH-END ( -- addr , end of history buffer ) + kh-history kh_history_size + +; + +: LINENUM@ ( addr -- w , stores in BigEndian format ) + dup c@ 8 shift + swap 1+ c@ or +; + +: LINENUM! ( w addr -- ) + over -8 shift over c! + 1+ c! +; + +variable KH-LOOK ( cursor offset into history, point to 1st count byte of line ) +variable KH-MAX +variable KH-COUNTER ( 16 bit counter for line # ) +variable KH-SPAN ( total number of characters in line ) +variable KH-MATCH-SPAN ( span for matching on shift-up ) +variable KH-CURSOR ( points to next insertion point ) +variable KH-ADDRESS ( address to store chars ) +variable KH-INSIDE ( true if we are scrolling inside the history buffer ) + +: KH.MAKE.ROOM ( N -- , make room for N more bytes at beginning) + >r ( save N ) + kh-history dup r@ + ( source dest ) + kh_history_size r> - 0 max move +; + +: KH.NEWEST.LINE ( -- addr count , most recent line ) + kh-history count +; + +: KH.REWIND ( -- , move cursor to most recent line ) + 0 kh-look ! +; + +: KH.CURRENT.ADDR ( -- $addr , count byte of current line ) + kh-look @ kh-history + +; + +: KH.CURRENT.LINE ( -- addr count ) + kh.current.addr count +; + +: KH.COMPARE ( addr count -- flag , true if redundant ) + kh.newest.line compare 0= \ note: ANSI COMPARE is different than JForth days +; + +: KH.NUM.ADDR ( -- addr , address of current line's line count ) + kh.current.line + +; + +: KH.CURRENT.NUM ( -- # , number of current line ) + kh.num.addr LINENUM@ +; + +: KH.ADDR++ ( $addr -- $addr' , convert one kh to previous ) + count + 3 + +; +: KH.ADDR-- ( $addr -- $addr' , convert one kh to next ) + dup 1- c@ \ get next lines endcount + 4 + \ account for lineNum and two count bytes + - \ calc previous address +; + +: KH.ENDCOUNT.ADDR ( -- addr , address of current end count ) + kh.num.addr 2+ +; + +: KH.ADD.LINE ( addr count -- ) + dup 256 > + IF ." KH.ADD.LINE - Too big for history!" 2drop + ELSE ( add to end ) +\ Compare with most recent line. + 2dup kh.compare + IF 2drop + ELSE + >r ( save count ) +\ Set look pointer to point to first count byte of last string. + 0 kh-look ! +\ Make room for this line of text and line header. +\ PLB20100823 Was cell+ which broke on 64-bit code. + r@ KH_LINE_EXTRA_SIZE + kh.make.room +\ Set count bytes at beginning and end. + r@ kh-history c! ( start count ) + r@ kh.endcount.addr c! + kh-counter @ kh.num.addr LINENUM! ( line ) +\ Number lines modulo 1024 + kh-counter @ 1+ $ 3FF and kh-counter ! + kh-history 1+ ( calc destination ) + r> cmove ( copy chars into space ) + THEN + THEN +; + +: KH.BACKUP.LINE { | cantmove addr' -- cantmove , advance KH-LOOK if in bounds } + true -> cantmove ( default flag, at end of history ) +\ KH-LOOK points to count at start of current line + kh.current.addr c@ \ do we have any lines? + IF + kh.current.addr kh.addr++ -> addr' + addr' kh-end U< \ within bounds? + IF + addr' c@ \ older line has chars? + IF + addr' kh-history - kh-look ! + false -> cantmove + THEN + THEN + THEN + cantmove +; + +: KH.FORWARD.LINE ( -- cantmove? ) + kh-look @ 0= dup not + IF kh.current.addr kh.addr-- + kh-history - kh-look ! + THEN +; + +: KH.OLDEST.LINE ( -- addr count | 0, oldest in buffer ) + BEGIN kh.backup.line + UNTIL + kh.current.line dup 0= + IF + nip + THEN +; + +: KH.FIND.LINE ( line# -- $addr ) + kh.rewind + BEGIN kh.current.num over - + WHILE kh.backup.line + IF ." Line not in History Buffer!" cr drop 0 exit + THEN + REPEAT + drop kh.current.addr +; + + +: KH-BUFFER ( -- buffer ) + kh-address @ +; + +: KH.RETURN ( -- , move to beginning of line ) + 0 out ! + 13 emit +; + +: KH.REPLACE.LINE ( addr count -- , make this the current line of input ) + kh.return + tio.erase.eol + dup kh-span ! + dup kh-cursor ! + 2dup kh-buffer swap cmove + type +; + +: KH.GET.MATCH ( -- , search for line with same start ) + kh-match-span @ 0= ( keep length for multiple matches ) + IF kh-span @ kh-match-span ! + THEN + BEGIN + kh.backup.line not + WHILE + kh.current.line drop + kh-buffer kh-match-span @ text= + IF kh.current.line kh.replace.line + exit + THEN + REPEAT +; + +: KH.FAR.RIGHT + kh-span @ kh-cursor @ - dup 0> + IF + tio.forwards + kh-span @ kh-cursor ! + ELSE drop + THEN +; + +: KH.FAR.LEFT ( -- ) + kh.return + kh-cursor off +; + +: KH.GET.OLDER ( -- , goto previous line ) + kh-inside @ + IF kh.backup.line drop + THEN + kh.current.line kh.replace.line + kh-inside on +; + +: KH.GET.NEWER ( -- , next line ) + kh.forward.line + IF + kh-inside off + tib 0 + ELSE kh.current.line + THEN + kh.replace.line +; + +: KH.CLEAR.LINE ( -- , rewind history scrolling and clear line ) + kh.rewind + tib 0 kh.replace.line + kh-inside off +; + +: KH.GO.RIGHT ( -- ) + kh-cursor @ kh-span @ < + IF 1 kh-cursor +! + 1 tio.forwards + THEN +; + +: KH.GO.LEFT ( -- ) + kh-cursor @ ?dup + IF 1- kh-cursor ! + 1 tio.backwards + THEN +; + +: KH.REFRESH ( -- , redraw current line as is ) + kh.return + kh-buffer kh-span @ type + tio.erase.eol + + kh.return + kh-cursor @ ?dup + IF tio.forwards + THEN + + kh-span @ out ! +; + +: KH.BACKSPACE ( -- , backspace character from buffer and screen ) + kh-cursor @ ?dup ( past 0? ) + IF kh-span @ < + IF ( inside line ) + kh-buffer kh-cursor @ + ( -- source ) + dup 1- ( -- source dest ) + kh-span @ kh-cursor @ - cmove +\ ." Deleted!" cr + ELSE + backspace + THEN + -1 kh-span +! + -1 kh-cursor +! + ELSE bell + THEN + kh.refresh +; + +: KH.DELETE ( -- , forward delete ) + kh-cursor @ kh-span @ < ( before end ) + IF ( inside line ) + kh-buffer kh-cursor @ + 1+ ( -- source ) + dup 1- ( -- source dest ) + kh-span @ kh-cursor @ - 0 max cmove + -1 kh-span +! + kh.refresh + THEN +; + +: KH.HANDLE.WINDOWS.KEY ( char -- , handle fkeys or arrows used by Windows ANSI.SYS ) + CASE + $ 8D OF kh.get.match ENDOF + 0 kh-match-span ! ( reset if any other key ) + $ 48 OF kh.get.older ENDOF + $ 50 OF kh.get.newer ENDOF + $ 4D OF kh.go.right ENDOF + $ 4B OF kh.go.left ENDOF + $ 91 OF kh.clear.line ENDOF + $ 74 OF kh.far.right ENDOF + $ 73 OF kh.far.left ENDOF + $ 53 OF kh.delete ENDOF + ENDCASE +; + +: KH.HANDLE.ANSI.KEY ( char -- , handle fkeys or arrows used by ANSI terminal ) + CASE + $ 41 OF kh.get.older ENDOF + $ 42 OF kh.get.newer ENDOF + $ 43 OF kh.go.right ENDOF + $ 44 OF kh.go.left ENDOF + ENDCASE +; + +: KH.SPECIAL.KEY ( char -- true | false , handle fkeys or arrows, true if handled ) + true >r + CASE + + $ E0 OF key kh.handle.windows.key + ENDOF + + ASCII_ESCAPE OF + key dup $ 4F = \ for TELNET + $ 5B = OR \ for regular ANSI terminals + IF + key kh.handle.ansi.key + ELSE + rdrop false >r + THEN + ENDOF + + ASCII_BACKSPACE OF kh.backspace ENDOF + ASCII_DELETE OF kh.backspace ENDOF + ASCII_CTRL_X OF kh.clear.line ENDOF + ASCII_CTRL_A OF kh.far.left ENDOF + ASCII_CTRL_E OF kh.far.right ENDOF + + rdrop false >r + + ENDCASE + r> +; + +: KH.SMART.KEY ( -- char ) + BEGIN + key dup kh.special.key + WHILE + drop + REPEAT +; + +: KH.INSCHAR { charc | repaint -- } + false -> repaint + kh-cursor @ kh-span @ < + IF +\ Move characters up + kh-buffer kh-cursor @ + ( -- source ) + dup 1+ ( -- source dest ) + kh-span @ kh-cursor @ - cmove> + true -> repaint + THEN +\ write character to buffer + charc kh-buffer kh-cursor @ + c! + 1 kh-cursor +! + 1 kh-span +! + repaint + IF kh.refresh + ELSE charc emit + THEN +; + +: EOL? ( char -- flag , true if an end of line character ) + dup 13 = + swap 10 = OR +; + +: KH.GETLINE ( max -- ) + kh-max ! + kh-span off + kh-cursor off + kh-inside off + kh.rewind + 0 kh-match-span ! + BEGIN + kh-max @ kh-span @ > + IF kh.smart.key + dup EOL? not ( ) + ELSE 0 false + THEN ( -- char flag ) + WHILE ( -- char ) + kh.inschar + REPEAT drop + kh-span @ kh-cursor @ - ?dup + IF tio.forwards ( move to end of line ) + THEN + space + flushemit +; + +: KH.ACCEPT ( addr max -- numChars ) + swap kh-address ! + kh.getline + kh-span @ 0> + IF kh-buffer kh-span @ kh.add.line + THEN + kh-span @ +; + +: TEST.HISTORY + 4 0 DO + pad 128 kh.accept + cr pad swap type cr + LOOP +; + +}private + + +: HISTORY# ( -- , dump history buffer with numbers) + cr kh.oldest.line ?dup + IF + BEGIN kh.current.num 3 .r ." ) " type ?pause cr + kh.forward.line 0= + WHILE kh.current.line + REPEAT + THEN +; + +: HISTORY ( -- , dump history buffer ) + cr kh.oldest.line ?dup + IF + BEGIN type ?pause cr + kh.forward.line 0= + WHILE kh.current.line + REPEAT + THEN +; + +: XX ( line# -- , execute line x of history ) + kh.find.line ?dup + IF count evaluate + THEN +; + + +: HISTORY.RESET ( -- , clear history tables ) + kh-history kh_history_size erase + kh-counter off +; + +: HISTORY.ON ( -- , install history vectors ) + history.reset + what's accept ['] (accept) = + IF ['] kh.accept is accept + THEN +; + +: HISTORY.OFF ( -- , uninstall history vectors ) + what's accept ['] kh.accept = + IF ['] (accept) is accept + THEN +; + + +: AUTO.INIT + auto.init + history.on +; +: AUTO.TERM + history.off + auto.term +; + +if.forgotten history.off + +0 [IF] +history.reset +history.on +[THEN]