Mercurial > hg > xemacs-beta
comparison lisp/utils/edmacro.el @ 187:b405438285a2 r20-3b20
Import from CVS: tag r20-3b20
author | cvs |
---|---|
date | Mon, 13 Aug 2007 09:56:28 +0200 |
parents | 8eaf7971accc |
children |
comparison
equal
deleted
inserted
replaced
186:24ac94803b48 | 187:b405438285a2 |
---|---|
1 ;;; edmacro.el --- keyboard macro editor | 1 ;;; edmacro.el --- keyboard macro editor |
2 | 2 |
3 ;; Copyright (C) 1993, 1994 Free Software Foundation, Inc. | 3 ;; Copyright (C) 1993, 1994, 1997 Free Software Foundation, Inc. |
4 | 4 |
5 ;; Author: Dave Gillespie <daveg@synaptics.com> | 5 ;; Author: Dave Gillespie <daveg@synaptics.com> |
6 ;; Hrvoje Niksic <hniksic@srce.hr> -- XEmacs port | 6 ;; Hrvoje Niksic <hniksic@srce.hr> -- XEmacs rewrite |
7 ;; Maintainer: Hrvoje Niksic <hniksic@srce.hr> | 7 ;; Maintainer: Hrvoje Niksic <hniksic@srce.hr> |
8 ;; Version: 3.17 | 8 ;; Version: 3.19 |
9 ;; Keywords: abbrev | 9 ;; Keywords: abbrev, internal |
10 | 10 |
11 ;; This file is part of XEmacs. | 11 ;; This file is part of XEmacs. |
12 | 12 |
13 ;; XEmacs is free software; you can redistribute it and/or modify | 13 ;; XEmacs is free software; you can redistribute it and/or modify |
14 ;; it under the terms of the GNU General Public License as published by | 14 ;; it under the terms of the GNU General Public License as published by |
24 ;; along with XEmacs; see the file COPYING. If not, write to the Free | 24 ;; along with XEmacs; see the file COPYING. If not, write to the Free |
25 ;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | 25 ;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA |
26 ;; 02111-1307, USA. | 26 ;; 02111-1307, USA. |
27 | 27 |
28 ;;; Synched up with: FSF 19.34. | 28 ;;; Synched up with: FSF 19.34. |
29 ;;; The important parts of this file have been rewritten for XEmacs, | 29 ;;; Most of this file has been rewritten for XEmacs, so the |
30 ;;; so it's completely different from the FSF version. The original | 30 ;;; implementations are out of synch. The original version depended |
31 ;;; could not be used because it worked with the Emacs key | 31 ;;; too closely on GNU Emacs key representation and the equivalence of |
32 ;;; representation, and it mixed characters and integers too freely. | 32 ;;; characters and integers to be usable. |
33 | 33 |
34 ;;; Commentary: | 34 ;;; Commentary: |
35 | 35 |
36 ;;; Usage: | 36 ;;; Usage: |
37 ;; | 37 ;; |
80 ;; characters, the command-name comments will be wrong but that | 80 ;; characters, the command-name comments will be wrong but that |
81 ;; won't hurt anything. | 81 ;; won't hurt anything. |
82 | 82 |
83 ;; With a prefix argument, `edit-kbd-macro' will format the | 83 ;; With a prefix argument, `edit-kbd-macro' will format the |
84 ;; macro in a more concise way that omits the comments. | 84 ;; macro in a more concise way that omits the comments. |
85 | |
86 ;; This package requires GNU Emacs 19 or later, and daveg's CL | |
87 ;; package 2.02 or later. (CL 2.02 comes standard starting with | |
88 ;; Emacs 19.18.) This package does not work with Emacs 18 or | |
89 ;; Lucid Emacs. | |
90 | |
91 ;; Ported to XEmacs. This code will not run on GNU Emacs 19. -hniksic | |
92 | 85 |
93 ;;; Code: | 86 ;;; Code: |
94 | 87 |
95 (eval-when-compile | 88 (eval-when-compile |
96 (require 'cl)) | 89 (require 'cl)) |
190 (insert ";; Original keys: " fmt "\n") | 183 (insert ";; Original keys: " fmt "\n") |
191 (unless store-hook | 184 (unless store-hook |
192 (insert "\nCommand: " (if cmd (symbol-name cmd) "none") "\n") | 185 (insert "\nCommand: " (if cmd (symbol-name cmd) "none") "\n") |
193 (let ((keys (where-is-internal (or cmd mac)))) | 186 (let ((keys (where-is-internal (or cmd mac)))) |
194 (if keys | 187 (if keys |
195 (insert "Key: " (edmacro-format-keys (car keys)) "\n") | 188 (dolist (key keys) |
189 (insert "Key: " (edmacro-format-keys key) "\n")) | |
196 (insert "Key: none\n")))) | 190 (insert "Key: none\n")))) |
197 (insert "\nMacro:\n\n") | 191 (insert "\nMacro:\n\n") |
198 (save-excursion | 192 (save-excursion |
199 (insert fmtv "\n")) | 193 (insert fmtv "\n")) |
200 (recenter '(4)) | 194 (recenter '(4)) |
218 ;;;###autoload | 212 ;;;###autoload |
219 (defun read-kbd-macro (start &optional end) | 213 (defun read-kbd-macro (start &optional end) |
220 "Read the region as a keyboard macro definition. | 214 "Read the region as a keyboard macro definition. |
221 The region is interpreted as spelled-out keystrokes, e.g., \"M-x abc RET\". | 215 The region is interpreted as spelled-out keystrokes, e.g., \"M-x abc RET\". |
222 See documentation for `edmacro-mode' for details. | 216 See documentation for `edmacro-mode' for details. |
223 Leading/trailing \"C-x (\" and \"C-x )\" in the text are allowed and ignored. | |
224 The resulting macro is installed as the \"current\" keyboard macro. | 217 The resulting macro is installed as the \"current\" keyboard macro. |
225 | 218 |
226 In Lisp, may also be called with a single STRING argument in which case | 219 In Lisp, may also be called with a single STRING argument in which case |
227 the result is returned rather than being installed as the current macro. | 220 the result is returned rather than being installed as the current macro. |
228 The result will be a string if possible, otherwise an event vector. | 221 The result will be a vector of keystrokes." |
229 Second argument NEED-VECTOR means to return an event vector always." | |
230 (interactive "r") | 222 (interactive "r") |
231 (if (stringp start) | 223 (if (stringp start) |
232 (edmacro-parse-keys start) | 224 (edmacro-parse-keys start) |
233 (setq last-kbd-macro (edmacro-parse-keys (buffer-substring start end))))) | 225 (setq last-kbd-macro (edmacro-parse-keys (buffer-substring start end))))) |
234 | 226 |
240 ;;;###autoload | 232 ;;;###autoload |
241 (defun format-kbd-macro (&optional macro verbose) | 233 (defun format-kbd-macro (&optional macro verbose) |
242 "Return the keyboard macro MACRO as a human-readable string. | 234 "Return the keyboard macro MACRO as a human-readable string. |
243 This string is suitable for passing to `read-kbd-macro'. | 235 This string is suitable for passing to `read-kbd-macro'. |
244 Second argument VERBOSE means to put one command per line with comments. | 236 Second argument VERBOSE means to put one command per line with comments. |
245 If VERBOSE is `1', put everything on one line. If VERBOSE is omitted | 237 If VERBOSE is nil, put everything on one line." |
246 or nil, use a compact 80-column format." | |
247 (and macro (symbolp macro) (setq macro (symbol-function macro))) | 238 (and macro (symbolp macro) (setq macro (symbol-function macro))) |
248 (edmacro-format-keys (or macro last-kbd-macro) verbose)) | 239 (edmacro-format-keys (or macro last-kbd-macro) verbose)) |
249 | 240 |
250 | 241 |
251 ;;; Commands for *Edit Macro* buffer. | 242 ;;; Commands for *Edit Macro* buffer. |
458 ("H" . hyper) | 449 ("H" . hyper) |
459 ("s" . super))) | 450 ("s" . super))) |
460 | 451 |
461 ;;; Parsing a human-readable keyboard macro. | 452 ;;; Parsing a human-readable keyboard macro. |
462 | 453 |
463 ;; Changes for XEmacs -- these two functions re-written from scratch. | 454 ;; In XEmacs version of edmacro, edmacro-parse-keys always returns a |
464 ;; edmacro-parse-keys always returns a vector. edmacro-format-keys | 455 ;; vector. edmacro-format-keys accepts a vector (but works with a |
465 ;; accepts a vector (but works with a string too). Vector may contain | 456 ;; string too). |
466 ;; keypress events. -hniksic | |
467 (defun edmacro-parse-keys (string) | 457 (defun edmacro-parse-keys (string) |
468 (let* ((pos 0) | 458 (let* ((pos 0) |
469 (case-fold-search nil) | 459 (case-fold-search nil) |
470 res) | 460 res) |
471 (while (and (< pos (length string)) | 461 (while (and (< pos (length string)) |
476 ;; Comment (discard to EOL) . | 466 ;; Comment (discard to EOL) . |
477 (setq pos (string-match "$" string pos)) | 467 (setq pos (string-match "$" string pos)) |
478 (push (edmacro-parse-word word) res)))) | 468 (push (edmacro-parse-word word) res)))) |
479 (mapvector 'identity (apply 'nconc (nreverse res))))) | 469 (mapvector 'identity (apply 'nconc (nreverse res))))) |
480 | 470 |
481 ;; Parse a word. | 471 ;; Parse a "word". |
482 (defun edmacro-parse-word (word) | 472 (defun edmacro-parse-word (word) |
483 (let ((force-sym nil) | 473 (let ((force-sym nil) |
484 (times 1) | 474 (times 1) |
485 abbr) | 475 abbr) |
486 (when (string-match "\\([0-9]+\\)\\*." word) | 476 (when (string-match "\\([0-9]+\\)\\*." word) |
533 ((setq abbr (assoc word word-to-sym)) | 523 ((setq abbr (assoc word word-to-sym)) |
534 ;; Convert to symbol. | 524 ;; Convert to symbol. |
535 (list (cdr abbr))) | 525 (list (cdr abbr))) |
536 ((string-match "^\\^" word) | 526 ((string-match "^\\^" word) |
537 ;; ^X == C-x | 527 ;; ^X == C-x |
538 (if (/= (length word) 2) | 528 (if (= (length word) 2) |
539 (error "^ must be followed by one character")) | 529 `((control ,(aref word 1))) |
540 `((control ,(aref word 1)))) | 530 (mapcar 'identity word))) |
541 ((string-match "^M--?[0-9]+$" word) | 531 ((string-match "^M--?[0-9]+$" word) |
542 ;; Special case: M- followed by an optional hyphen and | 532 ;; Special case: M- followed by an optional hyphen and |
543 ;; one or more digits | 533 ;; one or more digits |
544 (mapcar (lambda (digit) | 534 (mapcar (lambda (digit) |
545 (list 'meta digit)) | 535 (list 'meta digit)) |
546 (substring word 2))) | 536 (substring word 2))) |
547 ((string-match "^\\([MCSsAH]\\|Sh\\)-" word) | 537 ((string-match "^\\([MCSsAH]\\|Sh\\)-" word) |
548 ;; Parse C-* and stuff | 538 ;; Parse C-* and stuff |
549 (list | 539 (let ((pos1 0) |
550 (let ((pos1 0) | 540 (r1 nil) |
551 (r1 nil) | 541 follow curpart prefix) |
552 follow curpart prefix) | 542 (while (progn (setq curpart (substring word pos1)) |
553 (while (progn (setq curpart (substring word pos1)) | 543 (string-match "^\\([MCSsAH]\\|Sh\\)-" |
554 (string-match "^\\([MCSsAH]\\|Sh\\)-" | 544 curpart)) |
555 curpart)) | 545 (setq prefix (assoc (match-string 1 curpart) |
556 (setq prefix (assoc (match-string 1 curpart) | 546 edmacro-modifiers)) |
557 edmacro-modifiers)) | 547 (push (cdr prefix) r1) |
558 (push (cdr prefix) r1) | 548 (incf pos1 (1+ (length (car prefix))))) |
559 (incf pos1 (1+ (length (car prefix))))) | 549 (setq follow (substring word pos1)) |
560 (setq follow (substring word pos1)) | 550 (if (equal follow "") |
561 (if (equal follow "") | 551 ;; we've got something like "C-M-" -- just let it be, |
562 (error "%s must precede a string" | 552 ;; because of the way `edmacro-format-keys' works. |
563 (substring word 0 pos1))) | 553 (mapcar 'identity word) |
564 (nconc (nreverse r1) (list (funcall conv follow)))))) | 554 (list (nconc (nreverse r1) (list (funcall conv follow))))))) |
565 (force-sym | 555 (force-sym |
566 ;; This must be a symbol | 556 ;; This must be a symbol |
567 (list (intern word))) | 557 (list (intern word))) |
568 (t | 558 (t |
569 ;; Characters | 559 ;; Characters |
572 (loop repeat times do (setq new (append add new))) | 562 (loop repeat times do (setq new (append add new))) |
573 new))) | 563 new))) |
574 | 564 |
575 ;; Convert the keypress events in vector x to keys, and return a | 565 ;; Convert the keypress events in vector x to keys, and return a |
576 ;; vector of keys. If a list element is not a keypress event, ignore | 566 ;; vector of keys. If a list element is not a keypress event, ignore |
577 ;; it. | 567 ;; it. `events-to-keys' won't quite cut it here, as it is buggy. |
578 (defun edmacro-events-to-keys (x &optional list) | 568 (defun edmacro-events-to-keys (x &optional list) |
579 (let (new) | 569 (let (new) |
580 (mapc (lambda (el) | 570 (mapc (lambda (el) |
581 (cond ((key-press-event-p el) | 571 (cond ((key-press-event-p el) |
582 (push (let ((mods (event-modifiers el))) | 572 (push (let ((mods (event-modifiers el))) |
592 (setq new (nreverse new)) | 582 (setq new (nreverse new)) |
593 (if list | 583 (if list |
594 new | 584 new |
595 (mapvector 'identity new)))) | 585 (mapvector 'identity new)))) |
596 | 586 |
597 ;; Collapse a list of keys into a list of function keys, where | 587 ;; Collapse a list of keys into a list of function keys, if any. |
598 ;; applicable. | |
599 (defun edmacro-fkeys (keys) | 588 (defun edmacro-fkeys (keys) |
600 (let (new k lookup) | 589 (let (new k lookup) |
601 (while keys | 590 (while keys |
602 (setq k (nconc k (list (car keys)))) | 591 (setq k (nconc k (list (car keys)))) |
603 (setq lookup (lookup-key function-key-map (mapvector 'identity k))) | 592 (setq lookup (lookup-key function-key-map (mapvector 'identity k))) |
614 (pop keys)) | 603 (pop keys)) |
615 (when (keymapp lookup) | 604 (when (keymapp lookup) |
616 (push k new)) | 605 (push k new)) |
617 (apply 'nconc (nreverse new)))) | 606 (apply 'nconc (nreverse new)))) |
618 | 607 |
619 ;; Convert a character or symbol to string | 608 ;; Convert a character or symbol to string. |
620 (defun edmacro-conv (char-or-sym add-<>) | 609 (defun edmacro-conv (char-or-sym add-<>) |
621 (let ((char-to-word '((?\0 . "NUL") | 610 (let ((char-to-word '((?\0 . "NUL") |
622 (?\r . "RET") | 611 (?\r . "RET") |
623 (?\n . "LFD") | 612 (?\n . "LFD") |
624 (?\t . "TAB") | 613 (?\t . "TAB") |
657 (defun edmacro-format-1 (keys command times togetherp) | 646 (defun edmacro-format-1 (keys command times togetherp) |
658 (let ((res "") | 647 (let ((res "") |
659 (start keys) | 648 (start keys) |
660 el) | 649 el) |
661 (while keys | 650 (while keys |
662 (when (or (eq (car keys) ?-) | 651 (when (not (or togetherp (eq start keys))) |
663 (eq (car keys) '-) | |
664 (eq (car keys) ?>) | |
665 (not (or togetherp (eq start keys)))) | |
666 (callf concat res " ")) | 652 (callf concat res " ")) |
667 (if (> times 1) | 653 (if (> times 1) |
668 (setq res (concat (format "%d*" times) res))) | 654 (setq res (concat (format "%d*" times) res))) |
669 (setq el (car keys)) | 655 (setq el (car keys)) |
670 (callf concat res | 656 (callf concat res |
685 (> times 1)) | 671 (> times 1)) |
686 (concat "<" my ">") | 672 (concat "<" my ">") |
687 my))) | 673 my))) |
688 (t | 674 (t |
689 (cdr (edmacro-conv el t))))) | 675 (cdr (edmacro-conv el t))))) |
676 (and (cdr keys) | |
677 (memq (car keys) '(?- '- ?> ?^)) | |
678 (callf concat res " ")) | |
690 (pop keys)) | 679 (pop keys)) |
691 (if command | 680 (if command |
692 (callf concat res | 681 (callf concat res |
693 (make-string (max (- 3 (/ (length res) tab-width)) 1) ?\t) | 682 (make-string (max (- 3 (/ (length res) tab-width)) 1) ?\t) |
694 ";; " | 683 ";; " |
704 (not seq1)) | 693 (not seq1)) |
705 | 694 |
706 ;;; Formatting a keyboard macro as human-readable text. | 695 ;;; Formatting a keyboard macro as human-readable text. |
707 | 696 |
708 (defun edmacro-format-keys (macro &optional verbose) | 697 (defun edmacro-format-keys (macro &optional verbose) |
709 ;; XEmacs: | |
710 ;; If we're dealing with events, convert them to symbols first; | 698 ;; If we're dealing with events, convert them to symbols first; |
711 ;; also, deal with Fkeys. | 699 ;; Then, collapse them into function keys, if possible. |
712 (setq macro (edmacro-fkeys (edmacro-events-to-keys macro t))) | 700 (setq macro (edmacro-fkeys (edmacro-events-to-keys macro t))) |
713 (let ((res "")) | 701 (let ((res "")) |
714 (while macro | 702 (while macro |
715 (let (key lookup (times 1) self-insert-p) | 703 (let (key lookup (times 1) self-insert-p) |
716 (loop | 704 (loop |