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