1 ! Copyright (C) 2006, 2009 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors arrays combinators documents kernel math
4 math.order sequences unicode ;
7 GENERIC: prev-elt ( loc document elt -- newloc )
8 GENERIC: next-elt ( loc document elt -- newloc )
10 : prev/next-elt ( loc document elt -- start end )
11 [ prev-elt ] [ next-elt ] 3bi ;
13 : elt-string ( loc document elt -- string )
14 [ prev/next-elt ] [ drop ] 2bi doc-range ;
16 : set-elt-string ( string loc document elt -- )
17 [ prev/next-elt ] [ drop ] 2bi set-doc-range ;
23 : prev ( loc document quot: ( loc document -- loc ) -- loc )
25 { [ pick { 0 0 } = ] [ 2drop ] }
26 { [ pick second zero? ] [ drop [ first 1 - ] dip line-end ] }
30 : next ( loc document quot: ( loc document -- loc ) -- loc )
32 { [ 2over doc-end = ] [ 2drop ] }
33 { [ 2over line-end? ] [ 2drop first 1 + 0 2array ] }
37 : modify-col ( loc document quot: ( col str -- col' ) -- loc )
39 [ [ first2 swap ] dip doc-line ] dip call
45 drop [ [ last-grapheme-from ] modify-col ] prev ;
48 drop [ [ first-grapheme-from ] modify-col ] next ;
50 SINGLETON: one-char-elt
52 M: one-char-elt prev-elt 2drop ;
54 M: one-char-elt next-elt 2drop ;
58 : blank-at? ( n seq -- n seq ? )
59 2dup ?nth unicode:blank? ;
61 : break-detector ( ? -- quot )
62 '[ unicode:blank? _ xor ] ; inline
64 : prev-word ( col str ? -- col )
65 break-detector find-last-from drop ?1+ ;
67 : next-word ( col str ? -- col )
68 [ break-detector find-from drop ] [ drop length ] 2bi or ;
72 SINGLETON: one-word-elt
74 M: one-word-elt prev-elt
76 [ [ 1 - ] dip f prev-word ] modify-col ;
78 M: one-word-elt next-elt
80 [ f next-word ] modify-col ;
82 SINGLETON: word-start-elt
84 M: word-start-elt prev-elt
85 drop one-word-elt prev-elt ;
87 M: word-start-elt next-elt 2drop ;
93 [ [ [ 1 - ] dip blank-at? prev-word ] modify-col ]
98 [ [ blank-at? next-word ] modify-col ]
101 SINGLETON: one-line-elt
103 M: one-line-elt prev-elt
104 2drop first 0 2array ;
106 M: one-line-elt next-elt
107 drop [ first dup ] dip doc-line length 2array ;
111 :: prev-paragraph ( loc document -- loc' )
112 loc first 1 [-] document value>>
113 [ empty? ] find-last-from drop [ 1 + ] [ 0 ] if* :> line#
115 loc first line# = loc second 0 = and [
121 :: next-paragraph ( loc document -- loc' )
122 loc first 1 + document value>>
123 [ empty? ] find-from drop :> line#
126 1 - dup document doc-line length 2array
127 dup loc = [ first 1 + 0 2array ] when
134 SINGLETON: paragraph-elt
136 M: paragraph-elt prev-elt drop prev-paragraph ;
138 M: paragraph-elt next-elt drop next-paragraph ;
140 TUPLE: page-elt { #lines integer read-only } ;
142 C: <page-elt> page-elt
146 2dup [ first ] [ #lines>> ] bi* <
147 [ 2drop { 0 0 } ] [ #lines>> neg +line ] if ;
150 3dup [ first ] [ last-line# ] [ #lines>> ] tri* - >
151 [ drop nip doc-end ] [ nip #lines>> +line ] if ;
153 CONSTANT: line-elt T{ page-elt { #lines 1 } }
157 M: doc-elt prev-elt 3drop { 0 0 } ;
159 M: doc-elt next-elt drop nip doc-end ;