Mercurial > hg > xemacs-beta
diff lisp/utils/edmacro.el @ 24:4103f0995bd7 r19-15b95
Import from CVS: tag r19-15b95
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:51:03 +0200 |
parents | 8fc7fe29b841 |
children | 7d55a9ba150c |
line wrap: on
line diff
--- a/lisp/utils/edmacro.el Mon Aug 13 08:50:31 2007 +0200 +++ b/lisp/utils/edmacro.el Mon Aug 13 08:51:03 2007 +0200 @@ -3,26 +3,29 @@ ;; Copyright (C) 1993, 1994 Free Software Foundation, Inc. ;; Author: Dave Gillespie <daveg@synaptics.com> -;; Maintainer: Dave Gillespie <daveg@synaptics.com> -;; Version: 2.01 +;; Hrvoje Niksic <hniksic@srce.hr> -- XEmacs port +;; Maintainer: Hrvoje Niksic <hniksic@srce.hr> +;; Version: 3.05 ;; Keywords: abbrev -;; This file is part of GNU Emacs. +;; This file is part of XEmacs. -;; GNU Emacs is free software; you can redistribute it and/or modify +;; XEmacs is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 2, or (at your option) ;; any later version. -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. +;; XEmacs is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. +;; along with XEmacs; see the file COPYING. If not, write to the Free +;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +;; 02111-1307, USA. + +;;; Synched up with: FSF 19.34. ;;; Commentary: @@ -68,12 +71,12 @@ ;; Emacs 19.18.) This package does not work with Emacs 18 or ;; Lucid Emacs. -;; You bet it does. -hniksic +;; But it works with XEmacs. At least the modified version. -hniksic ;;; Code: (eval-when-compile - (require 'cl)) + (require 'cl)) ;;; The user-level commands for editing macros. @@ -104,13 +107,16 @@ 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) - (member keys '("\r" [return]))) + (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)) @@ -245,8 +251,8 @@ (let ((key (edmacro-parse-keys (buffer-substring (match-beginning 1) (match-end 1))))) - (unless (equal key "") - (if (equal key "none") + (unless (equal key []) + (if (equal key [?n ?o ?n ?e]) (setq no-keys t) (push key keys) (let ((b (key-binding key))) @@ -291,7 +297,7 @@ (fset cmd mac))) (if no-keys (when cmd - (loop for key in (where-is-internal cmd '(keymap)) do + (loop for key in (where-is-internal cmd) do (global-unset-key key))) (when keys (if (= (length mac) 0) @@ -432,18 +438,18 @@ (if match (cdr (assoc (cdr match) word-to-sym)) arg)))) - (force-sym nil) - res word found) + 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)) (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) + (when (string-match "^<\\([^<>]+\\)>$" word) (setq word (match-string 1 word)) (setq force-sym t)) (setq match (assoc word word-to-sym)) @@ -452,7 +458,8 @@ ;; Octal value of character. (setq add (list - (edmacro-int-char (string-to-int (substring word 1)))))) + (edmacro-int-char + (edmacro-octal-string-to-integer (substring word 1)))))) ((string-match "^<<.+>>$" word) ;; Extended command. (setq add @@ -465,18 +472,18 @@ 'execute-extended-command)) '(meta x)))) (mapcar conv-chars (concat (substring word 2 -2) "\r"))) - )) + )) ((or (equal word "REM") (string-match "^;;" word)) ;; Comment. (setq pos (string-match "$" string pos))) (match - ;; Convert to symbol. - (setq add (list (cdr 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 `((control ,(aref word 0))))) + (setq add (list 'control (aref word 0)))) ((string-match "^[MCSsAH]-" word) ;; Parse C-* (setq @@ -512,17 +519,18 @@ (loop repeat times do (setq new (append new add))) (setq add new)) (setq res (nconc res add)))) - (mapvector 'identity res))) + (mapvector 'identity res))) (defun edmacro-conv (char-or-sym add-<>) (let ((char-to-word '((?\0 . "NUL") - (?\r . "RET") - (?\n . "LFD") - (?\t . "TAB") - (?\e . "ESC") - (?\ . "SPC") - (?\C-? . "DEL"))) + (?\r . "RET") + (?\n . "LFD") + (?\t . "TAB") + (?\e . "ESC") + (?\ . "SPC") + (?\C-? . "DEL"))) (symbol-to-char '((return . ?\r) + (linefeed . ?\n) (space . ?\ ) (delete . ?\C-?) (tab . ?\t) @@ -540,9 +548,12 @@ (concat "<" (symbol-name char-or-sym) ">") (symbol-name char-or-sym)) (let ((found (assq char-or-sym char-to-word))) - (if found - (cdr found) - (single-key-description char-or-sym))))))) + (cond (found + (cdr found)) + ((< char-or-sym 128) + (single-key-description char-or-sym)) + (t + (format "\\%o" (edmacro-int-char char-or-sym))))))))) (defun edmacro-format-1 (keys command times togetherp) (let ((res "") @@ -589,62 +600,108 @@ (if togetherp (format " * %d" (length start)))))) res)) -(defun edmacro-format-keys (macro &optional verbose) - (let ((cnt 0) - (res "")) - ;; XEmacs: - ;; If we're dealing with events, convert them to symbols first. - (and (fboundp 'events-to-keys) - (eventp (aref macro 0)) - (setq macro (events-to-keys macro t))) +;; 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)) + (mapvector 'identity new)))) - ;; I'm not sure I understand the original code, but this seems to - ;; work. - (and (eq verbose 1) - (setq verbose nil)) - - ;; Oh come on -- I want a list! Much easier to process... - (setq macro (mapcar 'identity macro)) +;; Collapse a list of keys into a list of function keys, where +;; applicable. +(defun edmacro-fkeys (keys) + (let (new k) + (while keys + (setq k (nconc k (list (car keys)))) + (setq lookup (lookup-key function-key-map (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)) - (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 lookup (not (commandp lookup)))) - (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)))) - (setq key (nconc key (list (car macro))) - macro (cdr macro) - self-insert-p t)) - (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) - (if verbose "\n" " ")) - (loop repeat times - do - (callf concat res - (edmacro-format-1 key (if verbose lookup - nil) - 1 self-insert-p) - (if verbose "\n" " ")))) - )) - res)) +(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)) + + ;; Oh come on -- I want 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 (mapvector 'identity key))) + while + (and lookup (not (commandp lookup)))) + ;; (lookup-key [?\C-x ?e]) seems to return a vector! + (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)))) + (setq key (nconc key (list (car macro))) + macro (cdr macro) + self-insert-p t)) + (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 @@ -653,11 +710,31 @@ 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 (consp (setq ev (aref macro i))) + (when (and (consp (setq ev (aref macro i))) + (not (memq (car ev) ; ha ha + '(hyper super control meta alt control shift)))) (cond ((equal (cadadr ev) '(menu-bar)) (setq macro (vconcat (edmacro-subseq macro 0 i) (vector 'menu-bar (car ev)) @@ -705,7 +782,7 @@ (prin1 definition (current-buffer)) (insert "))\n") (if keys - (let ((keys (where-is-internal macroname '(keymap)))) + (let ((keys (where-is-internal macroname))) (while keys (insert (format "(global-set-key %S '%s)\n" (car keys) macroname)) (setq keys (cdr keys)))))))