Function: viper-record-kbd-macro
viper-record-kbd-macro is a byte-compiled function defined in
viper-macs.el.gz.
Signature
(viper-record-kbd-macro MACRO-NAME STATE MACRO-BODY &optional SCOPE)
Documentation
Record a Vi macro.
Can be used in viper-custom-file-name to define permanent macros.
MACRO-NAME is a string of characters or a vector of keys. STATE is
either vi-state or insert-state. It specifies the Viper state in which to
define the macro. MACRO-BODY is a string that represents the keyboard macro.
Optional SCOPE says whether the macro should be global (t), mode-specific
(a major-mode symbol), or buffer-specific (buffer name, a string).
If SCOPE is nil, the user is asked to specify the scope.
Source Code
;; Defined in /usr/src/emacs/lisp/emulation/viper-macs.el.gz
;;; Recording, unrecording, executing
;; Accepts as macro names: strings and vectors.
;; strings must be strings of characters; vectors must be vectors of keys
;; in canonical form, which is essentially the form used in XEmacs.
;; More general definitions are inherited by more specific scopes:
;; global->major mode->buffer. More specific definitions override more general
(defun viper-record-kbd-macro (macro-name state macro-body &optional scope)
"Record a Vi macro.
Can be used in `viper-custom-file-name' to define permanent macros.
MACRO-NAME is a string of characters or a vector of keys. STATE is
either `vi-state' or `insert-state'. It specifies the Viper state in which to
define the macro. MACRO-BODY is a string that represents the keyboard macro.
Optional SCOPE says whether the macro should be global \(t), mode-specific
\(a major-mode symbol), or buffer-specific \(buffer name, a string).
If SCOPE is nil, the user is asked to specify the scope."
(let* (state-name keymap
(macro-alist-var
(cond ((eq state 'vi-state)
(setq state-name "Vi state"
keymap viper-vi-kbd-map)
'viper-vi-kbd-macro-alist)
((memq state '(insert-state replace-state))
(setq state-name "Insert state"
keymap viper-insert-kbd-map)
'viper-insert-kbd-macro-alist)
(t
(setq state-name "Emacs state"
keymap viper-emacs-kbd-map)
'viper-emacs-kbd-macro-alist)
))
new-elt old-elt old-sub-elt msg
temp lis lis2)
(if (= (length macro-name) 0)
(error "Can't map an empty macro name"))
;; Macro-name is usually a vector. However, command history or macros
;; recorded in viper-custom-file-name may be recorded as strings.
;; So, convert to vectors.
(setq macro-name (viper-fixup-macro macro-name))
(if (viper-char-array-p macro-name)
(setq macro-name (viper-char-array-to-macro macro-name)))
(setq macro-body (viper-fixup-macro macro-body))
(if (viper-char-array-p macro-body)
(setq macro-body (viper-char-array-to-macro macro-body)))
;; don't ask if scope is given and is of the right type
(or (eq scope t)
(stringp scope)
(and scope (symbolp scope))
(progn
(setq scope
(cond
((y-or-n-p
(format-message
"Map this macro for buffer `%s' only? "
(buffer-name)))
(setq msg
(format-message
"%S is mapped to %s for %s in `%s'"
(viper-display-macro macro-name)
(viper-abbreviate-string
(format
"%S"
(setq temp (viper-display-macro macro-body)))
14 "" ""
(if (stringp temp) " ....\"" " ....]"))
state-name (buffer-name)))
(buffer-name))
((y-or-n-p
(format-message
"Map this macro for the major mode `%S' only? "
major-mode))
(setq msg
(format-message
"%S is mapped to %s for %s in `%S'"
(viper-display-macro macro-name)
(viper-abbreviate-string
(format
"%S"
(setq temp (viper-display-macro macro-body)))
14 "" ""
(if (stringp macro-body) " ....\"" " ....]"))
state-name major-mode))
major-mode)
(t
(setq msg
(format
"%S is globally mapped to %s in %s"
(viper-display-macro macro-name)
(viper-abbreviate-string
(format
"%S"
(setq temp (viper-display-macro macro-body)))
14 "" ""
(if (stringp macro-body) " ....\"" " ....]"))
state-name))
t)))
(if (y-or-n-p
(format "Save this macro in %s? "
(abbreviate-file-name viper-custom-file-name)))
(viper-save-string-in-file
(format "\n(viper-record-kbd-macro %S '%S %s '%S)"
(viper-display-macro macro-name)
state
;; if we don't let vector macro-body through %S,
;; the symbols `\.' `\[' etc will be converted into
;; characters, causing invalid read error on recorded
;; macros in viper-custom-file-name.
;; I am not sure is macro-body can still be a string at
;; this point, but I am preserving this option anyway.
(if (vectorp macro-body)
(format "%S" macro-body)
macro-body)
scope)
viper-custom-file-name))
(message "%s" msg)
))
(setq new-elt
(cons macro-name
(cond ((eq scope t) (list nil nil (cons t nil)))
((symbolp scope)
(list nil (list (cons scope nil)) (cons t nil)))
((stringp scope)
(list (list (cons scope nil)) nil (cons t nil))))))
(setq old-elt (assoc macro-name (symbol-value macro-alist-var)))
(if (null old-elt)
(progn
;; insert new-elt in macro-alist-var and keep the list sorted
(define-key
keymap
(vector (viper-key-to-emacs-key (aref macro-name 0)))
#'viper-exec-mapped-kbd-macro)
(setq lis (symbol-value macro-alist-var))
(while (and lis (string< (viper-array-to-string (car (car lis)))
(viper-array-to-string macro-name)))
(setq lis2 (cons (car lis) lis2))
(setq lis (cdr lis)))
(setq lis2 (reverse lis2))
(set macro-alist-var (append lis2 (cons new-elt lis)))
(setq old-elt new-elt)))
(setq old-sub-elt
(cond ((eq scope t) (viper-kbd-global-pair old-elt))
((symbolp scope) (assoc scope (viper-kbd-mode-alist old-elt)))
((stringp scope) (assoc scope (viper-kbd-buf-alist old-elt)))))
(if old-sub-elt
(setcdr old-sub-elt macro-body)
(cond ((symbolp scope) (setcar (cdr (cdr old-elt))
(cons (cons scope macro-body)
(viper-kbd-mode-alist old-elt))))
((stringp scope) (setcar (cdr old-elt)
(cons (cons scope macro-body)
(viper-kbd-buf-alist old-elt))))))
))