1 ;;; viper-macs.el --- functions implementing keyboard macros for Viper
3 ;; Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
5 ;; This file is part of GNU Emacs.
7 ;; GNU Emacs is free software; you can redistribute it and/or modify
8 ;; it under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation; either version 2, or (at your option)
12 ;; GNU Emacs is distributed in the hope that it will be useful,
13 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ;; GNU General Public License for more details.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GNU Emacs; see the file COPYING. If not, write to the
19 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 ;; Boston, MA 02111-1307, USA.
27 (defvar vip-ex-work-buf
)
28 (defvar vip-custom-file-name
)
29 (defvar vip-current-state
)
32 (let ((load-path (cons (expand-file-name ".") load-path
)))
33 (or (featurep 'viper-util
)
34 (load "viper-util.el" nil nil
'nosuffix
))
35 (or (featurep 'viper-keym
)
36 (load "viper-keym.el" nil nil
'nosuffix
))
37 (or (featurep 'viper-mous
)
38 (load "viper-mous.el" nil nil
'nosuffix
))
40 (load "viper.el" nil nil
'nosuffix
))
50 ;; Register holding last macro.
51 (defvar vip-last-macro-reg nil
)
53 ;; format of the elements of kbd alists:
54 ;; (name ((buf . macr)...(buf . macr)) ((maj-mode . macr)...) (t . macr))
55 ;; kbd macro alist for Vi state
56 (defvar vip-vi-kbd-macro-alist nil
)
57 ;; same for insert/replace state
58 (defvar vip-insert-kbd-macro-alist nil
)
59 ;; same for emacs state
60 (defvar vip-emacs-kbd-macro-alist nil
)
62 ;; Internal var that passes info between start-kbd-macro and end-kbd-macro
64 (defvar vip-kbd-macro-parameters nil
)
66 (defvar vip-this-kbd-macro nil
67 "Vector of keys representing the name of currently running Viper kbd macro.")
68 (defvar vip-last-kbd-macro nil
69 "Vector of keys representing the name of last Viper keyboard macro.")
71 (defconst vip-fast-keyseq-timeout
200
72 "*Key sequence separated by no more than this many milliseconds is viewed as a macro, if such a macro is defined.
73 This also controls ESC-keysequences generated by keyboard function keys.")
76 (defvar vip-repeat-from-history-key
'f12
77 "Prefix key for invocation of vip-repeat-from-history function,
78 which repeats previous destructive commands from the history of such
80 This function can then be invoked as <this-key> 1 or <this-key> 2.
81 The notation for these keys is borrowed from XEmacs. Basically,
82 a key is a symbol, e.g., `a', `\\1', `f2', etc., or a list, e.g.,
83 `(meta control f1)'.")
92 macro-name macro-body map-args ins
)
93 (save-window-excursion
94 (set-buffer vip-ex-work-buf
)
100 (setq map-args
(ex-map-read-args mod-char
)
101 macro-name
(car map-args
)
102 macro-body
(cdr map-args
))
103 (setq vip-kbd-macro-parameters
(list ins mod-char macro-name macro-body
))
105 (vip-end-mapping-kbd-macro 'ignore
)
106 (ex-fixup-history (format "map%s %S" mod-char
107 (vip-display-macro macro-name
)))
108 ;; if defining macro for insert, switch there for authentic WYSIWYG
109 (if ins
(vip-change-state-to-insert))
110 (start-kbd-macro nil
)
111 (define-key vip-vi-intercept-map
"\C-x)" 'vip-end-mapping-kbd-macro
)
112 (define-key vip-insert-intercept-map
"\C-x)" 'vip-end-mapping-kbd-macro
)
113 (define-key vip-emacs-intercept-map
"\C-x)" 'vip-end-mapping-kbd-macro
)
114 (message "Mapping %S in %s state. Hit `C-x )' to complete the mapping"
115 (vip-display-macro macro-name
)
116 (if ins
"Insert" "Vi")))
124 (save-window-excursion
125 (set-buffer vip-ex-work-buf
)
132 (setq macro-name
(ex-unmap-read-args mod-char
))
133 (setq temp
(vip-fixup-macro (vconcat macro-name
))) ;; copy and fixup
134 (ex-fixup-history (format "unmap%s %S" mod-char
135 (vip-display-macro temp
)))
136 (vip-unrecord-kbd-macro macro-name
(if ins
'insert-state
'vi-state
))
140 ;; read arguments for ex-map
141 (defun ex-map-read-args (variant)
142 (let ((cursor-in-echo-area t
)
144 temp key event message
145 macro-name macro-body args
)
148 (setq args
(concat (ex-get-inline-cmd-args ".*map[!]*[ \t]?" "\n\C-m")
150 temp
(read-from-string args
)
151 macro-name
(car temp
)
152 macro-body
(car (read-from-string args
(cdr temp
))))
156 '("map: Macro name and body must be a quoted string or a vector"))))
158 ;; We expect macro-name to be a vector, a string, or a quoted string.
159 ;; In the second case, it will emerge as a symbol when read from
160 ;; the above read-from-string. So we need to convert it into a string
162 (cond ((vectorp macro-name
) nil
)
163 ((stringp macro-name
)
164 (setq macro-name
(vconcat macro-name
)))
165 (t (setq macro-name
(vconcat (prin1-to-string macro-name
)))))
166 (message ":map%s <Name>" variant
)(sit-for 2)
169 '(?\C-m ?
\n (control m
) (control j
) return linefeed
)))
170 (setq key-seq
(vconcat key-seq
(if key
(vector key
) [])))
171 ;; the only keys available for editing are these-- no help while there
174 '(?
\b ?\d
'^?
'^H
(control h
) (control \?) backspace delete
))
175 (setq key-seq
(subseq key-seq
0 (- (length key-seq
) 2))))
179 variant
(if (> (length key-seq
) 0)
180 (prin1-to-string (vip-display-macro key-seq
))
183 (setq event
(vip-read-key))
184 ;;(setq event (vip-read-event))
186 (if (vip-mouse-event-p event
)
188 (message "%s (No mouse---only keyboard keys, please)"
192 (vip-event-key event
)))
194 (setq macro-name key-seq
))
196 (if (= (length macro-name
) 0)
197 (error "Can't map an empty macro name"))
198 (setq macro-name
(vip-fixup-macro macro-name
))
199 (if (vip-char-array-p macro-name
)
200 (setq macro-name
(vip-char-array-to-macro macro-name
)))
203 (cond ((vip-char-array-p macro-body
)
204 (setq macro-body
(vip-char-array-to-macro macro-body
)))
205 ((vectorp macro-body
) nil
)
206 (t (error "map: Invalid syntax in macro definition"))))
207 (setq cursor-in-echo-area nil
)(sit-for 0) ; this overcomes xemacs tty bug
208 (cons macro-name macro-body
)))
212 ;; read arguments for ex-unmap
213 (defun ex-unmap-read-args (variant)
214 (let ((cursor-in-echo-area t
)
215 (macro-alist (if (string= variant
"!")
216 vip-insert-kbd-macro-alist
217 vip-vi-kbd-macro-alist
))
218 ;; these are disabled just in case, to avoid surprises when doing
220 vip-vi-kbd-minor-mode vip-insert-kbd-minor-mode
221 vip-emacs-kbd-minor-mode
222 vip-vi-intercept-minor-mode vip-insert-intercept-minor-mode
223 vip-emacs-intercept-minor-mode
225 key key-seq macro-name
)
226 (setq macro-name
(ex-get-inline-cmd-args ".*unma?p?[!]*[ \t]*"))
228 (if (> (length macro-name
) 0)
230 (message ":unmap%s <Name>" variant
) (sit-for 2)
233 (member key
'(?\C-m ?
\n (control m
) (control j
) return linefeed
)))
234 (setq key-seq
(vconcat key-seq
(if key
(vector key
) [])))
235 ;; the only keys available for editing are these-- no help while there
238 '(?
\b ?\d
'^?
'^H
(control h
) (control \?) backspace delete
))
239 (setq key-seq
(subseq key-seq
0 (- (length key-seq
) 2))))
240 ((member key
'(tab (control i
) ?
\t))
241 (setq key-seq
(subseq key-seq
0 (1- (length key-seq
))))
245 variant
(if (> (length key-seq
) 0)
247 (vip-display-macro key-seq
))
250 (vip-do-sequence-completion key-seq macro-alist message
))
255 variant
(if (> (length key-seq
) 0)
257 (vip-display-macro key-seq
))
260 (setq event
(vip-read-key))
261 ;;(setq event (vip-read-event))
263 (if (vip-mouse-event-p event
)
265 (message "%s (No mouse---only keyboard keys, please)"
269 (vip-event-key event
)))
271 (setq macro-name key-seq
))
273 (if (= (length macro-name
) 0)
274 (error "Can't unmap an empty macro name"))
276 ;; convert macro names into vector, if starts with a `['
277 (if (memq (elt macro-name
0) '(?\
[ ?
\"))
278 (car (read-from-string macro-name
))
279 (vconcat macro-name
))
283 ;; Terminate a Vi kbd macro.
284 ;; optional argument IGNORE, if t, indicates that we are dealing with an
285 ;; existing macro that needs to be registered, but there is no need to
286 ;; terminate a kbd macro.
287 (defun vip-end-mapping-kbd-macro (&optional ignore
)
289 (define-key vip-vi-intercept-map
"\C-x)" nil
)
290 (define-key vip-insert-intercept-map
"\C-x)" nil
)
291 (define-key vip-emacs-intercept-map
"\C-x)" nil
)
292 (if (and (not ignore
)
293 (or (not vip-kbd-macro-parameters
)
294 (not defining-kbd-macro
)))
295 (error "Not mapping a kbd-macro"))
296 (let ((mod-char (nth 1 vip-kbd-macro-parameters
))
297 (ins (nth 0 vip-kbd-macro-parameters
))
298 (macro-name (nth 2 vip-kbd-macro-parameters
))
299 (macro-body (nth 3 vip-kbd-macro-parameters
)))
300 (setq vip-kbd-macro-parameters nil
)
304 (setq macro-body
(vip-events-to-macro last-kbd-macro
))
305 ;; always go back to Vi, since this is where we started
307 (vip-change-state-to-vi)))
309 (vip-record-kbd-macro macro-name
310 (if ins
'insert-state
'vi-state
)
311 (vip-display-macro macro-body
))
313 (ex-fixup-history (format "map%s %S %S" mod-char
314 (vip-display-macro macro-name
)
315 (vip-display-macro macro-body
)))
320 (defadvice start-kbd-macro
(after vip-kbd-advice activate
)
321 "Remove Viper's intercepting bindings for C-x ).
322 This may be needed if the previous `:map' command terminated abnormally."
323 (define-key vip-vi-intercept-map
"\C-x)" nil
)
324 (define-key vip-insert-intercept-map
"\C-x)" nil
)
325 (define-key vip-emacs-intercept-map
"\C-x)" nil
))
329 ;;; Recording, unrecording, executing
331 ;; accepts as macro names: strings and vectors.
332 ;; strings must be strings of characters; vectors must be vectors of keys
333 ;; in canonic form. the canonic form is essentially the form used in XEmacs
334 (defun vip-record-kbd-macro (macro-name state macro-body
&optional scope
)
335 "Record a Vi macro. Can be used in `.vip' file to define permanent macros.
336 MACRO-NAME is a string of characters or a vector of keys. STATE is
337 either `vi-state' or `insert-state'. It specifies the Viper state in which to
338 define the macro. MACRO-BODY is a string that represents the keyboard macro.
339 Optional SCOPE says whether the macro should be global \(t\), mode-specific
340 \(a major-mode symbol\), or buffer-specific \(buffer name, a string\).
341 If SCOPE is nil, the user is asked to specify the scope."
342 (let* (state-name keymap
344 (cond ((eq state
'vi-state
)
345 (setq state-name
"Vi state"
346 keymap vip-vi-kbd-map
)
347 'vip-vi-kbd-macro-alist
)
348 ((memq state
'(insert-state replace-state
))
349 (setq state-name
"Insert state"
350 keymap vip-insert-kbd-map
)
351 'vip-insert-kbd-macro-alist
)
353 (setq state-name
"Emacs state"
354 keymap vip-emacs-kbd-map
)
355 'vip-emacs-kbd-macro-alist
)
357 new-elt old-elt old-sub-elt msg
360 (if (= (length macro-name
) 0)
361 (error "Can't map an empty macro name"))
363 ;; Macro-name is usually a vector. However, command history or macros
364 ;; recorded in ~/.vip may be recorded as strings. So, convert to vectors.
365 (setq macro-name
(vip-fixup-macro macro-name
))
366 (if (vip-char-array-p macro-name
)
367 (setq macro-name
(vip-char-array-to-macro macro-name
)))
368 (setq macro-body
(vip-fixup-macro macro-body
))
369 (if (vip-char-array-p macro-body
)
370 (setq macro-body
(vip-char-array-to-macro macro-body
)))
372 ;; don't ask if scope is given and is of the right type
375 (and scope
(symbolp scope
))
381 "Map this macro for buffer `%s' only? "
385 "%S is mapped to %s for %s in `%s'"
386 (vip-display-macro macro-name
)
387 (vip-abbreviate-string
390 (setq temp
(vip-display-macro macro-body
)))
392 (if (stringp temp
) " ....\"" " ....]"))
393 state-name
(buffer-name)))
397 "Map this macro for the major mode `%S' only? "
401 "%S is mapped to %s for %s in `%S'"
402 (vip-display-macro macro-name
)
403 (vip-abbreviate-string
406 (setq temp
(vip-display-macro macro-body
)))
408 (if (stringp macro-body
) " ....\"" " ....]"))
409 state-name major-mode
))
414 "%S is globally mapped to %s in %s"
415 (vip-display-macro macro-name
)
416 (vip-abbreviate-string
419 (setq temp
(vip-display-macro macro-body
)))
421 (if (stringp macro-body
) " ....\"" " ....]"))
425 (format "Save this macro in %s? "
426 (vip-abbreviate-file-name vip-custom-file-name
)))
427 (vip-save-string-in-file
428 (format "\n(vip-record-kbd-macro %S '%S %s '%S)"
429 (vip-display-macro macro-name
)
431 ;; if we don't let vector macro-body through %S,
432 ;; the symbols `\.' `\[' etc will be converted into
433 ;; characters, causing invalid read error on recorded
435 ;; I am not sure is macro-body can still be a string at
436 ;; this point, but I am preserving this option anyway.
437 (if (vectorp macro-body
)
438 (format "%S" macro-body
)
441 vip-custom-file-name
))
448 (cond ((eq scope t
) (list nil nil
(cons t nil
)))
450 (list nil
(list (cons scope nil
)) (cons t nil
)))
452 (list (list (cons scope nil
)) nil
(cons t nil
))))))
453 (setq old-elt
(assoc macro-name
(eval macro-alist-var
)))
457 ;; insert new-elt in macro-alist-var and keep the list sorted
460 (vector (vip-key-to-emacs-key (aref macro-name
0)))
461 'vip-exec-mapped-kbd-macro
)
462 (setq lis
(eval macro-alist-var
))
463 (while (and lis
(string< (vip-array-to-string (car (car lis
)))
464 (vip-array-to-string macro-name
)))
465 (setq lis2
(cons (car lis
) lis2
))
466 (setq lis
(cdr lis
)))
468 (setq lis2
(reverse lis2
))
469 (set macro-alist-var
(append lis2
(cons new-elt lis
)))
470 (setq old-elt new-elt
)))
472 (cond ((eq scope t
) (vip-kbd-global-pair old-elt
))
473 ((symbolp scope
) (assoc scope
(vip-kbd-mode-alist old-elt
)))
474 ((stringp scope
) (assoc scope
(vip-kbd-buf-alist old-elt
)))))
476 (setcdr old-sub-elt macro-body
)
477 (cond ((symbolp scope
) (setcar (cdr (cdr old-elt
))
478 (cons (cons scope macro-body
)
479 (vip-kbd-mode-alist old-elt
))))
480 ((stringp scope
) (setcar (cdr old-elt
)
481 (cons (cons scope macro-body
)
482 (vip-kbd-buf-alist old-elt
))))))
487 ;; macro name must be a vector of vip-style keys
488 (defun vip-unrecord-kbd-macro (macro-name state
)
489 "Delete macro MACRO-NAME from Viper STATE.
490 MACRO-NAME must be a vector of vip-style keys. This command is used by Viper
491 internally, but the user can also use it in ~/.vip to delete pre-defined macros
492 supplied with Viper. The best way to avoid mistakes in macro names to be passed
493 to this function is to use vip-describe-kbd-macros and copy the name from
495 (let* (state-name keymap
497 (cond ((eq state
'vi-state
)
498 (setq state-name
"Vi state"
499 keymap vip-vi-kbd-map
)
500 'vip-vi-kbd-macro-alist
)
501 ((memq state
'(insert-state replace-state
))
502 (setq state-name
"Insert state"
503 keymap vip-insert-kbd-map
)
504 'vip-insert-kbd-macro-alist
)
506 (setq state-name
"Emacs state"
507 keymap vip-emacs-kbd-map
)
508 'vip-emacs-kbd-macro-alist
)
510 buf-mapping mode-mapping global-mapping
511 macro-pair macro-entry
)
513 ;; Macro-name is usually a vector. However, command history or macros
514 ;; recorded in ~/.vip may appear as strings. So, convert to vectors.
515 (setq macro-name
(vip-fixup-macro macro-name
))
516 (if (vip-char-array-p macro-name
)
517 (setq macro-name
(vip-char-array-to-macro macro-name
)))
519 (setq macro-entry
(assoc macro-name
(eval macro-alist-var
)))
520 (if (= (length macro-name
) 0)
521 (error "Can't unmap an empty macro name"))
522 (if (null macro-entry
)
523 (error "%S is not mapped to a macro for %s in `%s'"
524 (vip-display-macro macro-name
)
525 state-name
(buffer-name)))
527 (setq buf-mapping
(vip-kbd-buf-pair macro-entry
)
528 mode-mapping
(vip-kbd-mode-pair macro-entry
)
529 global-mapping
(vip-kbd-global-pair macro-entry
))
531 (cond ((and (cdr buf-mapping
)
532 (or (and (not (cdr mode-mapping
)) (not (cdr global-mapping
)))
534 (format "Unmap %S for `%s' only? "
535 (vip-display-macro macro-name
)
537 (setq macro-pair buf-mapping
)
538 (message "%S is unmapped for %s in `%s'"
539 (vip-display-macro macro-name
)
540 state-name
(buffer-name)))
541 ((and (cdr mode-mapping
)
542 (or (not (cdr global-mapping
))
544 (format "Unmap %S for the major mode `%S' only? "
545 (vip-display-macro macro-name
)
547 (setq macro-pair mode-mapping
)
548 (message "%S is unmapped for %s in %S"
549 (vip-display-macro macro-name
) state-name major-mode
))
550 ((cdr (setq macro-pair
(vip-kbd-global-pair macro-entry
)))
552 "Global mapping of %S for %s is removed"
553 (vip-display-macro macro-name
) state-name
))
554 (t (error "%S is not mapped to a macro for %s in `%s'"
555 (vip-display-macro macro-name
)
556 state-name
(buffer-name))))
557 (setcdr macro-pair nil
)
558 (or (cdr buf-mapping
)
562 (set macro-alist-var
(delq macro-entry
(eval macro-alist-var
)))
563 (if (vip-can-release-key (aref macro-name
0)
564 (eval macro-alist-var
))
567 (vector (vip-key-to-emacs-key (aref macro-name
0)))
572 ;; Check if MACRO-ALIST has an entry for a macro name starting with
573 ;; CHAR. If not, this indicates that the binding for this char
574 ;; in vip-vi/insert-kbd-map can be released.
575 (defun vip-can-release-key (char macro-alist
)
576 (let ((lis macro-alist
)
580 (while (and lis can-release
)
581 (setq macro-name
(car (car lis
)))
582 (if (eq char
(aref macro-name
0))
583 (setq can-release nil
))
584 (setq lis
(cdr lis
)))
588 (defun vip-exec-mapped-kbd-macro (count)
589 "Dispatch kbd macro."
591 (let* ((macro-alist (cond ((eq vip-current-state
'vi-state
)
592 vip-vi-kbd-macro-alist
)
593 ((memq vip-current-state
594 '(insert-state replace-state
))
595 vip-insert-kbd-macro-alist
)
597 vip-emacs-kbd-macro-alist
)))
598 (unmatched-suffix "")
599 ;; Macros and keys are executed with other macros turned off
600 ;; For macros, this is done to avoid macro recursion
601 vip-vi-kbd-minor-mode vip-insert-kbd-minor-mode
602 vip-emacs-kbd-minor-mode
603 next-best-match keyseq event-seq
604 macro-first-char macro-alist-elt macro-body
607 (setq macro-first-char last-command-event
608 event-seq
(vip-read-fast-keysequence macro-first-char macro-alist
)
609 keyseq
(vip-events-to-macro event-seq
)
610 macro-alist-elt
(assoc keyseq macro-alist
)
611 next-best-match
(vip-find-best-matching-macro macro-alist keyseq
))
613 (if (null macro-alist-elt
)
614 (setq macro-alist-elt
(car next-best-match
)
615 unmatched-suffix
(subseq event-seq
(cdr next-best-match
))))
617 (cond ((null macro-alist-elt
))
618 ((setq macro-body
(vip-kbd-buf-definition macro-alist-elt
)))
619 ((setq macro-body
(vip-kbd-mode-definition macro-alist-elt
)))
620 ((setq macro-body
(vip-kbd-global-definition macro-alist-elt
))))
622 ;; when defining keyboard macro, don't use the macro mappings
623 (if (and macro-body
(not defining-kbd-macro
))
624 ;; block cmd executed as part of a macro from entering command history
625 (let ((command-history command-history
))
626 (setq vip-this-kbd-macro
(car macro-alist-elt
))
627 (execute-kbd-macro (vip-macro-to-events macro-body
) count
)
628 (setq vip-this-kbd-macro nil
629 vip-last-kbd-macro
(car macro-alist-elt
))
630 (vip-set-unread-command-events unmatched-suffix
))
631 ;; If not a macro, or the macro is suppressed while defining another
632 ;; macro, put keyseq back on the event queue
633 (vip-set-unread-command-events event-seq
)
634 ;; if the user typed arg, then use it if prefix arg is not set by
635 ;; some other command (setting prefix arg can happen if we do, say,
636 ;; 2dw and there is a macro starting with 2. Then control will go to
638 (or prefix-arg
(setq prefix-arg count
))
639 (setq command
(key-binding (read-key-sequence nil
)))
640 (if (commandp command
)
641 (command-execute command
)
647 ;;; Displaying and completing macros
649 (defun vip-describe-kbd-macros ()
650 "Show currently defined keyboard macros."
652 (with-output-to-temp-buffer " *vip-info*"
653 (princ "Macros in Vi state:\n===================\n")
654 (mapcar 'vip-describe-one-macro vip-vi-kbd-macro-alist
)
655 (princ "\n\nMacros in Insert and Replace states:\n====================================\n")
656 (mapcar 'vip-describe-one-macro vip-insert-kbd-macro-alist
)
657 (princ "\n\nMacros in Emacs state:\n======================\n")
658 (mapcar 'vip-describe-one-macro vip-emacs-kbd-macro-alist
)
661 (defun vip-describe-one-macro (macro)
662 (princ (format "\n *** Mappings for %S:\n ------------\n"
663 (vip-display-macro (car macro
))))
664 (princ " ** Buffer-specific:")
665 (if (vip-kbd-buf-alist macro
)
666 (mapcar 'vip-describe-one-macro-elt
(vip-kbd-buf-alist macro
))
668 (princ "\n ** Mode-specific:")
669 (if (vip-kbd-mode-alist macro
)
670 (mapcar 'vip-describe-one-macro-elt
(vip-kbd-mode-alist macro
))
672 (princ "\n ** Global:")
673 (if (vip-kbd-global-definition macro
)
674 (princ (format "\n %S" (cdr (vip-kbd-global-pair macro
))))
678 (defun vip-describe-one-macro-elt (elt)
679 (let ((name (car elt
))
681 (princ (format "\n * %S:\n %S\n" name defn
))))
685 ;; check if SEQ is a prefix of some car of an element in ALIST
686 (defun vip-keyseq-is-a-possible-macro (seq alist
)
687 (let ((converted-seq (vip-events-to-macro seq
)))
690 (function (lambda (elt)
691 (vip-prefix-subseq-p converted-seq elt
)))
692 (vip-this-buffer-macros alist
))))))
694 ;; whether SEQ1 is a prefix of SEQ2
695 (defun vip-prefix-subseq-p (seq1 seq2
)
696 (let ((len1 (length seq1
))
697 (len2 (length seq2
)))
699 (equal seq1
(subseq seq2
0 len1
)))))
701 ;; find the longest common prefix
702 (defun vip-common-seq-prefix (&rest seqs
)
703 (let* ((first (car seqs
))
708 (if (= (length seqs
) 0)
710 (setq len
(apply 'min
(mapcar 'length seqs
))))
713 (mapcar (function (lambda (s)
714 (equal (elt first idx
)
717 (setq pref
(vconcat pref
(vector (elt first idx
)))))
721 ;; get all sequences that match PREFIX from a given A-LIST
722 (defun vip-extract-matching-alist-members (pref alist
)
723 (delq nil
(mapcar (function (lambda (elt)
724 (if (vip-prefix-subseq-p pref elt
)
726 (vip-this-buffer-macros alist
))))
728 (defun vip-do-sequence-completion (seq alist compl-message
)
729 (let* ((matches (vip-extract-matching-alist-members seq alist
))
730 (new-seq (apply 'vip-common-seq-prefix matches
))
732 (cond ((and (equal seq new-seq
) (= (length matches
) 1))
733 (message "%s (Sole completion)" compl-message
)
736 (message "%s (No match)" compl-message
)
739 ((member seq matches
)
740 (message "%s (Complete, but not unique)" compl-message
)
742 (vip-display-vector-completions matches
))
744 (vip-display-vector-completions matches
)))
748 (defun vip-display-vector-completions (list)
749 (with-output-to-temp-buffer "*Completions*"
750 (display-completion-list
751 (mapcar 'prin1-to-string
752 (mapcar 'vip-display-macro list
)))))
756 ;; alist is the alist of macros
757 ;; str is the fast key sequence entered
758 ;; returns: (matching-macro-def . unmatched-suffix-start-index)
759 (defun vip-find-best-matching-macro (alist str
)
762 (str-len (length str
))
763 match unmatched-start-idx found macro-def
)
764 (while (and (not found
) lis
)
765 (setq macro-def
(car lis
)
766 def-len
(length (car macro-def
)))
767 (if (and (>= str-len def-len
)
768 (equal (car macro-def
) (subseq str
0 def-len
)))
769 (if (or (vip-kbd-buf-definition macro-def
)
770 (vip-kbd-mode-definition macro-def
)
771 (vip-kbd-global-definition macro-def
))
774 (setq lis
(cdr lis
)))
777 (setq match macro-def
778 unmatched-start-idx def-len
)
780 unmatched-start-idx
0))
782 (cons match unmatched-start-idx
)))
786 ;; returns a list of names of macros defined for the current buffer
787 (defun vip-this-buffer-macros (macro-alist)
792 (if (or (vip-kbd-buf-definition elt
)
793 (vip-kbd-mode-definition elt
)
794 (vip-kbd-global-definition elt
))
797 (setq candidates
(delq nil candidates
))))
800 ;; if seq of Viper key symbols (representing a macro) can be converted to a
801 ;; string--do so. Otherwise, do nothing.
802 (defun vip-display-macro (macro-name-or-body)
803 (cond ((vip-char-symbol-sequence-p macro-name-or-body
)
804 (mapconcat 'symbol-name macro-name-or-body
""))
805 ((vip-char-array-p macro-name-or-body
)
806 (mapconcat 'char-to-string macro-name-or-body
""))
807 (t macro-name-or-body
)))
809 ;; convert sequence of events (that came presumably from emacs kbd macro) into
810 ;; Viper's macro, which is a vector of the form
812 ;; Each desc is either a symbol of (meta symb), (shift symb), etc.
813 ;; Here we purge events that happen to be lists. In most cases, these events
814 ;; got into a macro definition unintentionally; say, when the user moves mouse
815 ;; during a macro definition, then something like (switch-frame ...) might get
816 ;; in. Another reason for purging lists-events is that we can't store them in
817 ;; textual form (say, in .emacs) and then read them back.
818 (defun vip-events-to-macro (event-seq)
819 (vconcat (delq nil
(mapcar (function (lambda (elt)
822 (vip-event-key elt
))))
825 ;; convert strings or arrays of characters to Viper macro form
826 (defun vip-char-array-to-macro (array)
827 (let ((vec (vconcat array
))
830 (setq macro
(mapcar 'character-to-event vec
))
832 (vconcat (mapcar 'vip-event-key macro
))))
834 ;; For macros bodies and names, goes over MACRO and checks if all members are
835 ;; names of keys (actually, it only checks if they are symbols or lists
836 ;; if a digit is found, it is converted into a symbol (e.g., 0 -> \0, etc).
837 ;; If MACRO is not a list or vector -- doesn't change MACRO.
838 (defun vip-fixup-macro (macro)
839 (let ((len (length macro
))
842 (if (or (vectorp macro
) (listp macro
))
843 (while (and (< idx len
) (not break
))
844 (setq elt
(elt macro idx
))
847 (if (and (<= 0 elt
) (<= elt
9))
848 (cond ((arrayp macro
)
851 (intern (char-to-string (+ ?
0 elt
)))))
853 (setcar (nthcdr idx macro
)
854 (intern (char-to-string (+ ?
0 elt
)))))
857 (vip-fixup-macro elt
))
860 (setq idx
(1+ idx
))))
863 (error "Wrong type macro component, symbol-or-listp, %S" elt
)
866 (defun vip-char-array-p (array)
867 (eval (cons 'and
(mapcar 'vip-characterp array
))))
869 (defun vip-macro-to-events (macro-body)
870 (vconcat (mapcar 'vip-key-to-emacs-key macro-body
)))
873 ;; check if vec is a vector of character symbols
874 (defun vip-char-symbol-sequence-p (vec)
880 (function (lambda (elt)
881 (and (symbolp elt
) (= (length (symbol-name elt
)) 1))))
885 ;; Check if vec is a vector of key-press events representing characters
887 (defun vip-event-vector-p (vec)
889 (eval (cons 'and
(mapcar '(lambda (elt) (if (eventp elt
) t
)) vec
)))))
892 ;;; Reading fast key sequences
894 ;; Assuming that CHAR was the first character in a fast succession of key
895 ;; strokes, read the rest. Return the vector of keys that was entered in
896 ;; this fast succession of key strokes.
897 ;; A fast keysequence is one that is terminated by a pause longer than
898 ;; vip-fast-keyseq-timeout.
899 (defun vip-read-fast-keysequence (event macro-alist
)
900 (let ((lis (vector event
))
902 (while (and (vip-fast-keysequence-p)
903 (vip-keyseq-is-a-possible-macro lis macro-alist
))
904 (setq next-event
(vip-read-key))
905 ;;(setq next-event (vip-read-event))
906 (or (vip-mouse-event-p next-event
)
907 (setq lis
(vconcat lis
(vector next-event
)))))
911 ;;; Keyboard macros in registers
913 ;; sets register to last-kbd-macro carefully.
914 (defun vip-set-register-macro (reg)
915 (if (get-register reg
)
916 (if (y-or-n-p "Register contains data. Overwrite? ")
919 "Macro not saved in register. Can still be invoked via `C-x e'")))
920 (set-register reg last-kbd-macro
))
922 (defun vip-register-macro (count)
923 "Keyboard macros in registers - a modified \@ command."
925 (let ((reg (downcase (read-char))))
926 (cond ((or (and (<= ?a reg
) (<= reg ?z
)))
927 (setq vip-last-macro-reg reg
)
928 (if defining-kbd-macro
931 (vip-set-register-macro reg
))
932 (execute-kbd-macro (get-register reg
) count
)))
933 ((or (= ?
@ reg
) (= ?\^j reg
) (= ?\^m reg
))
934 (if vip-last-macro-reg
936 (error "No previous kbd macro"))
937 (execute-kbd-macro (get-register vip-last-macro-reg
) count
))
939 (start-kbd-macro count
))
941 (setq reg
(downcase (read-char)))
942 (if (or (and (<= ?a reg
) (<= reg ?z
)))
944 (setq vip-last-macro-reg reg
)
945 (vip-set-register-macro reg
))))
947 (error "`%c': Unknown register" reg
)))))
950 (defun vip-global-execute ()
951 "Call last keyboad macro for each line in the region."
952 (if (> (point) (mark t
)) (exchange-point-and-mark))
954 (call-last-kbd-macro)
955 (while (< (point) (mark t
))
958 (call-last-kbd-macro)))
961 ;;; viper-macs.el ends here