2005-01-03 02:55:54 -05:00
|
|
|
! Copyright (C) 2005 Slava Pestov.
|
2005-07-12 20:30:05 -04:00
|
|
|
! See http://factor.sf.net/license.txt for BSD license.
|
2005-01-03 02:55:54 -05:00
|
|
|
IN: line-editor
|
2005-07-12 20:30:05 -04:00
|
|
|
USING: kernel math namespaces sequences strings vectors ;
|
2005-01-03 02:55:54 -05:00
|
|
|
|
2005-01-04 00:41:14 -05:00
|
|
|
SYMBOL: history
|
|
|
|
SYMBOL: history-index
|
|
|
|
|
2005-10-01 01:44:49 -04:00
|
|
|
SYMBOL: line-text
|
|
|
|
SYMBOL: caret
|
|
|
|
|
2005-01-04 00:41:14 -05:00
|
|
|
: history-length ( -- n )
|
|
|
|
#! Call this in the line editor scope.
|
2005-04-26 00:35:55 -04:00
|
|
|
history get length ;
|
2005-01-04 00:41:14 -05:00
|
|
|
|
|
|
|
: reset-history ( -- )
|
|
|
|
#! Call this in the line editor scope. After user input,
|
|
|
|
#! resets the history index.
|
|
|
|
history-length history-index set ;
|
|
|
|
|
2005-10-01 01:44:49 -04:00
|
|
|
! A point is a mutable object holding an index in the line
|
|
|
|
! editor. Changing text in the points registered with the
|
|
|
|
! line editor will move the point if it is after the changed
|
|
|
|
! text.
|
|
|
|
TUPLE: point index ;
|
|
|
|
|
|
|
|
: (point-update) ( len from to index -- index )
|
|
|
|
pick over > [
|
|
|
|
>r 3drop r>
|
2005-01-04 00:41:14 -05:00
|
|
|
] [
|
2005-10-01 01:44:49 -04:00
|
|
|
3dup -rot between? [ 2drop ] [ >r - + r> ] if +
|
2005-09-24 15:21:17 -04:00
|
|
|
] if ;
|
2005-01-04 00:41:14 -05:00
|
|
|
|
2005-10-01 01:44:49 -04:00
|
|
|
: point-update ( len from to point -- )
|
2005-01-04 00:41:14 -05:00
|
|
|
#! Call this in the line editor scope.
|
2005-10-01 01:44:49 -04:00
|
|
|
[ point-index (point-update) ] keep set-point-index ;
|
2005-01-04 00:41:14 -05:00
|
|
|
|
2005-10-01 01:44:49 -04:00
|
|
|
: line-replace ( str from to -- )
|
2005-01-04 00:41:14 -05:00
|
|
|
#! Call this in the line editor scope.
|
2005-10-01 01:44:49 -04:00
|
|
|
reset-history
|
|
|
|
pick length pick pick caret get point-update
|
|
|
|
line-text [ replace-slice ] change ;
|
2005-01-04 00:41:14 -05:00
|
|
|
|
2005-10-01 01:44:49 -04:00
|
|
|
: line-remove ( from to -- )
|
2005-01-04 00:41:14 -05:00
|
|
|
#! Call this in the line editor scope.
|
2005-10-01 01:44:49 -04:00
|
|
|
"" -rot line-replace ;
|
2005-01-04 00:41:14 -05:00
|
|
|
|
2005-10-01 01:44:49 -04:00
|
|
|
: line-length line-text get length ;
|
|
|
|
|
|
|
|
: set-line-text ( text -- )
|
2005-01-04 00:41:14 -05:00
|
|
|
#! Call this in the line editor scope.
|
2005-10-01 01:44:49 -04:00
|
|
|
0 line-length line-replace ;
|
2005-01-04 00:41:14 -05:00
|
|
|
|
2005-01-03 02:55:54 -05:00
|
|
|
: line-clear ( -- )
|
|
|
|
#! Call this in the line editor scope.
|
2005-10-01 01:44:49 -04:00
|
|
|
"" set-line-text ;
|
2005-01-03 02:55:54 -05:00
|
|
|
|
2005-10-01 01:44:49 -04:00
|
|
|
! An element is a unit of text; character, word, etc.
|
|
|
|
GENERIC: next-elt* ( i str element -- i )
|
|
|
|
GENERIC: prev-elt* ( i str element -- i )
|
2005-01-03 02:55:54 -05:00
|
|
|
|
2005-10-01 01:44:49 -04:00
|
|
|
TUPLE: char-elt ;
|
2005-01-03 02:55:54 -05:00
|
|
|
|
2005-10-01 01:44:49 -04:00
|
|
|
M: char-elt next-elt* 2drop 1+ ;
|
|
|
|
M: char-elt prev-elt* 2drop 1- ;
|
2005-01-03 02:55:54 -05:00
|
|
|
|
2005-10-01 01:44:49 -04:00
|
|
|
TUPLE: word-elt ;
|
2005-01-03 02:55:54 -05:00
|
|
|
|
2005-10-01 01:44:49 -04:00
|
|
|
M: word-elt next-elt* ( i str element -- i )
|
|
|
|
drop dup length >r [ blank? ] find* drop dup -1 =
|
|
|
|
[ drop r> ] [ r> drop 1+ ] if ;
|
2005-01-03 02:55:54 -05:00
|
|
|
|
2005-10-01 01:44:49 -04:00
|
|
|
M: word-elt prev-elt* ( i str element -- i )
|
|
|
|
drop >r 1- r> [ blank? ] find-last* drop 1+ ;
|
2005-01-03 02:55:54 -05:00
|
|
|
|
2005-10-01 01:44:49 -04:00
|
|
|
TUPLE: document-elt ;
|
2005-01-03 02:55:54 -05:00
|
|
|
|
2005-10-01 01:44:49 -04:00
|
|
|
M: document-elt next-elt* rot 2drop length ;
|
|
|
|
M: document-elt prev-elt* 3drop 0 ;
|
2005-09-27 00:24:42 -04:00
|
|
|
|
2005-10-01 01:44:49 -04:00
|
|
|
: caret-pos caret get point-index ;
|
|
|
|
|
|
|
|
: set-caret-pos caret get set-point-index ;
|
|
|
|
|
|
|
|
: next-elt@ ( element -- from to )
|
|
|
|
>r caret-pos dup line-text get r> next-elt* line-length min ;
|
|
|
|
|
|
|
|
: next-elt ( element -- )
|
|
|
|
next-elt@ set-caret-pos drop ;
|
|
|
|
|
|
|
|
: prev-elt@ ( element -- from to )
|
|
|
|
>r caret-pos dup line-text get r> prev-elt* 0 max swap ;
|
|
|
|
|
|
|
|
: prev-elt ( element -- )
|
|
|
|
prev-elt@ drop set-caret-pos ;
|
|
|
|
|
|
|
|
: delete-next-elt ( element -- )
|
|
|
|
next-elt@ line-remove ;
|
|
|
|
|
|
|
|
: delete-prev-elt ( element -- )
|
|
|
|
prev-elt@ line-remove ;
|
|
|
|
|
|
|
|
: insert-char ( ch -- )
|
2005-01-03 02:55:54 -05:00
|
|
|
#! Call this in the line editor scope.
|
2005-10-01 01:44:49 -04:00
|
|
|
ch>string caret-pos dup line-replace ;
|
2005-01-03 02:55:54 -05:00
|
|
|
|
2005-10-01 01:44:49 -04:00
|
|
|
: commit-history ( -- )
|
|
|
|
#! Call this in the line editor scope. Adds the currently
|
|
|
|
#! entered text to the history.
|
|
|
|
line-text get dup empty?
|
|
|
|
[ drop ] [ history get push reset-history ] if ;
|
|
|
|
|
|
|
|
: <line-editor> ( -- editor )
|
|
|
|
[
|
|
|
|
"" line-text set
|
|
|
|
0 <point> caret set
|
|
|
|
{ } clone history set
|
|
|
|
0 history-index set
|
|
|
|
] make-hash ;
|
|
|
|
|
|
|
|
: goto-history ( n -- )
|
2005-01-03 02:55:54 -05:00
|
|
|
#! Call this in the line editor scope.
|
2005-10-01 01:44:49 -04:00
|
|
|
dup history get nth set-line-text history-index set ;
|
2005-07-27 01:46:06 -04:00
|
|
|
|
2005-10-01 01:44:49 -04:00
|
|
|
: history-prev ( -- )
|
2005-07-27 01:46:06 -04:00
|
|
|
#! Call this in the line editor scope.
|
2005-10-01 01:44:49 -04:00
|
|
|
history-index get dup 0 = [
|
|
|
|
drop
|
|
|
|
] [
|
|
|
|
dup history-length = [ commit-history ] when
|
|
|
|
1- goto-history
|
|
|
|
] if ;
|
2005-07-27 01:46:06 -04:00
|
|
|
|
2005-10-01 01:44:49 -04:00
|
|
|
: history-next ( -- )
|
2005-07-27 01:46:06 -04:00
|
|
|
#! Call this in the line editor scope.
|
2005-10-01 01:44:49 -04:00
|
|
|
history-index get dup 1+ history-length >=
|
|
|
|
[ drop ] [ 1+ goto-history ] if ;
|