2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4 ;; MODULE : session-edit.scm
5 ;; DESCRIPTION : editing routines for sessions
6 ;; COPYRIGHT : (C) 2001--2009 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 session-edit)
15 (:use (utils library tree)
16 (utils library cursor)
18 (dynamic scripts-edit)
21 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
23 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
25 (tm-define (toggle-session-math-input)
26 (:synopsis "Toggle mathematical input in sessions.")
27 (:check-mark "v" session-math-input?)
28 (session-use-math-input (not (session-math-input?)))
29 (with-innermost t io-context?
32 (define session-multiline-input #f)
34 (tm-define (session-multiline-input?)
35 session-multiline-input)
37 (tm-define (toggle-session-multiline-input)
38 (:synopsis "Toggle multi-line input in sessions.")
39 (:check-mark "v" session-multiline-input?)
40 (set! session-multiline-input (not session-multiline-input)))
42 (define session-scheme-trees #t)
44 (tm-define (session-scheme-trees?)
47 (tm-define (toggle-session-scheme-trees)
48 (:synopsis "Toggle pretty tree output in scheme sessions.")
49 (:check-mark "v" session-scheme-trees?)
50 (set! session-scheme-trees (not session-scheme-trees)))
52 (define session-scheme-math #f)
54 (tm-define (session-scheme-math?)
57 (tm-define (toggle-session-scheme-math)
58 (:synopsis "Toggle pretty tree output in scheme sessions.")
59 (:check-mark "v" session-scheme-math?)
60 (set! session-scheme-math (not session-scheme-math)))
62 (define session-output-timings #f)
64 (tm-define (session-output-timings?)
65 session-output-timings)
67 (tm-define (toggle-session-output-timings)
68 (:synopsis "Toggle output of evaluation timings.")
69 (:check-mark "v" session-output-timings?)
70 (set! session-output-timings (not session-output-timings)))
72 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
74 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
76 (tm-define (session-document-context? t)
77 (and (tm-func? t 'document)
78 (tm-func? (tree-ref t :up) 'session)))
80 (tm-define (subsession-document-context? t)
81 (or (and (tm-func? t 'document)
82 (tm-func? (tree-ref t :up) 'session))
83 (and (tm-func? t 'document)
84 (tm-func? (tree-ref t :up) 'unfolded)
85 (== (tree-index t) 1))))
87 (tm-define io-tags '(unfolded-io folded-io unfolded-io-math folded-io-math))
89 (tm-define (io-context? t)
90 (and (tree-in? t io-tags)
91 (tm-func? (tree-ref t :up) 'document)))
93 (tm-define (io-folded-context? t)
94 (and (tree-in? t '(folded-io folded-io-math))
95 (tm-func? (tree-ref t :up) 'document)))
97 (tm-define (io-unfolded-context? t)
98 (and (tree-in? t '(unfolded-io unfolded-io-math))
99 (tm-func? (tree-ref t :up) 'document)))
101 (tm-define (io-prog-context? t)
102 (and (tree-in? t '(folded-io unfolded-io))
103 (tm-func? (tree-ref t :up) 'document)))
105 (tm-define (io-math-context? t)
106 (and (tree-in? t '(folded-io-math unfolded-io-math))
107 (tm-func? (tree-ref t :up) 'document)))
109 (tm-define (input-context? t)
111 (== (tree-down-index t) 1)))
113 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
115 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
117 (define (io-next t forward?)
118 (and-with u (tree-ref t (if forward? :next :previous))
119 (if (io-context? u) u (io-next u forward?))))
121 (define (io-extreme t last?)
122 (with u (tree-ref t :up (if last? :last :first))
123 (if (io-context? u) u
124 (io-next u (not last?)))))
126 (define (io-update-math t)
127 (if (session-math-input?)
128 (when (io-prog-context? t)
129 (tree-assign-node! t 'folded-io-math)
130 (tree-assign (tree-ref t 1) '(document "")))
131 (when (io-math-context? t)
132 (tree-assign-node! t 'folded-io)
133 (tree-assign (tree-ref t 1) '(document "")))))
135 (define (io-create t p forward?)
136 (let* ((d (tree-ref t :up))
137 (i (+ (tree-index t) (if forward? 1 0)))
138 (l (if (session-math-input?) 'folded-io-math 'folded-io))
139 (b `(,l ,p (document "") (document))))
140 (tree-insert d i (list b))
143 (define (session-forall-sub fun t)
144 (for (u (tree-children t))
145 (when (io-context? u)
147 (when (and (tm-func? u 'unfolded)
148 (tm-func? (tree-ref u 1) 'document))
149 (session-forall-sub fun (tree-ref u 1)))))
151 (define (session-forall fun)
152 (with-innermost t subsession-document-context?
153 (session-forall-sub fun t)))
155 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
157 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
159 (tm-define (make-session lan ses)
160 (let* ((ban `(output (document "")))
161 (l (if (session-math-input?) 'folded-io-math 'folded-io))
162 (p (connection-prompt lan ses))
163 (in `(,l (document ,p) (document "") (document)))
164 (s `(session ,lan ,ses (document ,ban ,in))))
165 (insert-go-to s '(2 1 1 0 0))
166 (with-innermost t input-context?
167 (with u (tree-ref t :previous 0)
168 (if (url-exists? (url "$TEXMACS_STYLE_PATH" (string-append lan ".ts")))
169 (init-add-package lan))
170 (session-feed lan ses :start u t '())))))
172 (define (io-process-input t)
173 (if (tm-func? t 'folded-io)
174 (tree-assign-node! t 'unfolded-io))
175 (if (tm-func? t 'folded-io-math)
176 (tree-assign-node! t 'unfolded-io-math))
177 (let* ((lan (get-env "prog-language"))
178 (ses (get-env "prog-session"))
179 (p (connection-prompt lan ses))
180 (in (tree->stree (tree-ref t 1)))
183 (when (session-output-timings?) (set! opts (cons :timings opts)))
184 (when (io-math-context? t) (set! opts (cons :math-input opts)))
185 (with u (or (io-next t #t) (io-create t p #t))
186 (session-feed lan ses in out u opts)
187 (tree-go-to u 1 :end))))
189 (tm-define (kbd-return)
190 (:context input-context?)
191 (if (session-multiline-input?)
195 (tm-define (kbd-shift-return)
196 (:context input-context?)
197 (if (session-multiline-input?)
201 (tm-define (session-evaluate)
202 (with-innermost t input-context?
203 (io-process-input t)))
205 (tm-define (session-evaluate-all)
208 (when (not (tree-empty? (tree-ref t 1)))
209 (io-process-input t)))))
211 (tm-define (session-evaluate-above)
212 (with-innermost me input-context?
215 (when (not (tree-empty? (tree-ref t 1)))
216 (when (path-inf? (tree->path t) (tree->path me))
217 (io-process-input t)))))))
219 (tm-define (session-evaluate-below)
220 (with-innermost me input-context?
223 (when (not (tree-empty? (tree-ref t 1)))
224 (when (path-inf-eq? (tree->path me) (tree->path t))
225 (io-process-input t)))))))
227 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
229 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
231 (tm-define (kbd-left)
232 (:context io-context?)
233 (go-to-remain-inside go-left io-context? 1))
235 (tm-define (kbd-right)
236 (:context io-context?)
237 (go-to-remain-inside go-right io-context? 1))
240 (with p (cursor-path)
241 (go-to-remain-inside go-up io-context? 1)
242 (when (== (cursor-path) p)
243 (go-to-previous-tag-same-argument io-tags))))
246 (with p (cursor-path)
247 (go-to-remain-inside go-down io-context? 1)
248 (when (== (cursor-path) p)
249 (go-to-next-tag-same-argument io-tags))))
252 (:context io-context?)
255 (tm-define (kbd-down)
256 (:context io-context?)
259 (tm-define (kbd-page-up)
260 (:context input-context?)
262 (go-to-next-inside go-to-previous-node io-context? 1)))
264 (tm-define (kbd-page-down)
265 (:context input-context?)
267 (go-to-next-inside go-to-next-node io-context? 1)))
269 (tm-define (kbd-remove forward?)
270 (:context input-context?)
271 (with-innermost t input-context?
272 (cond ((and (tree-cursor-at? t 1 :start) (not forward?)) (noop))
273 ((and (tree-cursor-at? t 1 :end) forward?) (noop))
274 (else (remove-text forward?)))))
277 (:context input-context?)
278 (:require (plugin-supports-completions? (get-env "prog-language")))
279 (with-innermost t input-context?
280 (session-complete-try? t)))
282 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
283 ;; Structured keyboard movements
284 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
286 (define (io-input-simple-context? t)
288 (simple-context? (tree-down t))
291 (tm-define (document-context? t)
293 (:require (input-context? (tree-ref t :up)))
296 (tm-define (traverse-left)
297 (:context input-context?)
298 (go-to-remain-inside go-to-previous-word io-context? 1))
300 (tm-define (traverse-right)
301 (:context input-context?)
302 (go-to-remain-inside go-to-next-word io-context? 1))
304 (tm-define (traverse-up)
305 (:context input-context?)
308 (tm-define (traverse-down)
309 (:context input-context?)
312 (tm-define (traverse-previous)
313 (:context input-context?)
316 (tm-define (traverse-next)
317 (:context input-context?)
320 (tm-define (structured-left)
321 (:context io-input-simple-context?)
324 (tm-define (structured-right)
325 (:context io-input-simple-context?)
328 (tm-define (structured-up)
329 (:context io-input-simple-context?)
330 (go-to-remain-inside io-go-up 'session))
332 (tm-define (structured-down)
333 (:context io-input-simple-context?)
334 (go-to-remain-inside io-go-down 'session))
336 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
338 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
341 (:context io-unfolded-context?)
342 (with-innermost t io-unfolded-context?
344 (tree-go-to t 1 :end)))
347 (:context io-folded-context?)
348 (with-innermost t io-folded-context?
350 (tree-go-to t 1 :end)))
352 (tm-define (io-fold t)
353 (when (io-unfolded-context? t)
356 (tm-define (io-unfold t)
357 (when (io-folded-context? t)
360 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
362 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
364 (tm-define (io-insert forwards?)
365 (with-innermost t input-context?
366 (let* ((lan (get-env "prog-language"))
367 (ses (get-env "prog-session"))
368 (p (connection-prompt lan ses)))
369 (tree-go-to (io-create t p forwards?) 1 :end))))
371 (tm-define (io-insert-text forward?)
372 (with-innermost t input-context?
373 (let* ((d (tree-ref t :up))
374 (i (+ (tree-index t) (if forward? 1 0)))
375 (b `(textput (document ""))))
376 (tree-insert d i (list b))
377 (tree-go-to d i 0 :start))))
379 (tm-define (io-remove-banner)
380 (with-innermost t session-document-context?
381 (when (tm-func? (tree-ref t 0) 'output)
382 (tree-remove! t 0 1))))
384 (tm-define (io-remove-extreme last?)
385 (with-innermost t input-context?
386 (with u (io-extreme t last?)
387 (with v (io-next t (not last?))
389 (tree-go-to v 1 :end))
391 (tree-remove (tree-ref u :up) (tree-index u) 1))))))
393 (tm-define (io-remove forwards?)
394 (with-innermost t input-context?
396 (with u (io-next t #t)
398 (tree-remove (tree-ref t :up) (tree-index t) 1)
399 (tree-go-to u 1 :start))
400 (io-remove-extreme #t)))
401 (with u (io-next t #f)
402 (if u (tree-remove (tree-ref u :up) (tree-index u) 1)
403 (io-remove-banner))))))
405 (tm-define (structured-insert forwards?)
406 (:context input-context?)
407 (if forwards? (io-insert-fold)))
409 (tm-define (structured-insert-up)
410 (:context input-context?)
413 (tm-define (structured-insert-down)
414 (:context input-context?)
417 (tm-define (structured-remove forwards?)
418 (:context input-context?)
419 (io-remove forwards?))
421 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
422 ;; Session management
423 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
425 (tm-define (session-clear-all)
426 (session-forall (lambda (t) (tree-set! t 2 '(document)))))
428 (tm-define (session-fold-all)
429 (session-forall io-fold))
431 (tm-define (session-unfold-all)
432 (session-forall io-unfold))
434 (tm-define (io-insert-fold)
435 (with-innermost t input-context?
436 (tree-set! t `(unfolded (document "") (document ,t)))
437 (tree-go-to t 0 :end)))
439 (tm-define (session-split)
440 (:context session-document-context?)
441 (with-innermost t session-document-context?
442 (let* ((u (tree-ref t :up)) ;; session
443 (v (tree-ref u :up)) ;; document
444 (i (+ (tree-down-index t) 1))
447 (ses (tree-ref u 1)))
448 (when (< i (tree-arity t))
452 (tree-insert (tree-ref v j) 0 `(,lan ,ses))
453 (tree-insert (tree-ref v (+ j 1)) 0 `(,lan ,ses))
454 (tree-insert v (+ j 1) '((document "")))
455 (tree-go-to v (+ j 1) :end)))))