diff options
| author | Richard M. Stallman | 1998-06-11 20:17:43 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1998-06-11 20:17:43 +0000 |
| commit | 0a8cbe68813a5acb485cbc3a473c3cf77ccaacf3 (patch) | |
| tree | df13173285c73f529a90c59a9e45f7b58f06ba96 | |
| parent | 9b9794f024acd62ae52c2e12b31002b2c2469bfc (diff) | |
| download | emacs-0a8cbe68813a5acb485cbc3a473c3cf77ccaacf3.tar.gz emacs-0a8cbe68813a5acb485cbc3a473c3cf77ccaacf3.zip | |
Renamed from vi-dot.el.
All functions and variables renamed.
(repeat-last-kill-command): Variable deleted;
use real-last-command instead.
(kill-region): Advice definition deleted.
(universal-argument-more, universal-argument-other-key)
(typematic-universal-argument-more-or-less): Advice deleted.
(repeat-prefix-arg): Variable deleted.
(repeat-num-input-keys-at-prefix): Variable deleted.
(repeat): Use last-prefix-arg.
| -rw-r--r-- | lisp/repeat.el | 257 |
1 files changed, 96 insertions, 161 deletions
diff --git a/lisp/repeat.el b/lisp/repeat.el index 7cda492d1ce..69e136c174c 100644 --- a/lisp/repeat.el +++ b/lisp/repeat.el | |||
| @@ -1,11 +1,11 @@ | |||
| 1 | ;;; vi-dot.el --- convenient way to repeat the previous command | 1 | ;;; repeat.el --- convenient way to repeat the previous command |
| 2 | 2 | ||
| 3 | ;; Copyright (C) 1998 Free Software Foundation, Inc. | 3 | ;; Copyright (C) 1998 Free Software Foundation, Inc. |
| 4 | 4 | ||
| 5 | ;; Author: Will Mengarini <seldon@eskimo.com> | 5 | ;; Author: Will Mengarini <seldon@eskimo.com> |
| 6 | ;; Created: Mo 02 Mar 98 | 6 | ;; Created: Mo 02 Mar 98 |
| 7 | ;; Version: 0.51, We 13 May 98 | 7 | ;; Version: 0.51, We 13 May 98 |
| 8 | ;; Keywords: convenience, abbrev, vi, universal argument, typematic, repeat | 8 | ;; Keywords: convenience, vi, repeat |
| 9 | 9 | ||
| 10 | ;; This file is part of GNU Emacs. | 10 | ;; This file is part of GNU Emacs. |
| 11 | 11 | ||
| @@ -38,60 +38,40 @@ | |||
| 38 | ;; This is a pain in the ass. | 38 | ;; This is a pain in the ass. |
| 39 | 39 | ||
| 40 | ;; This package defines a command that repeats the preceding command, | 40 | ;; This package defines a command that repeats the preceding command, |
| 41 | ;; whatever that was. The command is called `vi-dot' because the vi editor, | 41 | ;; whatever that was, including its arguments, whatever they were. |
| 42 | ;; Emacs's arch-rival among the Great Unwashed, does that when "." is pressed | 42 | ;; This command is connected to the key C-x z. |
| 43 | ;; in its command mode. | 43 | ;; To repeat the previous command once, type C-x z. |
| 44 | 44 | ;; To repeat it a second time immediately after, type just z. | |
| 45 | ;; Starting with Emacs 20.3, this package is part of Emacs, and the | 45 | ;; By typing z again and again, you can repeat the command over and over. |
| 46 | ;; `vi-dot' command is bound to the key sequence C-x z. (You can actually | ||
| 47 | ;; keep repeating the most recent command by just repeating the z after the | ||
| 48 | ;; first C-x z.) However, you can use this package with older versions of | ||
| 49 | ;; Emacs. Make the binding with | ||
| 50 | ;; (require 'vi-dot) | ||
| 51 | ;; (global-set-key "\C-xz" 'vi-dot) | ||
| 52 | ;; in your .emacs to give the command its orthodox binding of C-x z. | ||
| 53 | |||
| 54 | ;; Since the whole point of vi-dot is to let you repeat commands that are | ||
| 55 | ;; bound to multiple keystrokes by leaning on a *single* key, it seems not to | ||
| 56 | ;; make sense to bind vi-dot itself to a multiple-character key sequence, but | ||
| 57 | ;; there aren't any appropriate single characters left in the orthodox global | ||
| 58 | ;; map. (Meta characters don't count because they require two keystrokes if | ||
| 59 | ;; you don't have a real meta key, and things like function keys can't be | ||
| 60 | ;; relied on to be available to all users. We considered rebinding C-z, | ||
| 61 | ;; since C-x C-z is also bound to the same command, but RMS decided too many | ||
| 62 | ;; users were accustomed to the orthodox meaning of C-z.) So the vi-dot | ||
| 63 | ;; command checks what key sequence it was invoked by, and allows you to | ||
| 64 | ;; repeat the final key in that sequence to keep repeating the command. | ||
| 65 | ;; For example, C-x ] C-x z z z will move forward 4 pages. | ||
| 66 | 46 | ||
| 67 | ;; This works correctly inside a keyboard macro as far as recording and | 47 | ;; This works correctly inside a keyboard macro as far as recording and |
| 68 | ;; playback go, but `edit-kbd-macro' gets it wrong. That shouldn't really | 48 | ;; playback go, but `edit-kbd-macro' gets it wrong. That shouldn't really |
| 69 | ;; matter; if you need to edit something like | 49 | ;; matter; if you need to edit something like |
| 70 | ;; C-x ] ;; forward-page | 50 | ;; C-x ] ;; forward-page |
| 71 | ;; C-x z ;; vi-dot | 51 | ;; C-x z ;; repeat |
| 72 | ;; zz ;; self-insert-command * 2 | 52 | ;; zz ;; self-insert-command * 2 |
| 73 | ;; C-x ;; Control-X-prefix | 53 | ;; C-x ;; Control-X-prefix |
| 74 | ;; you can just kill the bogus final 2 lines, then duplicate the vi-dot line | 54 | ;; you can just kill the bogus final 2 lines, then duplicate the repeat line |
| 75 | ;; as many times as it's really needed. Also, `edit-kbd-macro' works | 55 | ;; as many times as it's really needed. Also, `edit-kbd-macro' works |
| 76 | ;; correctly if `vi-dot' is invoked through a rebinding to a single keystroke | 56 | ;; correctly if `repeat' is invoked through a rebinding to a single keystroke |
| 77 | ;; and the global variable vi-dot-repeat-on-final-keystroke is set to a value | 57 | ;; and the global variable repeat-on-final-keystroke is set to a value |
| 78 | ;; that doesn't include that keystroke. For example, the lines | 58 | ;; that doesn't include that keystroke. For example, the lines |
| 79 | ;; (global-set-key "\C-z" 'vi-dot) | 59 | ;; (global-set-key "\C-z" 'repeat) |
| 80 | ;; (setq vi-dot-repeat-on-final-keystroke "z") | 60 | ;; (setq repeat-on-final-keystroke "z") |
| 81 | ;; in your .emacs would allow `edit-kbd-macro' to work correctly when C-z was | 61 | ;; in your .emacs would allow `edit-kbd-macro' to work correctly when C-z was |
| 82 | ;; used in a keyboard macro to invoke `vi-dot', but would still allow C-x z | 62 | ;; used in a keyboard macro to invoke `repeat', but would still allow C-x z |
| 83 | ;; to be used for `vi-dot' elsewhere. The real reason for documenting this | 63 | ;; to be used for `repeat' elsewhere. The real reason for documenting this |
| 84 | ;; isn't that anybody would need it for the `edit-kbd-macro' problem, but | 64 | ;; isn't that anybody would need it for the `edit-kbd-macro' problem, but |
| 85 | ;; that there might be other unexpected ramifications of re-executing on | 65 | ;; that there might be other unexpected ramifications of re-executing on |
| 86 | ;; repetitions of the final keystroke, and this shows how to do workarounds. | 66 | ;; repetitions of the final keystroke, and this shows how to do workarounds. |
| 87 | 67 | ||
| 88 | ;; If the preceding command had a prefix argument, that argument is applied | 68 | ;; If the preceding command had a prefix argument, that argument is applied |
| 89 | ;; to the vi-dot command, unless the vi-dot command is given a new prefix | 69 | ;; to the repeat command, unless the repeat command is given a new prefix |
| 90 | ;; argument, in which case it applies that new prefix argument to the | 70 | ;; argument, in which case it applies that new prefix argument to the |
| 91 | ;; preceding command. This means a key sequence like C-u - C-x C-t can be | 71 | ;; preceding command. This means a key sequence like C-u - C-x C-t can be |
| 92 | ;; repeated. (It shoves the preceding line upward in the buffer.) | 72 | ;; repeated. (It shoves the preceding line upward in the buffer.) |
| 93 | 73 | ||
| 94 | ;; Here are some other key sequences with which vi-dot might be useful: | 74 | ;; Here are some other key sequences with which repeat might be useful: |
| 95 | ;; C-u - C-t [shove preceding character backward in line] | 75 | ;; C-u - C-t [shove preceding character backward in line] |
| 96 | ;; C-u - M-t [shove preceding word backward in sentence] | 76 | ;; C-u - M-t [shove preceding word backward in sentence] |
| 97 | ;; C-x ^ enlarge-window [one line] (assuming frame has > 1 window) | 77 | ;; C-x ^ enlarge-window [one line] (assuming frame has > 1 window) |
| @@ -107,16 +87,9 @@ | |||
| 107 | ;; C-x { shrink-window-horizontally | 87 | ;; C-x { shrink-window-horizontally |
| 108 | ;; C-x } enlarge-window-horizontally | 88 | ;; C-x } enlarge-window-horizontally |
| 109 | 89 | ||
| 110 | ;; Using vi-dot.el doesn't entail a performance hit. There's a | 90 | ;; This command was first called `vi-dot', because |
| 111 | ;; straightforward way to implement a package like this that would save some | 91 | ;; it was inspired by the `.' command in the vi editor, |
| 112 | ;; data about each command as it was executed, but that Lisp would need to be | 92 | ;; but it was renamed to make its name more meaningful. |
| 113 | ;; interpreted on every keystroke, which is Bad. This implementation doesn't | ||
| 114 | ;; do it that way; the peformance impact on almost all keystrokes is 0. | ||
| 115 | |||
| 116 | ;; Buried in the implementation is a reference to a function in my | ||
| 117 | ;; typematic.el package, which isn't part of GNU Emacs. However, that | ||
| 118 | ;; package is *not* required by vi-dot; the reference allows it to be used, | ||
| 119 | ;; but doesn't require it. | ||
| 120 | 93 | ||
| 121 | ;;; Code: | 94 | ;;; Code: |
| 122 | 95 | ||
| @@ -124,34 +97,34 @@ | |||
| 124 | 97 | ||
| 125 | ;;;;; ************************* USER OPTIONS ************************** ;;;;; | 98 | ;;;;; ************************* USER OPTIONS ************************** ;;;;; |
| 126 | 99 | ||
| 127 | (defcustom vi-dot-too-dangerous '(kill-this-buffer) | 100 | (defcustom repeat-too-dangerous '(kill-this-buffer) |
| 128 | "Commands too dangerous to repeat with `vi-dot'." | 101 | "Commands too dangerous to repeat with \\[repeat]." |
| 129 | :group 'convenience | 102 | :group 'convenience |
| 130 | :type '(repeat function)) | 103 | :type '(repeat function)) |
| 131 | 104 | ||
| 132 | ;; If the last command was self-insert-command, the char to be inserted was | 105 | ;; If the last command was self-insert-command, the char to be inserted was |
| 133 | ;; obtained by that command from last-command-char, which has now been | 106 | ;; obtained by that command from last-command-char, which has now been |
| 134 | ;; clobbered by the command sequence that invoked vi-dot. We could get it | 107 | ;; clobbered by the command sequence that invoked `repeat'. We could get it |
| 135 | ;; from (recent-keys) & set last-command-char to that, "unclobbering" it, but | 108 | ;; from (recent-keys) & set last-command-char to that, "unclobbering" it, but |
| 136 | ;; this has the disadvantage that if the user types a sequence of different | 109 | ;; this has the disadvantage that if the user types a sequence of different |
| 137 | ;; chars then invokes vi-dot, only the final char will be inserted. In vi, | 110 | ;; chars then invokes repeat, only the final char will be inserted. In vi, |
| 138 | ;; the dot command can reinsert the entire most-recently-inserted sequence. | 111 | ;; the dot command can reinsert the entire most-recently-inserted sequence. |
| 139 | 112 | ||
| 140 | (defvar vi-dot-message-function nil | 113 | (defvar repeat-message-function nil |
| 141 | "If non-nil, function used by `vi-dot' command to say what it's doing. | 114 | "If non-nil, function used by `repeat' command to say what it's doing. |
| 142 | Message is something like \"Repeating command glorp\". | 115 | Message is something like \"Repeating command glorp\". |
| 143 | To disable such messages, set this variable to `ignore'. To customize | 116 | To disable such messages, set this variable to `ignore'. To customize |
| 144 | display, assign a function that takes one string as an arg and displays | 117 | display, assign a function that takes one string as an arg and displays |
| 145 | it however you want.") | 118 | it however you want.") |
| 146 | 119 | ||
| 147 | (defcustom vi-dot-repeat-on-final-keystroke t | 120 | (defcustom repeat-on-final-keystroke t |
| 148 | "Allow `vi-dot' to re-execute for repeating lastchar of a key sequence. | 121 | "Allow `repeat' to re-execute for repeating lastchar of a key sequence. |
| 149 | If this variable is t, `vi-dot' determines what key sequence | 122 | If this variable is t, `repeat' determines what key sequence |
| 150 | it was invoked by, extracts the final character of that sequence, and | 123 | it was invoked by, extracts the final character of that sequence, and |
| 151 | re-executes as many times as that final character is hit; so for example | 124 | re-executes as many times as that final character is hit; so for example |
| 152 | if `vi-dot' is bound to C-x z, typing C-x z z z repeats the previous command | 125 | if `repeat' is bound to C-x z, typing C-x z z z repeats the previous command |
| 153 | 3 times. If this variable is a sequence of characters, then re-execution | 126 | 3 times. If this variable is a sequence of characters, then re-execution |
| 154 | only occurs if the final character by which `vi-dot' was invoked is a | 127 | only occurs if the final character by which `repeat' was invoked is a |
| 155 | member of that sequence. If this variable is nil, no re-execution occurs." | 128 | member of that sequence. If this variable is nil, no re-execution occurs." |
| 156 | :group 'convenience | 129 | :group 'convenience |
| 157 | :type 'boolean) | 130 | :type 'boolean) |
| @@ -161,16 +134,16 @@ member of that sequence. If this variable is nil, no re-execution occurs." | |||
| 161 | ;; The basic strategy is to use last-command, a variable built in to Emacs. | 134 | ;; The basic strategy is to use last-command, a variable built in to Emacs. |
| 162 | ;; There are 2 issues that complicate this strategy. The first is that | 135 | ;; There are 2 issues that complicate this strategy. The first is that |
| 163 | ;; last-command is given a bogus value when any kill command is executed; | 136 | ;; last-command is given a bogus value when any kill command is executed; |
| 164 | ;; this is done to make it easy for 'yank-pop to know that it's being invoked | 137 | ;; this is done to make it easy for `yank-pop' to know that it's being invoked |
| 165 | ;; after a kill command. The second is that the meaning of the command is | 138 | ;; after a kill command. The second is that the meaning of the command is |
| 166 | ;; often altered by the prefix arg, but although Emacs (GNU 19.34) has a | 139 | ;; often altered by the prefix arg, but although Emacs (19.34) has a |
| 167 | ;; builtin prefix-arg specifying the arg for the next command, as well as a | 140 | ;; builtin prefix-arg specifying the arg for the next command, as well as a |
| 168 | ;; builtin current-prefix-arg, it has no builtin last-prefix-arg. | 141 | ;; builtin current-prefix-arg, it has no builtin last-prefix-arg. |
| 169 | 142 | ||
| 170 | ;; There's a builtin (this-command-keys), the return value of which could be | 143 | ;; There's a builtin (this-command-keys), the return value of which could be |
| 171 | ;; executed with (command-execute), but there's no (last-command-keys). | 144 | ;; executed with (command-execute), but there's no (last-command-keys). |
| 172 | ;; Using (last-command-keys) if it existed wouldn't be optimal, however, | 145 | ;; Using (last-command-keys) if it existed wouldn't be optimal, however, |
| 173 | ;; since it would complicate checking membership in vi-dot-too-dangerous. | 146 | ;; since it would complicate checking membership in repeat-too-dangerous. |
| 174 | 147 | ||
| 175 | ;; It would of course be trivial to implement last-prefix-arg & | 148 | ;; It would of course be trivial to implement last-prefix-arg & |
| 176 | ;; true-last-command by putting something in post-command-hook, but that | 149 | ;; true-last-command by putting something in post-command-hook, but that |
| @@ -181,90 +154,55 @@ member of that sequence. If this variable is nil, no re-execution occurs." | |||
| 181 | 154 | ||
| 182 | (require 'advice) | 155 | (require 'advice) |
| 183 | 156 | ||
| 184 | (defvar vi-dot-last-kill-command nil | 157 | (defvar repeat-last-kill-command nil |
| 185 | "True value of `this-command' before (`kill-region') clobbered it.") | 158 | "True value of `this-command' before (`kill-region') clobbered it.") |
| 186 | 159 | ||
| 187 | (defadvice kill-region (before vi-dot-save-last-kill-command act) | ||
| 188 | "Remember true value of this-command before (`kill-region') clobbers it." | ||
| 189 | (setq vi-dot-last-kill-command this-command)) | ||
| 190 | |||
| 191 | ;; Next cope with the prefix arg. I can advise the various functions that | ||
| 192 | ;; create prefix args to save the arg in a variable ... | ||
| 193 | |||
| 194 | (defvar vi-dot-prefix-arg nil | ||
| 195 | "Prefix arg created as most recent universal argument.") | ||
| 196 | |||
| 197 | ;; ... but alone that's not enough, because if last-command's prefix arg was | ||
| 198 | ;; nil, none of those functions were ever called, so whatever command before | ||
| 199 | ;; last-command did have a prefix arg has left it in vi-dot-prefix-arg, & I | ||
| 200 | ;; need a way to tell whether whatever's in there applies to last-command. | ||
| 201 | |||
| 202 | ;; From Info|ELisp|Command Loop|Reading Input|Key Sequence Input: | ||
| 203 | ;; - Variable: num-input-keys | ||
| 204 | ;; This variable's value is the number of key sequences processed so far | ||
| 205 | ;; in this Emacs session. This includes key sequences read from the | ||
| 206 | ;; terminal and key sequences read from keyboard macros being executed. | ||
| 207 | ;; num-input-keys counts key *sequences*, not key *strokes*; it's only | ||
| 208 | ;; incremented after reading a complete key sequence mapping to a command. | ||
| 209 | |||
| 210 | (defvar vi-dot-num-input-keys-at-prefix -1 | ||
| 211 | "# of key sequences read in Emacs session when prefix-arg defined.") | ||
| 212 | |||
| 213 | (mapcar (lambda (f) | ||
| 214 | (eval | ||
| 215 | `(defadvice ,f (after vi-dot-save-universal-arg act) | ||
| 216 | (setq vi-dot-prefix-arg current-prefix-arg | ||
| 217 | vi-dot-num-input-keys-at-prefix num-input-keys)))) | ||
| 218 | [universal-argument-more | ||
| 219 | universal-argument-other-key | ||
| 220 | typematic-universal-argument-more-or-less]) | ||
| 221 | |||
| 222 | ;; Coping with strings of self-insert commands gets hairy when they interact | 160 | ;; Coping with strings of self-insert commands gets hairy when they interact |
| 223 | ;; with auto-filling. Most problems are eliminated by remembering what we're | 161 | ;; with auto-filling. Most problems are eliminated by remembering what we're |
| 224 | ;; self-inserting, so we only need to get it from the undo information once. | 162 | ;; self-inserting, so we only need to get it from the undo information once. |
| 225 | 163 | ||
| 226 | (defvar vi-dot-last-self-insert nil | 164 | (defvar repeat-last-self-insert nil |
| 227 | "If last repeated command was `self-insert-command', it inserted this.") | 165 | "If last repeated command was `self-insert-command', it inserted this.") |
| 228 | 166 | ||
| 229 | ;; That'll require another keystroke count so we know we're in a string of | 167 | ;; That'll require another keystroke count so we know we're in a string of |
| 230 | ;; repetitions of self-insert commands: | 168 | ;; repetitions of self-insert commands: |
| 231 | 169 | ||
| 232 | (defvar vi-dot-num-input-keys-at-self-insert -1 | 170 | (defvar repeat-num-input-keys-at-self-insert -1 |
| 233 | "# key sequences read in Emacs session when `self-insert-command' repeated.") | 171 | "# key sequences read in Emacs session when `self-insert-command' repeated.") |
| 234 | 172 | ||
| 235 | ;;;;; *************** ANALOGOUS HACKS TO VI-DOT ITSELF **************** ;;;;; | 173 | ;;;;; *************** ANALOGOUS HACKS TO `repeat' ITSELF **************** ;;;;; |
| 236 | 174 | ||
| 237 | ;; That mechanism of checking num-input-keys to figure out what's really | 175 | ;; That mechanism of checking num-input-keys to figure out what's really |
| 238 | ;; going on can be useful to other commands that need to fine-tune their | 176 | ;; going on can be useful to other commands that need to fine-tune their |
| 239 | ;; interaction with vi-dot. Instead of requiring them to advise vi-dot, we | 177 | ;; interaction with repeat. Instead of requiring them to advise repeat, we |
| 240 | ;; can just defvar the value they need here, & setq it in the vi-dot command: | 178 | ;; can just defvar the value they need here, & setq it in the repeat command: |
| 241 | 179 | ||
| 242 | (defvar vi-dot-num-input-keys-at-vi-dot -1 | 180 | (defvar repeat-num-input-keys-at-repeat -1 |
| 243 | "# key sequences read in Emacs session when `vi-dot' last invoked.") | 181 | "# key sequences read in Emacs session when `repeat' last invoked.") |
| 244 | 182 | ||
| 245 | ;; Also, we can assign a name to the test for which that variable is | 183 | ;; Also, we can assign a name to the test for which that variable is |
| 246 | ;; intended, which thereby documents here how to use it, & makes code that | 184 | ;; intended, which thereby documents here how to use it, & makes code that |
| 247 | ;; uses it self-documenting: | 185 | ;; uses it self-documenting: |
| 248 | 186 | ||
| 249 | (defsubst vi-dot-is-really-this-command () | 187 | (defsubst repeat-is-really-this-command () |
| 250 | "Return t if this command is happening because user invoked `vi-dot'. | 188 | "Return t if this command is happening because user invoked `repeat'. |
| 251 | Usually, when a command is executing, the Emacs builtin variable | 189 | Usually, when a command is executing, the Emacs builtin variable |
| 252 | `this-command' identifies the command the user invoked. Some commands modify | 190 | `this-command' identifies the command the user invoked. Some commands modify |
| 253 | that variable on the theory they're doing more good than harm; `vi-dot' does | 191 | that variable on the theory they're doing more good than harm; `repeat' does |
| 254 | that, and usually does do more good than harm. However, like all do-gooders, | 192 | that, and usually does do more good than harm. However, like all do-gooders, |
| 255 | sometimes `vi-dot' gets surprising results from its altruism. The value of | 193 | sometimes `repeat' gets surprising results from its altruism. The value of |
| 256 | this function is always whether the value of `this-command' would've been | 194 | this function is always whether the value of `this-command' would've been |
| 257 | 'vi-dot if `vi-dot' hadn't modified it." | 195 | 'repeat if `repeat' hadn't modified it." |
| 258 | (= vi-dot-num-input-keys-at-vi-dot num-input-keys)) | 196 | (= repeat-num-input-keys-at-repeat num-input-keys)) |
| 259 | 197 | ||
| 260 | ;; An example of the use of (vi-dot-is-really-this-command) may still be | 198 | ;; An example of the use of (repeat-is-really-this-command) may still be |
| 261 | ;; available in <http://www.eskimo.com/~seldon/dotemacs.el>; search for | 199 | ;; available in <http://www.eskimo.com/~seldon/dotemacs.el>; search for |
| 262 | ;; "defun wm-switch-buffer". | 200 | ;; "defun wm-switch-buffer". |
| 263 | 201 | ||
| 264 | ;;;;; ******************* THE VI-DOT COMMAND ITSELF ******************* ;;;;; | 202 | ;;;;; ******************* THE REPEAT COMMAND ITSELF ******************* ;;;;; |
| 265 | 203 | ||
| 266 | ;;;###autoload | 204 | ;;;###autoload |
| 267 | (defun vi-dot (vi-dot-arg) | 205 | (defun repeat (repeat-arg) |
| 268 | "Repeat most recently executed command. | 206 | "Repeat most recently executed command. |
| 269 | With prefix arg, apply new prefix arg to that command; otherwise, maintain | 207 | With prefix arg, apply new prefix arg to that command; otherwise, maintain |
| 270 | prefix arg of most recently executed command if it had one. | 208 | prefix arg of most recently executed command if it had one. |
| @@ -272,34 +210,31 @@ This command is named after the `.' command in the vi editor. | |||
| 272 | 210 | ||
| 273 | If this command is invoked by a multi-character key sequence, it can then | 211 | If this command is invoked by a multi-character key sequence, it can then |
| 274 | be repeated by repeating the final character of that sequence. This behavior | 212 | be repeated by repeating the final character of that sequence. This behavior |
| 275 | can be modified by the global variable `vi-dot-repeat-on-final-keystroke'." | 213 | can be modified by the global variable `repeat-on-final-keystroke'." |
| 276 | ;; The most recently executed command could be anything, so surprises could | 214 | ;; The most recently executed command could be anything, so surprises could |
| 277 | ;; result if it were re-executed in a context where new dynamically | 215 | ;; result if it were re-executed in a context where new dynamically |
| 278 | ;; localized variables were shadowing global variables in a `let' clause in | 216 | ;; localized variables were shadowing global variables in a `let' clause in |
| 279 | ;; here. (Remember that GNU Emacs 19 is dynamically localized.) | 217 | ;; here. (Remember that GNU Emacs 19 is dynamically localized.) |
| 280 | ;; To avoid that, I tried the `lexical-let' of the Common Lisp extensions, | 218 | ;; To avoid that, I tried the `lexical-let' of the Common Lisp extensions, |
| 281 | ;; but that entails a very noticeable performance hit, so instead I use the | 219 | ;; but that entails a very noticeable performance hit, so instead I use the |
| 282 | ;; "vi-dot-" prefix, reserved by this package, for *local* variables that | 220 | ;; "repeat-" prefix, reserved by this package, for *local* variables that |
| 283 | ;; might be visible to re-executed commands, including this function's arg. | 221 | ;; might be visible to re-executed commands, including this function's arg. |
| 284 | (interactive "P") | 222 | (interactive "P") |
| 285 | (when (eq last-command 'kill-region) | 223 | (setq this-command real-last-command |
| 286 | (setq last-command vi-dot-last-kill-command)) | 224 | repeat-num-input-keys-at-repeat num-input-keys) |
| 287 | (setq this-command last-command | 225 | (when (eq real-last-command 'mode-exit) |
| 288 | vi-dot-num-input-keys-at-vi-dot num-input-keys) | 226 | (error "real-last-command is mode-exit & can't be repeated")) |
| 289 | (when (eq last-command 'mode-exit) | 227 | (when (memq real-last-command repeat-too-dangerous) |
| 290 | (error "last-command is mode-exit & can't be repeated")) | 228 | (error "Command %S too dangerous to repeat automatically" real-last-command)) |
| 291 | (when (memq last-command vi-dot-too-dangerous) | 229 | (when (null repeat-arg) |
| 292 | (error "Command %S too dangerous to repeat automatically" last-command)) | 230 | (setq repeat-arg last-prefix-arg)) |
| 293 | (when (and (null vi-dot-arg) | ||
| 294 | (<= (- num-input-keys vi-dot-num-input-keys-at-prefix) 2)) | ||
| 295 | (setq vi-dot-arg vi-dot-prefix-arg)) | ||
| 296 | ;; Now determine whether to loop on repeated taps of the final character | 231 | ;; Now determine whether to loop on repeated taps of the final character |
| 297 | ;; of the key sequence that invoked vi-dot. The Emacs global | 232 | ;; of the key sequence that invoked repeat. The Emacs global |
| 298 | ;; last-command-char contains the final character now, but may not still | 233 | ;; last-command-char contains the final character now, but may not still |
| 299 | ;; contain it after the previous command is repeated, so the character | 234 | ;; contain it after the previous command is repeated, so the character |
| 300 | ;; needs to be saved. | 235 | ;; needs to be saved. |
| 301 | (let ((vi-dot-repeat-char | 236 | (let ((repeat-repeat-char |
| 302 | (if (eq vi-dot-repeat-on-final-keystroke t) | 237 | (if (eq repeat-on-final-keystroke t) |
| 303 | ;; allow any final input event that was a character | 238 | ;; allow any final input event that was a character |
| 304 | (when (eq last-command-char | 239 | (when (eq last-command-char |
| 305 | last-command-event) | 240 | last-command-event) |
| @@ -307,60 +242,60 @@ can be modified by the global variable `vi-dot-repeat-on-final-keystroke'." | |||
| 307 | ;; allow only specified final keystrokes | 242 | ;; allow only specified final keystrokes |
| 308 | (car (memq last-command-char | 243 | (car (memq last-command-char |
| 309 | (listify-key-sequence | 244 | (listify-key-sequence |
| 310 | vi-dot-repeat-on-final-keystroke)))))) | 245 | repeat-on-final-keystroke)))))) |
| 311 | (if (memq last-command '(exit-minibuffer | 246 | (if (memq real-last-command '(exit-minibuffer |
| 312 | minibuffer-complete-and-exit | 247 | minibuffer-complete-and-exit |
| 313 | self-insert-and-exit)) | 248 | self-insert-and-exit)) |
| 314 | (let ((vi-dot-command (car command-history))) | 249 | (let ((repeat-command (car command-history))) |
| 315 | (vi-dot-message "Repeating %S" vi-dot-command) | 250 | (repeat-message "Repeating %S" repeat-command) |
| 316 | (eval vi-dot-command)) | 251 | (eval repeat-command)) |
| 317 | (if (null vi-dot-arg) | 252 | (if (null repeat-arg) |
| 318 | (vi-dot-message "Repeating command %S" last-command) | 253 | (repeat-message "Repeating command %S" real-last-command) |
| 319 | (setq vi-dot-num-input-keys-at-prefix num-input-keys | 254 | (setq repeat-num-input-keys-at-prefix num-input-keys |
| 320 | current-prefix-arg vi-dot-arg) | 255 | current-prefix-arg repeat-arg) |
| 321 | (vi-dot-message "Repeating command %S %S" vi-dot-arg last-command)) | 256 | (repeat-message "Repeating command %S %S" repeat-arg real-last-command)) |
| 322 | (if (eq last-command 'self-insert-command) | 257 | (if (eq real-last-command 'self-insert-command) |
| 323 | (let ((insertion | 258 | (let ((insertion |
| 324 | (if (<= (- num-input-keys | 259 | (if (<= (- num-input-keys |
| 325 | vi-dot-num-input-keys-at-self-insert) | 260 | repeat-num-input-keys-at-self-insert) |
| 326 | 1) | 261 | 1) |
| 327 | vi-dot-last-self-insert | 262 | repeat-last-self-insert |
| 328 | (let ((range (nth 1 buffer-undo-list))) | 263 | (let ((range (nth 1 buffer-undo-list))) |
| 329 | (condition-case nil | 264 | (condition-case nil |
| 330 | (setq vi-dot-last-self-insert | 265 | (setq repeat-last-self-insert |
| 331 | (buffer-substring (car range) | 266 | (buffer-substring (car range) |
| 332 | (cdr range))) | 267 | (cdr range))) |
| 333 | (error (error "%s %s %s" ;Danger, Will Robinson! | 268 | (error (error "%s %s %s" ;Danger, Will Robinson! |
| 334 | "vi-dot can't intuit what you" | 269 | "repeat can't intuit what you" |
| 335 | "inserted before auto-fill" | 270 | "inserted before auto-fill" |
| 336 | "clobbered it, sorry"))))))) | 271 | "clobbered it, sorry"))))))) |
| 337 | (setq vi-dot-num-input-keys-at-self-insert num-input-keys) | 272 | (setq repeat-num-input-keys-at-self-insert num-input-keys) |
| 338 | (loop repeat (prefix-numeric-value vi-dot-arg) do | 273 | (loop repeat (prefix-numeric-value repeat-arg) do |
| 339 | (vi-self-insert insertion))) | 274 | (repeat-self-insert insertion))) |
| 340 | (call-interactively last-command))) | 275 | (call-interactively real-last-command))) |
| 341 | (when vi-dot-repeat-char | 276 | (when repeat-repeat-char |
| 342 | ;; A simple recursion here gets into trouble with max-lisp-eval-depth | 277 | ;; A simple recursion here gets into trouble with max-lisp-eval-depth |
| 343 | ;; on long sequences of repetitions of a command like `forward-word' | 278 | ;; on long sequences of repetitions of a command like `forward-word' |
| 344 | ;; (only 32 repetitions are possible given the default value of 200 for | 279 | ;; (only 32 repetitions are possible given the default value of 200 for |
| 345 | ;; max-lisp-eval-depth), but if I now locally disable the repeat char I | 280 | ;; max-lisp-eval-depth), but if I now locally disable the repeat char I |
| 346 | ;; can iterate indefinitely here around a single level of recursion. | 281 | ;; can iterate indefinitely here around a single level of recursion. |
| 347 | (let (vi-dot-repeat-on-final-keystroke) | 282 | (let (repeat-on-final-keystroke) |
| 348 | (while (eq (read-event) vi-dot-repeat-char) | 283 | (while (eq (read-event) repeat-repeat-char) |
| 349 | (vi-dot vi-dot-arg)) | 284 | (repeat repeat-arg)) |
| 350 | (setq unread-command-events (list last-input-event)))))) | 285 | (setq unread-command-events (list last-input-event)))))) |
| 351 | 286 | ||
| 352 | (defun vi-self-insert (string) | 287 | (defun repeat-self-insert (string) |
| 353 | (let ((i 0)) | 288 | (let ((i 0)) |
| 354 | (while (< i (length string)) | 289 | (while (< i (length string)) |
| 355 | (let ((last-command-char (aref string i))) | 290 | (let ((last-command-char (aref string i))) |
| 356 | (self-insert-command 1)) | 291 | (self-insert-command 1)) |
| 357 | (setq i (1+ i))))) | 292 | (setq i (1+ i))))) |
| 358 | 293 | ||
| 359 | (defun vi-dot-message (format &rest args) | 294 | (defun repeat-message (format &rest args) |
| 360 | "Like `message' but displays with `vi-dot-message-function' if non-nil." | 295 | "Like `message' but displays with `repeat-message-function' if non-nil." |
| 361 | (let ((message (apply 'format format args))) | 296 | (let ((message (apply 'format format args))) |
| 362 | (if vi-dot-message-function | 297 | (if repeat-message-function |
| 363 | (funcall vi-dot-message-function message) | 298 | (funcall repeat-message-function message) |
| 364 | (message "%s" message)))) | 299 | (message "%s" message)))) |
| 365 | 300 | ||
| 366 | ;; OK, there's one situation left where that doesn't work correctly: when the | 301 | ;; OK, there's one situation left where that doesn't work correctly: when the |
| @@ -393,6 +328,6 @@ can be modified by the global variable `vi-dot-repeat-on-final-keystroke'." | |||
| 393 | 328 | ||
| 394 | ;;;;; ************************* EMACS CONTROL ************************* ;;;;; | 329 | ;;;;; ************************* EMACS CONTROL ************************* ;;;;; |
| 395 | 330 | ||
| 396 | (provide 'vi-dot) | 331 | (provide 'repeat) |
| 397 | 332 | ||
| 398 | ;;; vi-dot.el ends here | 333 | ;;; repeat.el ends here |