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