Mercurial > emacs
comparison lisp/emulation/viper-macs.el @ 49598:0d8b17d428b5
Trailing whitepace deleted.
author | Juanma Barranquero <lekktu@gmail.com> |
---|---|
date | Tue, 04 Feb 2003 13:24:35 +0000 |
parents | 633233bf2bbf |
children | 695cf19ef79e d7ddb3e565de |
comparison
equal
deleted
inserted
replaced
49597:e88404e8f2cf | 49598:0d8b17d428b5 |
---|---|
56 ;;; Variables | 56 ;;; Variables |
57 | 57 |
58 ;; Register holding last macro. | 58 ;; Register holding last macro. |
59 (defvar viper-last-macro-reg nil) | 59 (defvar viper-last-macro-reg nil) |
60 | 60 |
61 ;; format of the elements of kbd alists: | 61 ;; format of the elements of kbd alists: |
62 ;; (name ((buf . macr)...(buf . macr)) ((maj-mode . macr)...) (t . macr)) | 62 ;; (name ((buf . macr)...(buf . macr)) ((maj-mode . macr)...) (t . macr)) |
63 ;; kbd macro alist for Vi state | 63 ;; kbd macro alist for Vi state |
64 (defvar viper-vi-kbd-macro-alist nil) | 64 (defvar viper-vi-kbd-macro-alist nil) |
65 ;; same for insert/replace state | 65 ;; same for insert/replace state |
66 (defvar viper-insert-kbd-macro-alist nil) | 66 (defvar viper-insert-kbd-macro-alist nil) |
119 (define-key viper-emacs-intercept-map "\C-x)" 'viper-end-mapping-kbd-macro) | 119 (define-key viper-emacs-intercept-map "\C-x)" 'viper-end-mapping-kbd-macro) |
120 (message "Mapping %S in %s state. Hit `C-x )' to complete the mapping" | 120 (message "Mapping %S in %s state. Hit `C-x )' to complete the mapping" |
121 (viper-display-macro macro-name) | 121 (viper-display-macro macro-name) |
122 (if ins "Insert" "Vi"))) | 122 (if ins "Insert" "Vi"))) |
123 )) | 123 )) |
124 | 124 |
125 | 125 |
126 ;; Ex unmap | 126 ;; Ex unmap |
127 (defun ex-unmap () | 127 (defun ex-unmap () |
128 (let ((mod-char "") | 128 (let ((mod-char "") |
129 temp macro-name ins) | 129 temp macro-name ins) |
139 (setq temp (viper-fixup-macro (vconcat macro-name))) ;; copy and fixup | 139 (setq temp (viper-fixup-macro (vconcat macro-name))) ;; copy and fixup |
140 (ex-fixup-history (format "unmap%s %S" mod-char | 140 (ex-fixup-history (format "unmap%s %S" mod-char |
141 (viper-display-macro temp))) | 141 (viper-display-macro temp))) |
142 (viper-unrecord-kbd-macro macro-name (if ins 'insert-state 'vi-state)) | 142 (viper-unrecord-kbd-macro macro-name (if ins 'insert-state 'vi-state)) |
143 )) | 143 )) |
144 | 144 |
145 | 145 |
146 ;; read arguments for ex-map | 146 ;; read arguments for ex-map |
147 (defun ex-map-read-args (variant) | 147 (defun ex-map-read-args (variant) |
148 (let ((cursor-in-echo-area t) | 148 (let ((cursor-in-echo-area t) |
149 (key-seq []) | 149 (key-seq []) |
150 temp key event message | 150 temp key event message |
151 macro-name macro-body args) | 151 macro-name macro-body args) |
152 | 152 |
153 (condition-case nil | 153 (condition-case nil |
154 (setq args (concat (ex-get-inline-cmd-args ".*map[!]*[ \t]?" "\n\C-m") | 154 (setq args (concat (ex-get-inline-cmd-args ".*map[!]*[ \t]?" "\n\C-m") |
155 " nil nil ") | 155 " nil nil ") |
156 temp (read-from-string args) | 156 temp (read-from-string args) |
157 macro-name (car temp) | 157 macro-name (car temp) |
158 macro-body (car (read-from-string args (cdr temp)))) | 158 macro-body (car (read-from-string args (cdr temp)))) |
159 (error | 159 (error |
160 (signal | 160 (signal |
161 'error | 161 'error |
162 '("map: Macro name and body must be a quoted string or a vector")))) | 162 '("map: Macro name and body must be a quoted string or a vector")))) |
163 | 163 |
164 ;; We expect macro-name to be a vector, a string, or a quoted string. | 164 ;; We expect macro-name to be a vector, a string, or a quoted string. |
165 ;; In the second case, it will emerge as a symbol when read from | 165 ;; In the second case, it will emerge as a symbol when read from |
166 ;; the above read-from-string. So we need to convert it into a string | 166 ;; the above read-from-string. So we need to convert it into a string |
167 (if macro-name | 167 (if macro-name |
168 (cond ((vectorp macro-name) nil) | 168 (cond ((vectorp macro-name) nil) |
169 ((stringp macro-name) | 169 ((stringp macro-name) |
170 (setq macro-name (vconcat macro-name))) | 170 (setq macro-name (vconcat macro-name))) |
171 (t (setq macro-name (vconcat (prin1-to-string macro-name))))) | 171 (t (setq macro-name (vconcat (prin1-to-string macro-name))))) |
172 (message ":map%s <Name>" variant)(sit-for 2) | 172 (message ":map%s <Name>" variant)(sit-for 2) |
173 (while | 173 (while |
174 (not (member key | 174 (not (member key |
196 (sit-for 2) | 196 (sit-for 2) |
197 nil) | 197 nil) |
198 (viper-event-key event))) | 198 (viper-event-key event))) |
199 ) | 199 ) |
200 (setq macro-name key-seq)) | 200 (setq macro-name key-seq)) |
201 | 201 |
202 (if (= (length macro-name) 0) | 202 (if (= (length macro-name) 0) |
203 (error "Can't map an empty macro name")) | 203 (error "Can't map an empty macro name")) |
204 (setq macro-name (viper-fixup-macro macro-name)) | 204 (setq macro-name (viper-fixup-macro macro-name)) |
205 (if (viper-char-array-p macro-name) | 205 (if (viper-char-array-p macro-name) |
206 (setq macro-name (viper-char-array-to-macro macro-name))) | 206 (setq macro-name (viper-char-array-to-macro macro-name))) |
207 | 207 |
208 (if macro-body | 208 (if macro-body |
209 (cond ((viper-char-array-p macro-body) | 209 (cond ((viper-char-array-p macro-body) |
210 (setq macro-body (viper-char-array-to-macro macro-body))) | 210 (setq macro-body (viper-char-array-to-macro macro-body))) |
211 ((vectorp macro-body) nil) | 211 ((vectorp macro-body) nil) |
212 (t (error "map: Invalid syntax in macro definition")))) | 212 (t (error "map: Invalid syntax in macro definition")))) |
213 (setq cursor-in-echo-area nil)(sit-for 0) ; this overcomes xemacs tty bug | 213 (setq cursor-in-echo-area nil)(sit-for 0) ; this overcomes xemacs tty bug |
214 (cons macro-name macro-body))) | 214 (cons macro-name macro-body))) |
215 | 215 |
216 | 216 |
217 | 217 |
218 ;; read arguments for ex-unmap | 218 ;; read arguments for ex-unmap |
219 (defun ex-unmap-read-args (variant) | 219 (defun ex-unmap-read-args (variant) |
220 (let ((cursor-in-echo-area t) | 220 (let ((cursor-in-echo-area t) |
228 viper-vi-intercept-minor-mode viper-insert-intercept-minor-mode | 228 viper-vi-intercept-minor-mode viper-insert-intercept-minor-mode |
229 viper-emacs-intercept-minor-mode | 229 viper-emacs-intercept-minor-mode |
230 event message | 230 event message |
231 key key-seq macro-name) | 231 key key-seq macro-name) |
232 (setq macro-name (ex-get-inline-cmd-args ".*unma?p?[!]*[ \t]*")) | 232 (setq macro-name (ex-get-inline-cmd-args ".*unma?p?[!]*[ \t]*")) |
233 | 233 |
234 (if (> (length macro-name) 0) | 234 (if (> (length macro-name) 0) |
235 () | 235 () |
236 (message ":unmap%s <Name>" variant) (sit-for 2) | 236 (message ":unmap%s <Name>" variant) (sit-for 2) |
237 (while | 237 (while |
238 (not | 238 (not |
243 key | 243 key |
244 '(?\b ?\d '^? '^H (control h) (control \?) backspace delete)) | 244 '(?\b ?\d '^? '^H (control h) (control \?) backspace delete)) |
245 (setq key-seq (subseq key-seq 0 (- (length key-seq) 2)))) | 245 (setq key-seq (subseq key-seq 0 (- (length key-seq) 2)))) |
246 ((member key '(tab (control i) ?\t)) | 246 ((member key '(tab (control i) ?\t)) |
247 (setq key-seq (subseq key-seq 0 (1- (length key-seq)))) | 247 (setq key-seq (subseq key-seq 0 (1- (length key-seq)))) |
248 (setq message | 248 (setq message |
249 (format | 249 (format |
250 ":unmap%s %s" | 250 ":unmap%s %s" |
251 variant (if (> (length key-seq) 0) | 251 variant (if (> (length key-seq) 0) |
252 (prin1-to-string | 252 (prin1-to-string |
253 (viper-display-macro key-seq)) | 253 (viper-display-macro key-seq)) |
254 ""))) | 254 ""))) |
255 (setq key-seq | 255 (setq key-seq |
256 (viper-do-sequence-completion key-seq macro-alist message)) | 256 (viper-do-sequence-completion key-seq macro-alist message)) |
257 )) | 257 )) |
258 (setq message | 258 (setq message |
259 (format | 259 (format |
260 ":unmap%s %s" | 260 ":unmap%s %s" |
261 variant (if (> (length key-seq) 0) | 261 variant (if (> (length key-seq) 0) |
262 (prin1-to-string | 262 (prin1-to-string |
263 (viper-display-macro key-seq)) | 263 (viper-display-macro key-seq)) |
276 ) | 276 ) |
277 (setq macro-name key-seq)) | 277 (setq macro-name key-seq)) |
278 | 278 |
279 (if (= (length macro-name) 0) | 279 (if (= (length macro-name) 0) |
280 (error "Can't unmap an empty macro name")) | 280 (error "Can't unmap an empty macro name")) |
281 | 281 |
282 ;; convert macro names into vector, if starts with a `[' | 282 ;; convert macro names into vector, if starts with a `[' |
283 (if (memq (elt macro-name 0) '(?\[ ?\")) | 283 (if (memq (elt macro-name 0) '(?\[ ?\")) |
284 (car (read-from-string macro-name)) | 284 (car (read-from-string macro-name)) |
285 (vconcat macro-name)) | 285 (vconcat macro-name)) |
286 )) | 286 )) |
287 | 287 |
288 | 288 |
289 ;; Terminate a Vi kbd macro. | 289 ;; Terminate a Vi kbd macro. |
290 ;; optional argument IGNORE, if t, indicates that we are dealing with an | 290 ;; optional argument IGNORE, if t, indicates that we are dealing with an |
291 ;; existing macro that needs to be registered, but there is no need to | 291 ;; existing macro that needs to be registered, but there is no need to |
292 ;; terminate a kbd macro. | 292 ;; terminate a kbd macro. |
293 (defun viper-end-mapping-kbd-macro (&optional ignore) | 293 (defun viper-end-mapping-kbd-macro (&optional ignore) |
309 (end-kbd-macro nil) | 309 (end-kbd-macro nil) |
310 (setq macro-body (viper-events-to-macro last-kbd-macro)) | 310 (setq macro-body (viper-events-to-macro last-kbd-macro)) |
311 ;; always go back to Vi, since this is where we started | 311 ;; always go back to Vi, since this is where we started |
312 ;; defining macro | 312 ;; defining macro |
313 (viper-change-state-to-vi))) | 313 (viper-change-state-to-vi))) |
314 | 314 |
315 (viper-record-kbd-macro macro-name | 315 (viper-record-kbd-macro macro-name |
316 (if ins 'insert-state 'vi-state) | 316 (if ins 'insert-state 'vi-state) |
317 (viper-display-macro macro-body)) | 317 (viper-display-macro macro-body)) |
318 | 318 |
319 (ex-fixup-history (format "map%s %S %S" mod-char | 319 (ex-fixup-history (format "map%s %S %S" mod-char |
320 (viper-display-macro macro-name) | 320 (viper-display-macro macro-name) |
321 (viper-display-macro macro-body))) | 321 (viper-display-macro macro-body))) |
322 )) | 322 )) |
323 | 323 |
335 either `vi-state' or `insert-state'. It specifies the Viper state in which to | 335 either `vi-state' or `insert-state'. It specifies the Viper state in which to |
336 define the macro. MACRO-BODY is a string that represents the keyboard macro. | 336 define the macro. MACRO-BODY is a string that represents the keyboard macro. |
337 Optional SCOPE says whether the macro should be global \(t\), mode-specific | 337 Optional SCOPE says whether the macro should be global \(t\), mode-specific |
338 \(a major-mode symbol\), or buffer-specific \(buffer name, a string\). | 338 \(a major-mode symbol\), or buffer-specific \(buffer name, a string\). |
339 If SCOPE is nil, the user is asked to specify the scope." | 339 If SCOPE is nil, the user is asked to specify the scope." |
340 (let* (state-name keymap | 340 (let* (state-name keymap |
341 (macro-alist-var | 341 (macro-alist-var |
342 (cond ((eq state 'vi-state) | 342 (cond ((eq state 'vi-state) |
343 (setq state-name "Vi state" | 343 (setq state-name "Vi state" |
344 keymap viper-vi-kbd-map) | 344 keymap viper-vi-kbd-map) |
345 'viper-vi-kbd-macro-alist) | 345 'viper-vi-kbd-macro-alist) |
352 keymap viper-emacs-kbd-map) | 352 keymap viper-emacs-kbd-map) |
353 'viper-emacs-kbd-macro-alist) | 353 'viper-emacs-kbd-macro-alist) |
354 )) | 354 )) |
355 new-elt old-elt old-sub-elt msg | 355 new-elt old-elt old-sub-elt msg |
356 temp lis lis2) | 356 temp lis lis2) |
357 | 357 |
358 (if (= (length macro-name) 0) | 358 (if (= (length macro-name) 0) |
359 (error "Can't map an empty macro name")) | 359 (error "Can't map an empty macro name")) |
360 | 360 |
361 ;; Macro-name is usually a vector. However, command history or macros | 361 ;; Macro-name is usually a vector. However, command history or macros |
362 ;; recorded in ~/.viper may be recorded as strings. So, convert to | 362 ;; recorded in ~/.viper may be recorded as strings. So, convert to |
363 ;; vectors. | 363 ;; vectors. |
364 (setq macro-name (viper-fixup-macro macro-name)) | 364 (setq macro-name (viper-fixup-macro macro-name)) |
365 (if (viper-char-array-p macro-name) | 365 (if (viper-char-array-p macro-name) |
366 (setq macro-name (viper-char-array-to-macro macro-name))) | 366 (setq macro-name (viper-char-array-to-macro macro-name))) |
367 (setq macro-body (viper-fixup-macro macro-body)) | 367 (setq macro-body (viper-fixup-macro macro-body)) |
368 (if (viper-char-array-p macro-body) | 368 (if (viper-char-array-p macro-body) |
369 (setq macro-body (viper-char-array-to-macro macro-body))) | 369 (setq macro-body (viper-char-array-to-macro macro-body))) |
370 | 370 |
371 ;; don't ask if scope is given and is of the right type | 371 ;; don't ask if scope is given and is of the right type |
372 (or (eq scope t) | 372 (or (eq scope t) |
373 (stringp scope) | 373 (stringp scope) |
374 (and scope (symbolp scope)) | 374 (and scope (symbolp scope)) |
375 (progn | 375 (progn |
421 state-name)) | 421 state-name)) |
422 t))) | 422 t))) |
423 (if (y-or-n-p | 423 (if (y-or-n-p |
424 (format "Save this macro in %s? " | 424 (format "Save this macro in %s? " |
425 (viper-abbreviate-file-name viper-custom-file-name))) | 425 (viper-abbreviate-file-name viper-custom-file-name))) |
426 (viper-save-string-in-file | 426 (viper-save-string-in-file |
427 (format "\n(viper-record-kbd-macro %S '%S %s '%S)" | 427 (format "\n(viper-record-kbd-macro %S '%S %s '%S)" |
428 (viper-display-macro macro-name) | 428 (viper-display-macro macro-name) |
429 state | 429 state |
430 ;; if we don't let vector macro-body through %S, | 430 ;; if we don't let vector macro-body through %S, |
431 ;; the symbols `\.' `\[' etc will be converted into | 431 ;; the symbols `\.' `\[' etc will be converted into |
434 ;; I am not sure is macro-body can still be a string at | 434 ;; I am not sure is macro-body can still be a string at |
435 ;; this point, but I am preserving this option anyway. | 435 ;; this point, but I am preserving this option anyway. |
436 (if (vectorp macro-body) | 436 (if (vectorp macro-body) |
437 (format "%S" macro-body) | 437 (format "%S" macro-body) |
438 macro-body) | 438 macro-body) |
439 scope) | 439 scope) |
440 viper-custom-file-name)) | 440 viper-custom-file-name)) |
441 | 441 |
442 (message msg) | 442 (message msg) |
443 )) | 443 )) |
444 | 444 |
445 (setq new-elt | 445 (setq new-elt |
446 (cons macro-name | 446 (cons macro-name |
447 (cond ((eq scope t) (list nil nil (cons t nil))) | 447 (cond ((eq scope t) (list nil nil (cons t nil))) |
448 ((symbolp scope) | 448 ((symbolp scope) |
449 (list nil (list (cons scope nil)) (cons t nil))) | 449 (list nil (list (cons scope nil)) (cons t nil))) |
461 (setq lis (eval macro-alist-var)) | 461 (setq lis (eval macro-alist-var)) |
462 (while (and lis (string< (viper-array-to-string (car (car lis))) | 462 (while (and lis (string< (viper-array-to-string (car (car lis))) |
463 (viper-array-to-string macro-name))) | 463 (viper-array-to-string macro-name))) |
464 (setq lis2 (cons (car lis) lis2)) | 464 (setq lis2 (cons (car lis) lis2)) |
465 (setq lis (cdr lis))) | 465 (setq lis (cdr lis))) |
466 | 466 |
467 (setq lis2 (reverse lis2)) | 467 (setq lis2 (reverse lis2)) |
468 (set macro-alist-var (append lis2 (cons new-elt lis))) | 468 (set macro-alist-var (append lis2 (cons new-elt lis))) |
469 (setq old-elt new-elt))) | 469 (setq old-elt new-elt))) |
470 (setq old-sub-elt | 470 (setq old-sub-elt |
471 (cond ((eq scope t) (viper-kbd-global-pair old-elt)) | 471 (cond ((eq scope t) (viper-kbd-global-pair old-elt)) |
472 ((symbolp scope) (assoc scope (viper-kbd-mode-alist old-elt))) | 472 ((symbolp scope) (assoc scope (viper-kbd-mode-alist old-elt))) |
473 ((stringp scope) (assoc scope (viper-kbd-buf-alist old-elt))))) | 473 ((stringp scope) (assoc scope (viper-kbd-buf-alist old-elt))))) |
474 (if old-sub-elt | 474 (if old-sub-elt |
475 (setcdr old-sub-elt macro-body) | 475 (setcdr old-sub-elt macro-body) |
476 (cond ((symbolp scope) (setcar (cdr (cdr old-elt)) | 476 (cond ((symbolp scope) (setcar (cdr (cdr old-elt)) |
477 (cons (cons scope macro-body) | 477 (cons (cons scope macro-body) |
478 (viper-kbd-mode-alist old-elt)))) | 478 (viper-kbd-mode-alist old-elt)))) |
479 ((stringp scope) (setcar (cdr old-elt) | 479 ((stringp scope) (setcar (cdr old-elt) |
480 (cons (cons scope macro-body) | 480 (cons (cons scope macro-body) |
481 (viper-kbd-buf-alist old-elt)))))) | 481 (viper-kbd-buf-alist old-elt)))))) |
482 )) | 482 )) |
483 | 483 |
484 | 484 |
485 | 485 |
486 ;; macro name must be a vector of viper-style keys | 486 ;; macro name must be a vector of viper-style keys |
487 (defun viper-unrecord-kbd-macro (macro-name state) | 487 (defun viper-unrecord-kbd-macro (macro-name state) |
488 "Delete macro MACRO-NAME from Viper STATE. | 488 "Delete macro MACRO-NAME from Viper STATE. |
489 MACRO-NAME must be a vector of viper-style keys. This command is used by Viper | 489 MACRO-NAME must be a vector of viper-style keys. This command is used by Viper |
490 internally, but the user can also use it in ~/.viper to delete pre-defined | 490 internally, but the user can also use it in ~/.viper to delete pre-defined |
491 macros supplied with Viper. The best way to avoid mistakes in macro names to | 491 macros supplied with Viper. The best way to avoid mistakes in macro names to |
492 be passed to this function is to use viper-describe-kbd-macros and copy the | 492 be passed to this function is to use viper-describe-kbd-macros and copy the |
493 name from there." | 493 name from there." |
494 (let* (state-name keymap | 494 (let* (state-name keymap |
495 (macro-alist-var | 495 (macro-alist-var |
496 (cond ((eq state 'vi-state) | 496 (cond ((eq state 'vi-state) |
497 (setq state-name "Vi state" | 497 (setq state-name "Vi state" |
498 keymap viper-vi-kbd-map) | 498 keymap viper-vi-kbd-map) |
499 'viper-vi-kbd-macro-alist) | 499 'viper-vi-kbd-macro-alist) |
506 keymap viper-emacs-kbd-map) | 506 keymap viper-emacs-kbd-map) |
507 'viper-emacs-kbd-macro-alist) | 507 'viper-emacs-kbd-macro-alist) |
508 )) | 508 )) |
509 buf-mapping mode-mapping global-mapping | 509 buf-mapping mode-mapping global-mapping |
510 macro-pair macro-entry) | 510 macro-pair macro-entry) |
511 | 511 |
512 ;; Macro-name is usually a vector. However, command history or macros | 512 ;; Macro-name is usually a vector. However, command history or macros |
513 ;; recorded in ~/.viper may appear as strings. So, convert to vectors. | 513 ;; recorded in ~/.viper may appear as strings. So, convert to vectors. |
514 (setq macro-name (viper-fixup-macro macro-name)) | 514 (setq macro-name (viper-fixup-macro macro-name)) |
515 (if (viper-char-array-p macro-name) | 515 (if (viper-char-array-p macro-name) |
516 (setq macro-name (viper-char-array-to-macro macro-name))) | 516 (setq macro-name (viper-char-array-to-macro macro-name))) |
520 (error "Can't unmap an empty macro name")) | 520 (error "Can't unmap an empty macro name")) |
521 (if (null macro-entry) | 521 (if (null macro-entry) |
522 (error "%S is not mapped to a macro for %s in `%s'" | 522 (error "%S is not mapped to a macro for %s in `%s'" |
523 (viper-display-macro macro-name) | 523 (viper-display-macro macro-name) |
524 state-name (buffer-name))) | 524 state-name (buffer-name))) |
525 | 525 |
526 (setq buf-mapping (viper-kbd-buf-pair macro-entry) | 526 (setq buf-mapping (viper-kbd-buf-pair macro-entry) |
527 mode-mapping (viper-kbd-mode-pair macro-entry) | 527 mode-mapping (viper-kbd-mode-pair macro-entry) |
528 global-mapping (viper-kbd-global-pair macro-entry)) | 528 global-mapping (viper-kbd-global-pair macro-entry)) |
529 | 529 |
530 (cond ((and (cdr buf-mapping) | 530 (cond ((and (cdr buf-mapping) |
531 (or (and (not (cdr mode-mapping)) (not (cdr global-mapping))) | 531 (or (and (not (cdr mode-mapping)) (not (cdr global-mapping))) |
532 (y-or-n-p | 532 (y-or-n-p |
533 (format "Unmap %S for `%s' only? " | 533 (format "Unmap %S for `%s' only? " |
534 (viper-display-macro macro-name) | 534 (viper-display-macro macro-name) |
535 (buffer-name))))) | 535 (buffer-name))))) |
536 (setq macro-pair buf-mapping) | 536 (setq macro-pair buf-mapping) |
537 (message "%S is unmapped for %s in `%s'" | 537 (message "%S is unmapped for %s in `%s'" |
538 (viper-display-macro macro-name) | 538 (viper-display-macro macro-name) |
539 state-name (buffer-name))) | 539 state-name (buffer-name))) |
540 ((and (cdr mode-mapping) | 540 ((and (cdr mode-mapping) |
541 (or (not (cdr global-mapping)) | 541 (or (not (cdr global-mapping)) |
542 (y-or-n-p | 542 (y-or-n-p |
557 (or (cdr buf-mapping) | 557 (or (cdr buf-mapping) |
558 (cdr mode-mapping) | 558 (cdr mode-mapping) |
559 (cdr global-mapping) | 559 (cdr global-mapping) |
560 (progn | 560 (progn |
561 (set macro-alist-var (delq macro-entry (eval macro-alist-var))) | 561 (set macro-alist-var (delq macro-entry (eval macro-alist-var))) |
562 (if (viper-can-release-key (aref macro-name 0) | 562 (if (viper-can-release-key (aref macro-name 0) |
563 (eval macro-alist-var)) | 563 (eval macro-alist-var)) |
564 (define-key | 564 (define-key |
565 keymap | 565 keymap |
566 (vector (viper-key-to-emacs-key (aref macro-name 0))) | 566 (vector (viper-key-to-emacs-key (aref macro-name 0))) |
567 nil)) | 567 nil)) |
568 )) | 568 )) |
569 )) | 569 )) |
570 | 570 |
571 ;; Check if MACRO-ALIST has an entry for a macro name starting with | 571 ;; Check if MACRO-ALIST has an entry for a macro name starting with |
572 ;; CHAR. If not, this indicates that the binding for this char | 572 ;; CHAR. If not, this indicates that the binding for this char |
573 ;; in viper-vi/insert-kbd-map can be released. | 573 ;; in viper-vi/insert-kbd-map can be released. |
574 (defun viper-can-release-key (char macro-alist) | 574 (defun viper-can-release-key (char macro-alist) |
575 (let ((lis macro-alist) | 575 (let ((lis macro-alist) |
576 (can-release t) | 576 (can-release t) |
577 macro-name) | 577 macro-name) |
578 | 578 |
579 (while (and lis can-release) | 579 (while (and lis can-release) |
580 (setq macro-name (car (car lis))) | 580 (setq macro-name (car (car lis))) |
581 (if (eq char (aref macro-name 0)) | 581 (if (eq char (aref macro-name 0)) |
582 (setq can-release nil)) | 582 (setq can-release nil)) |
583 (setq lis (cdr lis))) | 583 (setq lis (cdr lis))) |
600 viper-vi-kbd-minor-mode viper-insert-kbd-minor-mode | 600 viper-vi-kbd-minor-mode viper-insert-kbd-minor-mode |
601 viper-emacs-kbd-minor-mode | 601 viper-emacs-kbd-minor-mode |
602 next-best-match keyseq event-seq | 602 next-best-match keyseq event-seq |
603 macro-first-char macro-alist-elt macro-body | 603 macro-first-char macro-alist-elt macro-body |
604 command) | 604 command) |
605 | 605 |
606 (setq macro-first-char last-command-event | 606 (setq macro-first-char last-command-event |
607 event-seq (viper-read-fast-keysequence macro-first-char macro-alist) | 607 event-seq (viper-read-fast-keysequence macro-first-char macro-alist) |
608 keyseq (viper-events-to-macro event-seq) | 608 keyseq (viper-events-to-macro event-seq) |
609 macro-alist-elt (assoc keyseq macro-alist) | 609 macro-alist-elt (assoc keyseq macro-alist) |
610 next-best-match (viper-find-best-matching-macro macro-alist keyseq)) | 610 next-best-match (viper-find-best-matching-macro macro-alist keyseq)) |
611 | 611 |
612 (if (null macro-alist-elt) | 612 (if (null macro-alist-elt) |
613 (setq macro-alist-elt (car next-best-match) | 613 (setq macro-alist-elt (car next-best-match) |
614 unmatched-suffix (subseq event-seq (cdr next-best-match)))) | 614 unmatched-suffix (subseq event-seq (cdr next-best-match)))) |
615 | 615 |
616 (cond ((null macro-alist-elt)) | 616 (cond ((null macro-alist-elt)) |
617 ((setq macro-body (viper-kbd-buf-definition macro-alist-elt))) | 617 ((setq macro-body (viper-kbd-buf-definition macro-alist-elt))) |
618 ((setq macro-body (viper-kbd-mode-definition macro-alist-elt))) | 618 ((setq macro-body (viper-kbd-mode-definition macro-alist-elt))) |
619 ((setq macro-body (viper-kbd-global-definition macro-alist-elt)))) | 619 ((setq macro-body (viper-kbd-global-definition macro-alist-elt)))) |
620 | 620 |
621 ;; when defining keyboard macro, don't use the macro mappings | 621 ;; when defining keyboard macro, don't use the macro mappings |
622 (if (and macro-body (not defining-kbd-macro)) | 622 (if (and macro-body (not defining-kbd-macro)) |
623 ;; block cmd executed as part of a macro from entering command history | 623 ;; block cmd executed as part of a macro from entering command history |
624 (let ((command-history command-history)) | 624 (let ((command-history command-history)) |
625 (setq viper-this-kbd-macro (car macro-alist-elt)) | 625 (setq viper-this-kbd-macro (car macro-alist-elt)) |
632 (viper-set-unread-command-events event-seq) | 632 (viper-set-unread-command-events event-seq) |
633 ;; if the user typed arg, then use it if prefix arg is not set by | 633 ;; if the user typed arg, then use it if prefix arg is not set by |
634 ;; some other command (setting prefix arg can happen if we do, say, | 634 ;; some other command (setting prefix arg can happen if we do, say, |
635 ;; 2dw and there is a macro starting with 2. Then control will go to | 635 ;; 2dw and there is a macro starting with 2. Then control will go to |
636 ;; this routine | 636 ;; this routine |
637 (or prefix-arg (setq prefix-arg count)) | 637 (or prefix-arg (setq prefix-arg count)) |
638 (setq command (key-binding (read-key-sequence nil))) | 638 (setq command (key-binding (read-key-sequence nil))) |
639 (if (commandp command) | 639 (if (commandp command) |
640 (command-execute command) | 640 (command-execute command) |
641 (beep 1))) | 641 (beep 1))) |
642 )) | 642 )) |
643 | 643 |
644 | 644 |
645 | 645 |
646 ;;; Displaying and completing macros | 646 ;;; Displaying and completing macros |
647 | 647 |
648 (defun viper-describe-kbd-macros () | 648 (defun viper-describe-kbd-macros () |
649 "Show currently defined keyboard macros." | 649 "Show currently defined keyboard macros." |
650 (interactive) | 650 (interactive) |
651 (with-output-to-temp-buffer " *viper-info*" | 651 (with-output-to-temp-buffer " *viper-info*" |
652 (princ "Macros in Vi state:\n===================\n") | 652 (princ "Macros in Vi state:\n===================\n") |
654 (princ "\n\nMacros in Insert and Replace states:\n====================================\n") | 654 (princ "\n\nMacros in Insert and Replace states:\n====================================\n") |
655 (mapcar 'viper-describe-one-macro viper-insert-kbd-macro-alist) | 655 (mapcar 'viper-describe-one-macro viper-insert-kbd-macro-alist) |
656 (princ "\n\nMacros in Emacs state:\n======================\n") | 656 (princ "\n\nMacros in Emacs state:\n======================\n") |
657 (mapcar 'viper-describe-one-macro viper-emacs-kbd-macro-alist) | 657 (mapcar 'viper-describe-one-macro viper-emacs-kbd-macro-alist) |
658 )) | 658 )) |
659 | 659 |
660 (defun viper-describe-one-macro (macro) | 660 (defun viper-describe-one-macro (macro) |
661 (princ (format "\n *** Mappings for %S:\n ------------\n" | 661 (princ (format "\n *** Mappings for %S:\n ------------\n" |
662 (viper-display-macro (car macro)))) | 662 (viper-display-macro (car macro)))) |
663 (princ " ** Buffer-specific:") | 663 (princ " ** Buffer-specific:") |
664 (if (viper-kbd-buf-alist macro) | 664 (if (viper-kbd-buf-alist macro) |
671 (princ "\n ** Global:") | 671 (princ "\n ** Global:") |
672 (if (viper-kbd-global-definition macro) | 672 (if (viper-kbd-global-definition macro) |
673 (princ (format "\n %S" (cdr (viper-kbd-global-pair macro)))) | 673 (princ (format "\n %S" (cdr (viper-kbd-global-pair macro)))) |
674 (princ " none")) | 674 (princ " none")) |
675 (princ "\n")) | 675 (princ "\n")) |
676 | 676 |
677 (defun viper-describe-one-macro-elt (elt) | 677 (defun viper-describe-one-macro-elt (elt) |
678 (let ((name (car elt)) | 678 (let ((name (car elt)) |
679 (defn (cdr elt))) | 679 (defn (cdr elt))) |
680 (princ (format "\n * %S:\n %S\n" name defn)))) | 680 (princ (format "\n * %S:\n %S\n" name defn)))) |
681 | 681 |
682 | 682 |
683 | 683 |
684 ;; check if SEQ is a prefix of some car of an element in ALIST | 684 ;; check if SEQ is a prefix of some car of an element in ALIST |
685 (defun viper-keyseq-is-a-possible-macro (seq alist) | 685 (defun viper-keyseq-is-a-possible-macro (seq alist) |
686 (let ((converted-seq (viper-events-to-macro seq))) | 686 (let ((converted-seq (viper-events-to-macro seq))) |
687 (eval (cons 'or | 687 (eval (cons 'or |
688 (mapcar | 688 (mapcar |
689 (lambda (elt) (viper-prefix-subseq-p converted-seq elt)) | 689 (lambda (elt) (viper-prefix-subseq-p converted-seq elt)) |
690 (viper-this-buffer-macros alist)))))) | 690 (viper-this-buffer-macros alist)))))) |
691 | 691 |
692 ;; whether SEQ1 is a prefix of SEQ2 | 692 ;; whether SEQ1 is a prefix of SEQ2 |
693 (defun viper-prefix-subseq-p (seq1 seq2) | 693 (defun viper-prefix-subseq-p (seq1 seq2) |
694 (let ((len1 (length seq1)) | 694 (let ((len1 (length seq1)) |
695 (len2 (length seq2))) | 695 (len2 (length seq2))) |
696 (if (<= len1 len2) | 696 (if (<= len1 len2) |
697 (equal seq1 (subseq seq2 0 len1))))) | 697 (equal seq1 (subseq seq2 0 len1))))) |
698 | 698 |
699 ;; find the longest common prefix | 699 ;; find the longest common prefix |
700 (defun viper-common-seq-prefix (&rest seqs) | 700 (defun viper-common-seq-prefix (&rest seqs) |
701 (let* ((first (car seqs)) | 701 (let* ((first (car seqs)) |
702 (rest (cdr seqs)) | 702 (rest (cdr seqs)) |
703 (pref []) | 703 (pref []) |
705 len) | 705 len) |
706 (if (= (length seqs) 0) | 706 (if (= (length seqs) 0) |
707 (setq len 0) | 707 (setq len 0) |
708 (setq len (apply 'min (mapcar 'length seqs)))) | 708 (setq len (apply 'min (mapcar 'length seqs)))) |
709 (while (< idx len) | 709 (while (< idx len) |
710 (if (eval (cons 'and | 710 (if (eval (cons 'and |
711 (mapcar (lambda (s) (equal (elt first idx) (elt s idx))) | 711 (mapcar (lambda (s) (equal (elt first idx) (elt s idx))) |
712 rest))) | 712 rest))) |
713 (setq pref (vconcat pref (vector (elt first idx))))) | 713 (setq pref (vconcat pref (vector (elt first idx))))) |
714 (setq idx (1+ idx))) | 714 (setq idx (1+ idx))) |
715 pref)) | 715 pref)) |
716 | 716 |
717 ;; get all sequences that match PREFIX from a given A-LIST | 717 ;; get all sequences that match PREFIX from a given A-LIST |
718 (defun viper-extract-matching-alist-members (pref alist) | 718 (defun viper-extract-matching-alist-members (pref alist) |
719 (delq nil (mapcar (lambda (elt) (if (viper-prefix-subseq-p pref elt) elt)) | 719 (delq nil (mapcar (lambda (elt) (if (viper-prefix-subseq-p pref elt) elt)) |
720 (viper-this-buffer-macros alist)))) | 720 (viper-this-buffer-macros alist)))) |
721 | 721 |
722 (defun viper-do-sequence-completion (seq alist compl-message) | 722 (defun viper-do-sequence-completion (seq alist compl-message) |
723 (let* ((matches (viper-extract-matching-alist-members seq alist)) | 723 (let* ((matches (viper-extract-matching-alist-members seq alist)) |
724 (new-seq (apply 'viper-common-seq-prefix matches)) | 724 (new-seq (apply 'viper-common-seq-prefix matches)) |
725 ) | 725 ) |
726 (cond ((and (equal seq new-seq) (= (length matches) 1)) | 726 (cond ((and (equal seq new-seq) (= (length matches) 1)) |
727 (message "%s (Sole completion)" compl-message) | 727 (message "%s (Sole completion)" compl-message) |
728 (sit-for 2)) | 728 (sit-for 2)) |
729 ((null matches) | 729 ((null matches) |
730 (message "%s (No match)" compl-message) | 730 (message "%s (No match)" compl-message) |
731 (sit-for 2) | 731 (sit-for 2) |
732 (setq new-seq seq)) | 732 (setq new-seq seq)) |
733 ((member seq matches) | 733 ((member seq matches) |
734 (message "%s (Complete, but not unique)" compl-message) | 734 (message "%s (Complete, but not unique)" compl-message) |
735 (sit-for 2) | 735 (sit-for 2) |
736 (viper-display-vector-completions matches)) | 736 (viper-display-vector-completions matches)) |
737 ((equal seq new-seq) | 737 ((equal seq new-seq) |
738 (viper-display-vector-completions matches))) | 738 (viper-display-vector-completions matches))) |
739 new-seq)) | 739 new-seq)) |
740 | 740 |
741 | 741 |
742 (defun viper-display-vector-completions (list) | 742 (defun viper-display-vector-completions (list) |
743 (with-output-to-temp-buffer "*Completions*" | 743 (with-output-to-temp-buffer "*Completions*" |
744 (display-completion-list | 744 (display-completion-list |
745 (mapcar 'prin1-to-string | 745 (mapcar 'prin1-to-string |
746 (mapcar 'viper-display-macro list))))) | 746 (mapcar 'viper-display-macro list))))) |
747 | 747 |
748 | 748 |
749 | 749 |
750 ;; alist is the alist of macros | 750 ;; alist is the alist of macros |
751 ;; str is the fast key sequence entered | 751 ;; str is the fast key sequence entered |
752 ;; returns: (matching-macro-def . unmatched-suffix-start-index) | 752 ;; returns: (matching-macro-def . unmatched-suffix-start-index) |
753 (defun viper-find-best-matching-macro (alist str) | 753 (defun viper-find-best-matching-macro (alist str) |
754 (let ((lis alist) | 754 (let ((lis alist) |
764 (viper-kbd-mode-definition macro-def) | 764 (viper-kbd-mode-definition macro-def) |
765 (viper-kbd-global-definition macro-def)) | 765 (viper-kbd-global-definition macro-def)) |
766 (setq found t)) | 766 (setq found t)) |
767 ) | 767 ) |
768 (setq lis (cdr lis))) | 768 (setq lis (cdr lis))) |
769 | 769 |
770 (if found | 770 (if found |
771 (setq match macro-def | 771 (setq match macro-def |
772 unmatched-start-idx def-len) | 772 unmatched-start-idx def-len) |
773 (setq match nil | 773 (setq match nil |
774 unmatched-start-idx 0)) | 774 unmatched-start-idx 0)) |
775 | 775 |
776 (cons match unmatched-start-idx))) | 776 (cons match unmatched-start-idx))) |
777 | 777 |
778 | 778 |
779 | 779 |
780 ;; returns a list of names of macros defined for the current buffer | 780 ;; returns a list of names of macros defined for the current buffer |
781 (defun viper-this-buffer-macros (macro-alist) | 781 (defun viper-this-buffer-macros (macro-alist) |
782 (let (candidates) | 782 (let (candidates) |
783 (setq candidates | 783 (setq candidates |
784 (mapcar (lambda (elt) | 784 (mapcar (lambda (elt) |
786 (viper-kbd-mode-definition elt) | 786 (viper-kbd-mode-definition elt) |
787 (viper-kbd-global-definition elt)) | 787 (viper-kbd-global-definition elt)) |
788 (car elt))) | 788 (car elt))) |
789 macro-alist)) | 789 macro-alist)) |
790 (setq candidates (delq nil candidates)))) | 790 (setq candidates (delq nil candidates)))) |
791 | 791 |
792 | 792 |
793 ;; if seq of Viper key symbols (representing a macro) can be converted to a | 793 ;; if seq of Viper key symbols (representing a macro) can be converted to a |
794 ;; string--do so. Otherwise, do nothing. | 794 ;; string--do so. Otherwise, do nothing. |
795 (defun viper-display-macro (macro-name-or-body) | 795 (defun viper-display-macro (macro-name-or-body) |
796 (cond ((viper-char-symbol-sequence-p macro-name-or-body) | 796 (cond ((viper-char-symbol-sequence-p macro-name-or-body) |
797 (mapconcat 'symbol-name macro-name-or-body "")) | 797 (mapconcat 'symbol-name macro-name-or-body "")) |
798 ((viper-char-array-p macro-name-or-body) | 798 ((viper-char-array-p macro-name-or-body) |
799 (mapconcat 'char-to-string macro-name-or-body "")) | 799 (mapconcat 'char-to-string macro-name-or-body "")) |
800 (t macro-name-or-body))) | 800 (t macro-name-or-body))) |
801 | 801 |
802 ;; convert sequence of events (that came presumably from emacs kbd macro) into | 802 ;; convert sequence of events (that came presumably from emacs kbd macro) into |
803 ;; Viper's macro, which is a vector of the form | 803 ;; Viper's macro, which is a vector of the form |
804 ;; [ desc desc ... ] | 804 ;; [ desc desc ... ] |
805 ;; Each desc is either a symbol of (meta symb), (shift symb), etc. | 805 ;; Each desc is either a symbol of (meta symb), (shift symb), etc. |
806 ;; Here we purge events that happen to be lists. In most cases, these events | 806 ;; Here we purge events that happen to be lists. In most cases, these events |
811 (defun viper-events-to-macro (event-seq) | 811 (defun viper-events-to-macro (event-seq) |
812 (vconcat (delq nil (mapcar (lambda (elt) (if (consp elt) | 812 (vconcat (delq nil (mapcar (lambda (elt) (if (consp elt) |
813 nil | 813 nil |
814 (viper-event-key elt))) | 814 (viper-event-key elt))) |
815 event-seq)))) | 815 event-seq)))) |
816 | 816 |
817 ;; convert strings or arrays of characters to Viper macro form | 817 ;; convert strings or arrays of characters to Viper macro form |
818 (defun viper-char-array-to-macro (array) | 818 (defun viper-char-array-to-macro (array) |
819 (let ((vec (vconcat array)) | 819 (let ((vec (vconcat array)) |
820 macro) | 820 macro) |
821 (if viper-xemacs-p | 821 (if viper-xemacs-p |
822 (setq macro (mapcar 'character-to-event vec)) | 822 (setq macro (mapcar 'character-to-event vec)) |
823 (setq macro vec)) | 823 (setq macro vec)) |
824 (vconcat (mapcar 'viper-event-key macro)))) | 824 (vconcat (mapcar 'viper-event-key macro)))) |
825 | 825 |
826 ;; For macros bodies and names, goes over MACRO and checks if all members are | 826 ;; For macros bodies and names, goes over MACRO and checks if all members are |
827 ;; names of keys (actually, it only checks if they are symbols or lists | 827 ;; names of keys (actually, it only checks if they are symbols or lists |
828 ;; if a digit is found, it is converted into a symbol (e.g., 0 -> \0, etc). | 828 ;; if a digit is found, it is converted into a symbol (e.g., 0 -> \0, etc). |
829 ;; If MACRO is not a list or vector -- doesn't change MACRO. | 829 ;; If MACRO is not a list or vector -- doesn't change MACRO. |
830 (defun viper-fixup-macro (macro) | 830 (defun viper-fixup-macro (macro) |
848 ((listp elt) | 848 ((listp elt) |
849 (viper-fixup-macro elt)) | 849 (viper-fixup-macro elt)) |
850 ((symbolp elt) nil) | 850 ((symbolp elt) nil) |
851 (t (setq break t))) | 851 (t (setq break t))) |
852 (setq idx (1+ idx)))) | 852 (setq idx (1+ idx)))) |
853 | 853 |
854 (if break | 854 (if break |
855 (error "Wrong type macro component, symbol-or-listp, %S" elt) | 855 (error "Wrong type macro component, symbol-or-listp, %S" elt) |
856 macro))) | 856 macro))) |
857 | 857 |
858 (defun viper-macro-to-events (macro-body) | 858 (defun viper-macro-to-events (macro-body) |
859 (vconcat (mapcar 'viper-key-to-emacs-key macro-body))) | 859 (vconcat (mapcar 'viper-key-to-emacs-key macro-body))) |
860 | 860 |
861 | 861 |
862 | 862 |
863 ;;; Reading fast key sequences | 863 ;;; Reading fast key sequences |
864 | 864 |
865 ;; Assuming that CHAR was the first character in a fast succession of key | 865 ;; Assuming that CHAR was the first character in a fast succession of key |
866 ;; strokes, read the rest. Return the vector of keys that was entered in | 866 ;; strokes, read the rest. Return the vector of keys that was entered in |
867 ;; this fast succession of key strokes. | 867 ;; this fast succession of key strokes. |
868 ;; A fast keysequence is one that is terminated by a pause longer than | 868 ;; A fast keysequence is one that is terminated by a pause longer than |
869 ;; viper-fast-keyseq-timeout. | 869 ;; viper-fast-keyseq-timeout. |
900 (progn | 900 (progn |
901 (end-kbd-macro) | 901 (end-kbd-macro) |
902 (viper-set-register-macro reg)) | 902 (viper-set-register-macro reg)) |
903 (execute-kbd-macro (get-register reg) count))) | 903 (execute-kbd-macro (get-register reg) count))) |
904 ((or (= ?@ reg) (= ?\^j reg) (= ?\^m reg)) | 904 ((or (= ?@ reg) (= ?\^j reg) (= ?\^m reg)) |
905 (if viper-last-macro-reg | 905 (if viper-last-macro-reg |
906 nil | 906 nil |
907 (error "No previous kbd macro")) | 907 (error "No previous kbd macro")) |
908 (execute-kbd-macro (get-register viper-last-macro-reg) count)) | 908 (execute-kbd-macro (get-register viper-last-macro-reg) count)) |
909 ((= ?\# reg) | 909 ((= ?\# reg) |
910 (start-kbd-macro count)) | 910 (start-kbd-macro count)) |
914 (progn | 914 (progn |
915 (setq viper-last-macro-reg reg) | 915 (setq viper-last-macro-reg reg) |
916 (viper-set-register-macro reg)))) | 916 (viper-set-register-macro reg)))) |
917 (t | 917 (t |
918 (error "`%c': Unknown register" reg))))) | 918 (error "`%c': Unknown register" reg))))) |
919 | 919 |
920 | 920 |
921 (defun viper-global-execute () | 921 (defun viper-global-execute () |
922 "Call last keyboad macro for each line in the region." | 922 "Call last keyboad macro for each line in the region." |
923 (if (> (point) (mark t)) (exchange-point-and-mark)) | 923 (if (> (point) (mark t)) (exchange-point-and-mark)) |
924 (beginning-of-line) | 924 (beginning-of-line) |