typo
[bpt/emacs.git] / lisp / emulation / viper.el
CommitLineData
4960e757 1;;; viper.el --- A full-featured Vi emulator for GNU Emacs and XEmacs,
6c2e12f4
KH
2;; a VI Plan for Emacs Rescue,
3;; and a venomous VI PERil.
4;; Viper Is also a Package for Emacs Rebels.
6c2e12f4 5
5fd6d89f 6;; Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
f0fa15c5 7;; 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
151496c0 8
50a07e18 9;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
02f34c70
MK
10;; Keywords: emulations
11
7eb605c7 12(defconst viper-version "3.13.1 of October 23, 2006"
03fc1246
MK
13 "The current version of Viper")
14
6c2e12f4
KH
15;; This file is part of GNU Emacs.
16
17;; GNU Emacs is free software; you can redistribute it and/or modify
18;; it under the terms of the GNU General Public License as published by
19;; the Free Software Foundation; either version 2, or (at your option)
20;; any later version.
21
22;; GNU Emacs is distributed in the hope that it will be useful,
23;; but WITHOUT ANY WARRANTY; without even the implied warranty of
24;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25;; GNU General Public License for more details.
26
27;; You should have received a copy of the GNU General Public License
1fb87c77 28;; along with GNU Emacs; see the file COPYING. If not, write to the
3a35cf56
LK
29;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
30;; Boston, MA 02110-1301, USA.
6c2e12f4
KH
31
32;;; Commentary:
33
3af0304a 34;; Viper is a full-featured Vi emulator for Emacs and XEmacs. It emulates and
6c2e12f4
KH
35;; improves upon the standard features of Vi and, at the same time, allows
36;; full access to all Emacs facilities. Viper supports multiple undo,
37;; file name completion, command, file, and search history and it extends
3af0304a 38;; Vi in many other ways. Viper is highly customizable through the various
6c2e12f4
KH
39;; hooks, user variables, and keymaps. It is implemented as a collection
40;; of minor modes and it is designed to provide full access to all Emacs
41;; major and minor modes.
42;;
3afbc435 43;;; History:
6c2e12f4
KH
44;;
45;; Viper is a new name for a package formerly known as VIP-19,
46;; which was a successor of VIP version 3.5 by Masahiko Sato
47;; <ms@sail.stanford.edu> and VIP version 4.2 by Aamod Sane
3af0304a 48;; <sane@cs.uiuc.edu>. Some ideas from vip 4.4.2 by Aamod Sane
6c2e12f4
KH
49;; were also shamelessly plagiarized.
50;;
51;; Viper maintains some degree of compatibility with these older
3af0304a 52;; packages. See the documentation for customization.
6c2e12f4
KH
53;;
54;; The main difference between Viper and these older packages are:
55;;
56;; 1. Viper emulates Vi at several levels, from almost complete conformity
57;; to a rather loose Vi-compliance.
58;;
59;; 2. Viper provides full access to all major and minor modes of Emacs
60;; without the need to type extra keys.
61;; The older versions of VIP (and other Vi emulators) do not work with
62;; some major and minor modes.
63;;
64;; 3. Viper supports vi-style undo.
65;;
66;; 4. Viper fully emulates (and improves upon) vi's replacement mode.
67;;
68;; 5. Viper has a better interface to ex, including command, variable, and
69;; file name completion.
70;;
71;; 6. Viper uses native Emacs history and completion features; it doesn't
72;; rely on other packages (such as gmhist.el and completer.el) to provide
73;; these features.
74;;
75;; 7. Viper supports Vi-style editing in the minibuffer, by allowing the
76;; user to switch from Insert state to Vi state to Replace state, etc.
77;;
78;; 8. Viper keeps history of recently inserted pieces of text and recently
79;; executed Vi-style destructive commands, such as `i', `d', etc.
80;; These pieces of text can be inserted in later insertion commands;
81;; the previous destructive commands can be re-executed.
82;;
83;; 9. Viper has Vi-style keyboard macros, which enhances the similar
84;; facility in the original Vi.
85;; First, one can execute any Emacs command while defining a
3af0304a 86;; macro, not just the Vi commands. Second, macros are defined in a
6c2e12f4 87;; WYSYWYG mode, using an interface to Emacs' WYSIWYG style of defining
3af0304a 88;; macros. Third, in Viper, one can define macros that are specific to
6c2e12f4
KH
89;; a given buffer, a given major mode, or macros defined for all buffers.
90;; The same macro name can have several different definitions:
91;; one global, several definitions for various major modes, and
92;; definitions for specific buffers.
d63a37ea 93;; Buffer-specific definitions override mode-specific
6c2e12f4
KH
94;; definitions, which, in turn, override global definitions.
95;;
96;;
97;;; Installation:
98;; -------------
99;;
100;; (require 'viper)
101;;
102
103;;; Acknowledgements:
104;; -----------------
d63a37ea
KH
105;; Bug reports and ideas contributed by many users have helped
106;; improve Viper and the various versions of VIP.
a1506d29 107;; See the on-line manual for a complete list of contributors.
6c2e12f4
KH
108;;
109;;
110;;; Notes:
111;;
112;; 1. Major modes.
113;; In most cases, Viper handles major modes correctly, i.e., they come up
3af0304a 114;; in the right state (either vi-state or emacs-state). For instance, text
6c2e12f4 115;; files come up in vi-state, while, say, Dired appears in emacs-state by
a1506d29 116;; default.
6c2e12f4
KH
117;; However, some modes do not appear in the right mode in the beginning,
118;; usually because they neglect to follow Emacs conventions (e.g., they don't
3af0304a 119;; use kill-all-local-variables when they start). Some major modes
6c2e12f4 120;; may fail to come up in emacs-state if they call hooks, such as
a1506d29
JB
121;; text-hook, for no good reason.
122;;
6c2e12f4
KH
123;; As an immediate solution, you can hit C-z to bring about the right mode.
124;; An interim solution is to add an appropriate hook to the mode like this:
a1506d29 125;;
6c2e12f4 126;; (add-hook 'your-favorite-mode 'viper-mode)
a1506d29 127;; or
8626cfa2 128;; (add-hook 'your-favorite-mode 'viper-change-state-to-emacs)
a1506d29 129;;
3af0304a 130;; whichever applies. The right thing to do, however, is to complain to the
6c2e12f4
KH
131;; author of the respective package. (Sometimes they also neglect to equip
132;; their modes with hooks, which is one more reason for complaining.)
a1506d29 133;;
6c2e12f4 134;; 2. Keymap handling
8626cfa2
MK
135;; Each Viper state (insert, vi, replace) is implemented as a collection of
136;; several minor modes, each with its own keymap.
6c2e12f4
KH
137;;
138;; Viper's Vi state consists of seven minor modes:
139;;
8626cfa2
MK
140;; viper-vi-intercept-minor-mode
141;; viper-vi-local-user-minor-mode
142;; viper-vi-global-user-minor-mode
143;; viper-vi-kbd-minor-mode
144;; viper-vi-state-modifier-minor-mode
145;; viper-vi-diehard-minor-mode
146;; viper-vi-basic-minor-mode
6c2e12f4
KH
147;;
148;; Bindings done to the keymap of the first mode overshadow those done to
149;; the second, which, in turn, overshadows those done to the third, etc.
150;;
8626cfa2 151;; The last viper-vi-basic-minor-mode contains most of the usual Vi bindings
3af0304a 152;; in its edit mode. This mode provides access to all Emacs facilities.
1e70790f 153;; Novice users, however, may want to set their viper-expert-level to 1
3af0304a 154;; in their .viper file. This will enable viper-vi-diehard-minor-mode. This
6c2e12f4
KH
155;; minor mode's bindings make Viper simulate the usual Vi very closely.
156;; For instance, C-c will not have its standard Emacs binding
157;; and so many of the goodies of Emacs are not available.
158;;
3af0304a 159;; A skilled user should set viper-expert-level to at least 3. This will
d63a37ea 160;; enable `C-c' and many Emacs facilities will become available.
8626cfa2 161;; In this case, viper-vi-diehard-minor-mode is inactive.
6c2e12f4
KH
162;;
163;; Viper gurus should have at least
1e70790f 164;; (setq viper-expert-level 4)
3af0304a 165;; in their ~/.viper files. This will unsuppress all Emacs keys that are not
6c2e12f4
KH
166;; essential for VI-style editing.
167;; Pick-and-choose users may want to put
1e70790f 168;; (setq viper-expert-level 5)
3af0304a 169;; in ~/.viper. Viper will then leave it up to the user to set the variables
8626cfa2 170;; viper-want-* See viper-set-expert-level for details.
6c2e12f4 171;;
8626cfa2 172;; The very first minor mode, viper-vi-intercept-minor-mode, is of no
3af0304a 173;; concern for the user. It is needed to bind Viper's vital keys, such as
6c2e12f4
KH
174;; ESC and C-z.
175;;
8626cfa2 176;; The second mode, viper-vi-local-user-minor-mode, usually has an
3af0304a 177;; empty keymap. However, the user can set bindings in this keymap, which
6c2e12f4 178;; will overshadow the corresponding bindings in the other two minor
3af0304a 179;; modes. This is useful, for example, for setting up ZZ in gnus,
6c2e12f4
KH
180;; rmail, mh-e, etc., to send message instead of saving it in a file.
181;; Likewise, in Dired mode, you may want to bind ZN and ZP to commands
182;; that would visit the next or the previous file in the Dired buffer.
3af0304a 183;; Setting local keys is tricky, so don't do it directly. Instead, use
8626cfa2 184;; viper-add-local-keys function (see its doc).
6c2e12f4 185;;
8626cfa2
MK
186;; The third minor mode, viper-vi-global-user-minor-mode, is also intended
187;; for the users but, unlike viper-vi-local-user-minor-mode, its key
3af0304a 188;; bindings are seen in all Viper buffers. This mode keys can be done
6c2e12f4
KH
189;; with define-key command.
190;;
8626cfa2 191;; The fourth minor mode, viper-vi-kbd-minor-mode, is used by keyboard
3af0304a 192;; macros. Users are NOT supposed to modify this keymap directly.
6c2e12f4 193;;
8626cfa2 194;; The fifth mode, viper-vi-state-modifier-minor-mode, can be used to set
6c2e12f4
KH
195;; key bindings that are visible in some major modes but not in others.
196;;
197;; Users are allowed to modify keymaps that belong to
8626cfa2
MK
198;; viper-vi-local-user-minor-mode, viper-vi-global-user-minor-mode,
199;; and viper-vi-state-modifier-minor-mode only.
6c2e12f4
KH
200;;
201;; Viper's Insert state also has seven minor modes:
202;;
8626cfa2
MK
203;; viper-insert-intercept-minor-mode
204;; viper-insert-local-user-minor-mode
205;; viper-insert-global-user-minor-mode
206;; viper-insert-kbd-minor-mode
207;; viper-insert-state-modifier-minor-mode
208;; viper-insert-diehard-minor-mode
209;; viper-insert-basic-minor-mode
6c2e12f4 210;;
8626cfa2
MK
211;; As with VI's editing modes, the first mode,
212;; viper-insert-intercept-minor-mode is used to bind vital keys that are not
213;; to be changed by the user.
6c2e12f4 214;;
8626cfa2 215;; The next mode, viper-insert-local-user-minor-mode, is used to customize
3af0304a 216;; bindings in the insert state of Viper. The third mode,
8626cfa2
MK
217;; viper-insert-global-user-minor-mode is like
218;; viper-insert-local-user-minor-mode, except that its bindings are seen in
3af0304a
MK
219;; all Viper buffers. As with viper-vi-local-user-minor-mode, its bindings
220;; should be done via the function viper-add-local-keys. Bindings for
8626cfa2 221;; viper-insert-global-user-minor-mode can be set with the define-key command.
6c2e12f4 222;;
8626cfa2 223;; The next minor mode, viper-insert-kbd-minor-mode,
a1506d29 224;; is used for keyboard VI-style macros defined with :map!.
6c2e12f4 225;;
8626cfa2
MK
226;; The fifth minor mode, viper-insert-state-modifier-minor-mode, is like
227;; viper-vi-state-modifier-minor-mode, except that it is used in the Insert
a1506d29 228;; state; it can be used to modify keys in a mode-specific fashion.
6c2e12f4 229;;
8626cfa2 230;; The minor mode viper-insert-diehard-minor-mode is in effect when
6c2e12f4 231;; the user wants a high degree of Vi compatibility (a bad idea, really!).
8626cfa2 232;; The last minor mode, viper-insert-basic-minor-mode, is always in effect
3af0304a 233;; when Viper is in insert state. It binds a small number of keys needed for
a1506d29 234;; Viper's operation.
6c2e12f4
KH
235;;
236;; Finally, Viper provides minor modes for overriding bindings set by Emacs
237;; modes when Viper is in Emacs state:
238;;
8626cfa2
MK
239;; viper-emacs-local-user-minor-mode
240;; viper-emacs-global-user-minor-mode
241;; viper-emacs-kbd-minor-mode
242;; viper-emacs-state-modifier-minor-mode
6c2e12f4 243;;
3af0304a 244;; These minor modes are in effect when Viper is in Emacs state. The keymap
8626cfa2
MK
245;; associated with viper-emacs-global-user-minor-mode,
246;; viper-emacs-global-user-map, overrides the global and local keymaps as
3af0304a 247;; well as the minor mode keymaps set by other modes. The keymap of
8626cfa2 248;; viper-emacs-local-user-minor-mode, viper-emacs-local-user-map, overrides
6c2e12f4 249;; everything, but it is used on a per buffer basis.
8626cfa2 250;; The keymap associated with viper-emacs-state-modifier-minor-mode
3af0304a 251;; overrides keys on a per-major-mode basis. The mode
8626cfa2 252;; viper-emacs-kbd-minor-mode is used to define Vi-style macros in Emacs
6c2e12f4
KH
253;; state.
254;;
255;; 3. There is also one minor mode that is used when Viper is in its
3af0304a 256;; replace-state (used for commands like cw, C, etc.). This mode is
6c2e12f4
KH
257;; called
258;;
8626cfa2 259;; viper-replace-minor-mode
6c2e12f4 260;;
3af0304a 261;; and its keymap is viper-replace-map. Replace minor mode is always
6c2e12f4
KH
262;; used in conjunction with the minor modes for insert-state, and its
263;; keymap overshadows the keymaps for insert minor modes.
264;;
a1506d29 265;; 4. Defining buffer-local bindings in Vi and Insert modes.
6c2e12f4
KH
266;; As mentioned before, sometimes, it is convenient to have
267;; buffer-specific of mode-specific key bindings in Vi and insert modes.
8626cfa2 268;; Viper provides a special function, viper-add-local-keys, to do precisely
3af0304a 269;; this. For instance, is you need to add couple of mode-specific bindings
a1506d29 270;; to Insert mode, you can put
6c2e12f4 271;;
a1506d29 272;; (viper-add-local-keys 'insert-state '((key1 . func1) (key2 .func2)))
6c2e12f4 273;;
3af0304a 274;; somewhere in a hook of this major mode. If you put something like this
6c2e12f4 275;; in your own elisp function, this will define bindings specific to the
8626cfa2 276;; buffer that was current at the time of the call to viper-add-local-keys.
6c2e12f4
KH
277;; The only thing to make sure here is that the major mode of this buffer
278;; is written according to Emacs conventions, which includes a call to
3af0304a 279;; (kill-all-local-variables). See viper-add-local-keys for more details.
6c2e12f4
KH
280;;
281;;
282;; TO DO (volunteers?):
283;;
284;; 1. Some of the code that is inherited from VIP-3.5 is rather
3af0304a
MK
285;; convoluted. Instead of viper-command-argument, keymaps should bind the
286;; actual commands. E.g., "dw" should be bound to a generic command
8626cfa2 287;; viper-delete that will delete things based on the value of
3af0304a 288;; last-command-char. This would greatly simplify the logic and the code.
6c2e12f4
KH
289;;
290;; 2. Somebody should venture to write a customization package a la
291;; options.el that would allow the user to change values of variables
292;; that meet certain specs (e.g., match a regexp) and whose doc string
3af0304a
MK
293;; starts with a '*'. Then, the user should be offered to save
294;; variables that were changed. This will make user's customization job
6c2e12f4
KH
295;; much easier.
296;;
297
60370d40 298;;; Code:
6c2e12f4
KH
299
300(require 'advice)
6c2e12f4
KH
301(require 'ring)
302
726e270f
MK
303;; compiler pacifier
304(defvar mark-even-if-inactive)
34317da2 305(defvar quail-mode)
1e70790f 306(defvar viper-expert-level)
2eb4bdca
MK
307(defvar viper-mode-string)
308(defvar viper-major-mode-modifier-list)
6c2e12f4 309
726e270f
MK
310;; loading happens only in non-interactive compilation
311;; in order to spare non-viperized emacs from being viperized
312(if noninteractive
313 (eval-when-compile
314 (let ((load-path (cons (expand-file-name ".") load-path)))
b484aa09
MK
315 (or (featurep 'viper-init)
316 (load "viper-init.el" nil nil 'nosuffix))
726e270f
MK
317 (or (featurep 'viper-cmd)
318 (load "viper-cmd.el" nil nil 'nosuffix))
319 )))
320;; end pacifier
6c2e12f4 321
aca9b721 322(require 'viper-init)
8ea74b0e 323(require 'viper-keym)
aca9b721 324
1e70790f 325;; better be defined before Viper custom group.
8626cfa2 326(defvar viper-custom-file-name (convert-standard-filename "~/.viper")
33c053f4 327 "Viper customization file.
1e70790f
MK
328If set by the user, this must be done _before_ Viper is loaded in `~/.emacs'.")
329
330(defgroup viper nil
331 "Vi emulation within Emacs.
8626cfa2 332NOTE: Viper customization should be saved in `viper-custom-file-name', which
1e70790f 333defaults to `~/.viper'."
8626cfa2 334 :prefix "viper-"
1e70790f
MK
335 :group 'emulations)
336
726e270f 337(require 'viper-cmd)
6c2e12f4 338
8e41a31c
MK
339(defgroup viper-misc nil
340 "Miscellaneous Viper customization."
341 :prefix "viper-"
342 :group 'viper)
343
344
8626cfa2 345(defcustom viper-always t
e36a387d
MK
346 "Non-nil means, arrange for vi-state to be a default when appropriate.
347This is different from `viper-mode' variable in that `viper-mode' determines
348whether to use Viper in the first place, while `viper-always', if nil, lets
1e70790f
MK
349user decide when to invoke Viper in a major mode."
350 :type 'boolean
351 :tag "Always Invoke Viper"
8e41a31c 352 :group 'viper-misc)
1e70790f
MK
353
354;; Non-viper variables that need to be saved in case the user decides to
355;; de-viperize emacs.
356(defvar viper-saved-non-viper-variables nil)
a1506d29 357
1e70790f
MK
358(defcustom viper-mode (cond (noninteractive nil)
359 (t 'ask))
360 "To Viperize or not to Viperize.
cbd9191d 361If t, viperize Emacs. If nil -- don't. If `ask', ask the user.
33c053f4 362This variable is used primarily when Viper is being loaded.
6c2e12f4 363
e36a387d 364Must be set in `~/.emacs' before Viper is loaded.
8e41a31c
MK
365DO NOT set this variable interactively, unless you are using the customization
366widget."
1e70790f
MK
367 :type '(choice (const nil) (const t) (const ask))
368 :tag "Set Viper Mode on Loading"
8e41a31c 369 :group 'viper-misc)
726e270f 370
2eb4bdca
MK
371(defcustom viper-vi-state-mode-list
372 '(fundamental-mode
373 makefile-mode
a1506d29 374
2eb4bdca
MK
375 awk-mode
376 m4-mode
3af0304a
MK
377 xrdb-mode
378 winmgr-mode
379 autoconf-mode
380 cvs-edit-mode
a1506d29 381
2eb4bdca
MK
382 html-mode html-helper-mode
383 emacs-lisp-mode lisp-mode lisp-interaction-mode
a1506d29
JB
384
385 jde-mode java-mode
3af0304a 386 cc-mode c-mode c++-mode objc-mode
2eb4bdca
MK
387 fortran-mode f90-mode
388 basic-mode
389 bat-mode
390 asm-mode
391 prolog-mode
3af0304a 392 flora-mode
55d7ff38 393 sql-mode
2eb4bdca
MK
394
395 text-mode indented-text-mode
396 tex-mode latex-mode bibtex-mode
55d7ff38 397 ps-mode
a1506d29 398
38685583 399 ;; completion-list-mode
560ef11a 400 diff-mode
4960e757 401 idl-mode
a1506d29 402
4986c2c6
MK
403 perl-mode
404 cperl-mode
2eb4bdca
MK
405 javascript-mode
406 tcl-mode
407 python-mode
a1506d29 408
2eb4bdca 409 sh-mode ksh-mode csh-mode
a1506d29 410
2eb4bdca
MK
411 gnus-article-mode
412 mh-show-mode
413 )
414 "Major modes that require Vi command state."
085d6698 415 :type '(repeat symbol)
8e41a31c 416 :group 'viper-misc)
c81246f3 417
2eb4bdca
MK
418(defcustom viper-emacs-state-mode-list
419 '(custom-mode
420
421 dired-mode
422 efs-mode
423 tar-mode
424
f3eabcdf
MK
425 browse-kill-ring-mode
426 recentf-mode
44766d63 427 recentf-dialog-mode
f3eabcdf
MK
428 occur-mode
429
2eb4bdca
MK
430 mh-folder-mode
431 gnus-group-mode
432 gnus-summary-mode
a1506d29 433
38685583
MK
434 completion-list-mode
435 help-mode
436
2eb4bdca
MK
437 Info-mode
438 Buffer-menu-mode
3af0304a 439 compilation-mode
a1506d29 440
54b171c7
MK
441 rcirc-mode
442
0680ea10
MK
443 jde-javadoc-checker-report-mode
444
2eb4bdca
MK
445 view-mode
446 vm-mode
447 vm-summary-mode)
448 "*A list of major modes that should come up in Emacs state.
449Normally, Viper would bring buffers up in Emacs state, unless the corresponding
450major mode has been placed on `viper-vi-state-mode-list' or
3af0304a
MK
451`viper-insert-state-mode-list'. So, don't place a new mode on this list,
452unless it is coming up in a wrong Viper state."
2eb4bdca
MK
453 :type '(repeat symbol)
454 :group 'viper-misc)
455
456(defcustom viper-insert-state-mode-list
657f9cb8
MK
457 '(internal-ange-ftp-mode
458 comint-mode
ac64a728 459 gud-mode
4960e757 460 inferior-emacs-lisp-mode
98c414c7 461 erc-mode
657f9cb8
MK
462 eshell-mode
463 shell-mode)
2eb4bdca
MK
464 "*A list of major modes that should come up in Vi Insert state."
465 :type '(repeat symbol)
466 :group 'viper-misc)
467
468
469;; used to set viper-major-mode-modifier-list in defcustom
470(defun viper-apply-major-mode-modifiers (&optional symbol value)
471 (if symbol
472 (set symbol value))
3af0304a
MK
473 (mapcar (lambda (triple)
474 (viper-modify-major-mode
475 (nth 0 triple) (nth 1 triple) (eval (nth 2 triple))))
2eb4bdca
MK
476 viper-major-mode-modifier-list))
477
3f9526a3 478;; We change standard bindings in some major modes, making them slightly
4960e757 479;; different than in "normal" vi/insert/emacs states
2eb4bdca
MK
480(defcustom viper-major-mode-modifier-list
481 '((help-mode emacs-state viper-slash-and-colon-map)
482 (comint-mode insert-state viper-comint-mode-modifier-map)
483 (comint-mode vi-state viper-comint-mode-modifier-map)
ac64a728 484 (gud-mode insert-state viper-comint-mode-modifier-map)
2eb4bdca 485 (shell-mode insert-state viper-comint-mode-modifier-map)
4960e757 486 (inferior-emacs-lisp-mode insert-state viper-comint-mode-modifier-map)
2eb4bdca
MK
487 (shell-mode vi-state viper-comint-mode-modifier-map)
488 (ange-ftp-shell-mode insert-state viper-comint-mode-modifier-map)
489 (ange-ftp-shell-mode vi-state viper-comint-mode-modifier-map)
490 (internal-ange-ftp-mode insert-state viper-comint-mode-modifier-map)
491 (internal-ange-ftp-mode vi-state viper-comint-mode-modifier-map)
492 (dired-mode emacs-state viper-dired-modifier-map)
493 (tar-mode emacs-state viper-slash-and-colon-map)
494 (mh-folder-mode emacs-state viper-slash-and-colon-map)
3f9526a3
MK
495 (gnus-group-mode emacs-state viper-gnus-modifier-map)
496 (gnus-summary-mode emacs-state viper-gnus-modifier-map)
2eb4bdca
MK
497 (Info-mode emacs-state viper-slash-and-colon-map)
498 (Buffer-menu-mode emacs-state viper-slash-and-colon-map)
98c414c7
MB
499 (erc-mode insert-state viper-comint-mode-modifier-map)
500 (erc-mode vi-state viper-comint-mode-modifier-map)
2eb4bdca
MK
501 )
502 "List specifying how to modify the various major modes to enable some Viperisms.
503The list has the structure: ((mode viper-state keymap) (mode viper-state
3af0304a
MK
504keymap) ...). If `mode' is on the list, the `kemap' will be made active (on
505the minor-mode-map-alist) in the specified viper state.
cbd9191d
JB
506If you change this list, have to restart Emacs for the change to take effect.
507However, if you did the change through the customization widget, then Emacs
2eb4bdca 508needs to be restarted only if you deleted a triple mode-state-keymap from the
cbd9191d 509list. No need to restart Emacs in case of insertion or modification of an
2eb4bdca
MK
510existing triple."
511 :type '(repeat
512 (list symbol
513 (choice (const emacs-state)
514 (const vi-state)
515 (const insert-state))
516 symbol))
517 :set 'viper-apply-major-mode-modifiers
518 :group 'viper-misc)
519
520
c81246f3 521
e36a387d 522\f
726e270f 523
e36a387d 524;;;###autoload
8626cfa2 525(defun toggle-viper-mode ()
328b4b70 526 "Toggle Viper on/off.
3af0304a 527If Viper is enabled, turn it off. Otherwise, turn it on."
8626cfa2
MK
528 (interactive)
529 (if (eq viper-mode t)
530 (viper-go-away)
531 (setq viper-mode nil)
532 (viper-mode)))
6c2e12f4 533
e36a387d
MK
534;;;###autoload
535(defun viper-mode ()
61c4714e 536 "Turn on Viper emulation of Vi in Emacs. See Info node `(viper)Top'."
e36a387d
MK
537 (interactive)
538 (if (not noninteractive)
539 (progn
540 ;; if the user requested viper-mode explicitly
541 (if viper-mode
542 ()
8626cfa2 543 (setq viper-mode t)
e36a387d
MK
544 (load-library "viper"))
545
a1506d29 546 (if viper-first-time ; Important check. Prevents mix-up of startup
3af0304a 547 (progn ; and expert-level msgs when viper-mode recurses
8626cfa2
MK
548 (setq viper-first-time nil)
549 (if (not viper-inhibit-startup-message)
e36a387d 550 (save-window-excursion
8626cfa2 551 (setq viper-inhibit-startup-message t)
e36a387d
MK
552 (delete-other-windows)
553 (switch-to-buffer "Viper Startup Message")
554 (erase-buffer)
555 (insert
556 (substitute-command-keys
1e70790f
MK
557 "Viper Is a Package for Emacs Rebels,
558a VI Plan for Emacs Rescue, and a venomous VI PERil.
e36a387d 559
1e70790f
MK
560Incidentally, Viper emulates Vi under GNU Emacs 20 and XEmacs 20.
561It supports all of what is good in Vi and Ex, while extending
e36a387d
MK
562and improving upon much of it.
563
3af0304a 564 1. Viper supports Vi at several levels. Level 1 is the closest to Vi,
e36a387d 565 level 5 provides the most flexibility to depart from many Vi conventions.
a1506d29 566
e36a387d 567 You will be asked to specify your user level in a following screen.
a1506d29 568
e36a387d 569 If you select user level 1 then the keys ^X, ^C, ^Z, and ^G will behave
3af0304a 570 as in VI, to smooth transition to Viper for the beginners. However, to
a1506d29
JB
571 use Emacs productively, you are advised to reach user level 3 or higher.
572
1e70790f
MK
573 At user level 2 or higher, ^X and ^C have Emacs, not Vi, bindings;
574 ^Z toggles Vi/Emacs states; ^G is Emacs' keyboard-quit (like ^C in Vi).
a1506d29 575
e36a387d 576 2. Vi exit functions (e.g., :wq, ZZ) work on INDIVIDUAL files -- they
1e70790f 577 do not cause Emacs to quit, except at user level 1 (for a novice).
e36a387d 578 3. ^X^C EXITS EMACS.
3af0304a
MK
579 4. Viper supports multiple undo: `u' will undo. Typing `.' will repeat
580 undo. Another `u' changes direction.
a1506d29 581
1e70790f
MK
582 6. Emacs Meta key is `C-\\' (in all modes) or `\\ ESC' (in Vi command mode).
583 On a window system, the best way is to use the Meta-key on your keyboard.
e36a387d 584 7. Try \\[keyboard-quit] and \\[abort-recursive-edit] repeatedly,if
a1506d29
JB
585 something funny happens. This would abort the current editing command.
586
1e70790f 587For more information on Viper:
726e270f 588
1e70790f
MK
589 a. Type `:help' in Vi command mode
590 b. Print Viper manual, found in ./etc/viper.dvi
591 c. Print the Quick Reference, found in ./etc/viperCard.dvi
592
593To submit a bug report or to contact the author, type :submitReport in Vi
3af0304a 594command mode. To shoo Viper away and return to pure Emacs (horror!), type:
1e70790f
MK
595
596 M-x viper-go-away
a1506d29 597
e36a387d
MK
598This startup message appears whenever you load Viper, unless you type `y' now."
599 ))
600 (goto-char (point-min))
601 (if (y-or-n-p "Inhibit Viper startup message? ")
8626cfa2
MK
602 (viper-save-setting
603 'viper-inhibit-startup-message
e36a387d 604 "Viper startup message inhibited"
8626cfa2 605 viper-custom-file-name t))
e36a387d
MK
606 ;;(kill-buffer (current-buffer))
607 (message
608 "The last message is in buffer `Viper Startup Message'")
609 (sit-for 4)
610 ))
1e70790f 611 (viper-set-expert-level 'dont-change-unless)))
c81246f3 612
4960e757
MK
613 (if (eq major-mode 'viper-mode)
614 (setq major-mode 'fundamental-mode))
7d027816 615
2eb4bdca
MK
616 (or (memq major-mode viper-emacs-state-mode-list) ; don't switch to Vi
617 (memq major-mode viper-insert-state-mode-list) ; don't switch
83f49acb
MK
618 (viper-change-state-to-vi))
619 )))
a1506d29 620
4960e757
MK
621
622;; Apply a little heuristic to invoke vi state on major-modes
623;; that are not listed in viper-vi-state-mode-list
624(defun this-major-mode-requires-vi-state (mode)
625 (cond ((memq mode viper-vi-state-mode-list) t)
626 ((memq mode viper-emacs-state-mode-list) nil)
627 ((memq mode viper-insert-state-mode-list) nil)
628 (t (and (eq (key-binding "a") 'self-insert-command)
629 (eq (key-binding " ") 'self-insert-command)))))
630
6c2e12f4 631\f
4af0c23b 632;; This hook designed to enable Vi-style editing in comint-based modes."
8626cfa2 633(defun viper-comint-mode-hook ()
e2de3a29
MK
634 (set (make-local-variable 'require-final-newline) nil)
635 (setq viper-ex-style-editing nil
8626cfa2
MK
636 viper-ex-style-motion nil)
637 (viper-change-state-to-insert))
34da0a2b 638
6c2e12f4 639
1e70790f
MK
640;; remove viper hooks from SYMBOL
641(defun viper-remove-hooks (symbol)
642 (cond ((not (boundp symbol)) nil)
643 ((not (listp (eval symbol))) nil)
644 ((string-match "-hook" (symbol-name symbol))
645 (remove-hook symbol 'viper-mode)
8626cfa2
MK
646 (remove-hook symbol 'viper-change-state-to-emacs)
647 (remove-hook symbol 'viper-change-state-to-insert)
648 (remove-hook symbol 'viper-change-state-to-vi)
1e70790f
MK
649 )))
650
651;; Remove local value in all existing buffers
652;; This doesn't delocalize vars (which would have been desirable)
653(defun viper-delocalize-var (symbol)
3af0304a
MK
654 (mapcar (lambda (buf) (save-excursion
655 (set-buffer buf)
656 (kill-local-variable symbol)))
1e70790f
MK
657 (buffer-list)))
658
659
660(defun viper-go-away ()
661 "De-Viperize Emacs.
3af0304a
MK
662This function tries to do as good a job as possible. However, it may undo some
663user customization, unrelated to Viper. For instance, if the user advised
1e70790f
MK
664`read-file-name', `describe-key', and some others, then this advice will be
665undone.
38685583 666It also can't undo some Viper settings."
1e70790f
MK
667 (interactive)
668
669 ;; restore non-viper vars
670 (setq-default
1e70790f 671 next-line-add-newlines
a1506d29
JB
672 (viper-standard-value
673 'next-line-add-newlines viper-saved-non-viper-variables)
1e70790f 674 require-final-newline
a1506d29
JB
675 (viper-standard-value
676 'require-final-newline viper-saved-non-viper-variables)
1e70790f 677 scroll-step
a1506d29 678 (viper-standard-value 'scroll-step viper-saved-non-viper-variables)
1e70790f
MK
679 mode-line-buffer-identification
680 (viper-standard-value
5489c3d3
MK
681 'mode-line-buffer-identification viper-saved-non-viper-variables)
682 global-mode-string
c004db97 683 (delq 'viper-mode-string global-mode-string))
5489c3d3 684
8626cfa2 685 (if viper-emacs-p
5489c3d3
MK
686 (setq-default
687 mark-even-if-inactive
688 (viper-standard-value
689 'mark-even-if-inactive viper-saved-non-viper-variables)))
1e70790f 690
a1506d29 691 ;; Ideally, we would like to be able to de-localize local variables
38685583
MK
692 (unless
693 (and (fboundp 'add-to-ordered-list) (boundp 'emulation-mode-map-alists))
694 (viper-delocalize-var 'minor-mode-map-alist))
1e70790f 695 (viper-delocalize-var 'require-final-newline)
7d027816 696 (if viper-xemacs-p (viper-delocalize-var 'bar-cursor))
1e70790f 697
a1506d29 698
1e70790f 699 ;; deactivate all advices done by Viper.
8626cfa2 700 (ad-deactivate-regexp "viper-")
1e70790f
MK
701
702 (setq viper-mode nil)
703
8ea74b0e
MK
704 (when (and (fboundp 'add-to-ordered-list) (boundp 'emulation-mode-map-alists))
705 (setq emulation-mode-map-alists
706 (delq 'viper--intercept-key-maps
707 (delq 'viper--key-maps emulation-mode-map-alists))
708 ))
709
8626cfa2
MK
710 (viper-delocalize-var 'viper-vi-minibuffer-minor-mode)
711 (viper-delocalize-var 'viper-insert-minibuffer-minor-mode)
712 (viper-delocalize-var 'viper-vi-intercept-minor-mode)
713 (viper-delocalize-var 'viper-insert-intercept-minor-mode)
a1506d29 714
8626cfa2
MK
715 (viper-delocalize-var 'viper-vi-local-user-minor-mode)
716 (viper-delocalize-var 'viper-vi-kbd-minor-mode)
717 (viper-delocalize-var 'viper-vi-global-user-minor-mode)
718 (viper-delocalize-var 'viper-vi-state-modifier-minor-mode)
719 (viper-delocalize-var 'viper-vi-diehard-minor-mode)
720 (viper-delocalize-var 'viper-vi-basic-minor-mode)
a1506d29 721
8626cfa2 722 (viper-delocalize-var 'viper-replace-minor-mode)
a1506d29 723
8626cfa2
MK
724 (viper-delocalize-var 'viper-insert-local-user-minor-mode)
725 (viper-delocalize-var 'viper-insert-kbd-minor-mode)
726 (viper-delocalize-var 'viper-insert-global-user-minor-mode)
727 (viper-delocalize-var 'viper-insert-state-modifier-minor-mode)
728 (viper-delocalize-var 'viper-insert-diehard-minor-mode)
729 (viper-delocalize-var 'viper-insert-basic-minor-mode)
a1506d29 730
8626cfa2
MK
731 (viper-delocalize-var 'viper-emacs-intercept-minor-mode)
732 (viper-delocalize-var 'viper-emacs-local-user-minor-mode)
733 (viper-delocalize-var 'viper-emacs-kbd-minor-mode)
734 (viper-delocalize-var 'viper-emacs-global-user-minor-mode)
735 (viper-delocalize-var 'viper-emacs-state-modifier-minor-mode)
736
c004db97
MK
737 (viper-delocalize-var 'viper-current-state)
738 (viper-delocalize-var 'viper-mode-string)
739
8626cfa2
MK
740 (setq-default viper-vi-minibuffer-minor-mode nil
741 viper-insert-minibuffer-minor-mode nil
742 viper-vi-intercept-minor-mode nil
743 viper-insert-intercept-minor-mode nil
a1506d29 744
8626cfa2
MK
745 viper-vi-local-user-minor-mode nil
746 viper-vi-kbd-minor-mode nil
747 viper-vi-global-user-minor-mode nil
748 viper-vi-state-modifier-minor-mode nil
749 viper-vi-diehard-minor-mode nil
750 viper-vi-basic-minor-mode nil
a1506d29 751
8626cfa2 752 viper-replace-minor-mode nil
a1506d29 753
8626cfa2
MK
754 viper-insert-local-user-minor-mode nil
755 viper-insert-kbd-minor-mode nil
756 viper-insert-global-user-minor-mode nil
757 viper-insert-state-modifier-minor-mode nil
758 viper-insert-diehard-minor-mode nil
759 viper-insert-basic-minor-mode nil
760
761 viper-emacs-intercept-minor-mode nil
762 viper-emacs-local-user-minor-mode nil
763 viper-emacs-kbd-minor-mode nil
764 viper-emacs-global-user-minor-mode nil
765 viper-emacs-state-modifier-minor-mode nil
c004db97
MK
766
767 viper-current-state 'emacs-state
768 viper-mode-string viper-emacs-state-id
1e70790f
MK
769 )
770
771 ;; remove all hooks set by viper
772 (mapatoms 'viper-remove-hooks)
8626cfa2 773 (remove-hook 'comint-mode-hook 'viper-comint-mode-hook)
98c414c7 774 (remove-hook 'erc-mode-hook 'viper-comint-mode-hook)
8626cfa2 775 (remove-hook 'minibuffer-setup-hook 'viper-minibuffer-setup-sentinel)
2eb4bdca 776 (remove-hook 'change-major-mode-hook 'viper-major-mode-change-sentinel)
15c77b9e 777 (remove-hook 'post-command-hook 'viper-minibuffer-post-command-hook)
8626cfa2
MK
778
779 ;; unbind Viper mouse bindings
780 (viper-unbind-mouse-search-key)
781 (viper-unbind-mouse-insert-key)
41497c90
MK
782 ;; In emacs, we have to advice handle-switch-frame
783 ;; This advice is undone earlier, when all advices matchine "viper-" are
784 ;; deactivated.
785 (if viper-xemacs-p
786 (remove-hook 'mouse-leave-frame-hook 'viper-remember-current-frame))
787 ) ; end viper-go-away
1e70790f
MK
788
789
2eb4bdca
MK
790;; list of buffers that just changed their major mode
791;; used in a hack that triggers vi command mode whenever needed
792(defvar viper-new-major-mode-buffer-list nil)
793
794;; set appropriate Viper state in buffers that changed major mode
795(defun set-viper-state-in-major-mode ()
796 (mapcar
3af0304a
MK
797 (lambda (buf)
798 (if (viper-buffer-live-p buf)
799 (with-current-buffer buf
4960e757 800 (cond ((and (this-major-mode-requires-vi-state major-mode)
3af0304a
MK
801 (eq viper-current-state 'emacs-state))
802 (viper-mode))
803 ((memq major-mode viper-emacs-state-mode-list)
804 ;; not checking (eq viper-current-state 'emacs-state)
805 ;; because viper-current-state could have gotten it by
806 ;; default. We need viper-change-state-to-emacs here to have
807 ;; the keymaps take effect.
808 (viper-change-state-to-emacs))
809 ((and (memq major-mode viper-insert-state-mode-list)
810 (not (eq viper-current-state 'insert-state)))
811 (viper-change-state-to-insert))
812 )) ; with-current-buffer
813 )) ; function
2eb4bdca
MK
814 viper-new-major-mode-buffer-list)
815 ;; clear the list of bufs that changed major mode
816 (setq viper-new-major-mode-buffer-list nil)
817 ;; change the global value of hook
818 (remove-hook 'viper-post-command-hooks 'set-viper-state-in-major-mode))
819
820;; sets up post-command-hook to turn viper-mode, if the current mode is
821;; fundamental
822(defun viper-major-mode-change-sentinel ()
823 (save-match-data
824 (or (string-match "\*Minibuf-" (buffer-name))
a1506d29 825 (setq viper-new-major-mode-buffer-list
2eb4bdca
MK
826 (cons (current-buffer) viper-new-major-mode-buffer-list))))
827 ;; change the global value of hook
828 (add-hook 'viper-post-command-hooks 'set-viper-state-in-major-mode t))
829
1e70790f
MK
830
831
04090c34 832;; This sets major mode hooks to make them come up in vi-state.
8626cfa2 833(defun viper-set-hooks ()
6c2e12f4
KH
834 ;; It is of course a misnomer to call viper-mode a `major mode'.
835 ;; However, this has the effect that if the user didn't specify the
836 ;; default mode, new buffers that fall back on the default will come up
837 ;; in Fundamental Mode and Vi state.
4960e757
MK
838 ;; When viper-mode is executed in such a case, it will set the major mode
839 ;; back to fundamental-mode.
2eb4bdca
MK
840 (if (eq default-major-mode 'fundamental-mode)
841 (setq default-major-mode 'viper-mode))
a1506d29 842
2eb4bdca
MK
843 (add-hook 'change-major-mode-hook 'viper-major-mode-change-sentinel)
844 (add-hook 'find-file-hooks 'set-viper-state-in-major-mode)
e36a387d 845
2eb4bdca 846 ;; keep this because many modes we don't know about use this hook
bbe6126c 847 (defvar text-mode-hook)
6c2e12f4 848 (add-hook 'text-mode-hook 'viper-mode)
a1506d29 849
bbe6126c 850 (defvar emerge-startup-hook)
8626cfa2 851 (add-hook 'emerge-startup-hook 'viper-change-state-to-emacs)
34da0a2b 852
b93e5ce2
MK
853 ;; Zap bad bindings in flyspell-mouse-map, which prevent ESC from working
854 ;; over misspelled words (due to the overlay keymaps)
855 (defvar flyspell-mode-hook)
856 (add-hook 'flyspell-mode-hook
857 '(lambda ()
858 (define-key flyspell-mouse-map viper-ESC-key nil)))
241d963d
MK
859 ;; if viper is started from .emacs, it might be impossible to get certain
860 ;; info about the display and windows until emacs initialization is complete
861 ;; So do it via the window-setup-hook
862 (add-hook 'window-setup-hook
83f49acb
MK
863 '(lambda ()
864 (modify-frame-parameters
865 (selected-frame)
866 (list (cons 'viper-vi-state-cursor-color
867 (viper-get-cursor-color))))))
b93e5ce2 868
34da0a2b
MK
869 ;; Tell vc-diff to put *vc* in Vi mode
870 (if (featurep 'vc)
8626cfa2 871 (defadvice vc-diff (after viper-vc-ad activate)
34da0a2b 872 "Force Vi state in VC diff buffer."
8626cfa2
MK
873 (viper-change-state-to-vi))
874 (eval-after-load
34da0a2b 875 "vc"
8626cfa2 876 '(defadvice vc-diff (after viper-vc-ad activate)
34da0a2b 877 "Force Vi state in VC diff buffer."
8626cfa2 878 (viper-change-state-to-vi))))
a1506d29 879
8626cfa2 880 (eval-after-load
4af0c23b 881 "emerge"
8626cfa2
MK
882 '(defadvice emerge-quit (after viper-emerge-advice activate)
883 "Run `viper-change-state-to-vi' after quitting emerge."
884 (viper-change-state-to-vi)))
6c2e12f4 885 ;; In case Emerge was loaded before Viper.
8626cfa2
MK
886 (defadvice emerge-quit (after viper-emerge-advice activate)
887 "Run `viper-change-state-to-vi' after quitting emerge."
888 (viper-change-state-to-vi))
a1506d29 889
6c2e12f4 890 ;; passwd.el sets up its own buffer, which turns up in Vi mode,
3af0304a 891 ;; thus overriding the local map. We don't need Vi mode here.
8626cfa2 892 (eval-after-load
6c2e12f4 893 "passwd"
8626cfa2 894 '(defadvice read-passwd-1 (before viper-passwd-ad activate)
cbd9191d 895 "Switch to Emacs state while reading password."
8626cfa2 896 (viper-change-state-to-emacs)))
a1506d29 897
8ea74b0e
MK
898 (defadvice self-insert-command (around viper-self-insert-ad activate)
899 "Ignore all self-inserting keys in the vi-state."
900 (if (and (eq viper-current-state 'vi-state) (interactive-p))
901 (beep 1)
902 ad-do-it
903 ))
904
38685583
MK
905 (defadvice set-cursor-color (after viper-set-cursor-color-ad activate)
906 "Change cursor color in VI state."
38685583
MK
907 (modify-frame-parameters
908 (selected-frame)
909 (list (cons 'viper-vi-state-cursor-color (ad-get-arg 0))))
910 )
911
8ea74b0e
MK
912 (when (and (fboundp 'add-to-ordered-list) (boundp 'emulation-mode-map-alists))
913 ;; needs to be as early as possible
914 (add-to-ordered-list
915 'emulation-mode-map-alists 'viper--intercept-key-maps 100)
916 ;; needs to be after cua-mode
917 (add-to-ordered-list 'emulation-mode-map-alists 'viper--key-maps 500)
918 )
919
4af0c23b 920 ;; Emacs shell, ange-ftp, and comint-based modes
2eb4bdca 921 (add-hook 'comint-mode-hook 'viper-comint-mode-hook) ; comint
98c414c7 922 (add-hook 'erc-mode-hook 'viper-comint-mode-hook) ; ERC
34da0a2b 923
8ea74b0e
MK
924 (add-hook 'eshell-mode-hook
925 (lambda () (setq viper-auto-indent nil)))
926
2eb4bdca
MK
927 (viper-set-emacs-state-searchstyle-macros nil 'dired-mode) ; dired
928 (viper-set-emacs-state-searchstyle-macros nil 'tar-mode) ; tar
929 (viper-set-emacs-state-searchstyle-macros nil 'mh-folder-mode) ; mhe
930 (viper-set-emacs-state-searchstyle-macros nil 'gnus-group-mode) ; gnus
931 (viper-set-emacs-state-searchstyle-macros nil 'gnus-summary-mode)
932 (viper-set-emacs-state-searchstyle-macros nil 'Info-mode) ; info
933 (viper-set-emacs-state-searchstyle-macros nil 'Buffer-menu-mode) ;buffer-menu
34da0a2b 934
2eb4bdca
MK
935 ;; Modify major modes according to viper-major-mode-modifier-list
936 (viper-apply-major-mode-modifiers)
a1506d29 937
6c2e12f4
KH
938 ;; For RMAIL users.
939 ;; Put buf in Emacs state after edit.
8626cfa2 940 (eval-after-load
6c2e12f4 941 "rmailedit"
8626cfa2 942 '(defadvice rmail-cease-edit (after viper-rmail-advice activate)
cbd9191d 943 "Switch to Emacs state when done editing message."
8626cfa2 944 (viper-change-state-to-emacs)))
6c2e12f4 945 ;; In case RMAIL was loaded before Viper.
8626cfa2 946 (defadvice rmail-cease-edit (after viper-rmail-advice activate)
4af0c23b 947 "Switch to emacs state when done editing message."
8626cfa2 948 (viper-change-state-to-emacs))
34317da2
MK
949
950 ;; ISO accents
951 ;; Need to do it after loading iso-acc, or else this loading will wipe out
952 ;; the advice.
953 (eval-after-load
954 "iso-acc"
90066cb5
RF
955 '(defadvice iso-accents-mode (around viper-iso-accents-advice activate)
956 "Set viper-automatic-iso-accents to iso-accents-mode."
957 (let ((arg (ad-get-arg 0)))
958 ad-do-it
959 (setq viper-automatic-iso-accents
960 (if (eq viper-current-state 'vi-state)
961 (if arg
962 ;; if iso-accents-mode was called with positive arg, turn
963 ;; accents on
964 (> (prefix-numeric-value arg) 0)
965 ;; else: toggle viper-automatic-iso-accents
966 (not viper-automatic-iso-accents))
967 ;; other states: accept what iso-accents-mode has done
968 iso-accents-mode))
969 ;; turn off ISO accents in vi-state
970 (if (eq viper-current-state 'vi-state)
971 (viper-set-iso-accents-mode nil))
972 (if (memq viper-current-state '(vi-state insert-state replace-state))
973 (message "Viper ISO accents mode: %s"
974 (if viper-automatic-iso-accents "on" "off")))
975 )))
34317da2
MK
976
977 ;; International input methods
978 (if viper-emacs-p
979 (eval-after-load "mule-cmds"
90066cb5
RF
980 '(progn
981 (defadvice inactivate-input-method (after viper-mule-advice activate)
982 "Set viper-special-input-method to disable intl. input methods."
983 (viper-inactivate-input-method-action))
984 (defadvice activate-input-method (after viper-mule-advice activate)
985 "Set viper-special-input-method to enable intl. input methods."
986 (viper-activate-input-method-action))
987 ))
34317da2
MK
988 ;; XEmacs Although these hooks exist in Emacs, they don't seem to be always
989 ;; called on input-method activation/deactivation, so we the above advise
990 ;; functions instead.
991 (eval-after-load "mule-cmds"
90066cb5
RF
992 '(progn
993 (add-hook 'input-method-activate-hook
994 'viper-activate-input-method-action t)
995 (add-hook 'input-method-inactivate-hook
996 'viper-inactivate-input-method-action t)))
34317da2
MK
997 )
998 (eval-after-load "mule-cmds"
90066cb5
RF
999 '(defadvice toggle-input-method (around viper-mule-advice activate)
1000 "Adjust input-method toggling in vi-state."
1001 (if (and viper-special-input-method (eq viper-current-state 'vi-state))
1002 (viper-inactivate-input-method)
1003 ad-do-it)))
a1506d29 1004
8626cfa2 1005 ) ; viper-set-hooks
726e270f 1006
e36a387d
MK
1007
1008;; these are primarily advices and Vi-ish variable settings
8626cfa2
MK
1009(defun viper-non-hook-settings ()
1010
83f49acb
MK
1011 ;;;; Viper changes the default mode-line-buffer-identification
1012 ;;(setq-default mode-line-buffer-identification '(" %b"))
a1506d29 1013
e36a387d
MK
1014 ;; setup emacs-supported vi-style feel
1015 (setq next-line-add-newlines nil
1016 require-final-newline t)
a1506d29 1017
e36a387d 1018 ;; don't bark when mark is inactive
8626cfa2 1019 (if viper-emacs-p
5489c3d3 1020 (setq mark-even-if-inactive t))
a1506d29 1021
e36a387d 1022 (setq scroll-step 1)
a1506d29 1023
e36a387d 1024 ;; Variable displaying the current Viper state in the mode line.
8626cfa2 1025 (or (memq 'viper-mode-string global-mode-string)
e36a387d 1026 (setq global-mode-string
8626cfa2 1027 (append '("" viper-mode-string) (cdr global-mode-string))))
e36a387d 1028
899a431b 1029 (defadvice describe-key (before viper-describe-key-ad protect activate)
4960e757 1030 "Force to read key via `viper-read-key-sequence'."
ba5b5659
CY
1031 (interactive (let (key)
1032 (setq key (viper-read-key-sequence
1033 "Describe key (or click or menu item): "))
1034 (list key
1035 (prefix-numeric-value current-prefix-arg)
1036 ;; If KEY is a down-event, read also the
1037 ;; corresponding up-event.
1038 (and (vectorp key)
1039 (let ((last-idx (1- (length key))))
1040 (and (eventp (aref key last-idx))
1041 (memq 'down (event-modifiers
1042 (aref key last-idx)))))
1043 (or (and (eventp (aref key 0))
1044 (memq 'down (event-modifiers
1045 (aref key 0)))
1046 ;; For the C-down-mouse-2 popup
1047 ;; menu, there is no subsequent up-event.
1048 (= (length key) 1))
1049 (and (> (length key) 1)
1050 (eventp (aref key 1))
1051 (memq 'down (event-modifiers (aref key 1)))))
1052 (read-event))))))
a1506d29 1053
8626cfa2 1054 (defadvice describe-key-briefly
899a431b 1055 (before viper-describe-key-briefly-ad protect activate)
4960e757 1056 "Force to read key via `viper-read-key-sequence'."
ba5b5659
CY
1057 (interactive (let (key)
1058 (setq key (viper-read-key-sequence
1059 "Describe key (or click or menu item): "))
1060 ;; If KEY is a down-event, read and discard the
1061 ;; corresponding up-event.
1062 (and (vectorp key)
1063 (let ((last-idx (1- (length key))))
1064 (and (eventp (aref key last-idx))
1065 (memq 'down (event-modifiers (aref key last-idx)))))
1066 (read-event))
1067 (list key
1068 (if current-prefix-arg
1069 (prefix-numeric-value current-prefix-arg))
1070 1))))
a1506d29 1071
8626cfa2 1072 (defadvice find-file (before viper-add-suffix-advice activate)
e36a387d
MK
1073 "Use `read-file-name' for reading arguments."
1074 (interactive (cons (read-file-name "Find file: " nil default-directory)
560ef11a
MK
1075 ;; XEmacs: if Mule & prefix arg, ask for coding system
1076 (cond ((and viper-xemacs-p (featurep 'mule))
1e70790f
MK
1077 (list
1078 (and current-prefix-arg
560ef11a
MK
1079 (read-coding-system "Coding-system: "))))
1080 ;; Emacs: do wildcards
1081 ((and viper-emacs-p (boundp 'find-file-wildcards))
1082 (list find-file-wildcards))))
1083 ))
a1506d29 1084
8626cfa2 1085 (defadvice find-file-other-window (before viper-add-suffix-advice activate)
e36a387d
MK
1086 "Use `read-file-name' for reading arguments."
1087 (interactive (cons (read-file-name "Find file in other window: "
1088 nil default-directory)
560ef11a
MK
1089 ;; XEmacs: if Mule & prefix arg, ask for coding system
1090 (cond ((and viper-xemacs-p (featurep 'mule))
1e70790f
MK
1091 (list
1092 (and current-prefix-arg
560ef11a
MK
1093 (read-coding-system "Coding-system: "))))
1094 ;; Emacs: do wildcards
1095 ((and viper-emacs-p (boundp 'find-file-wildcards))
1096 (list find-file-wildcards))))
1097 ))
a1506d29 1098
1e70790f 1099
8626cfa2 1100 (defadvice find-file-other-frame (before viper-add-suffix-advice activate)
e36a387d
MK
1101 "Use `read-file-name' for reading arguments."
1102 (interactive (cons (read-file-name "Find file in other frame: "
1103 nil default-directory)
560ef11a
MK
1104 ;; XEmacs: if Mule & prefix arg, ask for coding system
1105 (cond ((and viper-xemacs-p (featurep 'mule))
1e70790f
MK
1106 (list
1107 (and current-prefix-arg
560ef11a
MK
1108 (read-coding-system "Coding-system: "))))
1109 ;; Emacs: do wildcards
1110 ((and viper-emacs-p (boundp 'find-file-wildcards))
1111 (list find-file-wildcards))))
1112 ))
1e70790f 1113
a1506d29 1114
8626cfa2
MK
1115 (defadvice read-file-name (around viper-suffix-advice activate)
1116 "Tell `exit-minibuffer' to run `viper-file-add-suffix' as a hook."
96dffd25 1117 (let ((viper-minibuffer-exit-hook
2eb4bdca
MK
1118 (append viper-minibuffer-exit-hook
1119 '(viper-minibuffer-trim-tail viper-file-add-suffix))))
e36a387d 1120 ad-do-it))
a1506d29 1121
8626cfa2 1122 (defadvice start-kbd-macro (after viper-kbd-advice activate)
e36a387d
MK
1123 "Remove Viper's intercepting bindings for C-x ).
1124 This may be needed if the previous `:map' command terminated abnormally."
8626cfa2
MK
1125 (define-key viper-vi-intercept-map "\C-x)" nil)
1126 (define-key viper-insert-intercept-map "\C-x)" nil)
1127 (define-key viper-emacs-intercept-map "\C-x)" nil))
41497c90 1128
8ea74b0e
MK
1129 (defadvice add-minor-mode (after
1130 viper-advice-add-minor-mode
1131 (toggle name &optional keymap after toggle-fun)
1132 activate)
38685583
MK
1133 "Run viper-normalize-minor-mode-map-alist after adding a minor mode."
1134 (viper-normalize-minor-mode-map-alist)
1135 (unless
1136 (and (fboundp 'add-to-ordered-list) (boundp 'emulation-mode-map-alists))
1137 (setq-default minor-mode-map-alist minor-mode-map-alist)))
8ea74b0e 1138
41497c90
MK
1139 ;; catch frame switching event
1140 (if (viper-window-display-p)
1141 (if viper-xemacs-p
1142 (add-hook 'mouse-leave-frame-hook
1143 'viper-remember-current-frame)
1144 (defadvice handle-switch-frame (before viper-frame-advice activate)
a1506d29 1145 "Remember the selected frame before the switch-frame event."
41497c90
MK
1146 (viper-remember-current-frame (selected-frame)))) )
1147
8626cfa2 1148 ) ; end viper-non-hook-settings
e36a387d 1149
4960e757 1150
726e270f 1151\f
41497c90
MK
1152;; Ask only if this-command/last-command are nil, i.e., when loading
1153(cond ((and (eq viper-mode 'ask) (null this-command) (null last-command))
1154 (save-window-excursion
1155 (with-output-to-temp-buffer " *viper-info*"
1156 (princ "
cbd9191d 1157You have loaded Viper, and are about to Viperize your Emacs!
e36a387d 1158
8626cfa2 1159Viper is a Package for Emacs Rebels and a venomous VI PERil,
e36a387d
MK
1160
1161It's time to decide: to Viperize or not to Viperize...
1162
a1506d29 1163If you wish to Viperize AND make this your way of life, please put
e36a387d
MK
1164
1165 (setq viper-mode t)
1166 (require 'viper)
1167
1168in your .emacs file (preferably, close to the top).
1169These two lines must come in the order given.
1170
8626cfa2
MK
1171** Viper users:
1172 **** The startup file name has been changed from .vip to .viper
1173 **** All vip-* style names have been converted to viper-* style."))
41497c90
MK
1174 (if (y-or-n-p "Viperize? ")
1175 (setq viper-mode t)
1176 (setq viper-mode nil))
1177 (message "")
1178 (kill-buffer " *viper-info*")))
1179
3af0304a 1180 ;; If viper-mode is t, then just continue. Viper will kick in.
41497c90 1181 ((eq viper-mode t))
2eb4bdca 1182 ;; Otherwise, it was asking Viper was not loaded through .emacs
41497c90 1183 ;; In this case, it was either through M-x viper-mode or via something
a1506d29 1184 ;; else, like the custom widget. If Viper was loaded through
41497c90
MK
1185 ;; M-x viper-mode, then viper will kick in anyway.
1186 (t (setq viper-mode nil)))
8626cfa2
MK
1187
1188(defun viper-load-custom-file ()
1189 (if (and (file-exists-p viper-custom-file-name)
1190 (not noninteractive))
1191 (load viper-custom-file-name)))
e36a387d 1192
726e270f
MK
1193
1194
1195\f
1e70790f
MK
1196
1197
1198;; save non-viper vars that Viper might change
1199(if (null viper-saved-non-viper-variables)
1200 (setq viper-saved-non-viper-variables
1201 (list
1e70790f
MK
1202 (cons 'next-line-add-newlines (list next-line-add-newlines))
1203 (cons 'require-final-newline (list require-final-newline))
1e70790f
MK
1204 (cons 'scroll-step (list scroll-step))
1205 (cons 'mode-line-buffer-identification
1206 (list (default-value 'mode-line-buffer-identification)))
1207 (cons 'global-mode-string (list global-mode-string))
8626cfa2 1208 (if viper-emacs-p
5489c3d3 1209 (cons 'mark-even-if-inactive (list mark-even-if-inactive)))
1e70790f 1210 )))
a1506d29
JB
1211
1212
e36a387d 1213;; Set some useful macros, advices
a1506d29 1214;; These must be BEFORE ~/.viper is loaded,
1e70790f 1215;; so the user can unrecord them in ~/.viper.
e36a387d
MK
1216(if viper-mode
1217 (progn
1218 ;; set advices and some variables that give emacs Vi look.
8626cfa2 1219 (viper-non-hook-settings)
e36a387d
MK
1220
1221 ;; repeat the 2nd previous command without rotating the command history
8626cfa2
MK
1222 (viper-record-kbd-macro
1223 (vector viper-repeat-from-history-key '\1) 'vi-state
1224 [(meta x) v i p e r - r e p e a t - f r o m - h i s t o r y return] 't)
e36a387d 1225 ;; repeat the 3d previous command without rotating the command history
8626cfa2
MK
1226 (viper-record-kbd-macro
1227 (vector viper-repeat-from-history-key '\2) 'vi-state
1228 [(meta x) v i p e r - r e p e a t - f r o m - h i s t o r y return] 't)
a1506d29
JB
1229
1230 ;; set macros for toggling case sensitivity and regexp search
8626cfa2 1231 (viper-set-searchstyle-toggling-macros nil)
e36a387d 1232 ;; Make %%% toggle parsing comments for matching parentheses
8626cfa2
MK
1233 (viper-set-parsing-style-toggling-macro nil)
1234
1235 ;; ~/.viper is loaded if exists
1236 (viper-load-custom-file)
a1506d29 1237
8626cfa2
MK
1238 ;; should be after loading custom file to avoid the pesky msg that
1239 ;; mouse-search/insert keys are already bound
1240 (viper-bind-mouse-search-key)
1241 (viper-bind-mouse-insert-key)
e36a387d 1242 ))
a1506d29 1243
6c2e12f4 1244
6c2e12f4 1245\f
8626cfa2 1246;; Applying Viper customization -- runs after (load .viper)
6c2e12f4 1247
8971f87b 1248;; Save user settings or Viper defaults for vars controlled by
a1506d29 1249;; viper-expert-level
1e70790f 1250(if (null viper-saved-user-settings)
a1506d29 1251 (setq viper-saved-user-settings
8626cfa2 1252 (list (cons 'viper-want-ctl-h-help (list viper-want-ctl-h-help))
1e70790f 1253 (cons 'viper-always (list viper-always))
8626cfa2
MK
1254 (cons 'viper-no-multiple-ESC (list viper-no-multiple-ESC))
1255 (cons 'viper-ex-style-motion (list viper-ex-style-motion))
34317da2
MK
1256 (cons 'viper-ex-style-editing
1257 (list viper-ex-style-editing))
a1506d29 1258 (cons 'viper-want-emacs-keys-in-vi
8626cfa2
MK
1259 (list viper-want-emacs-keys-in-vi))
1260 (cons 'viper-electric-mode (list viper-electric-mode))
1261 (cons 'viper-want-emacs-keys-in-insert
1262 (list viper-want-emacs-keys-in-insert))
1263 (cons 'viper-re-search (list viper-re-search)))))
a1506d29 1264
6c2e12f4 1265
e36a387d
MK
1266(if viper-mode
1267 (progn
8626cfa2
MK
1268 (viper-set-minibuffer-style)
1269 (if viper-buffer-search-char
1270 (viper-buffer-search-enable))
34317da2 1271 (viper-update-syntax-classes 'set-default)
e36a387d 1272 ))
a1506d29 1273
d5e52f99 1274\f
6c2e12f4 1275;;; Familiarize Viper with some minor modes that have their own keymaps
e36a387d
MK
1276(if viper-mode
1277 (progn
8626cfa2
MK
1278 (viper-harness-minor-mode "compile")
1279 (viper-harness-minor-mode "outline")
1280 (viper-harness-minor-mode "allout")
1281 (viper-harness-minor-mode "xref")
1282 (viper-harness-minor-mode "lmenu")
1283 (viper-harness-minor-mode "vc")
1284 (viper-harness-minor-mode "ltx-math") ; LaTeX-math-mode in AUC-TeX, which
1285 (viper-harness-minor-mode "latex") ; sits in one of these two files
1286 (viper-harness-minor-mode "cyrillic")
1287 (viper-harness-minor-mode "russian")
1288 (viper-harness-minor-mode "view-less")
1289 (viper-harness-minor-mode "view")
2eb4bdca 1290 (viper-harness-minor-mode "reftex")
3af0304a 1291 (viper-harness-minor-mode "flyspell")
e36a387d 1292 ))
6c2e12f4
KH
1293
1294
1295;; Intercept maps could go in viper-keym.el
1e70790f 1296;; We keep them here in case someone redefines them in ~/.viper
6c2e12f4 1297
8626cfa2
MK
1298(define-key viper-vi-intercept-map viper-ESC-key 'viper-intercept-ESC-key)
1299(define-key viper-insert-intercept-map viper-ESC-key 'viper-intercept-ESC-key)
6c2e12f4 1300
8626cfa2
MK
1301;; This is taken care of by viper-insert-global-user-map.
1302;;(define-key viper-replace-map viper-ESC-key 'viper-intercept-ESC-key)
6c2e12f4 1303
34da0a2b 1304
8626cfa2 1305;; The default viper-toggle-key is \C-z; for the novice, it suspends or
6c2e12f4 1306;; iconifies Emacs
8626cfa2
MK
1307(define-key viper-vi-intercept-map viper-toggle-key 'viper-toggle-key-action)
1308(define-key
1309 viper-emacs-intercept-map viper-toggle-key 'viper-change-state-to-vi)
a1506d29 1310
38685583 1311;;; Removed to avoid bad interaction with cua-mode.
328b4b70 1312;;; Escape from Emacs and Insert modes to Vi for one command
38685583
MK
1313;;(define-key viper-emacs-intercept-map "\C-c\\" 'viper-escape-to-vi)
1314;;(define-key viper-insert-intercept-map "\C-c\\" 'viper-escape-to-vi)
328b4b70
MK
1315
1316(if viper-mode
c004db97
MK
1317 (setq-default viper-emacs-intercept-minor-mode t
1318 viper-emacs-local-user-minor-mode t
1319 viper-emacs-global-user-minor-mode t
1320 viper-emacs-kbd-minor-mode t
1321 viper-emacs-state-modifier-minor-mode t))
1322(if (and viper-mode (eq viper-current-state 'emacs-state))
1323 (setq viper-emacs-intercept-minor-mode t
1324 viper-emacs-local-user-minor-mode t
1325 viper-emacs-global-user-minor-mode t
1326 viper-emacs-kbd-minor-mode t
1327 viper-emacs-state-modifier-minor-mode t))
6c2e12f4
KH
1328
1329
e36a387d 1330(if (and viper-mode
a1506d29 1331 (or viper-always
1e70790f 1332 (and (< viper-expert-level 5) (> viper-expert-level 0))))
8626cfa2 1333 (viper-set-hooks))
a1506d29 1334
2550055a
MK
1335;; Let all minor modes take effect after loading.
1336;; This may not be enough, so we also set default minor-mode-alist.
6c2e12f4 1337;; Without setting the default, new buffers that come up in emacs mode have
8626cfa2 1338;; minor-mode-map-alist = nil, unless we call viper-change-state-*
328b4b70 1339(if (and viper-mode (eq viper-current-state 'emacs-state))
6c2e12f4 1340 (progn
8626cfa2 1341 (viper-change-state-to-emacs)
38685583
MK
1342 (unless
1343 (and (fboundp 'add-to-ordered-list)
1344 (boundp 'emulation-mode-map-alists))
1345 (setq-default minor-mode-map-alist minor-mode-map-alist))
6c2e12f4 1346 ))
2eb4bdca 1347
4960e757 1348(if (and viper-mode (this-major-mode-requires-vi-state major-mode))
2eb4bdca 1349 (viper-mode))
6c2e12f4 1350
2550055a
MK
1351(if viper-mode
1352 (setq initial-major-mode
1353 `(lambda ()
1354 (funcall (quote ,initial-major-mode))
1355 (set-viper-state-in-major-mode))
1356 ))
1357
1358
d5e52f99 1359
8626cfa2 1360(run-hooks 'viper-load-hook) ; the last chance to change something
6c2e12f4 1361
d5e52f99 1362(provide 'viper)
6c2e12f4 1363
1e70790f 1364
e2de3a29
MK
1365;; Local Variables:
1366;; eval: (put 'viper-deflocalvar 'lisp-indent-hook 'defun)
1367;; End:
1e70790f 1368
e2de3a29 1369;; arch-tag: 5f3e844c-c4e6-4bbd-9b73-63bdc14e7d79
60370d40 1370;;; viper.el ends here