Mercurial > hg > xemacs-beta
diff lisp/utils/edmacro.el @ 151:59463afc5666 r20-3b2
Import from CVS: tag r20-3b2
author | cvs |
---|---|
date | Mon, 13 Aug 2007 09:37:19 +0200 |
parents | b980b6286996 |
children | 43dd3413c7c7 |
line wrap: on
line diff
--- a/lisp/utils/edmacro.el Mon Aug 13 09:36:20 2007 +0200 +++ b/lisp/utils/edmacro.el Mon Aug 13 09:37:19 2007 +0200 @@ -5,7 +5,7 @@ ;; Author: Dave Gillespie <daveg@synaptics.com> ;; Hrvoje Niksic <hniksic@srce.hr> -- XEmacs port ;; Maintainer: Hrvoje Niksic <hniksic@srce.hr> -;; Version: 3.10 +;; Version: 3.14 ;; Keywords: abbrev ;; This file is part of XEmacs. @@ -88,39 +88,42 @@ ;; Emacs 19.18.) This package does not work with Emacs 18 or ;; Lucid Emacs. -;; Ported to XEmacs. -hniksic +;; Ported to XEmacs. This code will not run on GNU Emacs 19. -hniksic ;;; Code: (eval-when-compile (require 'cl)) +(defgroup edmacro nil + "Keyboard macro editor." + :group 'keyboard) + +(defcustom edmacro-eight-bits nil + "*Non-nil if edit-kbd-macro should leave 8-bit characters intact. +Default nil means to write characters above \\177 in octal notation." + :type 'boolean + :group 'edmacro) + +(defcustom edmacro-format-hook nil + "*Hook run after formatting the keyboard macro." + :type 'hook + :group 'edmacro) + +(defvar edmacro-finish-hook nil) +(defvar edmacro-store-hook nil) +(defvar edmacro-original-buffer nil) + ;;; The user-level commands for editing macros. ;;;###autoload (define-key ctl-x-map "\C-k" 'edit-kbd-macro) -;;;###autoload -(defvar edmacro-eight-bits nil - "*Non-nil if edit-kbd-macro should leave 8-bit characters intact. -Default nil means to write characters above \\177 in octal notation.") - -(if (fboundp 'mapvector) - (defalias 'edmacro-mapvector 'mapvector) - (defun edmacro-mapvector (fun seq) - (map 'vector fun seq))) - (defvar edmacro-mode-map nil) (unless edmacro-mode-map (setq edmacro-mode-map (make-sparse-keymap)) (define-key edmacro-mode-map "\C-c\C-c" 'edmacro-finish-edit) (define-key edmacro-mode-map "\C-c\C-q" 'edmacro-insert-key)) -(defvar edmacro-store-hook) -(defvar edmacro-finish-hook) -(defvar edmacro-original-buffer) - -;; A lot of cruft here, but I got it to work eventually. Could use -;; some cleaning up. ;;;###autoload (defun edit-kbd-macro (keys &optional prefix finish-hook store-hook) "Edit a keyboard macro. @@ -130,74 +133,72 @@ its command name. With a prefix argument, format the macro in a more concise way." (interactive "kKeyboard macro to edit (C-x e, M-x, C-h l, or keys): \nP") - (when keys - (setq keys (edmacro-events-to-keys keys)) - (let ((cmd (if (arrayp keys) (key-binding keys) keys)) - (mac nil)) - (cond (store-hook - (setq mac keys) - (setq cmd nil)) - ((or (eq cmd 'call-last-kbd-macro) - (and (arrayp keys) - (= 1 (length keys)) - (eq ?\r (aref keys 0)))) - (or last-kbd-macro - (y-or-n-p "No keyboard macro defined. Create one? ") - (keyboard-quit)) - (setq mac (or last-kbd-macro "")) - (setq cmd 'last-kbd-macro)) - ((eq cmd 'execute-extended-command) - (setq cmd (read-command "Name of keyboard macro to edit: ")) - (if (string-equal cmd "") - (error "No command name given")) - (setq mac (symbol-function cmd))) - ((eq cmd 'view-lossage) - (setq mac (recent-keys)) - (setq cmd 'last-kbd-macro)) - ((null cmd) - (error "Key sequence %s is not defined" (key-description keys))) - ((symbolp cmd) - (setq mac (symbol-function cmd))) - (t - (setq mac cmd) - (setq cmd nil))) - (unless (arrayp mac) - (error "Key sequence %s is not a keyboard macro" - (key-description keys))) - (message "Formatting keyboard macro...") - (let* ((oldbuf (current-buffer)) - (mmac (edmacro-fix-menu-commands mac)) - (fmt (edmacro-format-keys mmac 1)) - (fmtv (edmacro-format-keys mmac (not prefix))) - (buf (get-buffer-create "*Edit Macro*"))) - (message "Formatting keyboard macro...done") - (switch-to-buffer buf) - (kill-all-local-variables) - (use-local-map edmacro-mode-map) - (setq buffer-read-only nil) - (setq major-mode 'edmacro-mode) - (setq mode-name "Edit Macro") - (set (make-local-variable 'edmacro-original-buffer) oldbuf) - (set (make-local-variable 'edmacro-finish-hook) finish-hook) - (set (make-local-variable 'edmacro-store-hook) store-hook) - (erase-buffer) - (insert ";; Keyboard Macro Editor. Press C-c C-c to finish; " - "press C-x k RET to cancel.\n") - (insert ";; Original keys: " fmt "\n") - (unless store-hook - (insert "\nCommand: " (if cmd (symbol-name cmd) "none") "\n") - (let ((keys (where-is-internal (or cmd mac)))) - (if keys - (while keys - (insert "Key: " (edmacro-format-keys (pop keys) 1) "\n")) - (insert "Key: none\n")))) - (insert "\nMacro:\n\n") - (save-excursion - (insert fmtv "\n")) - (recenter '(4)) - (when (eq mac mmac) - (set-buffer-modified-p nil)) - (run-hooks 'edmacro-format-hook))))) + (when (vectorp keys) + (setq keys (edmacro-events-to-keys keys))) + (let ((cmd (if (symbolp keys) keys (key-binding keys))) + (mac nil)) + (cond (store-hook + (setq mac keys) + (setq cmd nil)) + ((or (eq cmd 'call-last-kbd-macro) + (and (arrayp keys) + (= 1 (length keys)) + (or (eq 'return (aref keys 0)) + (eq ?\r (aref keys 0)) + (equal '(control ?m) (aref keys 0))))) + (or last-kbd-macro + (y-or-n-p "No keyboard macro defined. Create one? ") + (keyboard-quit)) + (setq mac (or last-kbd-macro [])) + (setq cmd 'last-kbd-macro)) + ((eq cmd 'execute-extended-command) + (setq cmd (edmacro-minibuf-read "Name of keyboard macro to edit: ")) + (if (string-equal cmd "") + (error "No command name given")) + (setq mac (symbol-function cmd))) + ((eq cmd 'view-lossage) + (setq mac (recent-keys)) + (setq cmd 'last-kbd-macro)) + ((null cmd) + (error "Key sequence `%s' is not defined" (key-description keys))) + ((symbolp cmd) + (setq mac (symbol-function cmd))) + (t + (setq mac cmd) + (setq cmd nil))) + (unless (arrayp mac) + (error "Key sequence `%s' is not a keyboard macro" + (key-description keys))) + (message "Formatting keyboard macro...") + (let ((oldbuf (current-buffer)) + (fmt (edmacro-format-keys mac)) + (fmtv (edmacro-format-keys mac (not prefix))) + (buf (get-buffer-create "*Edit Macro*"))) + (message "Formatting keyboard macro...done") + (switch-to-buffer buf) + (kill-all-local-variables) + (use-local-map edmacro-mode-map) + (setq buffer-read-only nil) + (setq major-mode 'edmacro-mode) + (setq mode-name "Edit Macro") + (set (make-local-variable 'edmacro-original-buffer) oldbuf) + (set (make-local-variable 'edmacro-finish-hook) finish-hook) + (set (make-local-variable 'edmacro-store-hook) store-hook) + (erase-buffer) + (insert ";; Keyboard Macro Editor. Press C-c C-c to finish; " + "press C-x k RET to cancel.\n") + (insert ";; Original keys: " fmt "\n") + (unless store-hook + (insert "\nCommand: " (if cmd (symbol-name cmd) "none") "\n") + (let ((keys (where-is-internal (or cmd mac)))) + (if keys + (insert "Key: " (edmacro-format-keys (car keys)) "\n") + (insert "Key: none\n")))) + (insert "\nMacro:\n\n") + (save-excursion + (insert fmtv "\n")) + (recenter '(4)) + (run-hooks 'edmacro-format-hook)))) ;;; The next two commands are provided for convenience and backward ;;; compatibility. @@ -228,7 +229,7 @@ Second argument NEED-VECTOR means to return an event vector always." (interactive "r") (if (stringp start) - (edmacro-parse-keys start end) + (edmacro-parse-keys start) (setq last-kbd-macro (edmacro-parse-keys (buffer-substring start end))))) ;;;###autoload @@ -245,6 +246,7 @@ or nil, use a compact 80-column format." (and macro (symbolp macro) (setq macro (symbol-function macro))) (edmacro-format-keys (or macro last-kbd-macro) verbose)) + ;;; Commands for *Edit Macro* buffer. @@ -289,9 +291,10 @@ (or (not (fboundp b)) (not (arrayp (symbol-function b)))) (not (y-or-n-p - (format "Key %s is already defined; %s" - (edmacro-format-keys key 1) - "proceed? "))) + (format + "Key `%s' is already defined; %s" + (edmacro-format-keys key) + "proceed? "))) (keyboard-quit)))))) t) ((looking-at "Macro:[ \t\n]*") @@ -305,8 +308,7 @@ (str (buffer-substring top (point-max))) (modp (buffer-modified-p)) (obuf edmacro-original-buffer) - (store-hook edmacro-store-hook) - (finish-hook edmacro-finish-hook)) + (store-hook edmacro-store-hook)) (unless (or cmd keys store-hook (equal str "")) (error "No command name or keys specified")) (when modp @@ -335,9 +337,7 @@ (global-set-key key (or cmd mac))))))))) (kill-buffer buf) (when (buffer-name obuf) - (switch-to-buffer obuf)) - (when finish-hook - (funcall finish-hook))))) + (switch-to-buffer obuf))))) (defun edmacro-insert-key (key) "Insert the written name of a key in the buffer." @@ -421,140 +421,196 @@ (interactive) (error "This mode can be enabled only by `edit-kbd-macro'")) (put 'edmacro-mode 'mode-class 'special) + - (defun edmacro-int-char (int) - (if (fboundp 'char-to-int) - (char-to-int int) + (if (fboundp 'int-char) + (int-char int) int)) +(defvar edmacro-read-history nil) + +;; Completing read on named keyboard macros only. +(defun edmacro-minibuf-read (prompt) + (intern (completing-read + prompt obarray + (lambda (arg) + (and (commandp arg) + (vectorp (symbol-function arg)))) + t nil 'edmacro-read-history))) + +(defvar edmacro-char-to-word + '((?\0 . "NUL") + (?\r . "RET") + (?\n . "LFD") + (?\t . "TAB") + (?\e . "ESC") + (?\ . "SPC") + (?\C-? . "DEL"))) + +(defvar edmacro-modifiers + '(("C" . control) + ("M" . meta) + ("S" . shift) + ("Sh" . shift) + ("A" . alt) + ("H" . hyper) + ("s" . super))) + ;;; Parsing a human-readable keyboard macro. ;; Changes for XEmacs -- these two functions re-written from scratch. ;; edmacro-parse-keys always returns a vector. edmacro-format-keys ;; accepts a vector (but works with a string too). Vector may contain ;; keypress events. -hniksic -(defun edmacro-parse-keys (string &optional ignored) +(defun edmacro-parse-keys (string) (let* ((pos 0) (case-fold-search nil) - (word-to-sym '(("NUL" . ?\0) - ("RET" . return) - ("LFD" . linefeed) - ("TAB" . tab) - ("ESC" . escape) - ("SPC" . space) - ("BS" . backspace) - ("DEL" . delete))) - (char-to-word '((?\0 . "NUL") - (?\r . "RET") - (?\n . "LFD") - (?\t . "TAB") - (?\e . "ESC") - (?\ . "SPC") - (?\C-? . "DEL"))) - (modifier-prefix-alist '(("C" . control) - ("M" . meta) - ("S" . shift) - ("Sh" . shift) - ("A" . alt) - ("H" . hyper) - ("s" . super))) - ;; string-to-symbol-or-char converter - (conv (lambda (arg) - (if (= (length arg) 1) - (aref arg 0) - (if (string-match "^<\\([^>]+\\)>$" arg) - (setq arg (match-string 1 arg))) - (let ((match (assoc arg word-to-sym))) - (if match - (cdr match) - (intern arg)))))) - (conv-chars (lambda (arg) - (let ((match (assoc arg char-to-word))) - (if match - (cdr (assoc (cdr match) word-to-sym)) - arg)))) res) (while (and (< pos (length string)) - (string-match "[^ \t\n\f]+" string pos)) - (let ((word (substring string (match-beginning 0) (match-end 0))) - (times 1) - (force-sym nil) - (add nil) - match) + (string-match "[^ \t\r\n\f]+" string pos)) + (let ((word (substring string (match-beginning 0) (match-end 0)))) (setq pos (match-end 0)) - (when (string-match "\\([0-9]+\\)\\*." word) - (setq times (string-to-int (substring word 0 (match-end 1)))) - (setq word (substring word (1+ (match-end 1))))) - (when (string-match "^<\\([^<>]+\\)>$" word) - (setq word (match-string 1 word)) - (setq force-sym t)) - (setq match (assoc word word-to-sym)) - ;; Add an element; `add' holds the list of elements to be - ;; added. - (cond ((string-match "^\\\\[0-7]+" word) - ;; Octal value of character. - (setq add - (list - (edmacro-int-char - (edmacro-octal-string-to-integer (substring word 1)))))) - ((string-match "^<<.+>>$" word) - ;; Extended command. - (setq add - (nconc - (list - (if (eq (key-binding [(meta x)]) - 'execute-extended-command) - '(meta x) - (or (car (where-is-internal - 'execute-extended-command)) - '(meta x)))) - (mapcar conv-chars (concat (substring word 2 -2) "\r"))) - )) - ((or (equal word "REM") (string-match "^;;" word)) - ;; Comment (discard to EOL) . - (setq pos (string-match "$" string pos))) - (match - ;; Convert to symbol. - (setq add (list (cdr match)))) - ((string-match "^\\^" word) - ;; ^X == C-x - (if (/= (length word) 2) - (error "^ must be followed by one character")) - (setq add (list 'control (aref word 0)))) - ((string-match "^\\([MCSsAH]\\|Sh\\)-" word) - ;; Parse C-* and stuff - (setq - add - (list - (let ((pos1 0) - (r1 nil) - follow curpart prefix) - (while (progn (setq curpart (substring word pos1)) - (string-match "^\\([MCSsAH]\\|Sh\\)-" - curpart)) - (setq prefix (assoc (match-string 1 curpart) - modifier-prefix-alist)) - (setq r1 (nconc r1 (list (cdr prefix)))) - (callf + pos1 (1+ (length (car prefix))))) - (setq follow (substring word pos1)) - (if (equal follow "") - (error "%s must precede a string" - (substring word 0 pos1))) - (nconc r1 (list (funcall conv follow))))))) - (force-sym - ;; This must be a symbol - (setq add (list (intern word)))) - (t - ;; Characters - (setq add (mapcar conv-chars word)))) - (let ((new nil)) - (loop repeat times do (setq new (append new add))) - (setq add new)) - (setq res (nconc res add)))) - (edmacro-mapvector 'identity res))) + (if (or (equal word "REM") (string-match "^;;" word)) + ;; Comment (discard to EOL) . + (setq pos (string-match "$" string pos)) + (push (edmacro-parse-word word) res)))) + (mapvector 'identity (apply 'nconc (nreverse res))))) +;; Parse a word. +(defun edmacro-parse-word (word) + (let ((force-sym nil) + (times 1) + abbr) + (when (string-match "\\([0-9]+\\)\\*." word) + (setq times (string-to-int (substring word 0 (match-end 1)))) + (setq word (substring word (1+ (match-end 1))))) + (when (string-match "^<\\([^<>]+\\)>$" word) + (setq word (match-string 1 word)) + (setq force-sym t)) + (let* ((word-to-sym '(("NUL" . ?\0) + ("RET" . return) + ("LFD" . linefeed) + ("TAB" . tab) + ("ESC" . escape) + ("SPC" . space) + ("BS" . backspace) + ("DEL" . delete))) + (conv (lambda (arg) + ;; string-to-symbol-or-char converter + (if (= (length arg) 1) + (aref arg 0) + (if (string-match "^<\\([^>]+\\)>$" arg) + (setq arg (match-string 1 arg))) + (let ((match (assoc arg word-to-sym))) + (if match + (cdr match) + (intern arg)))))) + (conv-chars (lambda (arg) + (let ((match (assoc arg edmacro-char-to-word))) + (if match + (cdr (assoc (cdr match) word-to-sym)) + arg)))) + (add + (cond + ((string-match "^\\\\[0-7]+" word) + ;; Octal value of character. + (list + (edmacro-int-char + (hexl-octal-string-to-integer (substring word 1))))) + ((string-match "^<<.+>>$" word) + ;; Extended command. + (nconc + (list + (if (eq (key-binding [(meta x)]) + 'execute-extended-command) + '(meta x) + (or (car (where-is-internal + 'execute-extended-command)) + '(meta x)))) + (mapcar conv-chars (concat (substring word 2 -2) "\r")))) + ((setq abbr (assoc word word-to-sym)) + ;; Convert to symbol. + (list (cdr abbr))) + ((string-match "^\\^" word) + ;; ^X == C-x + (if (/= (length word) 2) + (error "^ must be followed by one character")) + `((control ,(aref word 1)))) + ((string-match "^\\([MCSsAH]\\|Sh\\)-" word) + ;; Parse C-* and stuff + (list + (let ((pos1 0) + (r1 nil) + follow curpart prefix) + (while (progn (setq curpart (substring word pos1)) + (string-match "^\\([MCSsAH]\\|Sh\\)-" + curpart)) + (setq prefix (assoc (match-string 1 curpart) + edmacro-modifiers)) + (push (cdr prefix) r1) + (incf pos1 (1+ (length (car prefix))))) + (setq follow (substring word pos1)) + (if (equal follow "") + (error "%s must precede a string" + (substring word 0 pos1))) + (nconc (nreverse r1) (list (funcall conv follow)))))) + (force-sym + ;; This must be a symbol + (list (intern word))) + (t + ;; Characters + (mapcar conv-chars word)))) + (new nil)) + (loop repeat times do (setq new (append add new))) + new))) + +;; Convert the keypress events in vector x to keys, and return a +;; vector of keys. If a list element is not a keypress event, ignore +;; it. +(defun edmacro-events-to-keys (x &optional list) + (let (new) + (mapc (lambda (el) + (cond ((key-press-event-p el) + (push (let ((mods (event-modifiers el))) + (if mods + (append mods (list (event-key el))) + (event-key el))) + new)) + ((or (characterp el) + (symbolp el) + (listp el)) + (push el new)))) + x) + (setq new (nreverse new)) + (if list + new + (mapvector 'identity new)))) + +;; Collapse a list of keys into a list of function keys, where +;; applicable. +(defun edmacro-fkeys (keys) + (let (new k lookup) + (while keys + (setq k (nconc k (list (car keys)))) + (setq lookup (lookup-key function-key-map (mapvector 'identity k))) + (cond ((vectorp lookup) + (push (mapcar 'identity lookup) new) + (setq k nil)) + ((keymapp lookup) + nil) + ((null lookup) + (push k new) + (setq k nil)) + (t + (setq k nil))) + (pop keys)) + (when (keymapp lookup) + (push k new)) + (apply 'nconc (nreverse new)))) + +;; Convert a character or symbol to string (defun edmacro-conv (char-or-sym add-<>) (let ((char-to-word '((?\0 . "NUL") (?\r . "RET") @@ -597,7 +653,9 @@ (start keys) el) (while keys - (unless (or (eq start keys) togetherp) + (when (or (eq (car keys) ?-) + (eq (car keys) '-) + (not (or togetherp (eq start keys)))) (callf concat res " ")) (if (> times 1) (setq res (concat (format "%d*" times) res))) @@ -608,185 +666,89 @@ (if (or (let (cnv) (while el - (let ((found (assq (car el) - '((control . "C-") - (meta . "M-") - (shift . "S-") - (alt . "A-") - (hyper . "H-") - (super . "s-"))))) + (let ((found (find (car el) edmacro-modifiers + :key 'cdr))) (callf concat my (if found - (cdr found) + (concat (car found) "-") (setq cnv (edmacro-conv (car el) nil)) (cdr cnv)))) - (setq el (cdr el))) + (pop el)) (car cnv)) (> times 1)) (concat "<" my ">") my))) (t (cdr (edmacro-conv el t))))) - (setq keys (cdr keys))) + (pop keys)) (if command (callf concat res - (concat - (make-string (max (- 3 (/ (length res) tab-width)) 1) ?\t) - ";; " - (symbol-name command) - (if togetherp (format " * %d" (length start)))))) + (make-string (max (- 3 (/ (length res) tab-width)) 1) ?\t) + ";; " + (symbol-name command) + (if togetherp (format " * %d" (length start))))) res)) -;; Convert the keypress events in vector x to keys, and return a -;; vector of keys. If a list element is not a keypress event, ignore -;; it. -(defun edmacro-events-to-keys (x) - (if (or (not (fboundp 'events-to-keys)) - (not (arrayp x))) - x - (let ((cnt 0) - (len (length x)) - new el) - (while (< cnt len) - (setq el (aref x cnt)) - (cond ((eventp el) - (if (mouse-event-p el) - (setq el nil) - (setq el (aref (events-to-keys (vector el)) 0)))) - (t - nil)) ; leave it be. - (if el - (setq new (nconc new (list el)))) - (incf cnt)) - (edmacro-mapvector 'identity new)))) - -;; Collapse a list of keys into a list of function keys, where -;; applicable. -(defun edmacro-fkeys (keys) - (let (new k lookup) - (while keys - (setq k (nconc k (list (car keys)))) - (setq lookup (lookup-key function-key-map (edmacro-mapvector 'identity k))) - (cond ((vectorp lookup) - (setq new (nconc new (mapcar 'identity lookup))) - (setq k nil)) - ((keymapp lookup) - nil) - ((null lookup) - (setq new (nconc new k)) - (setq k nil)) - (t - (setq k nil))) - (setq keys (cdr keys))) - (if (keymapp lookup) - (setq new (nconc new k))) - new)) +(defsubst edmacro-seq-equal (seq1 seq2) + (while (and seq1 seq2 + (equal (car seq1) (car seq2))) + (pop seq1) + (pop seq2)) + (not seq1)) ;;; Formatting a keyboard macro as human-readable text. (defun edmacro-format-keys (macro &optional verbose) ;; XEmacs: - ;; If we're dealing with events, convert them to symbols first. - (setq macro (edmacro-events-to-keys macro)) - (if (zerop (length macro)) - "" - (let ((res "")) - ;; I'm not sure I understand the original code, but this seems to - ;; work. - (and (eq verbose 1) - (setq verbose nil)) - - ;; We prefer a list -- much easier to process... - (setq macro (mapcar 'identity macro)) - (setq macro (edmacro-fkeys macro)) - (while macro - (let (key lookup (times 1) self-insert-p) - (loop do - (setq key (nconc key (list (car macro))) - macro (cdr macro) - lookup (lookup-key global-map (edmacro-mapvector - 'identity key))) - while - (and macro lookup (not (commandp lookup)))) - ;; keyboard macro - (if (vectorp lookup) - (setq lookup nil)) - (if (and (eq lookup 'self-insert-command) - (= (length key) 1) - (not (memq (car key) + ;; If we're dealing with events, convert them to symbols first; + ;; also, deal with Fkeys. + (setq macro (edmacro-fkeys (edmacro-events-to-keys macro t))) + (let ((res "")) + (while macro + (let (key lookup (times 1) self-insert-p) + (loop + do (setq key (nconc key (list (car macro))) + macro (cdr macro) + lookup (lookup-key global-map (mapvector + 'identity key))) + while (and macro lookup (not (commandp lookup)))) + ;; keyboard macro + (if (vectorp lookup) + (setq lookup nil)) + (if (and (eq lookup 'self-insert-command) + (= (length key) 1) + (not (memq (car key) + '(?\ ?\r ?\n space return linefeed tab)))) + (while (and (< (length key) 23) + (eq (lookup-key global-map (car macro)) + 'self-insert-command) + (not (memq + (car macro) '(?\ ?\r ?\n space return linefeed tab)))) - (while (and (< (length key) 23) - (eq (lookup-key global-map (car macro)) - 'self-insert-command) - (not (memq - (car macro) - '(?\ ?\r ?\n space return linefeed tab)))) - (setq key (nconc key (list (car macro))) - macro (cdr macro) - self-insert-p t)) + (setq key (nconc key (list (car macro))) + macro (cdr macro) + self-insert-p t)) + (let ((keysize (length key))) (while (edmacro-seq-equal key macro) - (setq macro (nthcdr (length key) macro)) - (incf times))) - (if (or self-insert-p - (null (cdr key)) - (= times 1)) - (callf concat res (edmacro-format-1 key (if verbose lookup - nil) - times self-insert-p) - (and macro (if verbose "\n" " "))) - (loop repeat times - do - (callf concat res - (edmacro-format-1 key (if verbose lookup - nil) - 1 self-insert-p) - (and macro (if verbose "\n" " "))))))) - res))) - -(defun edmacro-seq-equal (seq1 seq2) - (while (and seq1 seq2 - (equal (car seq1) (car seq2))) - (setq seq1 (cdr seq1) - seq2 (cdr seq2))) - (not seq1)) - -(defsubst edmacro-oct-char-to-integer (character) - "Take a char and return its value as if it was a octal digit." - (if (and (>= character ?0) (<= character ?7)) - (- character ?0) - (error (format "Invalid octal digit `%c'." character)))) - -(defun edmacro-octal-string-to-integer (octal-string) - "Return decimal integer for OCTAL-STRING." - (interactive "sOctal number: ") - (let ((oct-num 0)) - (while (not (equal octal-string "")) - (setq oct-num (+ (* oct-num 8) - (edmacro-oct-char-to-integer - (string-to-char octal-string)))) - (setq octal-string (substring octal-string 1))) - oct-num)) - - -(defun edmacro-fix-menu-commands (macro) - (when (vectorp macro) - (let ((i 0) ev) - (while (< i (length macro)) - (when (and (consp (setq ev (aref macro i))) - (not (memq (car ev) ; ha ha - '(hyper super meta alt control shift)))) - (cond ((equal (cadadr ev) '(menu-bar)) - (setq macro (vconcat (edmacro-subseq macro 0 i) - (vector 'menu-bar (car ev)) - (edmacro-subseq macro (1+ i)))) - (incf i)) - ;; It would be nice to do pop-up menus, too, but not enough - ;; info is recorded in macros to make this possible. - (t - (error "Macros with mouse clicks are not %s" - "supported by this command")))) - (incf i)))) - macro) + (setq macro (nthcdr keysize macro)) + (incf times)))) + (if (or self-insert-p + (null (cdr key)) + (= times 1)) + (callf concat res + (edmacro-format-1 key (if verbose lookup + nil) + times self-insert-p) + (and macro (if verbose "\n" " "))) + (loop + repeat times + do + (callf concat res + (edmacro-format-1 key (if verbose lookup + nil) + 1 self-insert-p) + (and macro (if verbose "\n" " "))))))) + res)) ;;; The following probably ought to go in macros.el: @@ -822,7 +784,7 @@ (let ((keys (where-is-internal macroname))) (while keys (insert (format "(global-set-key %S '%s)\n" (car keys) macroname)) - (setq keys (cdr keys))))))) + (pop keys)))))) (provide 'edmacro)