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