The following message is a courtesy copy of an article
that has been posted to comp.emacs.xemacs as well.
A while back I heard about `vi-dot.el' on GNU Emacs, and immediately
loved the sound of it; the . repeat-any-command is one of the few
user-interface enhancements vi has over (X)Emacs --- or, rather, *had*,
until vi-dot came along.
The code states that
;; I've been told that this version of vi-dot.el is incompatible with XEmacs
;; because XEmacs lacks a num-input-keys variable.
so I decided to fix that. Some other nonportabilities (mostly in event
handling) cropped up, so I fixed them too --- in an utterly ugly fashion
that almost certainly breaks vi-dot for GNU Emacs.
This pair of patches is against XEmacs-21.4.3 and vi-dot.el 0.51 from
<
http://www.eskimo.com/~seldon/vi-dot.el>. It isn't posted to
gnu.emacs.sources because it only works with XEmacs and needs a
(noninvasive) core C code change. (It applies to 21.4.4rc3 OK; unless
something amazing happens between 21.4.4rc3 and 21.4.4, it will apply to
that too.)
This is sent as a heads-up, and as a notice that if anyone wants to get
vi-dot working in XEmacs it's not hard at all. This is very much a
pre-alpha port; I'm sure I've screwed up behaviour after a
`keyboard-escape-quit', but since I don't have a GNU Emacs anywhere I'm
not sure what the original code does in this situation. (Why does C-g
set `last-command' to `t' anyway?)
First, the XEmacs core change, adding `num-input-keys':
diff -durpN 21.4.3-orig/src/event-stream.c 21.4.3/src/event-stream.c
--- 21.4.3-orig/src/event-stream.c Wed Jul 4 16:23:56 2001
+++ 21.4.3/src/event-stream.c Mon Jul 23 17:09:41 2001
@@ -180,6 +180,10 @@ Lisp_Object Vthis_command;
last-command-properties for the next command. */
Lisp_Object Vthis_command_properties;
+/* The number of complete key sequences processed so far in this XEmacs
+ session. */
+int Vnum_input_keys;
+
/* The value of point when the last command was executed. */
Bufpos last_point_position;
@@ -3942,6 +3946,8 @@ execute_command_event (struct command_bu
Vlast_command_properties = Vthis_command_properties;
Vthis_command_properties = Qnil;
+ Vnum_input_keys++;
+
/* Emacs 18 doesn't unconditionally clear the echoed keystrokes,
so we don't either */
@@ -4720,6 +4726,11 @@ with pre/post-command hooks, subsequent
in preference to looking at and/or setting `this-command'.
*/ );
Vthis_command_properties = Qnil;
+
+ DEFVAR_INT ("num-input-keys", &Vnum_input_keys /*
+Number of complete key sequences processed so far in this XEmacs session.
+*/ );
+Vnum_input_keys = 0;
DEFVAR_LISP ("help-char", &Vhelp_char /*
Character to recognize as meaning Help.
And the evil hacks to vi-dot.el itself:
--- vi-dot.el.orig Wed May 13 10:28:02 1998
+++ vi-dot.el Tue Jul 24 21:19:52 2001
@@ -141,9 +141,6 @@
;; package is *not* required by vi-dot; the reference allows it to be used,
;; but doesn't require it.
-;; I've been told that this version of vi-dot.el is incompatible with XEmacs
-;; because XEmacs lacks a num-input-keys variable.
-
;;; Code:
(eval-when-compile (require 'cl))
@@ -170,6 +167,33 @@
;; have self-insert-string. Or users can code their own
;; insert-string-with-trumpet-fanfare and use that by customizing this:
+;; Support XEmacs.
+
+(and (string-match "XEmacs" emacs-version)
+ (not (fboundp 'self-insert-string))
+ (progn
+ (defun self-insert-char (char)
+ "Insert CHAR respecting things like overwrite mode & auto-fill."
+ (or (characterp char) (error "self-insert-char: arg %S not a char"
char))
+ (let ((last-command-char char))
+ (self-insert-command 1)))
+
+ (defun self-insert-string (string)
+ "Insert STRING respecting things like overwrite mode &
auto-fill."
+ (mapc 'self-insert-char string))
+
+ ;; self-insert-format expects to be used as a Zipfean alias
+ ;; in the (eval-expression) minibuffer, for doing things like
+ ;; inserting sequences of integers.
+
+ (defun self-insert-format (format &rest exprs)
+ "Self-insert each character of (format FORMAT &rest EXPRS)."
+ (self-insert-string (apply 'format format exprs)))
+
+ (defun vi-dot-quiet-message (fmt &rest args)
+ "Like `message', but uses progress-priority `display-message'
instead."
+ (apply 'lmessage 'progress fmt args))))
+
(defvar vi-dot-insert-function
(catch t (mapcar (lambda (f) (if (fboundp f) (throw t f)))
[self-insert-string
@@ -179,7 +203,8 @@
overwrite-mode; customize with your own insertion function, taking a single
string as an argument, if you have one.")
-(defvar vi-dot-message-function nil
+(defvar vi-dot-message-function (if (fboundp 'vi-dot-quiet-message)
+ 'vi-dot-quiet-message nil)
"If non-nil, function used by vi-dot command to say what it's doing.
Message is something like \"Repeating command glorp\".
To disable such messages, assign 'ignore to this variable. To customize
@@ -326,8 +351,10 @@
(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 (eq last-command 'mode-exited)
+ (error "last-command is mode-exited & can't be repeated"))
+ (when (eq last-command t)
+ (error "last-command errored & 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)
@@ -342,12 +369,11 @@
(if (eq vi-dot-repeat-on-final-keystroke t)
;; allow any final input event that was a character
(when (eq last-command-char
- last-command-event)
- last-command-char)
+ (event-to-character last-command-event))
+ last-command-char)
;; allow only specified final keystrokes
(car (memq last-command-char
- (listify-key-sequence
- vi-dot-repeat-on-final-keystroke))))))
+ vi-dot-repeat-on-final-keystroke)))))
(if (memq last-command '(exit-minibuffer
minibuffer-complete-and-exit
self-insert-and-exit))
@@ -384,10 +410,11 @@
;; (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))
- (setq unread-command-events (list last-input-event))))))
+ (let ((vi-dot-repeat-on-final-keystroke)
+ (event (make-event)))
+ (while (eq (event-to-character (next-command-event event)) vi-dot-repeat-char)
+ (vi-dot vi-dot-arg))
+ (setq unread-command-events (list event))))))
(defun vi-dot-message (format &rest args)
"Like `message' but displays with vi-dot-message-function if non-nil."
Enjoy.
--
`It's all about bossing computers around. Users have to say "please".
Programmers get to say "do what I want NOW or the hard disk gets it".'
-- Richard Heathfield on the nature of programming