2
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4
;; MODULE : fold-edit.scm
5
;; DESCRIPTION : routines for switching, folding and layers
6
;; COPYRIGHT : (C) 2002 Joris van der Hoeven
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>.
12
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
14
(texmacs-module (dynamic fold-edit)
15
(:use (utils library tree)
16
(utils library cursor)
17
(dynamic dynamic-drd)))
19
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
20
;; Abstract stuff for fold tags and switches
21
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
23
(tm-define (dynamic-context? t)
24
(or (toggle-tag? (tree-label t))
25
(switch-tag? (tree-label t))))
27
(tm-define (dynamic-first) (noop))
28
(tm-define (dynamic-previous) (noop))
29
(tm-define (dynamic-next) (noop))
30
(tm-define (dynamic-last) (noop))
32
(tm-define (structured-left)
33
(:context dynamic-context?)
36
(tm-define (structured-right)
37
(:context dynamic-context?)
40
(tm-define (structured-up)
41
(:context dynamic-context?)
44
(tm-define (structured-down)
45
(:context dynamic-context?)
48
(tm-define (structured-first)
49
(:context dynamic-context?)
52
(tm-define (structured-last)
53
(:context dynamic-context?)
56
(tm-define (structured-top)
57
(:context dynamic-context?)
60
(tm-define (structured-bottom)
61
(:context dynamic-context?)
64
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
65
;; Operations on toggle trees
66
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
68
(tm-define (toggle-toggle t)
69
(:synopsis "Toggle a fold/unfold")
70
(tree-assign-node! t (ahash-ref toggle-table (tree-label t))))
72
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
74
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
76
(tm-define (toggle-context? t)
77
(toggle-tag? (tree-label t)))
79
(tm-define (toggle-first-context? t)
80
(toggle-first-tag? (tree-label t)))
82
(tm-define (toggle-second-context? t)
83
(toggle-second-tag? (tree-label t)))
85
(tm-define (make-toggle tag)
87
(:synopsis "Insert a 'fold' environment")
88
(insert-go-to `(,tag (document "") (document "")) (list 0 0)))
92
(:synopsis "Fold at the current cursor position")
93
(with-innermost t toggle-second-context?
95
(tree-go-to t 0 :start)))
99
(:synopsis "Unfold at the current cursor position")
100
(with-innermost t toggle-first-context?
102
(tree-go-to t 1 :start)))
104
(tm-define (mouse-fold)
106
(:synopsis "Fold using the mouse")
109
(tree-go-to t :start)
112
(tm-define (mouse-unfold)
114
(:synopsis "Unfold using the mouse")
117
(tree-go-to t :start)
120
(tm-define (hidden-variant)
121
(:context toggle-first-context?)
124
(tm-define (hidden-variant)
125
(:context toggle-second-context?)
128
(tm-define (dynamic-first)
129
(:context toggle-context?)
132
(tm-define (dynamic-previous)
133
(:context toggle-context?)
136
(tm-define (dynamic-next)
137
(:context toggle-context?)
140
(tm-define (dynamic-last)
141
(:context toggle-context?)
144
(tm-define (tree-show-hidden t)
145
(:require (toggle-context? t))
148
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
149
;; Operations on switch trees
150
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
152
(define (switch-ref t i)
153
(and t (>= i 0) (< i (tree-arity t)) (not (tree-is? t i 'hidden))))
155
(define (switch-set t i on?)
156
(if (== i :last) (set! i (- (tree-arity t) 1)))
157
(when (and (>= i 0) (< i (tree-arity t)))
158
(cond ((and on? (tree-is? t i 'hidden))
159
(tree-assign-node (tree-ref t i) 'shown))
160
((and (not on?) (tree-is? t i 'shown))
161
(tree-assign-node (tree-ref t i) 'hidden))
162
((and on? (not (tree-is? t i 'shown)))
163
(tree-insert-node (tree-ref t i) 0 '(shown)))
164
((and (not on?) (not (tree-is? t i 'hidden)))
165
(tree-insert-node (tree-ref t i) 0 '(hidden))))))
167
(define (switch-set-range t first last on?)
168
(if (== last :last) (set! last (tree-arity t)))
169
(for (i first last) (switch-set t i on?)))
171
(define (switch-last-visible t)
172
(with v (- (tree-arity t) 1)
173
(while (and (>= v 0) (not (switch-ref t v)))
177
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
178
;; Routines on innermost switch
179
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
181
(tm-define (switch-context? t)
182
(switch-tag? (tree-label t)))
184
(tm-define (switch-arity)
185
(with t (tree-innermost switch-context?)
186
(and t (tree-arity t))))
188
(tm-define (switch-valid-child? i)
189
(with t (tree-innermost switch-context?)
190
(and t i (>= i 0) (< i (tree-arity t)))))
192
(tm-define (switch-index . args)
193
(:context switch-context?)
194
(and-let* ((i (if (null? args) :current (car args)))
195
(t (tree-innermost switch-context?))
196
(c (tree-down-index t))
197
(l (- (tree-arity t) 1))
198
(v (switch-last-visible t)))
202
((== i :previous) (max 0 (- c 1)))
203
((== i :next) (min l (+ c 1)))
204
((== i :var-previous) (- c 1))
205
((== i :var-next) (+ c 1))
206
((== i :rotate-backward) (if (= c 0) l (- c 1)))
207
((== i :rotate-forward) (if (= c l) 0 (+ c 1)))
212
(tm-define (switch-to i . args)
213
(set! i (switch-index i))
214
(if (null? args) (set! args '(:start)))
215
(when (switch-valid-child? i)
217
(with-innermost t switch-context?
218
(apply tree-go-to (cons* t i 0 args)))))
220
(tm-define (switch-insert-at i)
221
(set! i (if (== i :end) (switch-arity) (switch-index i)))
222
(with-innermost t switch-context?
223
(when (and (>= i 0) (<= i (tree-arity t)))
224
(let* ((empty (if (tree-in? t (big-switch-tag-list)) '(document "") ""))
225
(v (switch-index :visible)))
226
(tree-insert! t i `((shown ,empty)))
227
(if (tree-in? t (alternative-tag-list))
229
(switch-select (+ v 1)))
230
(tree-go-to t i :start)))))
232
(tm-define (switch-remove-at i)
233
(set! i (switch-index i))
234
(with-innermost t switch-context?
235
(when (and (>= i 0) (< i (tree-arity t)) (> (tree-arity t) 1))
236
(let* ((v (switch-index :visible))
237
(l (- (tree-arity t) 2)))
238
(switch-set-range t (max 0 (- i 1)) (min l (+ i 1)) #t)
240
(tree-go-to t (min i l) :start)
241
(if (tree-in? t (alternative-tag-list))
242
(switch-select (min i l))
243
(switch-select (max 0 (- v 1))))))))
245
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
246
;; Specific types of switches
247
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
249
(define (alternative-context? t)
250
(alternative-tag? (tree-label t)))
252
(tm-define (tree/switch-select t i)
253
(:require (alternative-context? t))
254
(switch-set-range t 0 :last #f)
257
(define (unroll-context? t)
258
(unroll-tag? (tree-label t)))
260
(tm-define (tree/switch-select t i)
261
(:require (unroll-context? t))
262
(switch-set-range t 0 (+ i 1) #t)
263
(switch-set-range t (+ i 1) :last #f))
265
(define (expanded-context? t)
266
(expanded-tag? (tree-label t)))
268
(tm-define (tree/switch-select t i)
269
(:require (expanded-context? t))
270
(switch-set-range t 0 :last #t))
272
(tm-define (switch-select i)
273
(with-innermost t switch-context?
274
(tree/switch-select t i)))
276
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
277
;; User interface to switches
278
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
280
(tm-define (make-switch tag)
281
(if (in? tag (big-switch-tag-list))
282
(insert-go-to `(,tag (shown (document ""))) '(0 0 0 0))
283
(insert-go-to `(,tag (shown "")) '(0 0 0))))
285
(tm-define (dynamic-first)
286
(:context switch-context?)
287
(switch-to :first :start))
289
(tm-define (dynamic-previous)
290
(:context switch-context?)
291
(switch-to :previous :end))
293
(tm-define (dynamic-next)
294
(:context switch-context?)
295
(switch-to :next :start))
297
(tm-define (dynamic-last)
298
(:context switch-context?)
299
(switch-to :last :end))
301
(tm-define (structured-insert forwards?)
302
(:context switch-context?)
303
(switch-insert-at (if forwards? :var-next :current)))
305
(tm-define (structured-insert-up)
306
(:context switch-context?)
307
(switch-insert-at :current))
309
(tm-define (structured-insert-down)
310
(:context switch-context?)
311
(switch-insert-at :var-next))
313
(tm-define (structured-remove forwards?)
314
(:context switch-context?)
315
(with-innermost t switch-context?
316
(with i (if forwards? :current :var-previous)
317
(set! i (switch-index i))
318
(cond ((< i 0) (tree-go-to t :start))
319
((and forwards? (= i (- (tree-arity t) 1))) (tree-go-to t :end))
320
(else (switch-remove-at i))))))
322
(tm-define (hidden-variant)
323
(:context switch-context?)
324
(switch-to :rotate-forward))
326
(tm-define (variant-circulate forward?)
327
(:context switch-context?)
328
(with-innermost t switch-context?
329
(let* ((old (tree-label t))
330
(val (big-switch-tag-list))
331
(rot (list-search-rotate val old))
332
(new (if (and forward? (nnull? rot)) (cadr rot) (cAr rot)))
334
(variant-replace old new)
337
(tm-define (tree-show-hidden t)
338
(:require (switch-context? t))
339
(with i (tree-down-index t)
340
(if (tree-is? (tree-ref t i) 'hidden)
341
(tree/switch-select t i))))
343
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
344
;; Analyzing the environments occurring in folds
345
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
347
(define fold-environments (make-ahash-table))
348
(define fold-environments-first (make-ahash-table))
349
(define fold-environments-second (make-ahash-table))
351
(define (fold-add-environment t first?)
352
(cond ((and (toggle-first-context? t)
353
(not (tree-is? t 'summarized-algorithm)))
354
(fold-add-environment (tree-ref t 1) #t))
355
((and (toggle-second-context? t)
356
(not (tree-is? t 'detailed-algorithm)))
357
(fold-add-environment (tree-ref t 1) #f))
358
((tm-func? t 'document 1)
359
(fold-add-environment (tree-ref t 0) first?))
362
(if (tree-compound? t) (set! tag (tree-label t)))
363
(if (== tag 'concat) (set! tag 'text))
364
(if (== tag 'document) (set! tag 'text))
365
(if (== tag 'render-proof) (set! tag 'proof))
366
(if (in? tag '(summarized-algorithm detailed-algorithm))
367
(set! tag 'algorithm))
368
(ahash-set! fold-environments tag #t)
369
(ahash-set! (if first?
370
fold-environments-first
371
fold-environments-second)
374
(define (fold-get-environments-sub t)
375
(if (tree-compound? t)
376
(for-each fold-get-environments-sub (tree-children t)))
377
(if (toggle-context? t)
378
(fold-add-environment t (toggle-first-context? t))))
380
(tm-define (fold-get-environments-in-buffer)
381
(set! fold-environments (make-ahash-table))
382
(set! fold-environments-first (make-ahash-table))
383
(set! fold-environments-second (make-ahash-table))
384
(fold-get-environments-sub (buffer-tree))
385
(with envl (map car (ahash-table->list fold-environments))
387
(list-sort (map symbol->string envl) string<=?)
388
fold-environments-first
389
fold-environments-second)))
391
(define (fold-matching-env? t tag)
392
(cond ((tree-in? t '(summarized-algorithm detailed-algorithm))
394
((toggle-first-context? t)
395
(fold-matching-env? (tree-ref t 1) tag))
396
((toggle-second-context? t)
397
(fold-matching-env? (tree-ref t 1) tag))
398
((tm-func? t 'document 1)
399
(fold-matching-env? (tree-ref t 0) tag))
400
((or (tree-atomic? t) (tree-in? t '(document concat)))
403
(tree-in? t '(proof render-proof)))
404
(else (tree-is? t tag))))
406
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
407
;; Global routines for folding/unfolding/compressing/expanding
408
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
410
(define (dynamic-operate-sub t mode)
411
(if (tree-compound? t)
412
(for-each (lambda (x) (dynamic-operate x mode)) (tree-children t)))
413
(cond ((toggle-first-context? t)
414
(cond ((== mode :var-last)
415
(tree-insert-node! t 0 '(traversed)))
416
((in? mode '(:unfold :expand :var-expand :last))
418
((and (pair? mode) (== (car mode) :unfold)
419
(fold-matching-env? t (cadr mode)))
421
((toggle-second-context? t)
422
(cond ((== mode :var-last)
424
(tree-insert-node! t 0 '(traversed)))
425
((in? mode '(:fold :compress :var-compress :first))
427
((and (pair? mode) (== (car mode) :fold)
428
(fold-matching-env? t (cadr mode)))
430
((and (== mode :expand) (switch-context? t))
431
(switch-set-range t 0 :last #t))
432
((and (== mode :compress) (switch-context? t))
434
(switch-set-range t 1 :last #f))
435
((alternative-context? t)
436
(cond ((== mode :first)
437
(switch-set-range t 1 :last #f)
440
(switch-set-range t 0 :last #f)
441
(switch-set t :last #t))
442
((== mode :var-expand)
443
(tree-assign-node! t 'expanded)
444
(switch-set-range t 0 :last #t))))
446
(cond ((== mode :var-last)
447
(switch-set-range t 1 :last #f)
449
(tree-insert-unary t 0 '(traversed)))
451
(switch-set-range t 1 :last #f)
454
(switch-set-range t 0 :last #t))
455
((== mode :var-expand)
456
(switch-set-range t 0 :last #t))
457
((== mode :var-compress)
459
(switch-set-range t 1 :last #f))))
460
((expanded-context? t)
461
(cond ((== mode :var-compress)
462
(tree-assign-node! t 'switch)
464
(switch-set-range t 1 :last #f))))))
466
(define (dynamic-operate t mode)
467
(when (tree-compound? t)
468
(cond ((tree-is? t 'traversed)
469
(when (!= mode :var-last)
470
(dynamic-operate (tree-ref t 0) mode)
471
(if (in? mode '(:unfold :expand :var-expand :first))
472
(tree-remove-node! t 0))))
473
((tree-is? t 'fold-back)
474
(if (== mode :last) (set! mode :var-last))
475
(dynamic-operate (tree-ref t 0) mode))
476
((tree-is? t 'keep-folded)
477
(if (== mode :var-last) (set! mode :last))
478
(dynamic-operate (tree-ref t 0) mode))
479
(else (dynamic-operate-sub t mode)))))
481
(tm-define (dynamic-operate-on-buffer mode)
482
(dynamic-operate (buffer-tree) mode)
483
(if (in? mode '(:first :var-first)) (tree-go-to (buffer-tree) :start))
484
(if (in? mode '(:last :var-last)) (tree-go-to (buffer-tree) :end)))
486
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
487
;; Global navigation in recursive fold/switch structure
488
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
490
(define (dynamic-traverse-folded t mode)
491
(cond ((in? mode '(:next :var-next))
493
(dynamic-operate (tree-ref t 1) :first)
494
(tree-go-to t 1 :end)
498
(define (dynamic-traverse-unfolded t mode)
499
(cond ((== mode :var-next)
501
(tree-insert-node! t 0 '(traversed))
503
((in? mode '(:previous :var-previous))
504
(with last-mode (if (== mode :previous) :last :var-last)
506
(dynamic-operate (tree-ref t 0) last-mode)
507
(tree-go-to t 0 :end)
511
(define (dynamic-traverse-switch t i l mode)
512
(cond ((and (== mode :var-next) (= i l) (unroll-context? t))
513
(dynamic-operate t :first)
514
(tree-insert-node! t 0 '(traversed))
516
((and (in? mode '(:next :var-next)) (< i l))
517
(dynamic-operate (tree-ref t (1+ i)) :first)
518
(tree-go-to t i :end)
521
((and (in? mode '(:previous :var-previous)) (> i 0))
522
(with last-mode (if (== mode :previous) :last :var-last)
523
(dynamic-operate (tree-ref t (- i 1)) last-mode)
524
(tree-go-to t i :start)
525
(switch-to :previous)
529
(define (dynamic-traverse-traversed t mode)
530
(and (in? mode '(:previous :var-previous))
532
(tree-remove-node! t 0)
533
(dynamic-operate t :last)
534
(if (and (== mode :var-previous) (tree-compound? t))
535
(for-each (lambda (x) (dynamic-operate x :var-last))
536
(tree-accessible-children t)))
539
(define (dynamic-traverse-list l mode)
541
(or (dynamic-traverse (car l) mode)
542
(dynamic-traverse-list (cdr l) mode))))
544
(define (dynamic-traverse t mode)
545
(cond ((tree-atomic? t) #f)
546
((tree-is? t 'traversed)
547
(dynamic-traverse-traversed t mode))
548
((tree-is? t 'fold-back)
549
(if (== mode :next) (set! mode :var-next))
550
(if (== mode :previous) (set! mode :var-previous))
551
(dynamic-traverse (tree-ref t 0) mode))
552
((tree-is? t 'keep-folded)
553
(if (== mode :var-next) (set! mode :next))
554
(if (== mode :var-previous) (set! mode :previous))
555
(dynamic-traverse (tree-ref t 0) mode))
556
((toggle-first-context? t)
557
(or (dynamic-traverse (tree-ref t 0) mode)
558
(dynamic-traverse-folded t mode)))
559
((toggle-second-context? t)
560
(or (dynamic-traverse (tree-ref t 1) mode)
561
(dynamic-traverse-unfolded t mode)))
562
((or (alternative-context? t) (unroll-context? t))
563
(let* ((i (switch-last-visible t))
564
(l (- (tree-arity t) 1)))
565
(or (dynamic-traverse (tree-ref t i) mode)
566
(dynamic-traverse-switch t i l mode))))
568
(let* ((c (tree-accessible-children t))
569
(forward? (in? mode '(:next :var-next)))
570
(l (if forward? c (reverse c))))
571
(dynamic-traverse-list l mode)))))
573
(tm-define (dynamic-traverse-buffer mode)
574
(dynamic-traverse (buffer-tree) mode))