"Fossies" - the Fresh Open Source Software Archive 
Member "TeXmacs-2.1.2-src/TeXmacs/progs/utils/library/tree.scm" (5 May 2022, 13271 Bytes) of package /linux/misc/TeXmacs-2.1.2-src.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Lisp source code syntax highlighting (style:
standard) with prefixed line numbers.
Alternatively you can here
view or
download the uninterpreted source code file.
See also the latest
Fossies "Diffs" side-by-side code changes report for "tree.scm":
2.1.1_vs_2.1.2.
1
2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3 ;;
4 ;; MODULE : tree.scm
5 ;; DESCRIPTION : routines for trees and for modifying documents
6 ;; COPYRIGHT : (C) 2002 Joris van der Hoeven
7 ;;
8 ;; This software falls under the GNU general public license version 3 or later.
9 ;; It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
10 ;; in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
11 ;;
12 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
13
14 (texmacs-module (utils library tree))
15
16 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
17 ;; In place versions of fundamental modification routines
18 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
19
20 (tm-define-macro (tree-assign! ref t)
21 `(begin
22 (set! ,ref (tree-assign ,ref ,t))
23 ,ref))
24
25 (tm-define (tree-insert t pos x)
26 (cond ((string? x) (tree-var-insert t pos x))
27 ((list? x) (tree-var-insert t pos (cons 'tuple x)))
28 (else (texmacs-error "tree-insert" "~S is not a string or a list" x))))
29
30 (tm-define tree-insert! tree-insert)
31 (tm-define tree-remove! tree-remove)
32 (tm-define tree-split! tree-split)
33 (tm-define tree-join! tree-join)
34 (tm-define tree-assign-node! tree-assign-node)
35
36 (tm-define-macro (tree-insert-node! ref pos t)
37 `(begin
38 (set! ,ref (tree-insert-node ,ref ,pos ,t))
39 ,ref))
40
41 (tm-define-macro (tree-remove-node! ref pos)
42 `(begin
43 (set! ,ref (tree-remove-node ,ref ,pos))
44 ,ref))
45
46 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
47 ;; Use fundamental modification routines in an intelligent way
48 ;; via a unique assignment routine
49 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
50
51 (define (tree-common-left t1 t2)
52 (cond ((and (tm-compound? t1) (tm-compound? t2))
53 (list-common-left (cdr (tm->list t1)) (cdr (tm->list t2))))
54 ((and (tm-atomic? t1) (tm-atomic? t2))
55 (list-common-left (string->list (tm->string t1))
56 (string->list (tm->string t2))))
57 (else 0)))
58
59 (define (tree-common-right t1 t2)
60 (cond ((and (tm-compound? t1) (tm-compound? t2))
61 (list-common-right (cdr (tm->list t1)) (cdr (tm->list t2))))
62 ((and (tm-atomic? t1) (tm-atomic? t2))
63 (list-common-right (string->list (tm->string t1))
64 (string->list (tm->string t2))))
65 (else 0)))
66
67 (define (tree-focus-index ref l)
68 (cond ((null? l) #f)
69 ((tree-inside? (car l) ref) 0)
70 ((and (list? (car l)) (tree-focus-index ref (car l))) 0)
71 (else
72 (with r (tree-focus-index ref (cdr l))
73 (if r (+ r 1) #f)))))
74
75 (define (tree-get-focus-index ref t l)
76 (if (or (== t ref) (not (tree-inside? t ref)))
77 (tree-focus-index ref l)
78 (with r (tree-focus-index t l)
79 (if r r (tree-get-focus-index ref (tree-up t) l)))))
80
81 (tm-define (tree-set-diff ref t)
82 (:type (-> tree content void))
83 (:synopsis "Assign @ref with @t.")
84 (let* ((p (tree->path ref))
85 (l (tree-common-left ref t))
86 (r (tree-common-right (tm-range ref l (tm-length ref))
87 (tm-range t l (tm-length t)))))
88 (cond ((not p)
89 (texmacs-error "tree-set-diff" "~S isn't part of a document" ref))
90 ((tm-equal? ref t) ref)
91 ((tree-inside? t ref)
92 (with q (tree->path t)
93 (tree-remove-node! ref (list-ref q (length p)))
94 (tree-set-diff ref t)))
95 ((and (tm-atomic? ref) (tm-atomic? t)
96 (= (+ l r) (tm-length ref)) (< (tm-length ref) (tm-length t)))
97 (tree-insert! ref l
98 (substring (tm->string t) l (- (tm-length t) r))))
99 ((and (tm-atomic? ref) (tm-atomic? t)
100 (= (+ l r) (tm-length t)) (> (tm-length ref) (tm-length t)))
101 (tree-remove! ref l (- (- (tm-length ref) r) l)))
102 ((not (tm-compound? t)) (tree-assign! ref t))
103 ((and (tm-compound? ref) (= l (tm-arity ref)) (= l (tm-arity t)))
104 (tree-assign-node! ref (tm-car t)))
105 ((and (tm-compound? ref)
106 (= (+ l r) (tm-arity ref)) (< (tm-arity ref) (tm-arity t)))
107 (tree-insert! ref l (sublist (tm-cdr t) l (- (tm-arity t) r)))
108 (if (== (tm-car ref) (tm-car t)) ref
109 (tree-assign-node! ref (tm-car t))))
110 ((and (tm-compound? ref)
111 (= (+ l r) (tm-arity t)) (> (tm-arity ref) (tm-arity t))
112 (not (tree-is-buffer? ref)))
113 (tree-remove! ref l (- (- (tm-arity ref) r) l))
114 (if (== (tm-car ref) (tm-car t)) ref
115 (tree-assign-node! ref (tm-car t))))
116 (else
117 (with pos (tree-focus-index ref (tm-cdr t))
118 (if (or (not pos) (tree-is-buffer? ref))
119 (tree-assign! ref t)
120 (let* ((tl (tm->list t))
121 (head (list-head tl (+ pos 1)))
122 (mid (list-ref tl (+ pos 1)))
123 (tail (list-tail tl (+ pos 2)))
124 (merged (append head tail)))
125 (set! ref (tree-set-diff ref mid))
126 (tree-insert-node! ref pos merged))))))))
127
128 (tm-define-macro (tree-set-diff! ref t)
129 (:synopsis "Assign @ref with @t.")
130 `(begin
131 (set! ,ref (tree-set-diff ,ref ,t))
132 ,ref))
133
134 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
135 ;; High level tree access
136 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
137
138 (tm-define (tree-ref t . l)
139 (:synopsis "Access a subtree of @t according to @l.")
140 (cond ((not (tree? t)) #f)
141 ;; NOTE: the following special cases are treated fast,
142 ((null? l) t)
143 ((integer? (car l))
144 (with i (car l)
145 (and (tree-compound? t) (>= i 0) (< i (tree-arity t))
146 (apply tree-ref (cons (tree-child-ref t i) (cdr l))))))
147 ((== (car l) :first)
148 (apply tree-ref (cons t (cons 0 (cdr l)))))
149 ((== (car l) :last)
150 (and (tree-compound? t)
151 (apply tree-ref (cons t (cons (- (tree-arity t) 1) (cdr l))))))
152 ((symbol? (car l))
153 (and (tree-compound? t)
154 (with i (list-find-index (tree-children t)
155 (cut tree-is? <> (car l)))
156 (apply tree-ref (cons t (cons i (cdr l)))))))
157 ;; but they can all be replaced by the general code below
158 (else (with r (select t l)
159 (and (nnull? r) (car r))))))
160
161 (define (tree-set-sub-error t l)
162 (texmacs-error "tree-set-sub" "~S does not admit a subtree along ~S" t l))
163
164 (define (tree-set-sub t l u)
165 (cond ((not (tree? t)) (texmacs-error "tree-set-sub" "~S is not a tree" t))
166 ;; NOTE: the following special cases are treated fast and apart
167 ((null? l)
168 (if (tree-active? t)
169 (tree-set-diff t u)
170 (tree-assign t u)))
171 ((integer? (car l))
172 (with i (car l)
173 (if (and (tree-compound? t) (>= i 0) (< i (tree-arity t)))
174 (if (or (nnull? (cdr l)) (tree-active? t))
175 (tree-set-sub (tree-child-ref t (car l)) (cdr l) u)
176 (tree-child-set! t (car l) u))
177 (tree-set-sub-error t l))))
178 ((== (car l) :first)
179 (tree-set-sub t (cons 0 (cdr l)) u))
180 ((== (car l) :last)
181 (if (tree-compound? t)
182 (tree-set-sub t (cons (- (tree-arity t) 1) (cdr l)) u)
183 (tree-set-sub-error t l)))
184 ((symbol? (car l))
185 (with i (and (tree-compound? t)
186 (list-find-index (tree-children t)
187 (cut tree-is? <> (car l))))
188 (if i (tree-set-sub t (cons i (cdr l)) u)
189 (tree-set-sub-error t l))))
190 ;; More cases can be treated for trees in a document
191 ((tree-active? t)
192 (with r (select t l)
193 (if (nnull? r)
194 (tree-set-diff (car r) u)
195 (tree-set-sub-error t l))))
196 (else (tree-set-sub-error t l))))
197
198 (tm-define (tree-set t . args)
199 (:synopsis "Set a subtree of @t to a new value according to @l.")
200 (with r (reverse args)
201 (tree-set-sub t (reverse (cdr r)) (car r))))
202
203 (tm-define-macro (tree-set! t . l)
204 (:synopsis "Set a subtree of @t to a new value according to @l.")
205 (if (list-1? l)
206 `(if (tree-active? ,t)
207 (tree-set-diff! ,t ,@l)
208 (tree-assign! ,t ,@l))
209 `(tree-set ,t ,@l)))
210
211 (tm-define (tree-start t . l)
212 (path->tree (cDr (apply tree->path (rcons (cons t l) :start)))))
213
214 (tm-define (tree-end t . l)
215 (path->tree (cDr (apply tree->path (rcons (cons t l) :end)))))
216
217 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
218 ;; Upward searching
219 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
220
221 (tm-define (tree-search-upwards t what)
222 (:synopsis "Find ancestor of @t which matches @what")
223 (cond ((list? what)
224 (tree-search-upwards t (lambda (x) (in? (tree-label x) what))))
225 ((symbol? what)
226 (tree-search-upwards t (lambda (x) (== (tree-label x) what))))
227 ((and (procedure? what) (what t)) t)
228 ((or (tree-is-buffer? t) (not (tree-up t))) #f)
229 (else (tree-search-upwards (tree-up t) what))))
230
231 (tm-define (tree-innermost x . opt-flag)
232 (:type (-> symbol tree)
233 (-> (list symbol) tree)
234 (-> (-> bool) tree))
235 (:synopsis "Search upwards from the cursor position.")
236 (with p ((if (null? opt-flag) cDDr cDr) (cursor-path))
237 (tree-search-upwards (path->tree p) x)))
238
239 (tm-define (inside-which l)
240 (:type (-> (list symbol) symbol))
241 (:synopsis "Get innermost node type among possibilities in @l.")
242 (with t (tree-innermost l)
243 (and t (tree-label t))))
244
245 (tm-define-macro (with-innermost t x . body)
246 `(let ((,t (tree-innermost ,x)))
247 (if ,t (begin ,@body))))
248
249 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
250 ;; Recursive replacement
251 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
252
253 (tm-define (tree-replace t what by)
254 (cond ((and (procedure? what) (procedure? by))
255 (if (what t) (by t)
256 (if (tree-compound? t)
257 (for-each (lambda (u) (tree-replace u what by))
258 (tree-children t)))))
259 ((symbol? what)
260 (tree-replace t (lambda (u) (tree-is? u what)) by))
261 ((symbol? by)
262 (tree-replace t what
263 (lambda (u) (if (tree-compound? u) (tree-assign-node u by)))))
264 (else
265 (let* ((w (tm->tree what))
266 (b (tm->tree by)))
267 (tree-replace t (lambda (u) (== u w))
268 (lambda (u) (tree-assign u (tree-copy b))))))))
269
270 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
271 ;; Further routines for trees
272 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
273
274 (tm-define (tree-is? t . l)
275 (let* ((st (apply tree-ref (cons t (cDr l))))
276 (lab (cAr l)))
277 (and st (== (tree-label st) lab))))
278
279 (tm-define (tree-in? t . l)
280 (let* ((st (apply tree-ref (cons t (cDr l))))
281 (ls (cAr l)))
282 (and st (in? (tree-label st) ls))))
283
284 (tm-define (tree->path t . l)
285 (:synopsis "Get the position of the tree @t.")
286 (if (null? l) (tree-get-path t)
287 (with i (cAr l)
288 (if (or (== i :start) (== i :end) (integer? i))
289 (let* ((u (apply tree-ref (cons t (cDr l))))
290 (p (and u (tree->path u))))
291 (cond ((not p) #f)
292 ((== i :start) (path-start (root-tree) p))
293 ((== i :end) (path-end (root-tree) p))
294 ((integer? i) (rcons p i))))
295 (with u (apply tree-ref (cons t l))
296 (and u (tree->path u)))))))
297
298 (tm-define (tree-cursor-path t . l)
299 (:synopsis "Retrieve the current cursor position relative to the tree @t.")
300 (let* ((p (apply tree->path (cons t l)))
301 (c (cursor-path)))
302 (and p (list-starts? c p) (list-tail c (length p)))))
303
304 (tm-define (tree-go-to t . l)
305 (:synopsis "Go to a position determined by @l inside the tree @t.")
306 (with p (apply tree->path (cons t l))
307 (if p (go-to p))))
308
309 (tm-define (tree-cursor-at? t . l)
310 (:synopsis "Is the cursor at the position determined by @l inside @t?")
311 (with p (apply tree->path (cons t l))
312 (== (cursor-path) p)))
313
314 (tm-define (tree-select t . l)
315 (:synopsis "Select the tree @(tree-ref t . l)")
316 (and-with t (apply tree-ref (cons t l))
317 (and-with p (tree->path t)
318 (selection-set (rcons p 0) (rcons p (tree-right-index t))))))
319
320 (tm-define (tree-focus t . l)
321 (:synopsis "Focus on the tree @(tree-ref t . l)")
322 (and-with t (apply tree-ref (cons t l))
323 (and-with p (tree->path t)
324 (set-manual-focus-path p))))
325
326 (tm-define-macro (with-focus-after t . body)
327 `(with tp (tree->tree-pointer ,t)
328 ,@body
329 (tree-focus (tree-pointer->tree tp))
330 (tree-pointer-detach tp)))
331
332 (tm-define-macro (conserve-focus . body)
333 `(with-focus-after (focus-tree)
334 ,@body))
335
336 (tm-define (tree-correct-old t . l)
337 (:synopsis "Deprecated old tree correction routine")
338 (with p (apply tree->path (cons t l))
339 (if p (path-correct-old p))))
340
341 (tm-define (tree-correct-node t . l)
342 (:synopsis "Make the node @(tree-ref t . l) correct")
343 (cpp-tree-correct-node (apply tree-ref (cons t l))))
344
345 (tm-define (tree-correct-downwards t . l)
346 (:synopsis "Correct the tree @(tree-ref t . l) and its descendants")
347 (cpp-tree-correct-downwards (apply tree-ref (cons t l))))
348
349 (tm-define (tree-correct-upwards t . l)
350 (:synopsis "Correct the tree @(tree-ref t . l) and its ancestors")
351 (cpp-tree-correct-upwards (apply tree-ref (cons t l))))
352
353 (tm-define (update-tree t . l)
354 (:synopsis "Re-typeset and render the tree @(tree-ref t . l)")
355 (and-let* ((u (apply tree-ref (cons t l)))
356 (p (tree->path u)))
357 (update-path p)))
358
359 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
360 ;; Try a modification with possibility for cancelation
361 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
362
363 (tm-define-macro (try-modification . body)
364 `(with mark-nr (mark-new)
365 (mark-start mark-nr)
366 (archive-state)
367 (with mark-ok (begin ,@body)
368 (if mark-ok
369 (mark-end mark-nr)
370 (mark-cancel mark-nr))
371 mark-ok)))