1 2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 3;; 4;; MODULE : generic-edit.scm 5;; DESCRIPTION : Generic editing routines 6;; COPYRIGHT : (C) 2001 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 (generic generic-edit) 15 (:use (utils library tree) 16 (utils library cursor) 17 (utils edit variants) 18 (bibtex bib-complete) 19 (source macro-search))) 20 21(tm-define (generic-context? t) #t) ;; overridden in, e.g., graphics mode 22 23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 24;; Basic cursor movements via the keyboard 25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 26 27(tm-define (kbd-horizontal t forwards?) 28 (and-with p (tree-outer t) 29 (kbd-horizontal p forwards?))) 30 31(tm-define (kbd-vertical t downwards?) 32 (and-with p (tree-outer t) 33 (kbd-vertical p downwards?))) 34 35(tm-define (kbd-extremal t forwards?) 36 (and-with p (tree-outer t) 37 (kbd-extremal p forwards?))) 38 39(tm-define (kbd-incremental t downwards?) 40 (and-with p (tree-outer t) 41 (kbd-incremental p downwards?))) 42 43(tm-define (kbd-horizontal t forwards?) 44 (:require (tree-is-buffer? t)) 45 (with move (lambda () (if forwards? (go-right) (go-left))) 46 (go-to-next-such-that move generic-context?))) 47 48(tm-define (kbd-vertical t downwards?) 49 (:require (tree-is-buffer? t)) 50 (with move (lambda () (if downwards? (go-down) (go-up))) 51 (go-to-next-such-that move generic-context?))) 52 53(tm-define (kbd-extremal t forwards?) 54 (:require (tree-is-buffer? t)) 55 (with move (lambda () (if forwards? (go-end-line) (go-start-line))) 56 (go-to-next-such-that move generic-context?))) 57 58(tm-define (kbd-incremental t downwards?) 59 (:require (tree-is-buffer? t)) 60 (with move (lambda () (if downwards? (go-page-down) (go-page-up))) 61 (go-to-next-such-that move generic-context?))) 62 63(tm-define (kbd-left) 64 (kbd-horizontal (focus-tree) #f)) 65(tm-define (kbd-right) 66 (kbd-horizontal (focus-tree) #t)) 67(tm-define (kbd-up) 68 (kbd-vertical (focus-tree) #f)) 69(tm-define (kbd-down) 70 (kbd-vertical (focus-tree) #t)) 71(tm-define (kbd-start-line) 72 (kbd-extremal (focus-tree) #f)) 73(tm-define (kbd-end-line) 74 (kbd-extremal (focus-tree) #t)) 75(tm-define (kbd-page-up) 76 (kbd-incremental (focus-tree) #f)) 77(tm-define (kbd-page-down) 78 (kbd-incremental (focus-tree) #t)) 79 80(tm-define (kbd-select r) 81 (select-from-shift-keyboard) 82 (r) 83 (select-from-cursor)) 84 85;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 86;; Basic editing via the keyboard 87;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 88 89(tm-define (insert-return) (insert-raw-return)) 90 91(tm-define (kbd-space-bar t shift?) 92 (and-with p (tree-outer t) 93 (kbd-space-bar p shift?))) 94 95(tm-define (kbd-enter t shift?) 96 (and-with p (tree-outer t) 97 (kbd-enter p shift?))) 98 99(tm-define (kbd-control-enter t shift?) 100 (and-with p (tree-outer t) 101 (kbd-control-enter p shift?))) 102 103(tm-define (kbd-alternate-enter t shift?) 104 (and-with p (tree-outer t) 105 (kbd-alternate-enter p shift?))) 106 107(tm-define (kbd-remove t forwards?) 108 (and-with p (tree-outer t) 109 (kbd-remove p forwards?))) 110 111(tm-define (kbd-variant t forwards?) 112 (and-with p (tree-outer t) 113 (kbd-variant p forwards?))) 114 115(tm-define (kbd-space-bar t shift?) 116 (:require (tree-is-buffer? t)) 117 (insert " ")) 118 119(tm-define (kbd-enter t shift?) 120 (:require (tree-is-buffer? t)) 121 (insert-return)) 122 123(tm-define (kbd-control-enter t shift?) 124 (:require (tree-is-buffer? t)) 125 (noop)) 126 127(tm-define (kbd-alternate-enter t shift?) 128 (:require (tree-is-buffer? t)) 129 (noop)) 130 131(tm-define (kbd-remove t forwards?) 132 (:require (tree-is-buffer? t)) 133 (remove-text forwards?)) 134 135(tm-define (kbd-remove t forwards?) 136 (:require (and (tree-is-buffer? t) (with-any-selection?))) 137 (clipboard-cut "nowhere") 138 (clipboard-clear "nowhere")) 139 140(tm-define (kbd-variant t forwards?) 141 (:require (tree-is-buffer? t)) 142 (if (and (not (complete-try?)) forwards?) 143 (with sh (kbd-system-rewrite (kbd-find-inv-binding '(kbd-alternate-tab))) 144 (set-message `(concat "Use " ,sh " in order to insert a tab") 145 "tab")))) 146 147(tm-define (kbd-variant t forwards?) 148 (:require (and (tree-in? t '(label reference pageref)) (cursor-inside? t))) 149 (if (complete-try?) (noop))) 150 151(tm-define (bib-cite-context? t) 152 (and (tree-in? t '(cite nocite cite-detail)) 153 (cursor-inside? t) 154 (or (not (tree-is? t 'cite-detail)) 155 (== (tree-index (tree-down t)) 0)))) 156 157(tm-define (kbd-variant t forwards?) 158 (:require (and (not (supports-db?)) (bib-cite-context? t))) 159 (with u (current-bib-file #t) 160 (with ttxt (tree-ref t (cADr (cursor-path))) 161 (if (or (url-none? u) (not ttxt)) 162 (set-message "No completions" "You must add a bibliography file") 163 (custom-complete (tm->tree (citekey-completions u ttxt))))))) 164 165(tm-define (kbd-alternate-variant t forwards?) 166 (and-with p (tree-outer t) 167 (kbd-alternate-variant p forwards?))) 168 169(tm-define (kbd-alternate-variant t forwards?) 170 (:require (tree-is-buffer? t)) 171 (make-htab "5mm")) 172 173(tm-define (kbd-space) 174 (kbd-space-bar (focus-tree) #f)) 175(tm-define (kbd-shift-space) 176 (kbd-space-bar (focus-tree) #t)) 177(tm-define (kbd-return) 178 (kbd-enter (focus-tree) #f)) 179(tm-define (kbd-shift-return) 180 (kbd-enter (focus-tree) #t)) 181(tm-define (kbd-control-return) 182 (kbd-control-enter (focus-tree) #f)) 183(tm-define (kbd-shift-control-return) 184 (kbd-control-enter (focus-tree) #t)) 185(tm-define (kbd-alternate-return) 186 (kbd-alternate-enter (focus-tree) #f)) 187(tm-define (kbd-shift-alternate-return) 188 (kbd-alternate-enter (focus-tree) #t)) 189(tm-define (kbd-backspace) 190 (kbd-remove (focus-tree) #f)) 191(tm-define (kbd-delete) 192 (kbd-remove (focus-tree) #t)) 193(tm-define (kbd-tab) 194 (kbd-variant (focus-tree) #t)) 195(tm-define (kbd-shift-tab) 196 (kbd-variant (focus-tree) #f)) 197(tm-define (kbd-alternate-tab) 198 (kbd-alternate-variant (focus-tree) #t)) 199(tm-define (kbd-shift-alternate-tab) 200 (kbd-alternate-variant (focus-tree) #f)) 201 202(tm-define (notify-activated t) (noop)) 203(tm-define (notify-disactivated t) (noop)) 204 205;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 206;; Basic predicates 207;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 208 209(tm-define (simple-tags) 210 '(concat document tformat table row cell shown hidden)) 211 212(tm-define (complex-context? t) 213 (and (nleaf? t) 214 (nin? (tree-label t) (simple-tags)))) 215 216(tm-define (simple-context? t) 217 (or (leaf? t) 218 (and (tree-in? t (simple-tags)) 219 (simple-context? (tree-down t))))) 220 221(tm-define (document-context? t) 222 (tree-is? t 'document)) 223 224(tm-define (table-markup-context? t) 225 (or (tree-in? t '(table tformat)) 226 (and (== (tree-arity t) 1) 227 (or (tree-in? (tree-ref t 0) '(table tformat)) 228 (and (tm-func? (tree-ref t 0) 'document 1) 229 (tree-in? (tree-ref t 0 0) '(table tformat))))))) 230 231(tm-define (structured-horizontal? t) 232 (or (tree-is-dynamic? t) 233 (table-markup-context? t))) 234 235(tm-define (structured-vertical? t) 236 (or (tree-in? t '(tree)) 237 (table-markup-context? t))) 238 239;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 240;; Tree traversal 241;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 242 243(tm-define (traverse-horizontal t forwards?) 244 (if forwards? (go-to-next-word) (go-to-previous-word))) 245 246(tm-define (traverse-vertical t downwards?) 247 (and-with p (tree-outer t) 248 (traverse-vertical p downwards?))) 249 250(tm-define (traverse-vertical t downwards?) 251 (:require (document-context? t)) 252 (with move (if downwards? go-to-next-tag go-to-previous-tag) 253 (move 'document))) 254 255(define (find-similar-upwards t l) 256 (cond ((in? (tree-label t) l) t) 257 ((and (not (tree-is-buffer? t)) (tree-up t)) 258 (find-similar-upwards (tree-up t) l)) 259 (else #f))) 260 261(define-macro (with-focus-in l . body) 262 `(begin 263 ,@body 264 (selection-cancel) 265 (and-with t (find-similar-upwards (focus-tree) ,l) 266 (tree-focus t)))) 267 268(tm-define (traverse-incremental t forwards?) 269 (let* ((l (similar-to (tree-label t))) 270 (fun (if forwards? go-to-next-tag go-to-previous-tag))) 271 (with-focus-in l (fun l)))) 272 273(tm-define (traverse-extremal t forwards?) 274 (let* ((l (similar-to (tree-label t))) 275 (fun (if forwards? go-to-next-tag go-to-previous-tag)) 276 (inc (lambda () (fun l)))) 277 (with-focus-in l 278 (go-to-repeat inc) 279 (structured-inner-extremal t forwards?)))) 280 281(tm-define (traverse-previous) 282 (traverse-incremental (focus-tree) #f)) 283(tm-define (traverse-next) 284 (traverse-incremental (focus-tree) #t)) 285(tm-define (traverse-first) 286 (traverse-extremal (focus-tree) #f)) 287(tm-define (traverse-last) 288 (traverse-extremal (focus-tree) #t)) 289(tm-define (traverse-left) 290 (traverse-horizontal (focus-tree) #f)) 291(tm-define (traverse-right) 292 (traverse-horizontal (focus-tree) #t)) 293(tm-define (traverse-up) 294 (traverse-vertical (focus-tree) #f)) 295(tm-define (traverse-down) 296 (traverse-vertical (focus-tree) #t)) 297(tm-define (traverse-previous-section-title) 298 (go-to-previous-tag (similar-to 'section))) 299 300;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 301;; Structured insert and remove 302;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 303 304(tm-define (structured-insert-horizontal t forwards?) 305 (and-with p (tree-outer t) 306 (structured-insert-horizontal p forwards?))) 307 308(tm-define (structured-insert-vertical t downwards?) 309 (and-with p (tree-outer t) 310 (structured-insert-vertical p downwards?))) 311 312(tm-define (structured-remove-horizontal t forwards?) 313 (and-with p (tree-outer t) 314 (structured-remove-horizontal p forwards?))) 315 316(tm-define (structured-remove-vertical t downwards?) 317 (and-with p (tree-outer t) 318 (structured-remove-vertical p downwards?))) 319 320(tm-define (structured-insert-horizontal t forwards?) 321 (:require (structured-horizontal? t)) 322 (when (tree->path t :down) 323 (insert-argument-at (tree->path t :down) forwards?))) 324 325(tm-define (structured-remove-horizontal t forwards?) 326 (:require (structured-horizontal? t)) 327 (when (tree->path t :down) 328 (remove-argument-at (tree->path t :down) forwards?))) 329 330(tm-define (structured-insert-extremal t forwards?) 331 (structured-extremal t forwards?) 332 (structured-insert-horizontal t forwards?)) 333 334(tm-define (structured-insert-incremental t downwards?) 335 (structured-incremental t downwards?) 336 (structured-insert-vertical t downwards?)) 337 338(tm-define (structured-insert-left) 339 (structured-insert-horizontal (focus-tree) #f)) 340(tm-define (structured-insert-right) 341 (structured-insert-horizontal (focus-tree) #t)) 342(tm-define (structured-remove-left) 343 (structured-remove-horizontal (focus-tree) #f)) 344(tm-define (structured-remove-right) 345 (structured-remove-horizontal (focus-tree) #t)) 346(tm-define (structured-insert-up) 347 (structured-insert-vertical (focus-tree) #f)) 348(tm-define (structured-insert-down) 349 (structured-insert-vertical (focus-tree) #t)) 350(tm-define (structured-remove-up) 351 (structured-remove-vertical (focus-tree) #f)) 352(tm-define (structured-remove-down) 353 (structured-remove-vertical (focus-tree) #t)) 354(tm-define (structured-insert-start) 355 (structured-insert-extremal (focus-tree) #f)) 356(tm-define (structured-insert-end) 357 (structured-insert-extremal (focus-tree) #t)) 358(tm-define (structured-insert-top) 359 (structured-insert-incremental (focus-tree) #f)) 360(tm-define (structured-insert-bottom) 361 (structured-insert-incremental (focus-tree) #t)) 362 363;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 364;; Structured movements 365;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 366 367(tm-define (structured-horizontal t forwards?) 368 (and-with p (tree-outer t) 369 (structured-horizontal p forwards?))) 370 371(tm-define (structured-horizontal t forwards?) 372 (:require (structured-horizontal? t)) 373 (with-focus-after t 374 (with move (if forwards? path-next-argument path-previous-argument) 375 (with p (move (root-tree) (tree->path (tree-down t))) 376 (if (nnull? p) (go-to p)))))) 377 378(tm-define (structured-vertical t downwards?) 379 (and-with p (tree-outer t) 380 (structured-vertical p downwards?))) 381 382(tm-define (structured-inner-extremal t forwards?) 383 (and-with p (tree-outer t) 384 (structured-inner-extremal p forwards?))) 385 386(tm-define (structured-inner-extremal t forwards?) 387 (:require (structured-horizontal? t)) 388 (with-focus-after t 389 (tree-go-to t :down (if forwards? :end :start)))) 390 391(tm-define (structured-extremal t forwards?) 392 (go-to-repeat (lambda () (structured-horizontal t forwards?))) 393 (structured-inner-extremal t forwards?)) 394 395(tm-define (structured-incremental t downwards?) 396 (go-to-repeat (lambda () (structured-vertical t downwards?))) 397 (structured-inner-extremal t downwards?)) 398 399(tm-define (structured-exit t forwards?) 400 (when (complex-context? t) 401 (tree-go-to t (if forwards? :end :start)))) 402 403(tm-define (structured-left) 404 (structured-horizontal (focus-tree) #f)) 405(tm-define (structured-right) 406 (structured-horizontal (focus-tree) #t)) 407(tm-define (structured-up) 408 (structured-vertical (focus-tree) #f)) 409(tm-define (structured-down) 410 (structured-vertical (focus-tree) #t)) 411(tm-define (structured-start) 412 (structured-extremal (focus-tree) #f)) 413(tm-define (structured-end) 414 (structured-extremal (focus-tree) #t)) 415(tm-define (structured-top) 416 (structured-incremental (focus-tree) #f)) 417(tm-define (structured-bottom) 418 (structured-incremental (focus-tree) #t)) 419(tm-define (structured-exit-left) 420 (structured-exit (focus-tree) #f)) 421(tm-define (structured-exit-right) 422 (structured-exit (focus-tree) #t)) 423 424;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 425;; Multi-purpose alignment 426;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 427 428(tm-define (geometry-speed t down?) 429 (and-with p (tree-outer t) 430 (geometry-speed p down?))) 431 432(tm-define (geometry-variant t forwards?) 433 (and-with p (tree-outer t) 434 (geometry-variant p forwards?))) 435 436(tm-define (geometry-default t) 437 (and-with p (tree-outer t) 438 (geometry-default p))) 439 440(tm-define (geometry-horizontal t forwards?) 441 (and-with p (tree-outer t) 442 (geometry-horizontal p forwards?))) 443 444(tm-define (geometry-vertical t down?) 445 (and-with p (tree-outer t) 446 (geometry-vertical p down?))) 447 448(tm-define (geometry-extremal t forwards?) 449 (and-with p (tree-outer t) 450 (geometry-extremal p forwards?))) 451 452(tm-define (geometry-incremental t down?) 453 (and-with p (tree-outer t) 454 (geometry-incremental p down?))) 455 456(tm-define (geometry-slower) 457 (geometry-speed (focus-tree) #f)) 458(tm-define (geometry-faster) 459 (geometry-speed (focus-tree) #t)) 460(tm-define (geometry-circulate forwards?) 461 (geometry-variant (focus-tree) forwards?)) 462(tm-define (geometry-reset) 463 (geometry-default (focus-tree))) 464(tm-define (geometry-left) 465 (geometry-horizontal (focus-tree) #f)) 466(tm-define (geometry-right) 467 (geometry-horizontal (focus-tree) #t)) 468(tm-define (geometry-up) 469 (geometry-vertical (focus-tree) #f)) 470(tm-define (geometry-down) 471 (geometry-vertical (focus-tree) #t)) 472(tm-define (geometry-start) 473 (geometry-extremal (focus-tree) #f)) 474(tm-define (geometry-end) 475 (geometry-extremal (focus-tree) #t)) 476(tm-define (geometry-top) 477 (geometry-incremental (focus-tree) #f)) 478(tm-define (geometry-bottom) 479 (geometry-incremental (focus-tree) #t)) 480 481;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 482;; Tree editing 483;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 484 485(tm-define (structured-insert-horizontal t forwards?) 486 (:require (tree-is? t 'tree)) 487 (if (== (tree-down-index t) 0) (set! t (tree-up t))) 488 (if (== (tm-car t) 'tree) 489 (with pos (tree-down-index t) 490 (if forwards? (set! pos (1+ pos))) 491 (tree-insert! t pos '("")) 492 (tree-go-to t pos 0)))) 493 494(tm-define (structured-remove-horizontal t forwards?) 495 (:require (tree-is? t 'tree)) 496 (if (== (tree-down-index t) 0) (set! t (tree-up t))) 497 (if (== (tm-car t) 'tree) 498 (with pos (tree-down-index t) 499 (cond (forwards? 500 (tree-remove! t pos 1) 501 (if (== pos (tree-arity t)) 502 (tree-go-to t :end) 503 (tree-go-to t pos :start))) 504 ((== pos 1) (tree-go-to t 0 :end)) 505 (else (tree-remove! t (- pos 1) 1)))))) 506 507(tm-define (structured-insert-vertical t downwards?) 508 (:require (tree-is? t 'tree)) 509 (if downwards? 510 (if (== (tree-down-index t) 0) 511 (with pos (tree-arity t) 512 (tree-insert! t pos '("")) 513 (tree-go-to t pos 0)) 514 (begin 515 (set! t (tree-down t)) 516 (tree-set! t `(tree ,t "")) 517 (tree-go-to t 1 0))) 518 (begin 519 (if (!= (tree-down-index t) 0) (set! t (tree-down t))) 520 (tree-set! t `(tree "" ,t)) 521 (tree-go-to t 0 0)))) 522 523(define (branch-active t) 524 (with i (tree-down-index t) 525 (if (and (= i 0) (tree-is? t :up 'tree)) 526 (tree-up t) 527 t))) 528 529(define (branch-go-to . l) 530 (apply tree-go-to l) 531 (if (tree-is? (cursor-tree) 'tree) 532 (with last (cAr l) 533 (if (nin? last '(:start :end)) (set! last :start)) 534 (tree-go-to (cursor-tree) 0 last)))) 535 536(tm-define (structured-horizontal t* forwards?) 537 (:require (tree-is? t* 'tree)) 538 (let* ((t (branch-active t*)) 539 (i (tree-down-index t))) 540 (cond ((and (not forwards?) (> i 1)) 541 (branch-go-to t (- i 1) :end)) 542 ((and forwards? (!= i 0) (< i (- (tree-arity t) 1))) 543 (branch-go-to t (+ i 1) :start))))) 544 545(tm-define (structured-vertical t* downwards?) 546 (:require (tree-is? t* 'tree)) 547 (let* ((t (branch-active t*)) 548 (i (tree-down-index t))) 549 (cond ((and (not downwards?) (!= i 0)) 550 (tree-go-to t 0 :end)) 551 ((and downwards? (== (tree-down-index t*) 0)) 552 (branch-go-to t* (quotient (tree-arity t*) 2) :start))))) 553 554(tm-define (structured-extremal t* forwards?) 555 (:require (tree-is? t* 'tree)) 556 (let* ((t (branch-active t*)) 557 (i (tree-down-index t))) 558 (cond ((not forwards?) 559 (branch-go-to t 1 :start)) 560 (forwards? 561 (branch-go-to t :last :end))))) 562 563(tm-define (structured-incremental t downwards?) 564 (:require (tree-is? t 'tree)) 565 (go-to-repeat (if downwards? structured-down structured-up))) 566 567;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 568;; Extra editing functions 569;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 570 571(tm-define (kill-paragraph) 572 (selection-set-start) 573 (go-end-paragraph) 574 (selection-set-end) 575 (clipboard-cut "primary")) 576 577(tm-define (yank-paragraph) 578 (selection-set-start) 579 (go-end-paragraph) 580 (selection-set-end) 581 (clipboard-copy "primary")) 582 583(tm-define (select-all) 584 (tree-select (buffer-tree))) 585 586(tm-define (go-to-line n . opt-from) 587 (if (nnull? opt-from) (cursor-history-add (car opt-from))) 588 (with-innermost t 'document 589 (tree-go-to t n 0))) 590 591(tm-define (go-to-column c . opt-from) 592 (if (nnull? opt-from) (cursor-history-add (car opt-from))) 593 (with-innermost t 'document 594 (with p (tree-cursor-path t) 595 (tree-go-to t (cADr p) c)))) 596 597(tm-define (select-word w t col) 598 (:synopsis "Selects word @w in tree @t, more or less around column @col.") 599 (let* ((st (tree->string t)) 600 (pos (- col (string-length w))) 601 (beg (string-contains st w (max 0 pos)))) ; returns index of w in st 602 (if beg 603 (with p (tree->path t) 604 (go-to (rcons p beg)) 605 (selection-set-start) 606 (go-to (rcons p (+ beg (string-length w)))) 607 (selection-set-end))) 608 beg)) 609 610;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 611;; Standard environment parameters for primitives 612;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 613 614(tm-define (standard-parameters l) 615 (:require (== l "action")) 616 (list "locus-color")) 617 618(tm-define (standard-parameters l) 619 (:require (== l "locus")) 620 (list "locus-color" "visited-color")) 621 622(tm-define (standard-parameters l) 623 (:require (== l "ornament")) 624 (list "ornament-shape" "ornament-title-style" "ornament-border" 625 "ornament-hpadding" "ornament-vpadding" 626 "ornament-color" "ornament-extra-color" 627 "ornament-sunny-color" "ornament-shadow-color")) 628 629(tm-define (standard-parameters l) 630 (:require (in? l '("reference" "pageref" "label" "tag"))) 631 (list)) 632 633(tm-define (search-parameters l) 634 (:require (in? (if (string? l) l (symbol->string l)) 635 '("reference" "pageref" "hlink"))) 636 (standard-parameters "locus")) 637 638(tm-define (parameter-choice-list l) 639 (:require (== l "ornament-shape")) 640 (list "classic" "rounded" "angular" "cartoon" 641 ;;"ring" 642 )) 643 644(tm-define (parameter-choice-list l) 645 (:require (== l "ornament-title-style")) 646 (list "classic" 647 "top left" "top center" "top right" 648 "bottom left" "bottom center" "bottom right")) 649 650;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 651;; Inserting various kinds of content 652;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 653 654(tm-define (label-insert t) 655 (and-with p (tree-outer t) 656 (label-insert p))) 657 658(tm-define (label-insert t) 659 (:require (tree-is-buffer? t)) 660 (make 'label)) 661 662(tm-define (make-label) 663 (label-insert (focus-tree))) 664 665(tm-define (make-specific s) 666 (if (or (== s "texmacs") (in-source?)) 667 (insert-go-to `(specific ,s "") '(1 0)) 668 (insert-go-to `(inactive (specific ,s "")) '(0 1 0)))) 669 670(define (url->delta-unix u) 671 (if (url-rooted? u) (set! u (url-delta (current-buffer) u))) 672 (url->unix u)) 673 674(tm-define (make-include u) 675 (insert `(include ,(url->delta-unix u)))) 676 677(tm-define (make-inline-image l) 678 (apply make-image (cons* (url->delta-unix (car l)) #f (cdr l)))) 679 680(tm-define (make-link-image l) 681 (apply make-image (cons* (url->delta-unix (car l)) #t (cdr l)))) 682 683(tm-define (make-graphics-over-selection) 684 (if (selection-active-any?) 685 (with selection (selection-tree) 686 (clipboard-cut "graphics background") 687 (insert-go-to `(draw-over ,selection (graphics)) '(1 1))))) 688 689;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 690;; Thumbnails facility 691;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 692 693(define (thumbnail-suffixes) 694 (list->url 695 (map url-wildcard 696 '("*.gif" "*.jpg" "*.jpeg" "*.JPG" "*.JPEG" "*.png" "*.PNG")))) 697 698(define (fill-row l nr) 699 (cond ((= nr 0) '()) 700 ((nnull? l) (cons (car l) (fill-row (cdr l) (- nr 1)))) 701 (else (cons "" (fill-row l (- nr 1)))))) 702 703(define (make-rows l nr) 704 (if (> (length l) nr) 705 (cons (list-head l nr) (make-rows (list-tail l nr) nr)) 706 (list (fill-row l nr)))) 707 708(define (make-thumbnails-sub l) 709 (define (mapper x) 710 `(image ,(url->delta-unix x) "0.22par" "" "" "")) 711 (let* ((l1 (map mapper l)) 712 (l2 (make-rows l1 4)) 713 (l3 (map (lambda (r) `(row ,@(map (lambda (c) `(cell ,c)) r))) l2))) 714 (insert `(tabular* (tformat (twith "table-width" "1par") 715 (twith "table-hyphen" "yes") 716 (table ,@l3)))))) 717 718(tm-define (make-thumbnails) 719 (:interactive #t) 720 (user-url "Picture directory" "directory" 721 (lambda (dir) 722 (let* ((find (url-append dir (thumbnail-suffixes))) 723 (files (url->list (url-expand (url-complete find "r")))) 724 (base (buffer-master)) 725 (rel-files (map (lambda (x) (url-delta base x)) files))) 726 (if (nnull? rel-files) (make-thumbnails-sub rel-files)))))) 727 728;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 729;; Routines for floats 730;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 731 732(tm-define (make-marginal-note) 733 (:synopsis "Insert a marginal note.") 734 (wrap-selection-small 735 (insert-go-to `(inactive (marginal-note "normal" "c" "")) '(0 2 0)))) 736 737(tm-define (test-marginal-note-hpos? hp) 738 (and-with t (tree-innermost 'marginal-note #t) 739 (tm-equal? (tree-ref t 0) hp))) 740(tm-define (set-marginal-note-hpos hp) 741 (:synopsis "Set the horizontal position of the marginal note to @hp.") 742 (:check-mark "v" test-marginal-note-hpos?) 743 (and-with t (tree-innermost 'marginal-note #t) 744 (tree-set t 0 hp))) 745 746(tm-define (test-marginal-note-valign? va) 747 (and-with t (tree-innermost 'marginal-note #t) 748 (tm-equal? (tree-ref t 1) va))) 749(tm-define (set-marginal-note-valign va) 750 (:synopsis "Set the vertical alignment of the marginal note to @va.") 751 (:check-mark "v" test-marginal-note-valign?) 752 (and-with t (tree-innermost 'marginal-note #t) 753 (tree-set t 1 va))) 754 755(tm-define (make-insertion s) 756 (:synopsis "Make an insertion of type @s.") 757 (with pos (if (== s "float") "tbh" "") 758 (insert-go-to (list 'float s pos (list 'document "")) 759 (list 2 0 0)))) 760 761(tm-define (insertion-positioning what flag) 762 (:synopsis "Allow/disallow the position @what for innermost float.") 763 (with-innermost t 'float 764 (let ((op (if flag string-union string-minus)) 765 (st (tree-ref t 1))) 766 (tree-set! st (op (tree->string st) what))))) 767 768(define (test-insertion-positioning? what) 769 (with-innermost t 'float 770 (with c (string-ref what 0) 771 (char-in-string? c (tree->string (tree-ref t 1)))))) 772 773(define (not-test-insertion-positioning? s) 774 (not (test-insertion-positioning? s))) 775 776(tm-define (toggle-insertion-positioning what) 777 (:check-mark "v" test-insertion-positioning?) 778 (insertion-positioning what (not-test-insertion-positioning? what))) 779 780(tm-define (toggle-insertion-positioning-not s) 781 (:check-mark "v" not-test-insertion-positioning?) 782 (toggle-insertion-positioning s)) 783 784;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 785;; Balloons 786;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 787 788(tm-define (balloon-context? t) 789 (tree-in? t (balloon-tag-list))) 790 791(define (integer-floor x) 792 (inexact->exact (floor x))) 793 794(tm-define (display-balloon body balloon halign valign extents) 795 (:secure #t) 796 (with (x1 y1 x2 y2) (tree-bounding-rectangle body) 797 (let* ((zf (get-window-zoom-factor)) 798 (sf (/ 5.0 zf)) 799 (balloon* `(with "magnification" ,(number->string zf) ,balloon)) 800 (w (widget-texmacs-output balloon* '(style "generic"))) 801 (ww (integer-floor (/ (tree->number (tree-ref extents 0)) sf))) 802 (wh (integer-floor (/ (tree->number (tree-ref extents 1)) sf))) 803 (ha (tree->stree halign)) 804 (va (tree->stree valign)) 805 (x (cond ((== ha "Left") (- (- x1 ww) (* 3 256))) 806 ((== ha "left") x1) 807 ((== ha "center") (quotient (+ x1 x2 (- ww)) 2)) 808 ((== ha "right") (- (- x2 ww) (* 3 256))) 809 ((== ha "Right") x2) 810 (else x1))) 811 (y (cond ((== va "Bottom") (- y1 (* 5 256))) 812 ((== va "bottom") (+ y1 wh)) 813 ((== va "center") (quotient (+ y1 y2 wh) 2)) 814 ((== va "top") y2) 815 ((== va "Top") (+ y2 wh (* 5 256))) 816 (else (- y1 (* 5 256)))))) 817 ;;(display* "size= " (widget-size w) "\n") 818 (show-balloon w x y)))) 819 820(tm-define (display-balloon* body balloon halign valign extents) 821 (:secure #t) 822 (with (mx my) (get-mouse-position) 823 (let* ((zf (get-window-zoom-factor)) 824 (sf (/ 5.0 zf)) 825 (balloon* `(with "magnification" ,(number->string zf) ,balloon)) 826 (w (widget-texmacs-output balloon* '(style "generic"))) 827 (ww (integer-floor (/ (tree->number (tree-ref extents 0)) sf))) 828 (wh (integer-floor (/ (tree->number (tree-ref extents 1)) sf))) 829 (ha (tree->stree halign)) 830 (va (tree->stree valign)) 831 (x (cond ((in? ha (list "Left" "left")) (- (- mx ww) (* 3 256))) 832 ((== ha "center") (+ (- mx (quotient ww 2)) (* 5 256))) 833 ((in? ha (list "right" "Right")) (+ mx (* 10 256))) 834 (else (+ mx (* 3 256))))) 835 (y (cond ((in? va (list "Bottom" "bottom")) (- my (* 16 256))) 836 ((== va "center") (- (+ my (quotient wh 2)) (* 8 256))) 837 ((in? va (list "top" "Top")) (+ my wh (* 5 256))) 838 (else (- my (* 5 256)))))) 839 (show-balloon w x y)))) 840 841(tm-define (make-balloon) 842 (:synopsis "Insert a balloon.") 843 (wrap-selection-small 844 (insert-go-to `(inactive (mouse-over-balloon "" "" "left" "Bottom")) 845 '(0 0 0)))) 846 847(tm-define (test-balloon-halign? ha) 848 (and-with t (tree-innermost balloon-context? #t) 849 (tm-equal? (tree-ref t 2) ha))) 850(tm-define (set-balloon-halign ha) 851 (:synopsis "Set the horizontal alignment of the marginal note to @ha.") 852 (:check-mark "v" test-balloon-halign?) 853 (and-with t (tree-innermost balloon-context? #t) 854 (tree-set t 2 ha))) 855 856(tm-define (test-balloon-valign? va) 857 (and-with t (tree-innermost balloon-context? #t) 858 (tm-equal? (tree-ref t 3) va))) 859(tm-define (set-balloon-valign va) 860 (:synopsis "Set the vertical alignment of the marginal note to @va.") 861 (:check-mark "v" test-balloon-valign?) 862 (and-with t (tree-innermost balloon-context? #t) 863 (tree-set t 3 va))) 864 865;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 866;; Sound and video 867;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 868 869(tm-define (make-sound u) 870 (if (not (url-none? u)) 871 (insert `(sound ,(url->delta-unix u))))) 872 873(tm-define (make-animation u) 874 (interactive 875 (lambda (w h len rep) 876 (if (== rep "no") (set! rep "false")) 877 (insert `(video ,(url->delta-unix u) ,w ,h ,len ,rep))) 878 "Width" "Height" "Length" "Repeat?")) 879 880;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 881;; Search, replace, spell and tab-completion 882;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 883 884(tm-define (key-press-command key) 885 ;; FIXME: this routine should do exactly the same as key-press, 886 ;; without modification of the internal state and without executing 887 ;; the actual shortcut. It should rather return a command which 888 ;; does all this, or #f 889 (and-with p (kbd-find-key-binding key) 890 (car p))) 891 892(tm-define (keyboard-press key time) 893 (:mode search-mode?) 894 (with cmd (key-press-command (string-append "search " key)) 895 (cond (cmd (cmd)) 896 ((key-press-search key) (noop)) 897 (else (key-press key))))) 898 899(tm-define (search-next) 900 (key-press-search "next")) 901 902(tm-define (search-previous) 903 (key-press-search "previous")) 904 905(tm-define (keyboard-press key time) 906 (:mode replace-mode?) 907 (with cmd (key-press-command (string-append "replace " key)) 908 (cond (cmd (cmd)) 909 ((key-press-replace key) (noop)) 910 (else (key-press key))))) 911 912(tm-define (keyboard-press key time) 913 (:mode spell-mode?) 914 (with cmd (key-press-command (string-append "spell " key)) 915 (cond (cmd (cmd)) 916 ((key-press-spell key) (noop)) 917 (else (key-press key))))) 918 919(tm-define (keyboard-press key time) 920 (:mode complete-mode?) 921 (with cmd (key-press-command (string-append "complete " key)) 922 (cond (cmd (cmd)) 923 ((key-press-complete key) (noop)) 924 (else (key-press key))))) 925 926(tm-define (keyboard-press key time) 927 (:mode remote-control-mode?) 928 ;;(display* "Press " key "\n") 929 (if (ahash-ref remote-control-remap key) 930 (begin 931 ;;(display* "Remap " (ahash-ref remote-control-remap key) "\n") 932 (key-press (ahash-ref remote-control-remap key))) 933 (key-press key))) 934 935(tm-define (focus-open-search-tool t) 936 (:interactive #t) 937 (noop)) 938