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
|
197
|
11 (defconst viper-version "3.001 (Polyglot) of September 23, 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
|
197
|
337 (defgroup viper-misc nil
|
|
338 "Miscellaneous Viper customization."
|
|
339 :prefix "viper-"
|
|
340 :group 'viper)
|
|
341
|
|
342
|
181
|
343 (defcustom viper-always t
|
163
|
344 "Non-nil means, arrange for vi-state to be a default when appropriate.
|
|
345 This is different from `viper-mode' variable in that `viper-mode' determines
|
|
346 whether to use Viper in the first place, while `viper-always', if nil, lets
|
175
|
347 user decide when to invoke Viper in a major mode."
|
|
348 :type 'boolean
|
|
349 :tag "Always Invoke Viper"
|
197
|
350 :group 'viper-misc)
|
0
|
351
|
175
|
352 ;; Non-viper variables that need to be saved in case the user decides to
|
|
353 ;; de-viperize emacs.
|
|
354 (defvar viper-saved-non-viper-variables nil)
|
|
355 ;; Contains user settings for vars affected by viper-set-expert-level function.
|
|
356 ;; Not a user option.
|
|
357 (defvar viper-saved-user-settings nil)
|
|
358
|
|
359 (defcustom viper-mode (cond (noninteractive nil)
|
|
360 (t 'ask))
|
|
361 "To Viperize or not to Viperize.
|
163
|
362 If t, viperize emacs. If nil -- don't. If `ask', ask the user.
|
|
363 This variable is used primatily when Viper is being loaded.
|
0
|
364
|
163
|
365 Must be set in `~/.emacs' before Viper is loaded.
|
197
|
366 DO NOT set this variable interactively, unless you are using the customization
|
|
367 widget."
|
175
|
368 :type '(choice (const nil) (const t) (const ask))
|
|
369 :tag "Set Viper Mode on Loading"
|
197
|
370 :group 'viper-misc)
|
0
|
371
|
181
|
372 (defcustom viper-non-vi-major-modes
|
|
373 '(custom-mode dired-mode efs-mode internal-ange-ftp-mode tar-mode
|
|
374 mh-folder-mode gnus-group-mode gnus-summary-mode Info-mode
|
|
375 Buffer-menu-mode view-mode vm-mode vm-summary-mode)
|
|
376 "*A list of major modes that should never come up in Vi command mode.
|
|
377 Viper automatically augments this list with some obvious modes, such as
|
197
|
378 `dired-mode', `tar-mode', etc. So, don't put a mode on this list, unless
|
181
|
379 it comes up in a wrong Viper state."
|
197
|
380 :type '(repeat symbol)
|
|
381 :group 'viper-misc)
|
0
|
382
|
175
|
383
|
0
|
384
|
|
385
|
|
386 ;;;###autoload
|
181
|
387 (defun toggle-viper-mode ()
|
|
388 (interactive)
|
|
389 (if (eq viper-mode t)
|
|
390 (viper-go-away)
|
|
391 (setq viper-mode nil)
|
|
392 (viper-mode)))
|
|
393
|
|
394 ;;;###autoload
|
0
|
395 (defun viper-mode ()
|
|
396 "Turn on Viper emulation of Vi."
|
|
397 (interactive)
|
|
398 (if (not noninteractive)
|
|
399 (progn
|
163
|
400 ;; if the user requested viper-mode explicitly
|
|
401 (if viper-mode
|
|
402 ()
|
181
|
403 (setq viper-mode t)
|
163
|
404 (load-library "viper"))
|
|
405
|
181
|
406 (if viper-first-time ; Important check. Prevents mix-up of startup and
|
|
407 (progn ; expert-level msgs when viper-mode recurses
|
|
408 (setq viper-first-time nil)
|
|
409 (if (not viper-inhibit-startup-message)
|
0
|
410 (save-window-excursion
|
181
|
411 (setq viper-inhibit-startup-message t)
|
0
|
412 (delete-other-windows)
|
|
413 (switch-to-buffer "Viper Startup Message")
|
|
414 (erase-buffer)
|
|
415 (insert
|
|
416 (substitute-command-keys
|
175
|
417 "Viper Is a Package for Emacs Rebels,
|
|
418 a VI Plan for Emacs Rescue, and a venomous VI PERil.
|
0
|
419
|
175
|
420 Incidentally, Viper emulates Vi under GNU Emacs 20 and XEmacs 20.
|
|
421 It supports all of what is good in Vi and Ex, while extending
|
0
|
422 and improving upon much of it.
|
|
423
|
|
424 1. Viper supports Vi at several levels. Level 1 is the closest to Vi,
|
|
425 level 5 provides the most flexibility to depart from many Vi conventions.
|
|
426
|
|
427 You will be asked to specify your user level in a following screen.
|
|
428
|
|
429 If you select user level 1 then the keys ^X, ^C, ^Z, and ^G will behave
|
|
430 as in VI, to smooth transition to Viper for the beginners. However, to
|
|
431 use Emacs productively, you are advised to reach user level 3 or higher.
|
|
432
|
175
|
433 At user level 2 or higher, ^X and ^C have Emacs, not Vi, bindings;
|
|
434 ^Z toggles Vi/Emacs states; ^G is Emacs' keyboard-quit (like ^C in Vi).
|
0
|
435
|
|
436 2. Vi exit functions (e.g., :wq, ZZ) work on INDIVIDUAL files -- they
|
175
|
437 do not cause Emacs to quit, except at user level 1 (for a novice).
|
0
|
438 3. ^X^C EXITS EMACS.
|
|
439 4. Viper supports multiple undo: `u' will undo. Typing `.' will repeat
|
|
440 undo. Another `u' changes direction.
|
|
441
|
175
|
442 6. Emacs Meta key is `C-\\' (in all modes) or `\\ ESC' (in Vi command mode).
|
|
443 On a window system, the best way is to use the Meta-key on your keyboard.
|
0
|
444 7. Try \\[keyboard-quit] and \\[abort-recursive-edit] repeatedly,if
|
|
445 something funny happens. This would abort the current editing command.
|
|
446
|
175
|
447 For more information on Viper:
|
0
|
448
|
175
|
449 a. Type `:help' in Vi command mode
|
|
450 b. Print Viper manual, found in ./etc/viper.dvi
|
|
451 c. Print the Quick Reference, found in ./etc/viperCard.dvi
|
|
452
|
|
453 To submit a bug report or to contact the author, type :submitReport in Vi
|
|
454 command mode. To shoo Viper away and return to pure Emacs (horror!), type:
|
|
455
|
|
456 M-x viper-go-away
|
0
|
457
|
|
458 This startup message appears whenever you load Viper, unless you type `y' now."
|
|
459 ))
|
|
460 (goto-char (point-min))
|
|
461 (if (y-or-n-p "Inhibit Viper startup message? ")
|
181
|
462 (viper-save-setting
|
|
463 'viper-inhibit-startup-message
|
0
|
464 "Viper startup message inhibited"
|
181
|
465 viper-custom-file-name t))
|
0
|
466 ;;(kill-buffer (current-buffer))
|
|
467 (message
|
|
468 "The last message is in buffer `Viper Startup Message'")
|
|
469 (sit-for 4)
|
|
470 ))
|
175
|
471 (viper-set-expert-level 'dont-change-unless)))
|
181
|
472
|
|
473 (or (memq major-mode viper-non-vi-major-modes) ; don't switch to Vi
|
|
474 (viper-change-state-to-vi)))))
|
163
|
475
|
0
|
476
|
|
477 ;; This hook designed to enable Vi-style editing in comint-based modes."
|
181
|
478 (defun viper-comint-mode-hook ()
|
78
|
479 (setq require-final-newline nil
|
185
|
480 viper-ex-style-editing nil
|
181
|
481 viper-ex-style-motion nil)
|
|
482 (viper-change-state-to-insert))
|
78
|
483
|
0
|
484
|
175
|
485 ;; remove viper hooks from SYMBOL
|
|
486 (defun viper-remove-hooks (symbol)
|
|
487 (cond ((not (boundp symbol)) nil)
|
|
488 ((not (listp (eval symbol))) nil)
|
|
489 ((string-match "-hook" (symbol-name symbol))
|
|
490 (remove-hook symbol 'viper-mode)
|
181
|
491 (remove-hook symbol 'viper-change-state-to-emacs)
|
|
492 (remove-hook symbol 'viper-change-state-to-insert)
|
|
493 (remove-hook symbol 'viper-change-state-to-vi)
|
175
|
494 )))
|
|
495
|
|
496 ;; Remove local value in all existing buffers
|
|
497 ;; This doesn't delocalize vars (which would have been desirable)
|
|
498 (defun viper-delocalize-var (symbol)
|
|
499 (mapcar (function (lambda (buf)
|
|
500 (save-excursion
|
|
501 (set-buffer buf)
|
|
502 (kill-local-variable symbol))))
|
|
503 (buffer-list)))
|
|
504
|
|
505
|
|
506 (defun viper-go-away ()
|
|
507 "De-Viperize Emacs.
|
|
508 This function tries to do as good a job as possible. However, it may undo some
|
|
509 user customization, unrelated to Viper. For instance, if the user advised
|
|
510 `read-file-name', `describe-key', and some others, then this advice will be
|
|
511 undone.
|
|
512 It also doesn't undo some Viper settings. For instance, `minor-mode-map-alist'
|
|
513 remains buffer-local."
|
|
514 (interactive)
|
|
515
|
|
516 ;; restore non-viper vars
|
|
517 (setq-default
|
|
518 default-major-mode
|
|
519 (viper-standard-value 'default-major-mode viper-saved-non-viper-variables)
|
|
520 next-line-add-newlines
|
|
521 (viper-standard-value
|
|
522 'next-line-add-newlines viper-saved-non-viper-variables)
|
|
523 require-final-newline
|
|
524 (viper-standard-value
|
|
525 'require-final-newline viper-saved-non-viper-variables)
|
|
526 scroll-step
|
|
527 (viper-standard-value 'scroll-step viper-saved-non-viper-variables)
|
|
528 mode-line-buffer-identification
|
|
529 (viper-standard-value
|
|
530 'mode-line-buffer-identification viper-saved-non-viper-variables)
|
|
531 global-mode-string
|
|
532 (viper-standard-value 'global-mode-string viper-saved-non-viper-variables))
|
|
533
|
181
|
534 (if viper-emacs-p
|
175
|
535 (setq-default
|
|
536 mark-even-if-inactive
|
|
537 (viper-standard-value
|
|
538 'mark-even-if-inactive viper-saved-non-viper-variables)))
|
|
539
|
|
540 ;; Ideally, we would like to be able to de-localize local variables
|
|
541 (viper-delocalize-var 'minor-mode-map-alist)
|
|
542 (viper-delocalize-var 'require-final-newline)
|
|
543
|
|
544
|
|
545 ;; deactivate all advices done by Viper.
|
181
|
546 (ad-deactivate-regexp "viper-")
|
175
|
547
|
|
548 (setq viper-mode nil)
|
|
549
|
181
|
550 (viper-delocalize-var 'viper-vi-minibuffer-minor-mode)
|
|
551 (viper-delocalize-var 'viper-insert-minibuffer-minor-mode)
|
|
552 (viper-delocalize-var 'viper-vi-intercept-minor-mode)
|
|
553 (viper-delocalize-var 'viper-insert-intercept-minor-mode)
|
175
|
554
|
181
|
555 (viper-delocalize-var 'viper-vi-local-user-minor-mode)
|
|
556 (viper-delocalize-var 'viper-vi-kbd-minor-mode)
|
|
557 (viper-delocalize-var 'viper-vi-global-user-minor-mode)
|
|
558 (viper-delocalize-var 'viper-vi-state-modifier-minor-mode)
|
|
559 (viper-delocalize-var 'viper-vi-diehard-minor-mode)
|
|
560 (viper-delocalize-var 'viper-vi-basic-minor-mode)
|
175
|
561
|
181
|
562 (viper-delocalize-var 'viper-replace-minor-mode)
|
175
|
563
|
181
|
564 (viper-delocalize-var 'viper-insert-local-user-minor-mode)
|
|
565 (viper-delocalize-var 'viper-insert-kbd-minor-mode)
|
|
566 (viper-delocalize-var 'viper-insert-global-user-minor-mode)
|
|
567 (viper-delocalize-var 'viper-insert-state-modifier-minor-mode)
|
|
568 (viper-delocalize-var 'viper-insert-diehard-minor-mode)
|
|
569 (viper-delocalize-var 'viper-insert-basic-minor-mode)
|
175
|
570
|
181
|
571 (viper-delocalize-var 'viper-emacs-intercept-minor-mode)
|
|
572 (viper-delocalize-var 'viper-emacs-local-user-minor-mode)
|
|
573 (viper-delocalize-var 'viper-emacs-kbd-minor-mode)
|
|
574 (viper-delocalize-var 'viper-emacs-global-user-minor-mode)
|
|
575 (viper-delocalize-var 'viper-emacs-state-modifier-minor-mode)
|
175
|
576
|
181
|
577 (setq-default viper-vi-minibuffer-minor-mode nil
|
|
578 viper-insert-minibuffer-minor-mode nil
|
|
579 viper-vi-intercept-minor-mode nil
|
|
580 viper-insert-intercept-minor-mode nil
|
175
|
581
|
181
|
582 viper-vi-local-user-minor-mode nil
|
|
583 viper-vi-kbd-minor-mode nil
|
|
584 viper-vi-global-user-minor-mode nil
|
|
585 viper-vi-state-modifier-minor-mode nil
|
|
586 viper-vi-diehard-minor-mode nil
|
|
587 viper-vi-basic-minor-mode nil
|
175
|
588
|
181
|
589 viper-replace-minor-mode nil
|
175
|
590
|
181
|
591 viper-insert-local-user-minor-mode nil
|
|
592 viper-insert-kbd-minor-mode nil
|
|
593 viper-insert-global-user-minor-mode nil
|
|
594 viper-insert-state-modifier-minor-mode nil
|
|
595 viper-insert-diehard-minor-mode nil
|
|
596 viper-insert-basic-minor-mode nil
|
175
|
597
|
181
|
598 viper-emacs-intercept-minor-mode nil
|
|
599 viper-emacs-local-user-minor-mode nil
|
|
600 viper-emacs-kbd-minor-mode nil
|
|
601 viper-emacs-global-user-minor-mode nil
|
|
602 viper-emacs-state-modifier-minor-mode nil
|
175
|
603 )
|
|
604
|
|
605 ;; remove all hooks set by viper
|
|
606 (mapatoms 'viper-remove-hooks)
|
181
|
607 (remove-hook 'comint-mode-hook 'viper-comint-mode-hook)
|
|
608 (remove-hook 'minibuffer-setup-hook 'viper-minibuffer-setup-sentinel)
|
|
609
|
|
610 ;; unbind Viper mouse bindings
|
|
611 (viper-unbind-mouse-search-key)
|
|
612 (viper-unbind-mouse-insert-key)
|
|
613 ;; In emacs, we have to advice handle-switch-frame
|
|
614 ;; This advice is undone earlier, when all advices matchine "viper-" are
|
|
615 ;; deactivated.
|
|
616 (if viper-xemacs-p
|
|
617 (remove-hook 'mouse-leave-frame-hook 'viper-remember-current-frame))
|
|
618 ) ; end viper-go-away
|
175
|
619
|
|
620
|
|
621
|
|
622
|
0
|
623 ;; This sets major mode hooks to make them come up in vi-state.
|
181
|
624 (defun viper-set-hooks ()
|
0
|
625
|
|
626 ;; It is of course a misnomer to call viper-mode a `major mode'.
|
|
627 ;; However, this has the effect that if the user didn't specify the
|
|
628 ;; default mode, new buffers that fall back on the default will come up
|
|
629 ;; in Fundamental Mode and Vi state.
|
|
630 (setq default-major-mode 'viper-mode)
|
|
631
|
|
632 ;; The following major modes should come up in vi-state
|
181
|
633 (defadvice fundamental-mode (after viper-fundamental-mode-ad activate)
|
|
634 "Run `viper-change-state-to-vi' on entry."
|
|
635 (viper-change-state-to-vi))
|
0
|
636
|
|
637 (defvar makefile-mode-hook)
|
|
638 (add-hook 'makefile-mode-hook 'viper-mode)
|
|
639
|
187
|
640 ;; Help mode is now for viewing only
|
0
|
641 (defvar help-mode-hook)
|
187
|
642 (add-hook 'help-mode-hook 'viper-change-state-to-emacs)
|
|
643 (viper-modify-major-mode 'help-mode 'emacs-state viper-slash-and-colon-map)
|
0
|
644
|
|
645 (defvar awk-mode-hook)
|
|
646 (add-hook 'awk-mode-hook 'viper-mode)
|
|
647
|
|
648 (defvar html-mode-hook)
|
|
649 (add-hook 'html-mode-hook 'viper-mode)
|
|
650 (defvar html-helper-mode-hook)
|
|
651 (add-hook 'html-helper-mode-hook 'viper-mode)
|
163
|
652
|
78
|
653 (defvar java-mode-hook)
|
|
654 (add-hook 'java-mode-hook 'viper-mode)
|
80
|
655
|
175
|
656 (defvar javascript-mode-hook)
|
|
657 (add-hook 'javascript-mode-hook 'viper-mode)
|
|
658
|
0
|
659 (defvar emacs-lisp-mode-hook)
|
|
660 (add-hook 'emacs-lisp-mode-hook 'viper-mode)
|
|
661 (defvar lisp-mode-hook)
|
|
662 (add-hook 'lisp-mode-hook 'viper-mode)
|
163
|
663 (defvar lisp-interaction-mode-hook)
|
|
664 (add-hook 'lisp-interaction-mode-hook 'viper-mode)
|
0
|
665
|
|
666 (defvar bibtex-mode-hook)
|
|
667 (add-hook 'bibtex-mode-hook 'viper-mode)
|
|
668
|
|
669 (defvar cc-mode-hook)
|
|
670 (add-hook 'cc-mode-hook 'viper-mode)
|
|
671
|
|
672 (defvar c-mode-hook)
|
|
673 (add-hook 'c-mode-hook 'viper-mode)
|
|
674
|
|
675 (defvar c++-mode-hook)
|
|
676 (add-hook 'c++-mode-hook 'viper-mode)
|
|
677
|
|
678 (defvar fortran-mode-hook)
|
163
|
679 (add-hook 'fortran-mode-hook 'viper-mode)
|
|
680 (defvar f90-mode-hook)
|
|
681 (add-hook 'f90-mode-hook 'viper-mode)
|
80
|
682
|
78
|
683 (defvar basic-mode-hook)
|
163
|
684 (add-hook 'basic-mode-hook 'viper-mode)
|
78
|
685 (defvar bat-mode-hook)
|
163
|
686 (add-hook 'bat-mode-hook 'viper-mode)
|
|
687
|
|
688 (defvar asm-mode-hook)
|
|
689 (add-hook 'asm-mode-hook 'viper-mode)
|
|
690
|
|
691 (defvar prolog-mode-hook)
|
|
692 (add-hook 'prolog-mode-hook 'viper-mode)
|
80
|
693
|
0
|
694 (defvar text-mode-hook)
|
|
695 (add-hook 'text-mode-hook 'viper-mode)
|
|
696
|
|
697 (add-hook 'completion-list-mode-hook 'viper-mode)
|
|
698 (add-hook 'compilation-mode-hook 'viper-mode)
|
|
699
|
175
|
700 (defvar perl-mode-hook)
|
|
701 (add-hook 'perl-mode-hook 'viper-mode)
|
|
702
|
|
703 (defvar tcl-mode-hook)
|
|
704 (add-hook 'tcl-mode-hook 'viper-mode)
|
|
705
|
|
706 (defvar python-mode-hook)
|
|
707 (add-hook 'python-mode-hook 'viper-mode)
|
0
|
708
|
|
709 (defvar emerge-startup-hook)
|
181
|
710 (add-hook 'emerge-startup-hook 'viper-change-state-to-emacs)
|
78
|
711
|
|
712 ;; Tell vc-diff to put *vc* in Vi mode
|
|
713 (if (featurep 'vc)
|
181
|
714 (defadvice vc-diff (after viper-vc-ad activate)
|
78
|
715 "Force Vi state in VC diff buffer."
|
181
|
716 (viper-change-state-to-vi))
|
|
717 (eval-after-load
|
78
|
718 "vc"
|
181
|
719 '(defadvice vc-diff (after viper-vc-ad activate)
|
78
|
720 "Force Vi state in VC diff buffer."
|
181
|
721 (viper-change-state-to-vi))))
|
80
|
722
|
181
|
723 (eval-after-load
|
0
|
724 "emerge"
|
181
|
725 '(defadvice emerge-quit (after viper-emerge-advice activate)
|
|
726 "Run `viper-change-state-to-vi' after quitting emerge."
|
|
727 (viper-change-state-to-vi)))
|
0
|
728 ;; In case Emerge was loaded before Viper.
|
181
|
729 (defadvice emerge-quit (after viper-emerge-advice activate)
|
|
730 "Run `viper-change-state-to-vi' after quitting emerge."
|
|
731 (viper-change-state-to-vi))
|
0
|
732
|
|
733 ;; passwd.el sets up its own buffer, which turns up in Vi mode,
|
|
734 ;; thus overriding the local map. We don't need Vi mode here.
|
181
|
735 (eval-after-load
|
0
|
736 "passwd"
|
181
|
737 '(defadvice read-passwd-1 (before viper-passwd-ad activate)
|
0
|
738 "Switch to emacs state while reading password."
|
181
|
739 (viper-change-state-to-emacs)))
|
0
|
740
|
|
741 ;; Emacs shell, ange-ftp, and comint-based modes
|
|
742 (defvar comint-mode-hook)
|
181
|
743 (viper-modify-major-mode
|
|
744 'comint-mode 'insert-state viper-comint-mode-modifier-map)
|
|
745 (viper-modify-major-mode
|
|
746 'comint-mode 'vi-state viper-comint-mode-modifier-map)
|
|
747 (viper-modify-major-mode
|
|
748 'shell-mode 'insert-state viper-comint-mode-modifier-map)
|
|
749 (viper-modify-major-mode
|
|
750 'shell-mode 'vi-state viper-comint-mode-modifier-map)
|
78
|
751 ;; ange-ftp in XEmacs
|
181
|
752 (viper-modify-major-mode
|
|
753 'ange-ftp-shell-mode 'insert-state viper-comint-mode-modifier-map)
|
|
754 (viper-modify-major-mode
|
|
755 'ange-ftp-shell-mode 'vi-state viper-comint-mode-modifier-map)
|
78
|
756 ;; ange-ftp in Emacs
|
181
|
757 (viper-modify-major-mode
|
|
758 'internal-ange-ftp-mode 'insert-state viper-comint-mode-modifier-map)
|
|
759 (viper-modify-major-mode
|
|
760 'internal-ange-ftp-mode 'vi-state viper-comint-mode-modifier-map)
|
78
|
761 ;; set hook
|
181
|
762 (add-hook 'comint-mode-hook 'viper-comint-mode-hook)
|
80
|
763
|
0
|
764 ;; Shell scripts
|
|
765 (defvar sh-mode-hook)
|
|
766 (add-hook 'sh-mode-hook 'viper-mode)
|
|
767 (defvar ksh-mode-hook)
|
|
768 (add-hook 'ksh-mode-hook 'viper-mode)
|
|
769
|
|
770 ;; Dired
|
181
|
771 (viper-modify-major-mode 'dired-mode 'emacs-state viper-dired-modifier-map)
|
|
772 (viper-set-emacs-state-searchstyle-macros nil 'dired-mode)
|
|
773 (add-hook 'dired-mode-hook 'viper-change-state-to-emacs)
|
0
|
774
|
78
|
775 ;; Tar
|
181
|
776 (viper-modify-major-mode 'tar-mode 'emacs-state viper-slash-and-colon-map)
|
|
777 (viper-set-emacs-state-searchstyle-macros nil 'tar-mode)
|
78
|
778
|
|
779 ;; MH-E
|
181
|
780 (viper-modify-major-mode
|
|
781 'mh-folder-mode 'emacs-state viper-slash-and-colon-map)
|
|
782 (viper-set-emacs-state-searchstyle-macros nil 'mh-folder-mode)
|
78
|
783 ;; changing state to emacs is needed so the preceding will take hold
|
181
|
784 (add-hook 'mh-folder-mode-hook 'viper-change-state-to-emacs)
|
78
|
785 (add-hook 'mh-show-mode-hook 'viper-mode)
|
|
786
|
|
787 ;; Gnus
|
181
|
788 (viper-modify-major-mode
|
|
789 'gnus-group-mode 'emacs-state viper-slash-and-colon-map)
|
|
790 (viper-set-emacs-state-searchstyle-macros nil 'gnus-group-mode)
|
|
791 (viper-modify-major-mode
|
|
792 'gnus-summary-mode 'emacs-state viper-slash-and-colon-map)
|
|
793 (viper-set-emacs-state-searchstyle-macros nil 'gnus-summary-mode)
|
78
|
794 ;; changing state to emacs is needed so the preceding will take hold
|
181
|
795 (add-hook 'gnus-group-mode-hook 'viper-change-state-to-emacs)
|
|
796 (add-hook 'gnus-summary-mode-hook 'viper-change-state-to-emacs)
|
78
|
797 (add-hook 'gnus-article-mode-hook 'viper-mode)
|
|
798
|
|
799 ;; Info
|
181
|
800 (viper-modify-major-mode 'Info-mode 'emacs-state viper-slash-and-colon-map)
|
|
801 (viper-set-emacs-state-searchstyle-macros nil 'Info-mode)
|
78
|
802 ;; Switching to emacs is needed so the above will take hold
|
181
|
803 (defadvice Info-mode (after viper-Info-ad activate)
|
78
|
804 "Switch to emacs mode."
|
181
|
805 (viper-change-state-to-emacs))
|
78
|
806
|
|
807 ;; Buffer menu
|
181
|
808 (viper-modify-major-mode
|
|
809 'Buffer-menu-mode 'emacs-state viper-slash-and-colon-map)
|
|
810 (viper-set-emacs-state-searchstyle-macros nil 'Buffer-menu-mode)
|
78
|
811 ;; Switching to emacs is needed so the above will take hold
|
181
|
812 (defadvice Buffer-menu-mode (after viper-Buffer-menu-ad activate)
|
78
|
813 "Switch to emacs mode."
|
181
|
814 (viper-change-state-to-emacs))
|
78
|
815
|
|
816 ;; View mode
|
163
|
817 (defvar view-mode-hook)
|
|
818 (defvar view-hook)
|
181
|
819 (add-hook 'view-hook 'viper-change-state-to-emacs)
|
|
820 (add-hook 'view-mode-hook 'viper-change-state-to-emacs)
|
0
|
821
|
|
822 ;; For VM users.
|
|
823 ;; Put summary and other VM buffers in Emacs state.
|
|
824 (defvar vm-mode-hooks)
|
|
825 (defvar vm-summary-mode-hooks)
|
181
|
826 (add-hook 'vm-mode-hooks 'viper-change-state-to-emacs)
|
|
827 (add-hook 'vm-summary-mode-hooks 'viper-change-state-to-emacs)
|
0
|
828
|
|
829 ;; For RMAIL users.
|
|
830 ;; Put buf in Emacs state after edit.
|
181
|
831 (eval-after-load
|
0
|
832 "rmailedit"
|
181
|
833 '(defadvice rmail-cease-edit (after viper-rmail-advice activate)
|
0
|
834 "Switch to emacs state when done editing message."
|
181
|
835 (viper-change-state-to-emacs)))
|
0
|
836 ;; In case RMAIL was loaded before Viper.
|
181
|
837 (defadvice rmail-cease-edit (after viper-rmail-advice activate)
|
0
|
838 "Switch to emacs state when done editing message."
|
181
|
839 (viper-change-state-to-emacs))
|
185
|
840
|
|
841 ;; ISO accents
|
|
842 ;; Need to do it after loading iso-acc, or else this loading will wipe out
|
|
843 ;; the advice.
|
|
844 (eval-after-load
|
|
845 "iso-acc"
|
|
846 (defadvice iso-accents-mode (around viper-iso-accents-advice activate)
|
|
847 "Set viper-automatic-iso-accents to iso-accents-mode."
|
|
848 (let ((arg (ad-get-arg 0)))
|
|
849 ad-do-it
|
|
850 (setq viper-automatic-iso-accents
|
|
851 (if (eq viper-current-state 'vi-state)
|
|
852 (if arg
|
|
853 ;; if iso-accents-mode was called with positive arg, turn
|
|
854 ;; accents on
|
|
855 (> (prefix-numeric-value arg) 0)
|
|
856 ;; else: toggle viper-automatic-iso-accents
|
|
857 (not viper-automatic-iso-accents))
|
|
858 ;; other states: accept what iso-accents-mode has done
|
|
859 iso-accents-mode))
|
|
860 ;; turn off ISO accents in vi-state
|
|
861 (if (eq viper-current-state 'vi-state)
|
|
862 (viper-set-iso-accents-mode nil))
|
|
863 (if (memq viper-current-state '(vi-state insert-state replace-state))
|
|
864 (message "Viper ISO accents mode: %s"
|
|
865 (if viper-automatic-iso-accents "on" "off")))
|
|
866 )))
|
|
867
|
|
868 ;; International input methods
|
|
869 (if viper-emacs-p
|
|
870 (eval-after-load "mule-cmds"
|
|
871 (progn
|
|
872 (defadvice inactivate-input-method (after viper-mule-advice activate)
|
|
873 "Set viper-special-input-method to disable intl. input methods."
|
|
874 (viper-inactivate-input-method-action))
|
|
875 (defadvice activate-input-method (after viper-mule-advice activate)
|
|
876 "Set viper-special-input-method to enable intl. input methods."
|
|
877 (viper-activate-input-method-action))
|
|
878 ))
|
|
879 ;; XEmacs Although these hooks exist in Emacs, they don't seem to be always
|
|
880 ;; called on input-method activation/deactivation, so we the above advise
|
|
881 ;; functions instead.
|
|
882 (eval-after-load "mule-cmds"
|
|
883 (progn
|
|
884 (add-hook 'input-method-activate-hook
|
|
885 'viper-activate-input-method-action t)
|
|
886 (add-hook 'input-method-inactivate-hook
|
|
887 'viper-inactivate-input-method-action t)))
|
|
888 )
|
|
889 (eval-after-load "mule-cmds"
|
|
890 (defadvice toggle-input-method (around viper-mule-advice activate)
|
|
891 "Adjust input-method toggling in vi-state."
|
|
892 (if (and viper-special-input-method (eq viper-current-state 'vi-state))
|
|
893 (viper-inactivate-input-method)
|
|
894 ad-do-it)))
|
|
895
|
181
|
896 ) ; viper-set-hooks
|
163
|
897
|
|
898
|
|
899 ;; these are primarily advices and Vi-ish variable settings
|
181
|
900 (defun viper-non-hook-settings ()
|
163
|
901
|
181
|
902 ;; This var is not local in Emacs, so we make it local. It must be local
|
|
903 ;; because although the stack of minor modes can be the same for all buffers,
|
|
904 ;; the associated *keymaps* can be different. In Viper,
|
|
905 ;; viper-vi-local-user-map, viper-insert-local-user-map, and others can have
|
|
906 ;; different keymaps for different buffers. Also, the keymaps associated
|
|
907 ;; with viper-vi/insert-state-modifier-minor-mode can be different.
|
163
|
908 (make-variable-buffer-local 'minor-mode-map-alist)
|
|
909
|
|
910 ;; Viper changes the default mode-line-buffer-identification
|
|
911 (setq-default mode-line-buffer-identification '(" %b"))
|
|
912
|
|
913 ;; setup emacs-supported vi-style feel
|
|
914 (setq next-line-add-newlines nil
|
|
915 require-final-newline t)
|
|
916
|
|
917 (make-variable-buffer-local 'require-final-newline)
|
|
918
|
|
919 ;; don't bark when mark is inactive
|
181
|
920 (if viper-emacs-p
|
175
|
921 (setq mark-even-if-inactive t))
|
163
|
922
|
|
923 (setq scroll-step 1)
|
|
924
|
|
925 ;; Variable displaying the current Viper state in the mode line.
|
181
|
926 (viper-deflocalvar viper-mode-string viper-emacs-state-id)
|
|
927 (or (memq 'viper-mode-string global-mode-string)
|
163
|
928 (setq global-mode-string
|
181
|
929 (append '("" viper-mode-string) (cdr global-mode-string))))
|
0
|
930
|
181
|
931 (defadvice read-key-sequence (around viper-read-keyseq-ad activate)
|
163
|
932 "Harness to work for Viper. This advice is harmless---don't worry!"
|
|
933 (let (inhibit-quit event keyseq)
|
|
934 (setq keyseq ad-do-it)
|
181
|
935 (setq event (if viper-xemacs-p
|
163
|
936 (elt keyseq 0) ; XEmacs returns vector of events
|
|
937 (elt (listify-key-sequence keyseq) 0)))
|
181
|
938 (if (viper-ESC-event-p event)
|
163
|
939 (let (unread-command-events)
|
181
|
940 (viper-set-unread-command-events keyseq)
|
|
941 (if (viper-fast-keysequence-p)
|
|
942 (let ((viper-vi-global-user-minor-mode nil)
|
|
943 (viper-vi-local-user-minor-mode nil)
|
|
944 (viper-replace-minor-mode nil) ; actually unnecessary
|
|
945 (viper-insert-global-user-minor-mode nil)
|
|
946 (viper-insert-local-user-minor-mode nil))
|
163
|
947 (setq keyseq ad-do-it))
|
|
948 (setq keyseq ad-do-it))))
|
|
949 keyseq))
|
|
950
|
181
|
951 (defadvice describe-key (before viper-read-keyseq-ad protect activate)
|
163
|
952 "Force to read key via `read-key-sequence'."
|
181
|
953 (interactive (list (viper-events-to-keys
|
163
|
954 (read-key-sequence "Describe key: ")))))
|
|
955
|
181
|
956 (defadvice describe-key-briefly
|
|
957 (before viper-read-keyseq-ad protect activate)
|
163
|
958 "Force to read key via `read-key-sequence'."
|
181
|
959 (interactive (list (viper-events-to-keys
|
163
|
960 (read-key-sequence "Describe key briefly: ")))))
|
|
961
|
|
962
|
185
|
963 ;; This is now done in viper-minibuffer-exit-hook
|
|
964 ;;;; Advice for use in find-file and read-file-name commands.
|
|
965 ;;(defadvice exit-minibuffer (before viper-exit-minibuffer-advice activate)
|
|
966 ;; "Run `viper-minibuffer-exit-hook' just before exiting the minibuffer."
|
|
967 ;; (run-hooks 'viper-minibuffer-exit-hook))
|
163
|
968
|
181
|
969 (defadvice find-file (before viper-add-suffix-advice activate)
|
163
|
970 "Use `read-file-name' for reading arguments."
|
|
971 (interactive (cons (read-file-name "Find file: " nil default-directory)
|
|
972 ;; if Mule and prefix argument, ask for coding system
|
181
|
973 (cond ((and viper-emacs-p
|
175
|
974 (boundp 'MULE)) ; Emacs 20 with MULE
|
|
975 nil)
|
181
|
976 ((and viper-xemacs-p
|
175
|
977 (featurep 'mule)) ; XEmacs 20 with MULE
|
|
978 (list
|
|
979 (and current-prefix-arg
|
|
980 (read-coding-system
|
|
981 "Coding-system: "))))
|
|
982 )
|
163
|
983 )))
|
|
984
|
181
|
985 (defadvice find-file-other-window (before viper-add-suffix-advice activate)
|
163
|
986 "Use `read-file-name' for reading arguments."
|
|
987 (interactive (cons (read-file-name "Find file in other window: "
|
|
988 nil default-directory)
|
|
989 ;; if Mule and prefix argument, ask for coding system
|
181
|
990 (cond ((and viper-emacs-p
|
175
|
991 (boundp 'MULE)) ; Emacs 20 with MULE
|
|
992 nil)
|
181
|
993 ((and viper-xemacs-p
|
175
|
994 (featurep 'mule)) ; XEmacs 20 with MULE
|
|
995 (list
|
|
996 (and current-prefix-arg
|
|
997 (read-coding-system
|
|
998 "Coding-system: "))))
|
|
999 )
|
163
|
1000 )))
|
|
1001
|
175
|
1002
|
181
|
1003 (defadvice find-file-other-frame (before viper-add-suffix-advice activate)
|
163
|
1004 "Use `read-file-name' for reading arguments."
|
|
1005 (interactive (cons (read-file-name "Find file in other frame: "
|
|
1006 nil default-directory)
|
|
1007 ;; if Mule and prefix argument, ask for coding system
|
181
|
1008 (cond ((and viper-emacs-p
|
175
|
1009 (boundp 'MULE)) ; Emacs 20 with MULE
|
|
1010 nil)
|
181
|
1011 ((and viper-xemacs-p
|
175
|
1012 (featurep 'mule)) ; XEmacs 20 with MULE
|
|
1013 (list
|
|
1014 (and current-prefix-arg
|
|
1015 (read-coding-system
|
|
1016 "Coding-system: "))))
|
|
1017 )
|
163
|
1018 )))
|
175
|
1019
|
163
|
1020
|
181
|
1021 (defadvice read-file-name (around viper-suffix-advice activate)
|
|
1022 "Tell `exit-minibuffer' to run `viper-file-add-suffix' as a hook."
|
185
|
1023 (let ((viper-minibuffer-exit-hook
|
|
1024 (append viper-minibuffer-exit-hook '(viper-file-add-suffix))))
|
163
|
1025 ad-do-it))
|
|
1026
|
181
|
1027 (defadvice start-kbd-macro (after viper-kbd-advice activate)
|
163
|
1028 "Remove Viper's intercepting bindings for C-x ).
|
|
1029 This may be needed if the previous `:map' command terminated abnormally."
|
181
|
1030 (define-key viper-vi-intercept-map "\C-x)" nil)
|
|
1031 (define-key viper-insert-intercept-map "\C-x)" nil)
|
|
1032 (define-key viper-emacs-intercept-map "\C-x)" nil))
|
|
1033
|
|
1034 ;; catch frame switching event
|
|
1035 (if (viper-window-display-p)
|
|
1036 (if viper-xemacs-p
|
|
1037 (add-hook 'mouse-leave-frame-hook
|
|
1038 'viper-remember-current-frame)
|
|
1039 (defadvice handle-switch-frame (before viper-frame-advice activate)
|
|
1040 "Remember the selected frame before the switch-frame event."
|
|
1041 (viper-remember-current-frame (selected-frame)))) )
|
|
1042
|
|
1043 ) ; end viper-non-hook-settings
|
155
|
1044
|
163
|
1045
|
181
|
1046 ;; Ask only if this-command/last-command are nil, i.e., when loading
|
|
1047 (cond ((and (eq viper-mode 'ask) (null this-command) (null last-command))
|
|
1048 (save-window-excursion
|
|
1049 (with-output-to-temp-buffer " *viper-info*"
|
|
1050 (princ "
|
163
|
1051 You have loaded Viper, and are about to Viperize your emacs!
|
|
1052
|
181
|
1053 Viper is a Package for Emacs Rebels and a venomous VI PERil,
|
163
|
1054
|
|
1055 It's time to decide: to Viperize or not to Viperize...
|
|
1056
|
|
1057 If you wish to Viperize AND make this your way of life, please put
|
|
1058
|
|
1059 (setq viper-mode t)
|
|
1060 (require 'viper)
|
|
1061
|
|
1062 in your .emacs file (preferably, close to the top).
|
|
1063 These two lines must come in the order given.
|
|
1064
|
181
|
1065 ** Viper users:
|
|
1066 **** The startup file name has been changed from .vip to .viper
|
|
1067 **** All vip-* style names have been converted to viper-* style."))
|
|
1068 (if (y-or-n-p "Viperize? ")
|
|
1069 (setq viper-mode t)
|
|
1070 (setq viper-mode nil))
|
|
1071 (message "")
|
|
1072 (kill-buffer " *viper-info*")))
|
|
1073
|
|
1074 ;; If viper-mode is t, then just continue. Viper will kick in.
|
|
1075 ((eq viper-mode t))
|
|
1076 ;; Otherwise, it was asking mode and Viper was not loaded through .emacs
|
|
1077 ;; In this case, it was either through M-x viper-mode or via something
|
|
1078 ;; else, like the custom widget. If Viper was loaded through
|
|
1079 ;; M-x viper-mode, then viper will kick in anyway.
|
|
1080 (t (setq viper-mode nil)))
|
|
1081
|
|
1082 (defun viper-load-custom-file ()
|
|
1083 (if (and (file-exists-p viper-custom-file-name)
|
|
1084 (not noninteractive))
|
|
1085 (load viper-custom-file-name)))
|
163
|
1086
|
|
1087
|
|
1088
|
|
1089
|
175
|
1090 ;; Get viper standard value of SYMBOL. If symbol is customized, get its
|
|
1091 ;; standard value. Otherwise, get the value saved in the alist STORAGE. If
|
|
1092 ;; STORAGE is nil, use viper-saved-user-settings.
|
|
1093 (defun viper-standard-value (symbol &optional storage)
|
|
1094 (or (eval (car (get symbol 'customized-value)))
|
|
1095 (eval (car (get symbol 'saved-value)))
|
|
1096 (nth 1 (assoc symbol (or storage viper-saved-user-settings)))))
|
|
1097
|
|
1098
|
|
1099
|
|
1100 ;; save non-viper vars that Viper might change
|
|
1101 (if (null viper-saved-non-viper-variables)
|
|
1102 (setq viper-saved-non-viper-variables
|
|
1103 (list
|
|
1104 (cons 'default-major-mode (list default-major-mode))
|
|
1105 (cons 'next-line-add-newlines (list next-line-add-newlines))
|
|
1106 (cons 'require-final-newline (list require-final-newline))
|
|
1107 (cons 'scroll-step (list scroll-step))
|
|
1108 (cons 'mode-line-buffer-identification
|
|
1109 (list (default-value 'mode-line-buffer-identification)))
|
|
1110 (cons 'global-mode-string (list global-mode-string))
|
181
|
1111 (if viper-emacs-p
|
175
|
1112 (cons 'mark-even-if-inactive (list mark-even-if-inactive)))
|
|
1113 )))
|
|
1114
|
163
|
1115
|
|
1116 ;; Set some useful macros, advices
|
175
|
1117 ;; These must be BEFORE ~/.viper is loaded,
|
|
1118 ;; so the user can unrecord them in ~/.viper.
|
163
|
1119 (if viper-mode
|
|
1120 (progn
|
|
1121 ;; set advices and some variables that give emacs Vi look.
|
181
|
1122 (viper-non-hook-settings)
|
163
|
1123
|
|
1124 ;; repeat the 2nd previous command without rotating the command history
|
181
|
1125 (viper-record-kbd-macro
|
|
1126 (vector viper-repeat-from-history-key '\1) 'vi-state
|
|
1127 [(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
|
1128 ;; repeat the 3d previous command without rotating the command history
|
181
|
1129 (viper-record-kbd-macro
|
|
1130 (vector viper-repeat-from-history-key '\2) 'vi-state
|
|
1131 [(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
|
1132
|
175
|
1133 ;; set macros for toggling case sensitivity and regexp search
|
181
|
1134 (viper-set-searchstyle-toggling-macros nil)
|
163
|
1135 ;; Make %%% toggle parsing comments for matching parentheses
|
181
|
1136 (viper-set-parsing-style-toggling-macro nil)
|
|
1137
|
|
1138 ;; ~/.viper is loaded if exists
|
|
1139 (viper-load-custom-file)
|
|
1140
|
|
1141 ;; should be after loading custom file to avoid the pesky msg that
|
|
1142 ;; mouse-search/insert keys are already bound
|
|
1143 (viper-bind-mouse-search-key)
|
|
1144 (viper-bind-mouse-insert-key)
|
163
|
1145 ))
|
80
|
1146
|
0
|
1147
|
|
1148
|
181
|
1149 ;; Applying Viper customization -- runs after (load .viper)
|
0
|
1150
|
175
|
1151 ;; Save user settings or Viper defaults for vars controled by
|
|
1152 ;; viper-expert-level
|
|
1153 (if (null viper-saved-user-settings)
|
|
1154 (setq viper-saved-user-settings
|
181
|
1155 (list (cons 'viper-want-ctl-h-help (list viper-want-ctl-h-help))
|
175
|
1156 (cons 'viper-always (list viper-always))
|
181
|
1157 (cons 'viper-no-multiple-ESC (list viper-no-multiple-ESC))
|
|
1158 (cons 'viper-ex-style-motion (list viper-ex-style-motion))
|
185
|
1159 (cons 'viper-ex-style-editing
|
|
1160 (list viper-ex-style-editing))
|
181
|
1161 (cons 'viper-want-emacs-keys-in-vi
|
|
1162 (list viper-want-emacs-keys-in-vi))
|
|
1163 (cons 'viper-electric-mode (list viper-electric-mode))
|
|
1164 (cons 'viper-want-emacs-keys-in-insert
|
|
1165 (list viper-want-emacs-keys-in-insert))
|
|
1166 (cons 'viper-re-search (list viper-re-search)))))
|
0
|
1167
|
|
1168
|
163
|
1169 (if viper-mode
|
|
1170 (progn
|
181
|
1171 (viper-set-minibuffer-style)
|
|
1172 (if viper-buffer-search-char
|
|
1173 (viper-buffer-search-enable))
|
185
|
1174 (viper-update-syntax-classes 'set-default)
|
163
|
1175 ))
|
0
|
1176
|
163
|
1177
|
0
|
1178 ;;; Familiarize Viper with some minor modes that have their own keymaps
|
163
|
1179 (if viper-mode
|
|
1180 (progn
|
181
|
1181 (viper-harness-minor-mode "compile")
|
|
1182 (viper-harness-minor-mode "outline")
|
|
1183 (viper-harness-minor-mode "allout")
|
|
1184 (viper-harness-minor-mode "xref")
|
|
1185 (viper-harness-minor-mode "lmenu")
|
|
1186 (viper-harness-minor-mode "vc")
|
|
1187 (viper-harness-minor-mode "ltx-math") ; LaTeX-math-mode in AUC-TeX, which
|
|
1188 (viper-harness-minor-mode "latex") ; sits in one of these two files
|
|
1189 (viper-harness-minor-mode "cyrillic")
|
|
1190 (viper-harness-minor-mode "russian")
|
|
1191 (viper-harness-minor-mode "view-less")
|
|
1192 (viper-harness-minor-mode "view")
|
163
|
1193 ))
|
0
|
1194
|
|
1195
|
|
1196 ;; Intercept maps could go in viper-keym.el
|
175
|
1197 ;; We keep them here in case someone redefines them in ~/.viper
|
0
|
1198
|
181
|
1199 (define-key viper-vi-intercept-map viper-ESC-key 'viper-intercept-ESC-key)
|
|
1200 (define-key viper-insert-intercept-map viper-ESC-key 'viper-intercept-ESC-key)
|
0
|
1201
|
181
|
1202 ;; This is taken care of by viper-insert-global-user-map.
|
|
1203 ;;(define-key viper-replace-map viper-ESC-key 'viper-intercept-ESC-key)
|
0
|
1204
|
78
|
1205
|
181
|
1206 ;; The default viper-toggle-key is \C-z; for the novice, it suspends or
|
0
|
1207 ;; iconifies Emacs
|
181
|
1208 (define-key viper-vi-intercept-map viper-toggle-key 'viper-toggle-key-action)
|
|
1209 (define-key
|
|
1210 viper-emacs-intercept-map viper-toggle-key 'viper-change-state-to-vi)
|
0
|
1211
|
|
1212
|
163
|
1213 (if (and viper-mode
|
|
1214 (or viper-always
|
175
|
1215 (and (< viper-expert-level 5) (> viper-expert-level 0))))
|
181
|
1216 (viper-set-hooks))
|
0
|
1217
|
|
1218 ;; Let all minor modes take effect after loading
|
|
1219 ;; this may not be enough, so we also set default minor-mode-alist.
|
|
1220 ;; Without setting the default, new buffers that come up in emacs mode have
|
181
|
1221 ;; minor-mode-map-alist = nil, unless we call viper-change-state-*
|
|
1222 (if (eq viper-current-state 'emacs-state)
|
0
|
1223 (progn
|
181
|
1224 (viper-change-state-to-emacs)
|
0
|
1225 (setq-default minor-mode-map-alist minor-mode-map-alist)
|
|
1226 ))
|
|
1227
|
|
1228
|
163
|
1229
|
181
|
1230 (run-hooks 'viper-load-hook) ; the last chance to change something
|
0
|
1231
|
163
|
1232 (provide 'viper)
|
0
|
1233
|
175
|
1234
|
|
1235 ;;; Local Variables:
|
181
|
1236 ;;; eval: (put 'viper-deflocalvar 'lisp-indent-hook 'defun)
|
175
|
1237 ;;; End:
|
|
1238
|
0
|
1239 ;;; viper.el ends here
|