changeset 22439:3dc0b9f57ff6

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.
author Richard M. Stallman <rms@gnu.org>
date Thu, 11 Jun 1998 20:17:43 +0000
parents 917424c9c149
children 8a51f757af2c
files lisp/repeat.el
diffstat 1 files changed, 96 insertions(+), 161 deletions(-) [+]
line wrap: on
line diff
--- a/lisp/repeat.el	Thu Jun 11 20:16:45 1998 +0000
+++ b/lisp/repeat.el	Thu Jun 11 20:17:43 1998 +0000
@@ -1,11 +1,11 @@
-;;; vi-dot.el --- convenient way to repeat the previous command
+;;; repeat.el --- convenient way to repeat the previous command
 
 ;; Copyright (C) 1998 Free Software Foundation, Inc.
 
 ;; Author: Will Mengarini <seldon@eskimo.com>
 ;; Created: Mo 02 Mar 98
 ;; Version: 0.51, We 13 May 98
-;; Keywords: convenience, abbrev, vi, universal argument, typematic, repeat
+;; Keywords: convenience, vi, repeat
 
 ;; This file is part of GNU Emacs.
 
@@ -38,60 +38,40 @@
 ;; This is a pain in the ass.
 
 ;; This package defines a command that repeats the preceding command,
-;; whatever that was.  The command is called `vi-dot' because the vi editor,
-;; Emacs's arch-rival among the Great Unwashed, does that when "." is pressed
-;; in its command mode.
-
-;; Starting with Emacs 20.3, this package is part of Emacs, and the
-;; `vi-dot' command is bound to the key sequence C-x z.  (You can actually
-;; keep repeating the most recent command by just repeating the z after the
-;; first C-x z.)  However, you can use this package with older versions of
-;; Emacs.  Make the binding with
-;;       (require 'vi-dot)
-;;       (global-set-key "\C-xz" 'vi-dot)
-;;     in your .emacs to give the command its orthodox binding of C-x z.
-
-;; Since the whole point of vi-dot is to let you repeat commands that are
-;; bound to multiple keystrokes by leaning on a *single* key, it seems not to
-;; make sense to bind vi-dot itself to a multiple-character key sequence, but
-;; there aren't any appropriate single characters left in the orthodox global
-;; map.  (Meta characters don't count because they require two keystrokes if
-;; you don't have a real meta key, and things like function keys can't be
-;; relied on to be available to all users.  We considered rebinding C-z,
-;; since C-x C-z is also bound to the same command, but RMS decided too many
-;; users were accustomed to the orthodox meaning of C-z.)  So the vi-dot
-;; command checks what key sequence it was invoked by, and allows you to
-;; repeat the final key in that sequence to keep repeating the command.
-;; For example, C-x ] C-x z z z will move forward 4 pages.
+;; whatever that was, including its arguments, whatever they were.
+;; This command is connected to the key C-x z.
+;; To repeat the previous command once, type C-x z.
+;; To repeat it a second time immediately after, type just z.
+;; By typing z again and again, you can repeat the command over and over.
 
 ;; This works correctly inside a keyboard macro as far as recording and
 ;; playback go, but `edit-kbd-macro' gets it wrong.  That shouldn't really
 ;; matter; if you need to edit something like
 ;;   C-x ]              ;; forward-page
-;;   C-x z              ;; vi-dot
+;;   C-x z              ;; repeat
 ;;   zz                 ;; self-insert-command * 2
 ;;   C-x                ;; Control-X-prefix
-;; you can just kill the bogus final 2 lines, then duplicate the vi-dot line
+;; you can just kill the bogus final 2 lines, then duplicate the repeat line
 ;; as many times as it's really needed.  Also, `edit-kbd-macro' works
-;; correctly if `vi-dot' is invoked through a rebinding to a single keystroke
-;; and the global variable vi-dot-repeat-on-final-keystroke is set to a value
+;; correctly if `repeat' is invoked through a rebinding to a single keystroke
+;; and the global variable repeat-on-final-keystroke is set to a value
 ;; that doesn't include that keystroke.  For example, the lines
-;;   (global-set-key "\C-z" 'vi-dot)
-;;   (setq vi-dot-repeat-on-final-keystroke "z")
+;;   (global-set-key "\C-z" 'repeat)
+;;   (setq repeat-on-final-keystroke "z")
 ;; in your .emacs would allow `edit-kbd-macro' to work correctly when C-z was
-;; used in a keyboard macro to invoke `vi-dot', but would still allow C-x z
-;; to be used for `vi-dot' elsewhere.  The real reason for documenting this
+;; used in a keyboard macro to invoke `repeat', but would still allow C-x z
+;; to be used for `repeat' elsewhere.  The real reason for documenting this
 ;; isn't that anybody would need it for the `edit-kbd-macro' problem, but
 ;; that there might be other unexpected ramifications of re-executing on
 ;; repetitions of the final keystroke, and this shows how to do workarounds.
 
 ;; If the preceding command had a prefix argument, that argument is applied
-;; to the vi-dot command, unless the vi-dot command is given a new prefix
+;; to the repeat command, unless the repeat command is given a new prefix
 ;; argument, in which case it applies that new prefix argument to the
 ;; preceding command.  This means a key sequence like C-u - C-x C-t can be
 ;; repeated.  (It shoves the preceding line upward in the buffer.)
 
-;; Here are some other key sequences with which vi-dot might be useful:
+;; Here are some other key sequences with which repeat might be useful:
 ;;   C-u - C-t      [shove preceding character backward in line]
 ;;   C-u - M-t      [shove preceding word backward in sentence]
 ;;         C-x ^    enlarge-window [one line] (assuming frame has > 1 window)
@@ -107,16 +87,9 @@
 ;;         C-x {    shrink-window-horizontally
 ;;         C-x }    enlarge-window-horizontally
 
-;; Using vi-dot.el doesn't entail a performance hit.  There's a
-;; straightforward way to implement a package like this that would save some
-;; data about each command as it was executed, but that Lisp would need to be
-;; interpreted on every keystroke, which is Bad.  This implementation doesn't
-;; do it that way; the peformance impact on almost all keystrokes is 0.
-
-;; Buried in the implementation is a reference to a function in my
-;; typematic.el package, which isn't part of GNU Emacs.  However, that
-;; package is *not* required by vi-dot; the reference allows it to be used,
-;; but doesn't require it.
+;; This command was first called `vi-dot', because
+;; it was inspired by the `.' command in the vi editor,
+;; but it was renamed to make its name more meaningful.
 
 ;;; Code:
 
@@ -124,34 +97,34 @@
 
 ;;;;; ************************* USER OPTIONS ************************** ;;;;;
 
-(defcustom vi-dot-too-dangerous '(kill-this-buffer)
-  "Commands too dangerous to repeat with `vi-dot'."
+(defcustom repeat-too-dangerous '(kill-this-buffer)
+  "Commands too dangerous to repeat with \\[repeat]."
   :group 'convenience
   :type '(repeat function))
 
 ;; If the last command was self-insert-command, the char to be inserted was
 ;; obtained by that command from last-command-char, which has now been
-;; clobbered by the command sequence that invoked vi-dot.  We could get it
+;; clobbered by the command sequence that invoked `repeat'.  We could get it
 ;; from (recent-keys) & set last-command-char to that, "unclobbering" it, but
 ;; this has the disadvantage that if the user types a sequence of different
-;; chars then invokes vi-dot, only the final char will be inserted.  In vi,
+;; chars then invokes repeat, only the final char will be inserted.  In vi,
 ;; the dot command can reinsert the entire most-recently-inserted sequence.
 
-(defvar vi-dot-message-function nil
-  "If non-nil, function used by `vi-dot' command to say what it's doing.
+(defvar repeat-message-function nil
+  "If non-nil, function used by `repeat' command to say what it's doing.
 Message is something like \"Repeating command glorp\".
 To disable such messages, set this variable to `ignore'.  To customize
 display, assign a function that takes one string as an arg and displays
 it however you want.")
 
-(defcustom vi-dot-repeat-on-final-keystroke t
-  "Allow `vi-dot' to re-execute for repeating lastchar of a key sequence.
-If this variable is t, `vi-dot' determines what key sequence
+(defcustom repeat-on-final-keystroke t
+  "Allow `repeat' to re-execute for repeating lastchar of a key sequence.
+If this variable is t, `repeat' determines what key sequence
 it was invoked by, extracts the final character of that sequence, and
 re-executes as many times as that final character is hit; so for example
-if `vi-dot' is bound to C-x z, typing C-x z z z repeats the previous command
+if `repeat' is bound to C-x z, typing C-x z z z repeats the previous command
 3 times.  If this variable is a sequence of characters, then re-execution
-only occurs if the final character by which `vi-dot' was invoked is a
+only occurs if the final character by which `repeat' was invoked is a
 member of that sequence.  If this variable is nil, no re-execution occurs."
   :group 'convenience
   :type 'boolean)
@@ -161,16 +134,16 @@
 ;; The basic strategy is to use last-command, a variable built in to Emacs.
 ;; There are 2 issues that complicate this strategy.  The first is that
 ;; last-command is given a bogus value when any kill command is executed;
-;; this is done to make it easy for 'yank-pop to know that it's being invoked
+;; this is done to make it easy for `yank-pop' to know that it's being invoked
 ;; after a kill command.  The second is that the meaning of the command is
-;; often altered by the prefix arg, but although Emacs (GNU 19.34) has a
+;; often altered by the prefix arg, but although Emacs (19.34) has a
 ;; builtin prefix-arg specifying the arg for the next command, as well as a
 ;; builtin current-prefix-arg, it has no builtin last-prefix-arg.
 
 ;; There's a builtin (this-command-keys), the return value of which could be
 ;; executed with (command-execute), but there's no (last-command-keys).
 ;; Using (last-command-keys) if it existed wouldn't be optimal, however,
-;; since it would complicate checking membership in vi-dot-too-dangerous.
+;; since it would complicate checking membership in repeat-too-dangerous.
 
 ;; It would of course be trivial to implement last-prefix-arg &
 ;; true-last-command by putting something in post-command-hook, but that
@@ -181,90 +154,55 @@
 
 (require 'advice)
 
-(defvar vi-dot-last-kill-command nil
+(defvar repeat-last-kill-command nil
   "True value of `this-command' before (`kill-region') clobbered it.")
 
-(defadvice kill-region (before vi-dot-save-last-kill-command act)
-  "Remember true value of this-command before (`kill-region') clobbers it."
-  (setq vi-dot-last-kill-command this-command))
-
-;; Next cope with the prefix arg.  I can advise the various functions that
-;; create prefix args to save the arg in a variable ...
-
-(defvar vi-dot-prefix-arg nil
-  "Prefix arg created as most recent universal argument.")
-
-;; ... but alone that's not enough, because if last-command's prefix arg was
-;; nil, none of those functions were ever called, so whatever command before
-;; last-command did have a prefix arg has left it in vi-dot-prefix-arg, & I
-;; need a way to tell whether whatever's in there applies to last-command.
-
-;; From Info|ELisp|Command Loop|Reading Input|Key Sequence Input:
-;;  - Variable: num-input-keys
-;;      This variable's value is the number of key sequences processed so far
-;;      in this Emacs session.  This includes key sequences read from the
-;;      terminal and key sequences read from keyboard macros being executed.
-;; num-input-keys counts key *sequences*, not key *strokes*; it's only
-;; incremented after reading a complete key sequence mapping to a command.
-
-(defvar vi-dot-num-input-keys-at-prefix -1
-  "# of key sequences read in Emacs session when prefix-arg defined.")
-
-(mapcar (lambda (f)
-          (eval
-           `(defadvice ,f (after vi-dot-save-universal-arg act)
-              (setq vi-dot-prefix-arg                  current-prefix-arg
-                    vi-dot-num-input-keys-at-prefix    num-input-keys))))
-        [universal-argument-more
-         universal-argument-other-key
-         typematic-universal-argument-more-or-less])
-
 ;; Coping with strings of self-insert commands gets hairy when they interact
 ;; with auto-filling.  Most problems are eliminated by remembering what we're
 ;; self-inserting, so we only need to get it from the undo information once.
 
-(defvar vi-dot-last-self-insert nil
+(defvar repeat-last-self-insert nil
   "If last repeated command was `self-insert-command', it inserted this.")
 
 ;; That'll require another keystroke count so we know we're in a string of
 ;; repetitions of self-insert commands:
 
-(defvar vi-dot-num-input-keys-at-self-insert -1
+(defvar repeat-num-input-keys-at-self-insert -1
   "# key sequences read in Emacs session when `self-insert-command' repeated.")
 
-;;;;; *************** ANALOGOUS HACKS TO VI-DOT ITSELF **************** ;;;;;
+;;;;; *************** ANALOGOUS HACKS TO `repeat' ITSELF **************** ;;;;;
 
 ;; That mechanism of checking num-input-keys to figure out what's really
 ;; going on can be useful to other commands that need to fine-tune their
-;; interaction with vi-dot.  Instead of requiring them to advise vi-dot, we
-;; can just defvar the value they need here, & setq it in the vi-dot command:
+;; interaction with repeat.  Instead of requiring them to advise repeat, we
+;; can just defvar the value they need here, & setq it in the repeat command:
 
-(defvar vi-dot-num-input-keys-at-vi-dot -1
-  "# key sequences read in Emacs session when `vi-dot' last invoked.")
+(defvar repeat-num-input-keys-at-repeat -1
+  "# key sequences read in Emacs session when `repeat' last invoked.")
 
 ;; Also, we can assign a name to the test for which that variable is
 ;; intended, which thereby documents here how to use it, & makes code that
 ;; uses it self-documenting:
 
-(defsubst vi-dot-is-really-this-command ()
-  "Return t if this command is happening because user invoked `vi-dot'.
+(defsubst repeat-is-really-this-command ()
+  "Return t if this command is happening because user invoked `repeat'.
 Usually, when a command is executing, the Emacs builtin variable
 `this-command' identifies the command the user invoked.  Some commands modify
-that variable on the theory they're doing more good than harm; `vi-dot' does
+that variable on the theory they're doing more good than harm; `repeat' does
 that, and usually does do more good than harm.  However, like all do-gooders,
-sometimes `vi-dot' gets surprising results from its altruism.  The value of
+sometimes `repeat' gets surprising results from its altruism.  The value of
 this function is always whether the value of `this-command' would've been
-'vi-dot if `vi-dot' hadn't modified it."
-  (= vi-dot-num-input-keys-at-vi-dot num-input-keys))
+'repeat if `repeat' hadn't modified it."
+  (= repeat-num-input-keys-at-repeat num-input-keys))
 
-;; An example of the use of (vi-dot-is-really-this-command) may still be
+;; An example of the use of (repeat-is-really-this-command) may still be
 ;; available in <http://www.eskimo.com/~seldon/dotemacs.el>; search for
 ;; "defun wm-switch-buffer".
 
-;;;;; ******************* THE VI-DOT COMMAND ITSELF ******************* ;;;;;
+;;;;; ******************* THE REPEAT COMMAND ITSELF ******************* ;;;;;
 
 ;;;###autoload
-(defun vi-dot (vi-dot-arg)
+(defun repeat (repeat-arg)
   "Repeat most recently executed command.
 With prefix arg, apply new prefix arg to that command; otherwise, maintain
 prefix arg of most recently executed command if it had one.
@@ -272,34 +210,31 @@
 
 If this command is invoked by a multi-character key sequence, it can then
 be repeated by repeating the final character of that sequence.  This behavior
-can be modified by the global variable `vi-dot-repeat-on-final-keystroke'."
+can be modified by the global variable `repeat-on-final-keystroke'."
   ;; The most recently executed command could be anything, so surprises could
   ;; result if it were re-executed in a context where new dynamically
   ;; localized variables were shadowing global variables in a `let' clause in
   ;; here.  (Remember that GNU Emacs 19 is dynamically localized.)
   ;; To avoid that, I tried the `lexical-let' of the Common Lisp extensions,
   ;; but that entails a very noticeable performance hit, so instead I use the
-  ;; "vi-dot-" prefix, reserved by this package, for *local* variables that
+  ;; "repeat-" prefix, reserved by this package, for *local* variables that
   ;; might be visible to re-executed commands, including this function's arg.
   (interactive "P")
-  (when (eq last-command 'kill-region)
-    (setq last-command vi-dot-last-kill-command))
-  (setq this-command                      last-command
-        vi-dot-num-input-keys-at-vi-dot   num-input-keys)
-  (when (eq last-command 'mode-exit)
-    (error "last-command is mode-exit & can't be repeated"))
-  (when (memq last-command vi-dot-too-dangerous)
-    (error "Command %S too dangerous to repeat automatically" last-command))
-  (when (and (null vi-dot-arg)
-             (<= (- num-input-keys vi-dot-num-input-keys-at-prefix) 2))
-    (setq vi-dot-arg vi-dot-prefix-arg))
+  (setq this-command                      real-last-command
+        repeat-num-input-keys-at-repeat   num-input-keys)
+  (when (eq real-last-command 'mode-exit)
+    (error "real-last-command is mode-exit & can't be repeated"))
+  (when (memq real-last-command repeat-too-dangerous)
+    (error "Command %S too dangerous to repeat automatically" real-last-command))
+  (when (null repeat-arg)
+    (setq repeat-arg last-prefix-arg))
   ;; Now determine whether to loop on repeated taps of the final character
-  ;; of the key sequence that invoked vi-dot.  The Emacs global
+  ;; of the key sequence that invoked repeat.  The Emacs global
   ;; last-command-char contains the final character now, but may not still
   ;; contain it after the previous command is repeated, so the character
   ;; needs to be saved.
-  (let ((vi-dot-repeat-char
-         (if (eq vi-dot-repeat-on-final-keystroke t)
+  (let ((repeat-repeat-char
+         (if (eq repeat-on-final-keystroke t)
              ;; allow any final input event that was a character
              (when (eq last-command-char
                        last-command-event)
@@ -307,60 +242,60 @@
            ;; allow only specified final keystrokes
            (car (memq last-command-char
                       (listify-key-sequence
-                       vi-dot-repeat-on-final-keystroke))))))
-    (if (memq last-command '(exit-minibuffer
-                             minibuffer-complete-and-exit
-                             self-insert-and-exit))
-        (let ((vi-dot-command (car command-history)))
-          (vi-dot-message "Repeating %S" vi-dot-command)
-          (eval vi-dot-command))
-      (if (null vi-dot-arg)
-          (vi-dot-message "Repeating command %S" last-command)
-        (setq vi-dot-num-input-keys-at-prefix      num-input-keys
-              current-prefix-arg                   vi-dot-arg)
-        (vi-dot-message "Repeating command %S %S" vi-dot-arg last-command))
-      (if (eq last-command 'self-insert-command)
+                       repeat-on-final-keystroke))))))
+    (if (memq real-last-command '(exit-minibuffer
+				  minibuffer-complete-and-exit
+				  self-insert-and-exit))
+        (let ((repeat-command (car command-history)))
+          (repeat-message "Repeating %S" repeat-command)
+          (eval repeat-command))
+      (if (null repeat-arg)
+          (repeat-message "Repeating command %S" real-last-command)
+        (setq repeat-num-input-keys-at-prefix      num-input-keys
+              current-prefix-arg                   repeat-arg)
+        (repeat-message "Repeating command %S %S" repeat-arg real-last-command))
+      (if (eq real-last-command 'self-insert-command)
           (let ((insertion
                  (if (<= (- num-input-keys
-                            vi-dot-num-input-keys-at-self-insert)
+                            repeat-num-input-keys-at-self-insert)
                          1)
-                     vi-dot-last-self-insert
+                     repeat-last-self-insert
                    (let ((range (nth 1 buffer-undo-list)))
                      (condition-case nil
-                         (setq vi-dot-last-self-insert
+                         (setq repeat-last-self-insert
                                (buffer-substring (car range)
                                                  (cdr range)))
                        (error (error "%s %s %s" ;Danger, Will Robinson! 
-                                     "vi-dot can't intuit what you"
+                                     "repeat can't intuit what you"
                                      "inserted before auto-fill"
                                      "clobbered it, sorry")))))))
-            (setq vi-dot-num-input-keys-at-self-insert num-input-keys)
-            (loop repeat (prefix-numeric-value vi-dot-arg) do
-                  (vi-self-insert insertion)))
-        (call-interactively last-command)))
-    (when vi-dot-repeat-char
+            (setq repeat-num-input-keys-at-self-insert num-input-keys)
+            (loop repeat (prefix-numeric-value repeat-arg) do
+                  (repeat-self-insert insertion)))
+        (call-interactively real-last-command)))
+    (when repeat-repeat-char
       ;; A simple recursion here gets into trouble with max-lisp-eval-depth
       ;; on long sequences of repetitions of a command like `forward-word'
       ;; (only 32 repetitions are possible given the default value of 200 for
       ;; max-lisp-eval-depth), but if I now locally disable the repeat char I
       ;; can iterate indefinitely here around a single level of recursion.
-      (let (vi-dot-repeat-on-final-keystroke)
-        (while (eq (read-event) vi-dot-repeat-char)
-          (vi-dot vi-dot-arg))
+      (let (repeat-on-final-keystroke)
+        (while (eq (read-event) repeat-repeat-char)
+          (repeat repeat-arg))
         (setq unread-command-events (list last-input-event))))))
 
-(defun vi-self-insert (string)
+(defun repeat-self-insert (string)
   (let ((i 0))
     (while (< i (length string))
       (let ((last-command-char (aref string i)))
 	(self-insert-command 1))
       (setq i (1+ i)))))
 
-(defun vi-dot-message (format &rest args)
-  "Like `message' but displays with `vi-dot-message-function' if non-nil."
+(defun repeat-message (format &rest args)
+  "Like `message' but displays with `repeat-message-function' if non-nil."
   (let ((message (apply 'format format args)))
-    (if vi-dot-message-function
-        (funcall vi-dot-message-function message)
+    (if repeat-message-function
+        (funcall repeat-message-function message)
       (message "%s" message))))
 
 ;; OK, there's one situation left where that doesn't work correctly: when the
@@ -393,6 +328,6 @@
 
 ;;;;; ************************* EMACS CONTROL ************************* ;;;;;
 
-(provide 'vi-dot)
+(provide 'repeat)
 
-;;; vi-dot.el ends here
+;;; repeat.el ends here