factor/library/ui/line-editor.factor

153 lines
3.8 KiB
Factor
Raw Normal View History

2005-01-03 02:55:54 -05:00
! Copyright (C) 2005 Slava Pestov.
! See http://factor.sf.net/license.txt for BSD license.
2005-01-03 02:55:54 -05:00
IN: line-editor
USING: kernel math namespaces prettyprint 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-10-03 19:53:32 -04:00
! Completion
SYMBOL: possibilities
2005-01-04 00:41:14 -05:00
: history-length ( -- n )
#! Call this in the line editor scope.
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 ;
2006-03-14 21:09:25 -05:00
: insert-string ( str -- )
2005-01-03 02:55:54 -05:00
#! Call this in the line editor scope.
2006-03-14 21:09:25 -05:00
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
V{ } clone history set
2005-10-01 01:44:49 -04:00
0 history-index set
2005-10-03 19:53:32 -04:00
possibilities off
2005-10-01 01:44:49 -04:00
] 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.
2006-01-28 15:49:31 -05:00
history-index get dup zero? [
2005-10-01 01:44:49 -04:00
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 ;
2005-10-03 19:53:32 -04:00
: line-completions ( -- seq )
T{ word-elt } prev-elt@ 2dup = [
2005-10-03 19:53:32 -04:00
2drop f
] [
line-text get subseq possibilities get completions
2005-10-03 19:53:32 -04:00
] if ;
: complete ( completion -- )
T{ word-elt } prev-elt@ line-replace ;