diff options
| author | Richard M. Stallman | 1998-05-18 05:28:11 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1998-05-18 05:28:11 +0000 |
| commit | fd51b1bc2c5b4976bf820897c6b9776e26b76141 (patch) | |
| tree | 76bfc78a81ee437658db4b8cd1a41b8ccb7368ba | |
| parent | 130901129f0de5bafd30384ace1b797884359ba8 (diff) | |
| download | emacs-fd51b1bc2c5b4976bf820897c6b9776e26b76141.tar.gz emacs-fd51b1bc2c5b4976bf820897c6b9776e26b76141.zip | |
Initial revision
| -rw-r--r-- | lisp/repeat.el | 405 |
1 files changed, 405 insertions, 0 deletions
diff --git a/lisp/repeat.el b/lisp/repeat.el new file mode 100644 index 00000000000..fd2f76866c3 --- /dev/null +++ b/lisp/repeat.el | |||
| @@ -0,0 +1,405 @@ | |||
| 1 | ;;; vi-dot.el --- convenient way to repeat the previous command | ||
| 2 | |||
| 3 | ;; Copyright (C) 1998 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | ;; Author: Will Mengarini <seldon@eskimo.com> | ||
| 6 | ;; Created: Mo 02 Mar 98 | ||
| 7 | ;; Version: 0.51, We 13 May 98 | ||
| 8 | ;; Keywords: convenience, abbrev, vi, universal argument, typematic, repeat | ||
| 9 | |||
| 10 | ;; This file is part of GNU Emacs. | ||
| 11 | |||
| 12 | ;; This program is free software; you can redistribute it and/or modify | ||
| 13 | ;; it under the terms of the GNU General Public License as published by | ||
| 14 | ;; the Free Software Foundation; either version 2, or (at your option) | ||
| 15 | ;; any later version. | ||
| 16 | |||
| 17 | ;; This program is distributed in the hope that it will be useful, | ||
| 18 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 19 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 20 | ;; GNU General Public License for more details. | ||
| 21 | |||
| 22 | ;; You should have received a copy of the GNU General Public License | ||
| 23 | ;; along with GNU Emacs; see the file COPYING. If not, write to the | ||
| 24 | ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
| 25 | ;; Boston, MA 02111-1307, USA. | ||
| 26 | |||
| 27 | ;;; Commentary: | ||
| 28 | |||
| 29 | ;; Sometimes the fastest way to get something done is just to lean on a key; | ||
| 30 | ;; moving forward through a series of words by leaning on M-f is an example. | ||
| 31 | ;; But 'forward-page is orthodoxily bound to C-x ], so moving forward through | ||
| 32 | ;; several pages requires | ||
| 33 | ;; Loop until desired page is reached: | ||
| 34 | ;; Hold down control key with left pinkie. | ||
| 35 | ;; Tap <x>. | ||
| 36 | ;; Lift left pinkie off control key. | ||
| 37 | ;; Tap <]>. | ||
| 38 | ;; This is a pain in the ass. | ||
| 39 | |||
| 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, | ||
| 42 | ;; Emacs's arch-rival among the Great Unwashed, does that when "." is pressed | ||
| 43 | ;; in its command mode. | ||
| 44 | |||
| 45 | ;; Starting with Emacs 20.3, this package is part of Emacs, and the | ||
| 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 | |||
| 67 | ;; 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 | ||
| 69 | ;; matter; if you need to edit something like | ||
| 70 | ;; C-x ] ;; forward-page | ||
| 71 | ;; C-x z ;; vi-dot | ||
| 72 | ;; zz ;; self-insert-command * 2 | ||
| 73 | ;; C-x ;; Control-X-prefix | ||
| 74 | ;; you can just kill the bogus final 2 lines, then duplicate the vi-dot line | ||
| 75 | ;; 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 | ||
| 77 | ;; and the global variable vi-dot-repeat-on-final-keystroke is set to a value | ||
| 78 | ;; that doesn't include that keystroke. For example, the lines | ||
| 79 | ;; (global-set-key "\C-z" 'vi-dot) | ||
| 80 | ;; (setq vi-dot-repeat-on-final-keystroke "z") | ||
| 81 | ;; 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 | ||
| 83 | ;; to be used for `vi-dot' elsewhere. The real reason for documenting this | ||
| 84 | ;; 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 | ||
| 86 | ;; repetitions of the final keystroke, and this shows how to do workarounds. | ||
| 87 | |||
| 88 | ;; 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 | ||
| 90 | ;; 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 | ||
| 92 | ;; repeated. (It shoves the preceding line upward in the buffer.) | ||
| 93 | |||
| 94 | ;; Here are some other key sequences with which vi-dot might be useful: | ||
| 95 | ;; C-u - C-t [shove preceding character backward in line] | ||
| 96 | ;; C-u - M-t [shove preceding word backward in sentence] | ||
| 97 | ;; C-x ^ enlarge-window [one line] (assuming frame has > 1 window) | ||
| 98 | ;; C-u - C-x ^ [shrink window one line] | ||
| 99 | ;; C-x ` next-error | ||
| 100 | ;; C-u - C-x ` [previous error] | ||
| 101 | ;; C-x DEL backward-kill-sentence | ||
| 102 | ;; C-x e call-last-kbd-macro | ||
| 103 | ;; C-x r i insert-register | ||
| 104 | ;; C-x r t string-rectangle | ||
| 105 | ;; C-x TAB indent-rigidly [one character] | ||
| 106 | ;; C-u - C-x TAB [outdent rigidly one character] | ||
| 107 | ;; C-x { shrink-window-horizontally | ||
| 108 | ;; C-x } enlarge-window-horizontally | ||
| 109 | |||
| 110 | ;; Using vi-dot.el doesn't entail a performance hit. There's a | ||
| 111 | ;; straightforward way to implement a package like this that would save some | ||
| 112 | ;; data about each command as it was executed, but that Lisp would need to be | ||
| 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 | |||
| 121 | ;;; Code: | ||
| 122 | |||
| 123 | (eval-when-compile (require 'cl)) | ||
| 124 | |||
| 125 | ;;;;; ************************* USER OPTIONS ************************** ;;;;; | ||
| 126 | |||
| 127 | (defvar vi-dot-too-dangerous '(kill-this-buffer) | ||
| 128 | "Commands too dangerous to repeat with `vi-dot'.") | ||
| 129 | |||
| 130 | ;; If the last command was self-insert-command, the char to be inserted was | ||
| 131 | ;; obtained by that command from last-command-char, which has now been | ||
| 132 | ;; clobbered by the command sequence that invoked vi-dot. We could get it | ||
| 133 | ;; from (recent-keys) & set last-command-char to that, "unclobbering" it, but | ||
| 134 | ;; this has the disadvantage that if the user types a sequence of different | ||
| 135 | ;; chars then invokes vi-dot, only the final char will be inserted. In vi, | ||
| 136 | ;; the dot command can reinsert the entire most-recently-inserted sequence. | ||
| 137 | ;; To do the same thing here, we need to extract the string to insert from | ||
| 138 | ;; the undo information, then insert a new copy in the buffer. However, the | ||
| 139 | ;; built-in `insert', which takes a string as an arg, is a little different | ||
| 140 | ;; from `self-insert-command', which takes only a prefix arg; `insert' ignores | ||
| 141 | ;; `overwrite-mode'. Emacs 19.34 has no self-insert-string. But there's | ||
| 142 | ;; one in my dotemacs.el (on the web), so if you want to, you can define that | ||
| 143 | ;; in your .emacs, & it'll Just Work, as it will in any future Emaecse that | ||
| 144 | ;; have self-insert-string. Or users can code their own | ||
| 145 | ;; insert-string-with-trumpet-fanfare and use that by customizing this: | ||
| 146 | |||
| 147 | (defvar vi-dot-insert-function | ||
| 148 | (catch t (mapcar (lambda (f) (if (fboundp f) (throw t f))) | ||
| 149 | [self-insert-string | ||
| 150 | insert])) | ||
| 151 | "Function used by `vi-dot' command to re-insert a string of characters. | ||
| 152 | In a vanilla Emacs this will default to `insert', which doesn't respect | ||
| 153 | `overwrite-mode'; customize with your own insertion function, taking a single | ||
| 154 | string as an argument, if you have one.") | ||
| 155 | |||
| 156 | (defvar vi-dot-message-function nil | ||
| 157 | "If non-nil, function used by `vi-dot' command to say what it's doing. | ||
| 158 | Message is something like \"Repeating command glorp\". | ||
| 159 | To disable such messages, assign 'ignore to this variable. To customize | ||
| 160 | display, assign a function that takes one string as an arg and displays | ||
| 161 | it however you want.") | ||
| 162 | |||
| 163 | (defvar vi-dot-repeat-on-final-keystroke t | ||
| 164 | "Allow `vi-dot' to re-execute for repeating lastchar of a key sequence. | ||
| 165 | If this variable is t, `vi-dot' determines what key sequence | ||
| 166 | it was invoked by, extracts the final character of that sequence, and | ||
| 167 | re-executes as many times as that final character is hit; so for example | ||
| 168 | if `vi-dot' is bound to C-x z, typing C-x z z z repeats the previous command | ||
| 169 | 3 times. If this variable is a sequence of characters, then re-execution | ||
| 170 | only occurs if the final character by which `vi-dot' was invoked is a | ||
| 171 | member of that sequence. If this variable is nil, no re-execution occurs.") | ||
| 172 | |||
| 173 | ;;;;; ****************** HACKS TO THE REST OF EMACS ******************* ;;;;; | ||
| 174 | |||
| 175 | ;; The basic strategy is to use last-command, a variable built in to Emacs. | ||
| 176 | ;; There are 2 issues that complicate this strategy. The first is that | ||
| 177 | ;; last-command is given a bogus value when any kill command is executed; | ||
| 178 | ;; this is done to make it easy for 'yank-pop to know that it's being invoked | ||
| 179 | ;; after a kill command. The second is that the meaning of the command is | ||
| 180 | ;; often altered by the prefix arg, but although Emacs (GNU 19.34) has a | ||
| 181 | ;; builtin prefix-arg specifying the arg for the next command, as well as a | ||
| 182 | ;; builtin current-prefix-arg, it has no builtin last-prefix-arg. | ||
| 183 | |||
| 184 | ;; There's a builtin (this-command-keys), the return value of which could be | ||
| 185 | ;; executed with (command-execute), but there's no (last-command-keys). | ||
| 186 | ;; Using (last-command-keys) if it existed wouldn't be optimal, however, | ||
| 187 | ;; since it would complicate checking membership in vi-dot-too-dangerous. | ||
| 188 | |||
| 189 | ;; It would of course be trivial to implement last-prefix-arg & | ||
| 190 | ;; true-last-command by putting something in post-command-hook, but that | ||
| 191 | ;; entails a performance hit; the approach taken below avoids that. | ||
| 192 | |||
| 193 | ;; First cope with (kill-region). It's straightforward to advise it to save | ||
| 194 | ;; the true value of this-command before clobbering it. | ||
| 195 | |||
| 196 | (require 'advice) | ||
| 197 | |||
| 198 | (defvar vi-dot-last-kill-command nil | ||
| 199 | "True value of `this-command' before (`kill-region') clobbered it.") | ||
| 200 | |||
| 201 | (defadvice kill-region (before vi-dot-save-last-kill-command act) | ||
| 202 | "Remember true value of this-command before (`kill-region') clobbers it." | ||
| 203 | (setq vi-dot-last-kill-command this-command)) | ||
| 204 | |||
| 205 | ;; Next cope with the prefix arg. I can advise the various functions that | ||
| 206 | ;; create prefix args to save the arg in a variable ... | ||
| 207 | |||
| 208 | (defvar vi-dot-prefix-arg nil | ||
| 209 | "Prefix arg created as most recent universal argument.") | ||
| 210 | |||
| 211 | ;; ... but alone that's not enough, because if last-command's prefix arg was | ||
| 212 | ;; nil, none of those functions were ever called, so whatever command before | ||
| 213 | ;; last-command did have a prefix arg has left it in vi-dot-prefix-arg, & I | ||
| 214 | ;; need a way to tell whether whatever's in there applies to last-command. | ||
| 215 | |||
| 216 | ;; From Info|ELisp|Command Loop|Reading Input|Key Sequence Input: | ||
| 217 | ;; - Variable: num-input-keys | ||
| 218 | ;; This variable's value is the number of key sequences processed so far | ||
| 219 | ;; in this Emacs session. This includes key sequences read from the | ||
| 220 | ;; terminal and key sequences read from keyboard macros being executed. | ||
| 221 | ;; num-input-keys counts key *sequences*, not key *strokes*; it's only | ||
| 222 | ;; incremented after reading a complete key sequence mapping to a command. | ||
| 223 | |||
| 224 | (defvar vi-dot-num-input-keys-at-prefix -1 | ||
| 225 | "# of key sequences read in Emacs session when prefix-arg defined.") | ||
| 226 | |||
| 227 | (mapcar (lambda (f) | ||
| 228 | (eval | ||
| 229 | `(defadvice ,f (after vi-dot-save-universal-arg act) | ||
| 230 | (setq vi-dot-prefix-arg current-prefix-arg | ||
| 231 | vi-dot-num-input-keys-at-prefix num-input-keys)))) | ||
| 232 | [universal-argument-more | ||
| 233 | universal-argument-other-key | ||
| 234 | typematic-universal-argument-more-or-less]) | ||
| 235 | |||
| 236 | ;; Coping with strings of self-insert commands gets hairy when they interact | ||
| 237 | ;; with auto-filling. Most problems are eliminated by remembering what we're | ||
| 238 | ;; self-inserting, so we only need to get it from the undo information once. | ||
| 239 | |||
| 240 | (defvar vi-dot-last-self-insert nil | ||
| 241 | "If last repeated command was `self-insert-command', it inserted this.") | ||
| 242 | |||
| 243 | ;; That'll require another keystroke count so we know we're in a string of | ||
| 244 | ;; repetitions of self-insert commands: | ||
| 245 | |||
| 246 | (defvar vi-dot-num-input-keys-at-self-insert -1 | ||
| 247 | "# key sequences read in Emacs session when `self-insert-command' repeated.") | ||
| 248 | |||
| 249 | ;;;;; *************** ANALOGOUS HACKS TO VI-DOT ITSELF **************** ;;;;; | ||
| 250 | |||
| 251 | ;; That mechanism of checking num-input-keys to figure out what's really | ||
| 252 | ;; going on can be useful to other commands that need to fine-tune their | ||
| 253 | ;; interaction with vi-dot. Instead of requiring them to advise vi-dot, we | ||
| 254 | ;; can just defvar the value they need here, & setq it in the vi-dot command: | ||
| 255 | |||
| 256 | (defvar vi-dot-num-input-keys-at-vi-dot -1 | ||
| 257 | "# key sequences read in Emacs session when `vi-dot' last invoked.") | ||
| 258 | |||
| 259 | ;; Also, we can assign a name to the test for which that variable is | ||
| 260 | ;; intended, which thereby documents here how to use it, & makes code that | ||
| 261 | ;; uses it self-documenting: | ||
| 262 | |||
| 263 | (defsubst vi-dot-is-really-this-command () | ||
| 264 | "Return t if this command is happening because user invoked `vi-dot'. | ||
| 265 | Usually, when a command is executing, the Emacs builtin variable | ||
| 266 | `this-command' identifies the command the user invoked. Some commands modify | ||
| 267 | that variable on the theory they're doing more good than harm; `vi-dot' does | ||
| 268 | that, and usually does do more good than harm. However, like all do-gooders, | ||
| 269 | sometimes `vi-dot' gets surprising results from its altruism. The value of | ||
| 270 | this function is always whether the value of `this-command' would've been | ||
| 271 | 'vi-dot if `vi-dot' hadn't modified it." | ||
| 272 | (= vi-dot-num-input-keys-at-vi-dot num-input-keys)) | ||
| 273 | |||
| 274 | ;; An example of the use of (vi-dot-is-really-this-command) may still be | ||
| 275 | ;; available in <http://www.eskimo.com/~seldon/dotemacs.el>; search for | ||
| 276 | ;; "defun wm-switch-buffer". | ||
| 277 | |||
| 278 | ;;;;; ******************* THE VI-DOT COMMAND ITSELF ******************* ;;;;; | ||
| 279 | |||
| 280 | ;;;###autoload | ||
| 281 | (defun vi-dot (vi-dot-arg) | ||
| 282 | "Repeat most recently executed command. | ||
| 283 | With prefix arg, apply new prefix arg to that command; otherwise, maintain | ||
| 284 | prefix arg of most recently executed command if it had one. | ||
| 285 | This command is named after the `.' command in the vi editor. | ||
| 286 | |||
| 287 | If this command is invoked by a multi-character key sequence, it can then | ||
| 288 | be repeated by repeating the final character of that sequence. This behavior | ||
| 289 | can be modified by the global variable `vi-dot-repeat-on-final-keystroke'." | ||
| 290 | ;; The most recently executed command could be anything, so surprises could | ||
| 291 | ;; result if it were re-executed in a context where new dynamically | ||
| 292 | ;; localized variables were shadowing global variables in a `let' clause in | ||
| 293 | ;; here. (Remember that GNU Emacs 19 is dynamically localized.) | ||
| 294 | ;; To avoid that, I tried the `lexical-let' of the Common Lisp extensions, | ||
| 295 | ;; but that entails a very noticeable performance hit, so instead I use the | ||
| 296 | ;; "vi-dot-" prefix, reserved by this package, for *local* variables that | ||
| 297 | ;; might be visible to re-executed commands, including this function's arg. | ||
| 298 | (interactive "P") | ||
| 299 | (when (eq last-command 'kill-region) | ||
| 300 | (setq last-command vi-dot-last-kill-command)) | ||
| 301 | (setq this-command last-command | ||
| 302 | vi-dot-num-input-keys-at-vi-dot num-input-keys) | ||
| 303 | (when (eq last-command 'mode-exit) | ||
| 304 | (error "last-command is mode-exit & can't be repeated")) | ||
| 305 | (when (memq last-command vi-dot-too-dangerous) | ||
| 306 | (error "Command %S too dangerous to repeat automatically" last-command)) | ||
| 307 | (when (and (null vi-dot-arg) | ||
| 308 | (<= (- num-input-keys vi-dot-num-input-keys-at-prefix) 2)) | ||
| 309 | (setq vi-dot-arg vi-dot-prefix-arg)) | ||
| 310 | ;; Now determine whether to loop on repeated taps of the final character | ||
| 311 | ;; of the key sequence that invoked vi-dot. The Emacs global | ||
| 312 | ;; last-command-char contains the final character now, but may not still | ||
| 313 | ;; contain it after the previous command is repeated, so the character | ||
| 314 | ;; needs to be saved. | ||
| 315 | (let ((vi-dot-repeat-char | ||
| 316 | (if (eq vi-dot-repeat-on-final-keystroke t) | ||
| 317 | ;; allow any final input event that was a character | ||
| 318 | (when (eq last-command-char | ||
| 319 | last-command-event) | ||
| 320 | last-command-char) | ||
| 321 | ;; allow only specified final keystrokes | ||
| 322 | (car (memq last-command-char | ||
| 323 | (listify-key-sequence | ||
| 324 | vi-dot-repeat-on-final-keystroke)))))) | ||
| 325 | (if (memq last-command '(exit-minibuffer | ||
| 326 | minibuffer-complete-and-exit | ||
| 327 | self-insert-and-exit)) | ||
| 328 | (let ((vi-dot-command (car command-history))) | ||
| 329 | (vi-dot-message "Repeating %S" vi-dot-command) | ||
| 330 | (eval vi-dot-command)) | ||
| 331 | (if (null vi-dot-arg) | ||
| 332 | (vi-dot-message "Repeating command %S" last-command) | ||
| 333 | (setq vi-dot-num-input-keys-at-prefix num-input-keys | ||
| 334 | current-prefix-arg vi-dot-arg) | ||
| 335 | (vi-dot-message "Repeating command %S %S" vi-dot-arg last-command)) | ||
| 336 | (if (eq last-command 'self-insert-command) | ||
| 337 | (let ((insertion | ||
| 338 | (if (<= (- num-input-keys | ||
| 339 | vi-dot-num-input-keys-at-self-insert) | ||
| 340 | 1) | ||
| 341 | vi-dot-last-self-insert | ||
| 342 | (let ((range (nth 1 buffer-undo-list))) | ||
| 343 | (condition-case nil | ||
| 344 | (setq vi-dot-last-self-insert | ||
| 345 | (buffer-substring (car range) | ||
| 346 | (cdr range))) | ||
| 347 | (error (error "%s %s %s" ;Danger, Will Robinson! | ||
| 348 | "vi-dot can't intuit what you" | ||
| 349 | "inserted before auto-fill" | ||
| 350 | "clobbered it, sorry"))))))) | ||
| 351 | (setq vi-dot-num-input-keys-at-self-insert num-input-keys) | ||
| 352 | (loop repeat (prefix-numeric-value vi-dot-arg) do | ||
| 353 | (funcall vi-dot-insert-function insertion))) | ||
| 354 | (call-interactively last-command))) | ||
| 355 | (when vi-dot-repeat-char | ||
| 356 | ;; A simple recursion here gets into trouble with max-lisp-eval-depth | ||
| 357 | ;; on long sequences of repetitions of a command like `forward-word' | ||
| 358 | ;; (only 32 repetitions are possible given the default value of 200 for | ||
| 359 | ;; max-lisp-eval-depth), but if I now locally disable the repeat char I | ||
| 360 | ;; can iterate indefinitely here around a single level of recursion. | ||
| 361 | (let (vi-dot-repeat-on-final-keystroke) | ||
| 362 | (while (eq (read-event) vi-dot-repeat-char) | ||
| 363 | (vi-dot vi-dot-arg)) | ||
| 364 | (setq unread-command-events (list last-input-event)))))) | ||
| 365 | |||
| 366 | (defun vi-dot-message (format &rest args) | ||
| 367 | "Like `message' but displays with `vi-dot-message-function' if non-nil." | ||
| 368 | (let ((message (apply 'format format args))) | ||
| 369 | (if vi-dot-message-function | ||
| 370 | (funcall vi-dot-message-function message) | ||
| 371 | (message "%s" message)))) | ||
| 372 | |||
| 373 | ;; OK, there's one situation left where that doesn't work correctly: when the | ||
| 374 | ;; most recent self-insertion provoked an auto-fill. The problem is that | ||
| 375 | ;; unravelling the undo information after an auto-fill is too hard, since all | ||
| 376 | ;; kinds of stuff can get in there as a result of comment prefixes etc. It'd | ||
| 377 | ;; be possible to advise do-auto-fill to record the most recent | ||
| 378 | ;; self-insertion before it does its thing, but that's a performance hit on | ||
| 379 | ;; auto-fill, which already has performance problems; so it's better to just | ||
| 380 | ;; leave it like this. If text didn't provoke an auto-fill when the user | ||
| 381 | ;; typed it, this'll correctly repeat its self-insertion, even if the | ||
| 382 | ;; repetition does cause auto-fill. | ||
| 383 | |||
| 384 | ;; If you wanted perfection, probably it'd be necessary to hack do-auto-fill | ||
| 385 | ;; into 2 functions, maybe-do-auto-fill & really-do-auto-fill, because only | ||
| 386 | ;; really-do-auto-fill should be advised. As things are, either the undo | ||
| 387 | ;; information would need to be scanned on every do-auto-fill invocation, or | ||
| 388 | ;; the code at the top of do-auto-fill deciding whether filling is necessary | ||
| 389 | ;; would need to be duplicated in the advice, wasting execution time when | ||
| 390 | ;; filling does turn out to be necessary. | ||
| 391 | |||
| 392 | ;; I thought maybe this story had a moral, something about functional | ||
| 393 | ;; decomposition; but now I'm not even sure of that, since a function | ||
| 394 | ;; call per se is a performance hit, & even the code that would | ||
| 395 | ;; correspond to really-do-auto-fill has performance problems that | ||
| 396 | ;; can make it necessary to stop typing while Emacs catches up. | ||
| 397 | ;; Maybe the real moral is that perfection is a chimera. | ||
| 398 | |||
| 399 | ;; Ah, hell, it's all going to fall into a black hole someday anyway. | ||
| 400 | |||
| 401 | ;;;;; ************************* EMACS CONTROL ************************* ;;;;; | ||
| 402 | |||
| 403 | (provide 'vi-dot) | ||
| 404 | |||
| 405 | ;;; vi-dot.el ends here | ||