diff options
-rw-r--r-- | lisp/ediff-hook.el | 5 | ||||
-rw-r--r-- | lisp/ediff-init.el | 189 | ||||
-rw-r--r-- | lisp/ediff-merg.el | 6 | ||||
-rw-r--r-- | lisp/ediff-ptch.el | 109 | ||||
-rw-r--r-- | lisp/ediff-util.el | 9 | ||||
-rw-r--r-- | lisp/ediff-wind.el | 2 | ||||
-rw-r--r-- | lisp/ediff.el | 42 | ||||
-rw-r--r-- | lisp/emulation/viper-cmd.el | 195 | ||||
-rw-r--r-- | lisp/emulation/viper-ex.el | 70 | ||||
-rw-r--r-- | lisp/emulation/viper-init.el | 347 | ||||
-rw-r--r-- | lisp/emulation/viper-keym.el | 35 | ||||
-rw-r--r-- | lisp/emulation/viper-macs.el | 21 | ||||
-rw-r--r-- | lisp/emulation/viper-mous.el | 31 | ||||
-rw-r--r-- | lisp/emulation/viper-util.el | 37 | ||||
-rw-r--r-- | lisp/emulation/viper.el | 377 |
15 files changed, 981 insertions, 494 deletions
diff --git a/lisp/ediff-hook.el b/lisp/ediff-hook.el index 4106ef17c98..eb8f6e8c453 100644 --- a/lisp/ediff-hook.el +++ b/lisp/ediff-hook.el @@ -243,6 +243,7 @@ (autoload 'ediff-buffers3 "ediff" "Compare three bufers" t) (autoload 'ebuffers3 "ediff" "Compare three bufers" t) + (autoload 'erevision "ediff" "Compare versions of a file" t) (autoload 'ediff-revision "ediff" "Compare versions of a file" t) ;; compare regions and windows @@ -317,6 +318,10 @@ "ediff-mult" "Display the registry of active Ediff sessions." t) + (autoload 'eregistry + "ediff-mult" + "Display the registry of active Ediff sessions." + t) (autoload 'ediff-documentation "ediff" "Display Ediff's manual." diff --git a/lisp/ediff-init.el b/lisp/ediff-init.el index 2199146dcc6..d825cae43f0 100644 --- a/lisp/ediff-init.el +++ b/lisp/ediff-init.el @@ -328,53 +328,79 @@ that Ediff doesn't know about.") ;; Hook variables -(defvar ediff-before-setup-windows-hook nil +(defcustom ediff-before-setup-windows-hook nil "*Hooks to run before Ediff sets its window configuration. This can be used to save the previous window config, which can be restored -on ediff-quit or ediff-suspend.") -(defvar ediff-after-setup-windows-hook nil +on ediff-quit or ediff-suspend." + :type 'hook + :group 'ediff) +(defcustom ediff-after-setup-windows-hook nil "*Hooks to run after Ediff sets its window configuration. -This can be used to set up control window or icon in a desired place.") -(defvar ediff-before-setup-control-frame-hook nil +This can be used to set up control window or icon in a desired place." + :type 'hook + :group 'ediff) +(defcustom ediff-before-setup-control-frame-hook nil "*Hooks run before setting up the frame to display Ediff Control Panel. Can be used to change control frame parameters to position it where it -is desirable.") -(defvar ediff-after-setup-control-frame-hook nil +is desirable." + :type 'hook + :group 'ediff) +(defcustom ediff-after-setup-control-frame-hook nil "*Hooks run after setting up the frame to display Ediff Control Panel. -Can be used to move the frame where it is desired.") -(defvar ediff-startup-hook nil - "*Hooks to run in the control buffer after Ediff has been set up.") -(defvar ediff-select-hook nil - "*Hooks to run after a difference has been selected.") -(defvar ediff-unselect-hook nil - "*Hooks to run after a difference has been unselected.") -(defvar ediff-prepare-buffer-hook nil - "*Hooks called after buffers A, B, and C are set up.") -(defvar ediff-load-hook nil - "*Hook run after Ediff is loaded. Can be used to change defaults.") +Can be used to move the frame where it is desired." + :type 'hook + :group 'ediff) +(defcustom ediff-startup-hook nil + "*Hooks to run in the control buffer after Ediff has been set up." + :type 'hook + :group 'ediff) +(defcustom ediff-select-hook nil + "*Hooks to run after a difference has been selected." + :type 'hook + :group 'ediff) +(defcustom ediff-unselect-hook nil + "*Hooks to run after a difference has been unselected." + :type 'hook + :group 'ediff) +(defcustom ediff-prepare-buffer-hook nil + "*Hooks called after buffers A, B, and C are set up." + :type 'hook + :group 'ediff) +(defcustom ediff-load-hook nil + "*Hook run after Ediff is loaded. Can be used to change defaults." + :type 'hook + :group 'ediff) -(defvar ediff-mode-hook nil +(defcustom ediff-mode-hook nil "*Hook run just after ediff-mode is set up in the control buffer. This is done before any windows or frames are created. One can use it to -set local variables that determine how the display looks like.") -(defvar ediff-keymap-setup-hook nil - "*Hook run just after the default bindings in Ediff keymap are set up.") +set local variables that determine how the display looks like." + :type 'hook + :group 'ediff) +(defcustom ediff-keymap-setup-hook nil + "*Hook run just after the default bindings in Ediff keymap are set up." + :type 'hook + :group 'ediff) -(defvar ediff-display-help-hook nil - "*Hooks run after preparing the help message.") - -(defvar ediff-suspend-hook (list 'ediff-default-suspend-function) - "*Hooks to run in the Ediff control buffer when Ediff is suspended.") -(defvar ediff-quit-hook (list 'ediff-cleanup-mess) - "*Hooks to run in the Ediff control buffer after finishing Ediff.") -(defvar ediff-cleanup-hook nil +(defcustom ediff-display-help-hook nil + "*Hooks run after preparing the help message." + :type 'hook + :group 'ediff) + +(defcustom ediff-suspend-hook (list 'ediff-default-suspend-function) + "*Hooks to run in the Ediff control buffer when Ediff is suspended." + :type 'hook + :group 'ediff) +(defcustom ediff-quit-hook (list 'ediff-cleanup-mess) + "*Hooks to run in the Ediff control buffer after finishing Ediff." + :type 'hook + :group 'ediff) +(defcustom ediff-cleanup-hook nil "*Hooks to run on exiting Ediff but before killing the control buffer. This is a place to do various cleanups, such as deleting the variant buffers. -Ediff provides a function, `ediff-janitor', as one such possible hook.") -(defvar ediff-quit-merge-hook 'ediff-maybe-save-and-delete-merge - "*Hooks to run before quitting a merge job. -The most common use is to save and delete the merge buffer.") - +Ediff provides a function, `ediff-janitor', as one such possible hook." + :type 'hook + :group 'ediff) ;; Error messages (defconst ediff-KILLED-VITAL-BUFFER @@ -430,29 +456,39 @@ See the documentation string of `ediff-focus-on-regexp-matches' for details.") (ediff-defvar-local ediff-hide-regexp-connective 'and "") -;; Copying difference regions between buffers. -(ediff-defvar-local ediff-killed-diffs-alist nil - "A list of killed diffs. -A diff is saved here if it is replaced by a diff -from another buffer. This alist has the form: -\((num (buff-object . diff) (buff-object . diff) (buff-object . diff)) ...), -where some buffer-objects may be missing.") +;;; Copying difference regions between buffers. + +;; A list of killed diffs. +;; A diff is saved here if it is replaced by a diff +;; from another buffer. This alist has the form: +;; \((num (buff-object . diff) (buff-object . diff) (buff-object . diff)) ...), +;; where some buffer-objects may be missing. +(ediff-defvar-local ediff-killed-diffs-alist nil "") ;; Highlighting -;;(defvar ediff-before-flag-bol (if ediff-emacs-p "->>\n" (make-glyph "->>\n")) -(defvar ediff-before-flag-bol (if ediff-xemacs-p (make-glyph "->>") "->>") - "*Flag placed above the highlighted block of differences. -Must end with newline.") -;;(defvar ediff-after-flag-eol (if ediff-emacs-p "<<-\n" (make-glyph "<<-")) -(defvar ediff-after-flag-eol (if ediff-xemacs-p (make-glyph "<<-") "<<-") - "*Flag placed below the highlighted block of differences. -Must end with newline.") - -(defvar ediff-before-flag-mol (if ediff-xemacs-p (make-glyph "->>") "->>") - "*Like ediff-before-flag, used when a difference starts in mid-line.") -(defvar ediff-after-flag-mol (if ediff-xemacs-p (make-glyph "<<-") "<<-") - "*Like ediff-after-flag, used when a difference starts in mid-line.") +(defcustom ediff-before-flag-bol (if ediff-xemacs-p (make-glyph "->>") "->>") + "*Flag placed before a highlighted block of differences, if block starts at beginning of a line." + :type 'string + :tag "Region before-flag at beginning of line" + :group 'ediff) + +(defcustom ediff-after-flag-eol (if ediff-xemacs-p (make-glyph "<<-") "<<-") + "*Flag placed after a highlighted block of differences, if block ends at end of a line." + :type 'string + :tag "Region after-flag at end of line" + :group 'ediff) + +(defcustom ediff-before-flag-mol (if ediff-xemacs-p (make-glyph "->>") "->>") + "*Flag placed before a highlighted block of differences, if block starts in mid-line." + :type 'string + :tag "Region before-flag in the middle of line" + :group 'ediff) +(defcustom ediff-after-flag-mol (if ediff-xemacs-p (make-glyph "<<-") "<<-") + "*Flag placed after a highlighted block of differences, if block ends in mid-line." + :type 'string + :tag "Region after-flag in the middle of line" + :group 'ediff) (ediff-defvar-local ediff-use-faces t @@ -490,11 +526,13 @@ Use `setq-default' if setting it in .emacs") (ediff-defvar-local ediff-quit-widened t "*Non-nil means: when finished, Ediff widens buffers A/B. Actually, Ediff restores the scope of visibility that existed at startup.") -(defvar ediff-keep-variants t - "*Nil means that non-modified variant buffers should be removed after some -interrogation. + +(defcustom ediff-keep-variants t + "*Nil means that non-modified variant buffers should be removed at the end of the session after some interrogation. Supplying a prefix argument to the quit command `q' temporarily reverses the -meaning of this variable.") +meaning of this variable." + :type 'boolean + :group 'ediff) (ediff-defvar-local ediff-highlight-all-diffs t "If nil, only the selected differences are highlighted. @@ -522,7 +560,7 @@ ediff-toggle-hilit. Use `setq-default' to set it.") (ediff-defvar-local ediff-buffer-values-orig-C nil "") ;; The original values of ediff-protected-variables for buffer Ancestor (ediff-defvar-local ediff-buffer-values-orig-Ancestor nil "") -;; Buffer-local variables to be saved then restored during Ediff sessions + ;; Buffer-local variables to be saved then restored during Ediff sessions (defconst ediff-protected-variables '( ;;buffer-read-only @@ -589,12 +627,14 @@ ediff-toggle-hilit. Use `setq-default' to set it.") ;; Priority of non-selected overlays. (defvar ediff-shadow-overlay-priority 100 "") -(defvar ediff-version-control-package 'vc +(defcustom ediff-version-control-package 'vc "Version control package used. Currently, Ediff supports vc.el, rcs.el, pcl-cvs.el, and generic-sc.el. The standard Emacs interface to RCS, CVS, SCCS, etc., is vc.el. However, some people find the other two packages more convenient. Set this variable to the -appropriate symbol: `rcs', `pcl-cvs', or `generic-sc' if you so desire.") +appropriate symbol: `rcs', `pcl-cvs', or `generic-sc' if you so desire." + :type 'symbol + :group 'ediff) (if ediff-xemacs-p @@ -1106,6 +1146,12 @@ If nil, Ediff tries to deduce the function from the binding of C-x C-q. Normally, this is the `toggle-read-only' function, but, if version control is used, it could be `vc-toggle-read-only' or `rcs-toggle-read-only'.") +(defcustom ediff-make-buffers-readonly-at-startup nil + "*Make all variant buffers read-only when Ediff starts up. +This property can be toggled interactively." + :type 'boolean + :group 'ediff) + ;;; Misc @@ -1121,9 +1167,11 @@ as `ediff-merge-directory' or `ediff-merge-directory-revisions'.") ;; file where the result of the merge is to be saved. used internally (ediff-defvar-local ediff-merge-store-file nil "") -(defvar ediff-no-emacs-help-in-control-buffer nil +(defcustom ediff-no-emacs-help-in-control-buffer nil "*Non-nil means C-h should not invoke Emacs help in control buffer. -Instead, C-h jumps to previous difference.") +Instead, C-h would jump to previous difference." + :type 'boolean + :group 'ediff) (defvar ediff-temp-file-prefix (let ((env (or (getenv "TMPDIR") @@ -1155,12 +1203,13 @@ More precisely, a regexp to match any one such character.") (defvar ediff-H-glyph (if ediff-xemacs-p (make-glyph "H"))) -(ediff-defvar-local ediff-temp-file-A nil - "Temporary file used for refining difference regions in buffer A.") -(ediff-defvar-local ediff-temp-file-B nil - "Temporary file used for refining difference regions in buffer B.") -(ediff-defvar-local ediff-temp-file-C nil - "Temporary file used for refining difference regions in buffer C.") +;; Temporary file used for refining difference regions in buffer A. +(ediff-defvar-local ediff-temp-file-A nil "") +;; Temporary file used for refining difference regions in buffer B. +(ediff-defvar-local ediff-temp-file-B nil "") +;; Temporary file used for refining difference regions in buffer C. +(ediff-defvar-local ediff-temp-file-C nil "") + ;;; In-line functions diff --git a/lisp/ediff-merg.el b/lisp/ediff-merg.el index 7d711cdaf1c..f2cdf4cbc22 100644 --- a/lisp/ediff-merg.el +++ b/lisp/ediff-merg.el @@ -49,6 +49,12 @@ (require 'ediff-init) +(defcustom ediff-quit-merge-hook 'ediff-maybe-save-and-delete-merge + "*Hooks to run before quitting a merge job. +The most common use is to save and delete the merge buffer." + :type 'hook + :group 'ediff-merge) + (defcustom ediff-default-variant 'combined "*The variant to be used as a default for buffer C in merging. diff --git a/lisp/ediff-ptch.el b/lisp/ediff-ptch.el index 67c29f98385..ca63ce1830b 100644 --- a/lisp/ediff-ptch.el +++ b/lisp/ediff-ptch.el @@ -50,28 +50,62 @@ (require 'ediff-init) +(defcustom ediff-patch-program "patch" + "*Name of the program that applies patches. +It is recommended to use GNU-compatible versions." + :type 'string + :group 'ediff-ptch) +(defcustom ediff-patch-options "-f" + "*Options to pass to ediff-patch-program. + +Note: the `-b' option should be specified in `ediff-backup-specs'. + +It is recommended to pass the `-f' option to the patch program, so it won't ask +questions. However, some implementations don't accept this option, in which +case the default value for this variable should be changed." + :type 'string + :group 'ediff-ptch) + (defvar ediff-last-dir-patch nil "Last directory used by an Ediff command for file to patch.") -(defvar ediff-backup-extension - (if (memq system-type '(vax-vms axp-vms emx ms-dos windows-nt windows-95)) - "_orig" ".orig") +;; the default backup extension +(defconst ediff-default-backup-extension + (if (memq system-type '(vax-vms axp-vms emx ms-dos)) + "_orig" ".orig")) + + +(defcustom ediff-backup-extension ediff-default-backup-extension "Backup extension used by the patch program. -See also `ediff-backup-specs'.") +See also `ediff-backup-specs'." + :type 'string + :group 'ediff-ptch) -(defcustom ediff-backup-specs (format "-b %s" ediff-backup-extension) +(defcustom ediff-backup-specs + (cond + ((zerop (call-process ediff-patch-program nil nil nil "-z." "-b")) + ;; GNU `patch' v. >= 2.2 + (format "-z%s -b" ediff-backup-extension)) + ((zerop (call-process ediff-patch-program nil nil nil "-b")) + ;; POSIX `patch' -- ediff-backup-extension must be ".orig" + (setq ediff-backup-extension ediff-default-backup-extension) + "-b") + (t + ;; traditional `patch' + (format "-b %s" ediff-backup-extension))) "*Backup directives to pass to the patch program. Ediff requires that the old version of the file \(before applying the patch\) -is saved in a file named `the-patch-file.extension'. Usually `extension' is +be saved in a file named `the-patch-file.extension'. Usually `extension' is `.orig', but this can be changed by the user and may depend on the system. Therefore, Ediff needs to know the backup extension used by the patch program. Some versions of the patch program let you specify `-b backup-extension'. -Other versions only permit `-b', which assumes some canned extension - \(usually `.orig'\). +Other versions only permit `-b', which assumes the extension `.orig' +\(in which case ediff-backup-extension MUST be also `.orig'\). The latest +versions of GNU patch require `-b -z backup-extension'. Note that both `ediff-backup-extension' and `ediff-backup-specs' -must be properly set. If your patch program takes the option `-b', +must be set properly. If your patch program takes the option `-b', but not `-b extension', the variable `ediff-backup-extension' must still be set so Ediff will know which extension to use." :type 'string @@ -89,26 +123,12 @@ still be set so Ediff will know which extension to use." "\\|" ; GNU unified format diff 2-liner "^--- \\([^ \t]+\\)[\t ]+.*\n\\+\\+\\+ \\([^ \t]+\\)" "\\)") - "*Regexp matching filename 2-liners at the start of each context diff." + "*Regexp matching filename 2-liners at the start of each context diff. +You probably don't want to change that, unless you are using an obscure patch +program." :type 'regexp :group 'ediff-ptch) -(defcustom ediff-patch-program "patch" - "*Name of the program that applies patches. -It is recommended to use GNU-compatible versions." - :type 'string - :group 'ediff-ptch) -(defcustom ediff-patch-options "-f" - "*Options to pass to ediff-patch-program. - -Note: the `-b' option should be specified in `ediff-backup-specs'. - -It is recommended to pass the `-f' option to the patch program, so it won't ask -questions. However, some implementations don't accept this option, in which -case the default value for this variable should be changed." - :type 'string - :group 'ediff-ptch) - ;; The buffer of the patch file. Local to control buffer. (ediff-defvar-local ediff-patchbufer nil "") @@ -476,7 +496,7 @@ Else, read patch file into a new buffer." (true-source-filename source-filename) (target-filename source-filename) target-buf buf-to-patch file-name-magic-p - patch-return-code ctl-buf backup-style aux-wind) + patch-return-code ctl-buf backup-style) (if (string-match "-V" ediff-patch-options) (error @@ -535,44 +555,33 @@ Else, read patch file into a new buffer." (concat true-source-filename ediff-backup-extension))) (progn (with-output-to-temp-buffer ediff-msg-buffer - (princ (format " -Patch has failed OR the backup version of the patched file was not created by -the patch program. + (princ (format + "Patch program has failed due to a bad patch file OR +because it couldn't create the backup for the file to be patched. -One reason may be that the values of the variables +The former could be caused by a corrupt patch file or because the %S +program doesn't understand the format of the patch file in use. +The second problem might be due to an incompatibility among these settings: + ediff-patch-program = %S ediff-patch-options = %S ediff-backup-extension = %S ediff-backup-specs = %S -are not appropriate for the program specified in the variable - - ediff-patch-program = %S - -Another reason could be that the %S program doesn't understand -the format of the patch file you used. - See Ediff on-line manual for more details on these variables. -\(Or use a GNU-compatible patch program and stay out of trouble.\) - -Type any key to continue... -" +In particular, check the documentation for `ediff-backup-specs'. " + ediff-patch-program + ediff-patch-program ediff-patch-options ediff-backup-extension ediff-backup-specs - ediff-patch-program - ediff-patch-program))) + ))) (beep 1) (if (setq aux-wind (get-buffer-window ediff-msg-buffer)) (progn (select-window aux-wind) (goto-char (point-max)))) - (read-char-exclusive) - (if aux-wind (bury-buffer)) ; ediff-msg-buffer - (if (setq aux-wind (get-buffer-window patch-diagnostics)) - (progn - (select-window aux-wind) - (bury-buffer))) + (switch-to-buffer-other-window patch-diagnostics) (error "Patch appears to have failed"))) ;; If black magic is involved, apply patch to a temp copy of the diff --git a/lisp/ediff-util.el b/lisp/ediff-util.el index 527a9e2972d..fbd5808726a 100644 --- a/lisp/ediff-util.el +++ b/lisp/ediff-util.el @@ -101,6 +101,7 @@ This mode is entered through one of the following commands: `ediff-patch-file' `ediff-patch-buffer' `epatch-buffer' + `erevision' `ediff-revision' Commands: @@ -404,7 +405,10 @@ to invocation.") (or (memq control-buffer ediff-this-buffer-ediff-sessions) (setq ediff-this-buffer-ediff-sessions (cons control-buffer ediff-this-buffer-ediff-sessions))) + (if ediff-make-buffers-readonly-at-startup + (setq buffer-read-only t)) ) + (ediff-eval-in-buffer ediff-buffer-B (ediff-nuke-selective-display) (run-hooks 'ediff-prepare-buffer-hook) @@ -414,7 +418,10 @@ to invocation.") (or (memq control-buffer ediff-this-buffer-ediff-sessions) (setq ediff-this-buffer-ediff-sessions (cons control-buffer ediff-this-buffer-ediff-sessions))) + (if ediff-make-buffers-readonly-at-startup + (setq buffer-read-only t)) ) + (if ediff-3way-job (ediff-eval-in-buffer ediff-buffer-C (ediff-nuke-selective-display) @@ -424,6 +431,8 @@ to invocation.") (setq ediff-this-buffer-ediff-sessions (cons control-buffer ediff-this-buffer-ediff-sessions))) + (if ediff-make-buffers-readonly-at-startup + (setq buffer-read-only t)) )) (if (ediff-buffer-live-p ediff-ancestor-buffer) diff --git a/lisp/ediff-wind.el b/lisp/ediff-wind.el index 6aff0d81278..ac942dc1eb1 100644 --- a/lisp/ediff-wind.el +++ b/lisp/ediff-wind.el @@ -177,7 +177,7 @@ responsibility." Expects three parameters: the control buffer, the desired width and height of the control frame. It returns an association list of the form \(\(top . <position>\) \(left . <position>\)\)" - :type 'boolean + :type 'function :group 'ediff-window) (defcustom ediff-control-frame-upward-shift (if ediff-xemacs-p 42 14) diff --git a/lisp/ediff.el b/lisp/ediff.el index 61b51da5702..677931f85f3 100644 --- a/lisp/ediff.el +++ b/lisp/ediff.el @@ -6,8 +6,8 @@ ;; Created: February 2, 1994 ;; Keywords: comparing, merging, patching, version control. -(defconst ediff-version "2.65" "The current version of Ediff") -(defconst ediff-date "May 1, 1997" "Date of last update") +(defconst ediff-version "2.66" "The current version of Ediff") +(defconst ediff-date "July 9, 1997" "Date of last update") ;; This file is part of GNU Emacs. @@ -109,6 +109,10 @@ (provide 'ediff) ;; Compiler pacifier +(defvar cvs-cookie-handle) +(defvar ediff-last-dir-patch) +(defvar ediff-patch-default-directory) + (and noninteractive (eval-when-compile (load-library "dired") @@ -136,26 +140,20 @@ (defcustom ediff-use-last-dir nil - "*If t, Ediff uses previous directory as default when reading file name." + "*If t, Ediff will use previous directory as default when reading file name." :type 'boolean :group 'ediff) -(defvar ediff-last-dir-A nil - "Last directory used by an Ediff command for file-A.") -(defvar ediff-last-dir-B nil - "Last directory used by an Ediff command for file-B.") -(defvar ediff-last-dir-C nil - "Last directory used by an Ediff command for file-C.") -(defvar ediff-last-dir-ancestor nil - "Last directory used by an Ediff command for the ancestor file.") -(defvar ediff-last-merge-autostore-dir - "Last directory used by an Ediff command as the output directory for merge.") - -;; Some defvars to reduce the number of compiler warnings -(defvar cvs-cookie-handle) -(defvar ediff-last-dir-patch) -(defvar ediff-patch-default-directory) -;; end of compiler pacifier +;; Last directory used by an Ediff command for file-A. +(defvar ediff-last-dir-A nil) +;; Last directory used by an Ediff command for file-B. +(defvar ediff-last-dir-B nil) +;; Last directory used by an Ediff command for file-C. +(defvar ediff-last-dir-C nil) +;; Last directory used by an Ediff command for the ancestor file. +(defvar ediff-last-dir-ancestor nil) +;; Last directory used by an Ediff command as the output directory for merge. +(defvar ediff-last-merge-autostore-dir) ;; Used as a startup hook to set `_orig' patch file read-only. @@ -878,7 +876,7 @@ lines. For small regions, use `ediff-regions-wordwise'." (ediff-regions-internal (get-buffer buffer-A) reg-A-beg reg-A-end (get-buffer buffer-B) reg-B-beg reg-B-end - startup-hooks 'ediff-regions-linewise nil))) ; no word mode + startup-hooks 'ediff-regions-linewise nil nil))) ; no word mode ;; compare region beg-A to end-A of buffer-A ;; to regions beg-B -- end-B in buffer-B. @@ -1235,6 +1233,10 @@ buffer. Use `vc.el' or `rcs.el' depending on `ediff-version-control-package'." (intern (format "ediff-%S-internal" ediff-version-control-package)) rev1 rev2 startup-hooks) )) + + +;;;###autoload +(defalias 'erevision 'ediff-revision) ;; Test if version control package is loaded and load if not diff --git a/lisp/emulation/viper-cmd.el b/lisp/emulation/viper-cmd.el index d8ff9bdaa67..a6a4eaeda34 100644 --- a/lisp/emulation/viper-cmd.el +++ b/lisp/emulation/viper-cmd.el @@ -13,7 +13,8 @@ (defvar vip-minibuffer-vi-face) (defvar vip-minibuffer-emacs-face) (defvar viper-always) -(defvar vip-mode-string ) +(defvar vip-mode-string) +(defvar vip-custom-file-name) (defvar iso-accents-mode) (defvar zmacs-region-stays) (defvar mark-even-if-inactive) @@ -77,14 +78,15 @@ (defconst vip-movement-commands '(?b ?B ?e ?E ?f ?F ?G ?h ?H ?j ?k ?l ?H ?M ?L ?n ?t ?T ?w ?W ?$ ?% ?^ ?( ?) ?- ?+ ?| ?{ ?} ?[ ?] ?' ?` - ?; ?, ?0 ?? ?/ + ?; ?, ?0 ?? ?/ ?\C-m ?\ ) "Movement commands") ;; define vip-movement-command-p (vip-test-com-defun vip-movement-command) -(defconst vip-digit-commands '(?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9) - "Digit commands") +;; Vi digit commands +(defconst vip-digit-commands '(?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9)) + ;; define vip-digit-command-p (vip-test-com-defun vip-digit-command) @@ -765,7 +767,7 @@ as a Meta key and any number of multiple escapes is allowed." (defun vip-toggle-key-action () "Action bound to `vip-toggle-key'." (interactive) - (if (and (< vip-expert-level 2) (equal vip-toggle-key "\C-z")) + (if (and (< viper-expert-level 2) (equal vip-toggle-key "\C-z")) (if (vip-window-display-p) (vip-iconify) (suspend-emacs)) @@ -1358,8 +1360,10 @@ If the prefix argument, ARG, is non-nil, it is used instead of `val'." (setq vip-last-insertion (nth 4 vip-d-com) vip-d-char (nth 4 vip-d-com))) (funcall m-com (cons val com)) - (if (and vip-keep-point-on-repeat (< save-point (point))) - (goto-char save-point)) ; go back to before repeat. + (cond ((and (< save-point (point)) vip-keep-point-on-repeat) + (goto-char save-point)) ; go back to before repeat. + ((and (< save-point (point)) vip-ex-style-editing-in-insert) + (or (bolp) (backward-char 1)))) (if (and (eolp) (not (bolp))) (backward-char 1)) )) @@ -2983,9 +2987,9 @@ controlled by the sign of prefix numeric value." (defun vip-toggle-parse-sexp-ignore-comments () (interactive) (setq vip-parse-sexp-ignore-comments (not vip-parse-sexp-ignore-comments)) - (prin1 (format "`%%' will %signore parentheses inside the comments" - (if vip-parse-sexp-ignore-comments "" "NOT "))) - ) + (princ (format + "From now on, `%%' will %signore parentheses inside comment fields" + (if vip-parse-sexp-ignore-comments "" "NOT ")))) ;; sentence ,paragraph and heading @@ -3180,9 +3184,9 @@ the Emacs binding of `/'." (setq msg "Search becomes vanilla-style"))) (t (setq msg "Search style remains unchanged"))) - (prin1 msg t))) + (princ msg t))) -(defun vip-set-vi-search-style-macros (unset) +(defun vip-set-search-style-toggling-macros (unset) "Set the macros for toggling the search style in Viper's vi-state. The macro that toggles case sensitivity is bound to `//', and the one that toggles regexp search is bound to `///'. @@ -3203,12 +3207,33 @@ With a prefix argument, this function unsets the macros. " 't) (if (interactive-p) (message - "// and /// now toggle case-sensitivity and regexp search."))) + "// and /// now toggle case-sensitivity and regexp search"))) (vip-unrecord-kbd-macro "//" 'vi-state) (sit-for 2) (vip-unrecord-kbd-macro "///" 'vi-state)))) -(defun vip-set-emacs-search-style-macros (unset &optional arg-majormode) + +(defun vip-set-parsing-style-toggling-macro (unset) + "Set `%%%' to be a macro that toggles whether comment fields should be parsed for matching parentheses. +This is used in conjunction with the `%' command. + +With a prefix argument, unsets the macro." + (interactive "P") + (or noninteractive + (if (not unset) + (progn + ;; Make %%% toggle parsing comments for matching parentheses + (vip-record-kbd-macro + "%%%" 'vi-state + [(meta x) v i p - t o g g l e - p a r s e - s e x p - i g n o r e - c o m m e n t s return] + 't) + (if (interactive-p) + (message + "%%%%%% now toggles whether comments should be parsed for matching parentheses"))) + (vip-unrecord-kbd-macro "%%%" 'vi-state)))) + + +(defun vip-set-emacs-state-search-style-macros (unset &optional arg-majormode) "Set the macros for toggling the search style in Viper's emacs-state. The macro that toggles case sensitivity is bound to `//', and the one that toggles regexp search is bound to `///'. @@ -3456,7 +3481,7 @@ Null string will repeat previous search." (error "Buffer not killed")))) -(defvar vip-smart-suffix-list +(defcustom vip-smart-suffix-list '("" "tex" "c" "cc" "C" "el" "java" "html" "htm" "pl" "P" "p") "*List of suffixes that Viper automatically tries to append to filenames ending with a `.'. This is useful when you the current directory contains files with the same @@ -3469,7 +3494,9 @@ Suffixes are tried in the order given and the first suffix for which a corresponding file exists is selected. If no file exists for any of the suffixes, the user is asked to confirm. -To turn this feature off, set this variable to nil.") +To turn this feature off, set this variable to nil." + :type '(set string) + :group 'viper) ;; Try to add suffix to files ending with a `.' ;; Useful when the user hits RET on a non-completed file name. @@ -3702,7 +3729,13 @@ cursor move past the beginning of line." (progn (forward-line 1) (delete-region (point) (1- (point))) - (fixup-whitespace))))))) + (fixup-whitespace) + ;; fixup-whitespace sometimes does not leave space + ;; between objects, so we insert it as in Vi + (or (looking-at " ") + (insert " ") + (backward-char 1)) + )))))) ;; Replace state @@ -4131,7 +4164,7 @@ One can use `` and '' to temporarily jump 1 step back." (pop-mark))) -(defun vip-set-expert-level (&optional dont-change-unless) +(defun viper-set-expert-level (&optional dont-change-unless) "Sets the expert level for a Viper user. Can be called interactively to change (temporarily or permanently) the current expert level. @@ -4145,11 +4178,11 @@ sensitive for VI-style look-and-feel." (interactive) - (if (not (natnump vip-expert-level)) (setq vip-expert-level 0)) + (if (not (natnump viper-expert-level)) (setq viper-expert-level 0)) (save-window-excursion (delete-other-windows) - ;; if 0 < vip-expert-level < vip-max-expert-level + ;; if 0 < viper-expert-level < viper-max-expert-level ;; & dont-change-unless = t -- use it; else ask (vip-ask-level dont-change-unless)) @@ -4158,7 +4191,7 @@ sensitive for VI-style look-and-feel." vip-ex-style-editing-in-insert t vip-want-ctl-h-help nil) - (cond ((eq vip-expert-level 1) ; novice or beginner + (cond ((eq viper-expert-level 1) ; novice or beginner (global-set-key ; in emacs-state vip-toggle-key (if (vip-window-display-p) 'vip-iconify 'suspend-emacs)) @@ -4170,68 +4203,60 @@ sensitive for VI-style look-and-feel." vip-want-emacs-keys-in-vi nil vip-want-emacs-keys-in-insert nil)) - ((and (> vip-expert-level 1) (< vip-expert-level 5)) + ((and (> viper-expert-level 1) (< viper-expert-level 5)) ;; intermediate to guru (setq vip-no-multiple-ESC (if (vip-window-display-p) t 'twice) vip-electric-mode t vip-want-emacs-keys-in-vi t - vip-want-emacs-keys-in-insert (> vip-expert-level 2)) + vip-want-emacs-keys-in-insert (> viper-expert-level 2)) - (if (eq vip-expert-level 4) ; respect user's ex-style motion + (if (eq viper-expert-level 4) ; respect user's ex-style motion ; and vip-no-multiple-ESC (progn - (setq-default vip-ex-style-editing-in-insert - (cdr (assoc 'vip-ex-style-editing-in-insert - vip-saved-user-settings)) - vip-ex-style-motion - (cdr (assoc 'vip-ex-style-motion - vip-saved-user-settings))) + (setq-default + vip-ex-style-editing-in-insert + (viper-standard-value 'vip-ex-style-editing-in-insert) + vip-ex-style-motion + (viper-standard-value 'vip-ex-style-motion)) (setq vip-ex-style-motion - (cdr (assoc 'vip-ex-style-motion vip-saved-user-settings)) + (viper-standard-value 'vip-ex-style-motion) vip-ex-style-editing-in-insert - (cdr (assoc 'vip-ex-style-editing-in-insert - vip-saved-user-settings)) + (viper-standard-value 'vip-ex-style-editing-in-insert) vip-re-search - (cdr (assoc 'vip-re-search vip-saved-user-settings)) + (viper-standard-value 'vip-re-search) vip-no-multiple-ESC - (cdr (assoc 'vip-no-multiple-ESC - vip-saved-user-settings)))))) - + (viper-standard-value 'vip-no-multiple-ESC))))) + ;; A wizard!! ;; Ideally, if 5 is selected, a buffer should pop up to let the ;; user toggle the values of variables. (t (setq-default vip-ex-style-editing-in-insert - (cdr (assoc 'vip-ex-style-editing-in-insert - vip-saved-user-settings)) + (viper-standard-value 'vip-ex-style-editing-in-insert) vip-ex-style-motion - (cdr (assoc 'vip-ex-style-motion - vip-saved-user-settings))) + (viper-standard-value 'vip-ex-style-motion)) (setq vip-want-ctl-h-help - (cdr (assoc 'vip-want-ctl-h-help vip-saved-user-settings)) + (viper-standard-value 'vip-want-ctl-h-help) viper-always - (cdr (assoc 'viper-always vip-saved-user-settings)) + (viper-standard-value 'viper-always) vip-no-multiple-ESC - (cdr (assoc 'vip-no-multiple-ESC vip-saved-user-settings)) + (viper-standard-value 'vip-no-multiple-ESC) vip-ex-style-motion - (cdr (assoc 'vip-ex-style-motion vip-saved-user-settings)) + (viper-standard-value 'vip-ex-style-motion) vip-ex-style-editing-in-insert - (cdr (assoc 'vip-ex-style-editing-in-insert - vip-saved-user-settings)) + (viper-standard-value 'vip-ex-style-editing-in-insert) vip-re-search - (cdr (assoc 'vip-re-search vip-saved-user-settings)) + (viper-standard-value 'vip-re-search) vip-electric-mode - (cdr (assoc 'vip-electric-mode - vip-saved-user-settings)) + (viper-standard-value 'vip-electric-mode) vip-want-emacs-keys-in-vi - (cdr (assoc 'vip-want-emacs-keys-in-vi - vip-saved-user-settings)) + (viper-standard-value 'vip-want-emacs-keys-in-vi) vip-want-emacs-keys-in-insert - (cdr (assoc 'vip-want-emacs-keys-in-insert - vip-saved-user-settings))))) + (viper-standard-value 'vip-want-emacs-keys-in-insert)))) + (vip-set-mode-vars-for vip-current-state) (if (or viper-always - (and (> vip-expert-level 0) (> 5 vip-expert-level))) + (and (> viper-expert-level 0) (> 5 viper-expert-level))) (vip-set-hooks))) ;; Ask user expert level. @@ -4241,48 +4266,8 @@ sensitive for VI-style look-and-feel." (save-window-excursion (switch-to-buffer ask-buffer) - (or (eq this-command 'vip-set-expert-level) - (and - (<= vip-expert-level vip-max-expert-level) - (>= vip-expert-level 1)) - (progn - (insert " - - *** Important Notice for VIP users*** - - This is VIPER - -@joke -Viper Is a Package for Emacs Rebels, -a VI Plan for Emacs Rescue, -and a venomous VI PERil. -@end joke - -Technically speaking, Viper is a new Vi emulator that replaces -the old VIP package. - -Viper emulates Vi much better than VIP. It also significantly -extends and improves upon Vi in many useful ways. - -Although many VIP settings in your ~/.vip are compatible with Viper, -you may have to change some of them. Please refer to the documentation, -which can be obtained by executing - -:help - -when Viper is in Vi state. - -If you will be so lucky as to find a bug, report it via the command - -:submitReport - -Type any key to continue... ") - - (read-char) - (erase-buffer))) - - (while (or (> vip-expert-level vip-max-expert-level) - (< vip-expert-level 1) + (while (or (> viper-expert-level viper-max-expert-level) + (< viper-expert-level 1) (null dont-change-unless)) (erase-buffer) (if repeated @@ -4295,7 +4280,7 @@ Type any key to continue... ") (insert " Please specify your level of familiarity with the venomous VI PERil (and the VI Plan for Emacs Rescue). -You can change it at any time by typing `M-x vip-set-expert-level RET' +You can change it at any time by typing `M-x viper-set-expert-level RET' 1 -- BEGINNER: Almost all Emacs features are suppressed. Feels almost like straight Vi. File name completion and @@ -4315,7 +4300,7 @@ You can change it at any time by typing `M-x vip-set-expert-level RET' Please, specify your level now: ") - (setq vip-expert-level (- (vip-read-char-exclusive) ?0)) + (setq viper-expert-level (- (vip-read-char-exclusive) ?0)) ) ; end while ;; tell the user if level was changed @@ -4323,12 +4308,12 @@ Please, specify your level now: ") (progn (insert (format "\n\n\n\n\n\t\tYou have selected user level %d" - vip-expert-level)) + viper-expert-level)) (if (y-or-n-p "Do you wish to make this change permanent? ") - ;; save the setting for vip-expert-level + ;; save the setting for viper-expert-level (vip-save-setting - 'vip-expert-level - (format "Saving user level %d ..." vip-expert-level) + 'viper-expert-level + (format "Saving user level %d ..." viper-expert-level) vip-custom-file-name)) )) (bury-buffer) ; remove ask-buffer from screen @@ -4368,7 +4353,7 @@ Please, specify your level now: ") (defun vip-save-kill-buffer () "Save then kill current buffer. " (interactive) - (if (< vip-expert-level 2) + (if (< viper-expert-level 2) (save-buffers-kill-emacs) (save-buffer) (kill-buffer (current-buffer)))) @@ -4442,7 +4427,7 @@ Please, specify your level now: ") 'vip-emacs-state-hook 'ex-cycle-other-window 'ex-cycle-through-non-files - 'vip-expert-level + 'viper-expert-level 'major-mode 'vip-device-type 'color-display-p diff --git a/lisp/emulation/viper-ex.el b/lisp/emulation/viper-ex.el index 8ef9eccec4a..4b29dc1465e 100644 --- a/lisp/emulation/viper-ex.el +++ b/lisp/emulation/viper-ex.el @@ -31,7 +31,7 @@ (defvar vip-ex-history) (defvar vip-related-files-and-buffers-ring) (defvar vip-local-search-start-marker) -(defvar vip-expert-level) +(defvar viper-expert-level) (defvar vip-custom-file-name) (defvar vip-case-fold-search) (defvar explicit-shell-file-name) @@ -52,6 +52,12 @@ (require 'viper-util) +(defgroup viper-ex nil + "Viper support for Ex commands" + :prefix "ex-" + :group 'viper) + + ;;; Variables @@ -112,10 +118,9 @@ ;; Value of ex count. (defvar ex-count nil) -;; Flag for global command. +;; Flag indicating that :global Ex command is being executed. (defvar ex-g-flag nil) - -;; If t, global command is executed on lines not matching ex-g-pat. +;; Flag indicating that :vglobal Ex command is being executed. (defvar ex-g-variant nil) ;; Save reg-exp used in substitute. @@ -128,8 +133,7 @@ ;; Pattern for global command. (defvar ex-g-pat nil) - -(defvar ex-unix-type-shell +(defcustom ex-unix-type-shell (let ((case-fold-search t)) (and (stringp shell-file-name) (string-match @@ -146,9 +150,11 @@ "bash$\\|bash.exe$" "\\)") shell-file-name))) - "Is the user using a unix-type shell?") + "Is the user using a unix-type shell under a non-OS?" + :type 'string + :group 'viper-ex) -(defvar ex-unix-type-shell-options +(defcustom ex-unix-type-shell-options (let ((case-fold-search t)) (if ex-unix-type-shell (cond ((string-match "\\(csh$\\|csh.exe$\\)" shell-file-name) @@ -157,7 +163,9 @@ "-noprofile") ; bash: ignore .profile ))) "Options to pass to the Unix-style shell. -Don't put `-c' here, as it is added automatically.") +Don't put `-c' here, as it is added automatically." + :type 'string + :group 'viper-ex) (defvar ex-nontrivial-find-file-function (cond (ex-unix-type-shell 'vip-ex-nontrivial-find-file-unix) @@ -190,13 +198,17 @@ Don't put `-c' here, as it is added automatically.") ;; multiple file names. Used for :edit and :next (defvar vip-keep-reading-filename nil) -(defconst ex-cycle-other-window t +(defcustom ex-cycle-other-window t "*If t, :n and :b cycles through files and buffers in other window. Then :N and :B cycles in the current window. If nil, this behavior is -reversed.") +reversed." + :type 'boolean + :group 'viper-ex) -(defconst ex-cycle-through-non-files nil - "*Cycle through *scratch* and other buffers that don't visit any file.") +(defcustom ex-cycle-through-non-files nil + "*Cycle through *scratch* and other buffers that don't visit any file." + :type 'boolean + :group 'viper-ex) ;; Last shell command executed with :! command. (defvar vip-ex-last-shell-com nil) @@ -427,7 +439,7 @@ reversed.") "*[ \t]*$")) (stay-regex (concat "\\(" "^[ \t]*$" - "\\|" "[?/].*[?/].*" + "\\|" "[?/].*" "\\|" "[ktgjmsz][ \t]*$" "\\|" "^[ \t]*ab.*" "\\|" "tr[ansfer \t]*" @@ -503,7 +515,6 @@ reversed.") ;; Read Ex commands -;; Ex commands themselves are implemented in viper-ex.el (defun vip-ex (&optional string) (interactive) (or string @@ -613,7 +624,15 @@ reversed.") (setq ex-token (if (= (mark t) (point)) "" (buffer-substring (1- (point)) (mark t)))) - (backward-char 1)) + (backward-char 1) + ;; if the user doesn't specify the final pattern delimiter, we're + ;; at newline now. In this case, insert the initial delimiter + ;; specified in variable c + (if (looking-at "\n") + (progn + (insert c) + (backward-char 1))) + ) (setq ex-token nil)) c))) @@ -1233,6 +1252,14 @@ reversed.") ;; Ex global command +;; This is executed in response to: +;; :global "pattern" ex-command +;; :vglobal "pattern" ex-command +;; :global executes ex-command on all lines matching <pattern> +;; :vglobal executes ex-command on all lines that don't match <pattern> +;; +;; With VARIANT nil, this functions executes :global +;; With VARIANT t, executes :vglobal (defun ex-global (variant) (let ((gcommand ex-token)) (if (or ex-g-flag ex-g-variant) @@ -1255,8 +1282,11 @@ reversed.") (if (null ex-addresses) (setq ex-addresses (list (point-max) (point-min))) (vip-default-ex-addresses)) - (let ((marks nil) (mark-count 0) - com-str (end (car ex-addresses)) (beg (car (cdr ex-addresses)))) + (let ((marks nil) + (mark-count 0) + (end (car ex-addresses)) + (beg (car (cdr ex-addresses))) + com-str) (if (> beg end) (error vip-FirstAddrExceedsSecond)) (save-excursion (vip-enlarge-region beg end) @@ -1492,7 +1522,7 @@ reversed.") (setq vip-ex-work-buf (get-buffer-create vip-ex-work-buf-name)) (set-buffer vip-ex-work-buf) (if (looking-at "!") (forward-char 1))) - (if (< vip-expert-level 3) + (if (< viper-expert-level 3) (save-buffers-kill-emacs) (kill-buffer (current-buffer)))) @@ -1984,7 +2014,7 @@ Please contact your system administrator. " (not writing-same-file) (set-buffer-modified-p t)) (if q-flag - (if (< vip-expert-level 2) + (if (< viper-expert-level 2) (save-buffers-kill-emacs) (kill-buffer (current-buffer)))) ))) diff --git a/lisp/emulation/viper-init.el b/lisp/emulation/viper-init.el index 91aa1e98b4b..842bd7b31dd 100644 --- a/lisp/emulation/viper-init.el +++ b/lisp/emulation/viper-init.el @@ -26,6 +26,8 @@ ;; compiler pacifier (defvar mark-even-if-inactive) (defvar viper-version) +(defvar viper-expert-level) +(defvar vip-expert-level) ;; end pacifier @@ -48,15 +50,24 @@ (defun vip-window-display-p () (and (vip-device-type) (not (memq (vip-device-type) '(tty stream pc))))) -(defvar vip-ms-style-os-p (memq system-type '(ms-dos windows-nt windows-95)) - "Tells if Emacs is running under an MS-style OS: ms-dos, windows-nt, W95.") -(defvar vip-vms-os-p (memq system-type '(vax-vms axp-vms)) - "Tells if Emacs is running under VMS.") - -(defvar vip-force-faces nil +(defcustom vip-ms-style-os-p (memq system-type '(ms-dos windows-nt windows-95)) + "Tells if Emacs is running under an MS-style OS: ms-dos, windows-nt, W95." + :type 'boolean + :tag "Is it Microsoft-made OS?" + :group 'viper) +(defcustom vip-vms-os-p (memq system-type '(vax-vms axp-vms)) + "Tells if Emacs is running under VMS." + :type 'boolean + :tag "Is it VMS?" + :group 'viper) + +(defcustom vip-force-faces nil "If t, Viper will think that it is running on a display that supports faces. -This is provided as a temporary relief for users of face-capable displays -that Viper doesn't know about.") +This is provided as a temporary relief for users of graphics-capable terminals +that Viper doesn't know about. +In all likelihood, you don't need to bother with this setting." + :type 'boolean + :group 'viper) (defun vip-has-face-support-p () (cond ((vip-window-display-p)) @@ -235,29 +246,28 @@ that deletes a file.") ;; Prevents recursive descend into startup messages. (defvar vip-first-time t) -(defvar vip-expert-level 0 +(defvar viper-expert-level (if (boundp 'vip-expert-level) vip-expert-level 0) "User's expert level. The minor mode vip-vi-diehard-minor-mode is in effect when -vip-expert-level is 1 or 2 or when vip-want-emacs-keys-in-vi is t. +viper-expert-level is 1 or 2 or when vip-want-emacs-keys-in-vi is t. The minor mode vip-insert-diehard-minor-mode is in effect when -vip-expert-level is 1 or 2 or if vip-want-emacs-keys-in-insert is t. -Use `M-x vip-set-expert-level' to change this.") +viper-expert-level is 1 or 2 or if vip-want-emacs-keys-in-insert is t. +Use `M-x viper-set-expert-level' to change this.") ;; Max expert level supported by Viper. This is NOT a user option. ;; It is here to make it hard for the user from resetting it. -(defconst vip-max-expert-level 5) +(defconst viper-max-expert-level 5) -;; Contains user settings for vars affected by vip-set-expert-level function. -;; Not a user option. -(defvar vip-saved-user-settings nil) - ;;; ISO characters -(vip-deflocalvar vip-automatic-iso-accents nil +(vip-deflocalvar vip-automatic-iso-accents nil "") +(defcustom vip-automatic-iso-accents nil "*If non-nil, ISO accents will be turned on in insert/replace emacs states and turned off in vi-state. For some users, this behavior may be too primitive. In this case, use -insert/emacs/vi state hooks.") +insert/emacs/vi state hooks." + :type 'boolean + :group 'viper) ;; VI-style Undo @@ -271,10 +281,13 @@ insert/emacs/vi state hooks.") ;; erased by vip-change-state-to-vi and vip-repeat. (defconst vip-buffer-undo-list-mark 'viper) -(defvar vip-keep-point-on-undo nil +(defcustom vip-keep-point-on-undo nil "*Non-nil means not to move point while undoing commands. This style is different from Emacs and Vi. Try it to see if -it better fits your working style.") +it better fits your working style." + :type 'boolean + :tag "Preserve Position of Point After Undo" + :group 'viper) ;; Replace mode and changing text @@ -291,41 +304,57 @@ it better fits your working style.") ;; Indicates that the current destructive command has started in replace mode. (vip-deflocalvar vip-began-as-replace nil "") -(defvar vip-allow-multiline-replace-regions t +(defcustom vip-allow-multiline-replace-regions t "If non-nil, Viper will allow multi-line replace regions. This is an extension to standard Vi. If nil, commands that attempt to replace text spanning multiple lines first -delete the text being replaced, as in standard Vi.") +delete the text being replaced, as in standard Vi." + :type 'boolean + :group 'viper) + +(defcustom vip-replace-overlay-cursor-color "Red" + "*Cursor color when Viper is in Replace state." + :type 'string + :group 'viper) +(defcustom vip-insert-state-cursor-color "Green" + "Cursor color when Viper is in insert state." + :type 'string + :group 'viper) -(defvar vip-replace-overlay-cursor-color "Red" - "*Cursor color to use in Replace state") -(defvar vip-insert-state-cursor-color nil - "Cursor color for Viper insert state.") -(put 'vip-insert-state-cursor-color 'permanent-local t) ;; place to save cursor colow when switching to insert mode (vip-deflocalvar vip-saved-cursor-color nil "") (vip-deflocalvar vip-replace-overlay nil "") (put 'vip-replace-overlay 'permanent-local t) -(defvar vip-replace-overlay-pixmap "gray3" - "Pixmap to use for search face on non-color displays.") -(defvar vip-search-face-pixmap "gray3" - "Pixmap to use for search face on non-color displays.") +(defcustom vip-replace-overlay-pixmap "gray3" + "Pixmap to use for search face on non-color displays." + :type 'string + :group 'viper) +(defcustom vip-search-face-pixmap "gray3" + "Pixmap to use for search face on non-color displays." + :type 'string + :group 'viper) -(defvar vip-replace-region-end-delimiter "$" +(defcustom vip-replace-region-end-delimiter "$" "A string marking the end of replacement regions. It is used only with TTYs or if `vip-use-replace-region-delimiters' -is non-nil.") -(defvar vip-replace-region-start-delimiter "" +is non-nil." + :type 'string + :group 'viper) +(defcustom vip-replace-region-start-delimiter "" "A string marking the beginning of replacement regions. It is used only with TTYs or if `vip-use-replace-region-delimiters' -is non-nil.") -(defvar vip-use-replace-region-delimiters (not (vip-has-face-support-p)) +is non-nil." + :type 'string + :group 'viper) +(defcustom vip-use-replace-region-delimiters (not (vip-has-face-support-p)) "*If non-nil, Viper will always use `vip-replace-region-end-delimiter' and `vip-replace-region-start-delimiter' to delimit replacement regions, even on -color displays. By default, the delimiters are used only on TTYs.") +color displays. By default, the delimiters are used only on TTYs." + :type 'boolean + :group 'viper) ;; XEmacs requires glyphs (if vip-xemacs-p @@ -358,8 +387,12 @@ color displays. By default, the delimiters are used only on TTYs.") (vip-deflocalvar vip-replace-chars-deleted 0 "") ;; Insertion ring and command ring -(defvar vip-insertion-ring-size 14 - "The size of the insertion ring.") +(defcustom vip-insertion-ring-size 14 + "The size of history of inserted text. +This is a list where Viper keeps the history of previously inserted pieces of +text." + :type 'integer + :group 'viper) ;; The insertion ring. (defvar vip-insertion-ring nil) ;; This is temp insertion ring. Used to do rotation for display purposes. @@ -367,14 +400,33 @@ color displays. By default, the delimiters are used only on TTYs.") (defvar vip-temp-insertion-ring nil) (defvar vip-last-inserted-string-from-insertion-ring "") -(defvar vip-command-ring-size 14 - "The size of the command ring.") +(defcustom vip-command-ring-size 14 + "The size of history of Vi commands repeatable with dot." + :type 'integer + :group 'viper) ;; The command ring. (defvar vip-command-ring nil) ;; This is temp command ring. Used to do rotation for display purposes. ;; When rotation just started, it is initialized to vip-command-ring. (defvar vip-temp-command-ring nil) +;; Fast keyseq and ESC keyseq timeouts +(defcustom vip-fast-keyseq-timeout 200 + "*Key sequence separated by no more than this many milliseconds is viewed as a Vi-style macro, if such a macro is defined. +Setting this too high may slow down your typing. Setting this value too low +will make it hard to use Vi-stile timeout macros." + :type 'integer + :group 'viper) + +(defcustom vip-ESC-keyseq-timeout (if (vip-window-display-p) + 0 vip-fast-keyseq-timeout) + "*Key sequence beginning with ESC and separated by no more than this many milliseconds is considered to be generated by a keyboard function key. +Setting this too high may slow down switching from insert to vi state. Setting +this value too low will make it impossible to use function keys in insert mode +on a dumb terminal." + :type 'integer + :group 'viper) + ;; Modes and related variables ;; Current mode. One of: `emacs-state', `vi-state', `insert-state' @@ -392,22 +444,38 @@ color displays. By default, the delimiters are used only on TTYs.") ;; Whether to preserve the indent, used by C-d in insert mode. (vip-deflocalvar vip-preserve-indent nil) -(vip-deflocalvar vip-auto-indent nil - "*Autoindent if t.") -(vip-deflocalvar vip-electric-mode t - "*If t, enable electric behavior. -Currently only enables auto-indentation `according to mode'.") - -(defconst vip-shift-width 8 - "*The shiftwidth variable.") +(vip-deflocalvar vip-auto-indent nil "") +(defcustom vip-auto-indent nil + "*Enable autoindent, if t. +This is a buffer-local variable." + :type 'boolean + :group 'viper) + +(vip-deflocalvar vip-electric-mode t "") +(defcustom vip-electric-mode t + "*If t, electrify Viper. +Currently, this only electrifies auto-indentation, making it appropriate to the +mode of the buffer. +This means that auto-indentation will depart from standard Vi and will indent +appropriate to the mode of the buffer. This is especially useful for editing +programs and LaTeX documents." + :type 'boolean + :group 'viper) + +(defcustom vip-shift-width 8 + "*The shiftwidth variable." + :type 'integer + :group 'viper) ;; Variables for repeating destructive commands -(defconst vip-keep-point-on-repeat t +(defcustom vip-keep-point-on-repeat t "*If t, don't move point when repeating previous command. This is useful for doing repeated changes with the '.' key. The user can change this to nil, if she likes when the cursor moves -to a new place after repeating previous Vi command.") +to a new place after repeating previous Vi command." + :type 'boolean + :group 'viper) ;; Remember insert point as a marker. This is a local marker that must be ;; initialized to nil and moved with `vip-move-marker-locally'. @@ -482,55 +550,96 @@ to a new place after repeating previous Vi command.") ;; Last search string (defvar vip-s-string "") -(defvar vip-quote-string "> " - "String inserted at the beginning of quoted region.") +(defcustom vip-quote-string "> " + "String inserted at the beginning of quoted region." + :type 'string + :group 'viper) ;; If t, search is forward. (defvar vip-s-forward nil) -(defconst vip-case-fold-search nil - "*If not nil, search ignores cases.") +(defcustom vip-case-fold-search nil + "*If not nil, search ignores cases." + :type 'boolean + :group 'viper) -(defconst vip-re-search t - "*If not nil, search is reg-exp search, otherwise vanilla search.") +(defcustom vip-re-search t + "*If not nil, search is regexp search, otherwise vanilla search." + :type 'boolean + :tag "Regexp Search" + :group 'viper) -(defvar vip-search-scroll-threshold 2 +(defcustom vip-search-scroll-threshold 2 "*If search lands within this threshnold from the window top/bottom, the window will be scrolled up or down appropriately, to reveal context. If you want Viper search to behave as usual in Vi, set this variable to a -negative number.") - -(defconst vip-re-query-replace t - "*If t then do regexp replace, if nil then do string replace.") - -(defconst vip-re-replace t - "*If t, do regexp replace. nil means do string replace.") - -(defvar vip-parse-sexp-ignore-comments t - "*If t, `%' ignores the parentheses that occur inside comments.") - -(vip-deflocalvar vip-ex-style-motion t - "*Ex-style: the commands l,h do not cross lines, etc.") - -(vip-deflocalvar vip-ex-style-editing-in-insert t - "*The keys ^H, ^? don't jump lines in insert, ESC moves cursor back, etc. -Note: this doesn't preclude ^H and ^? from deleting characters by moving -past the insertion point. This is a feature, not a bug. ") - -(vip-deflocalvar vip-delete-backwards-in-replace nil +negative number." + :type 'boolean + :group 'viper) + +(defcustom vip-re-query-replace t + "*If t then do regexp replace, if nil then do string replace." + :type 'boolean + :tag "Regexp Query Replace" + :group 'viper) + +(defcustom vip-re-replace t + "*If t, do regexp replace. nil means do string replace." + :type 'boolean + :tag "Regexp Replace" + :group 'viper) + +(defcustom vip-parse-sexp-ignore-comments t + "*If t, `%' ignores the parentheses that occur inside comments." + :type 'boolean + :group 'viper) + +(vip-deflocalvar vip-ex-style-motion t "") +(defcustom vip-ex-style-motion t + "*If t, the commands l,h do not cross lines, etc (Ex-style). +If nil, these commands cross line boundaries." + :type 'boolean + :group 'viper) + +(vip-deflocalvar vip-ex-style-editing-in-insert t "") +(defcustom vip-ex-style-editing-in-insert t + "*If t, `Backspace' and `Delete' don't cross line boundaries in insert, etc. +Note: this doesn't preclude `Backspace' and `Delete' from deleting characters +by moving past the insertion point. This is a feature, not a bug." + :type 'boolean + :group 'viper) + +(vip-deflocalvar vip-ESC-moves-cursor-back vip-ex-style-editing-in-insert "") +(defcustom vip-ESC-moves-cursor-back nil + "*If t, ESC moves cursor back when changing from insert to vi state. +If nil, the cursor stays where it was." + :type 'boolean + :group 'viper) + +(vip-deflocalvar vip-delete-backwards-in-replace nil "") +(defcustom vip-delete-backwards-in-replace nil "*If t, DEL key will delete characters while moving the cursor backwards. -If nil, the cursor will move backwards without deleting anything.") - -(defconst vip-buffer-search-char nil - "*Key bound for buffer-searching.") - -(defconst vip-search-wrap-around-t t - "*If t, search wraps around.") +If nil, the cursor will move backwards without deleting anything." + :type 'boolean + :group 'viper) + +(defcustom vip-buffer-search-char nil + "*Key used for buffer-searching. Must be a character type, e.g., ?g." + :type '(choice (const nil) character) + :group 'viper) + +(defcustom vip-search-wrap-around-t t + "*If t, search wraps around." + :type 'boolean + :tag "Search Wraps Around" + :group 'viper) -(vip-deflocalvar vip-related-files-and-buffers-ring nil - "*Ring of file and buffer names that are considered to be related to the -current buffer. -These buffers can be cycled through via :R and :P commands.") +(vip-deflocalvar vip-related-files-and-buffers-ring nil "") +(defcustom vip-related-files-and-buffers-ring nil + "*List of file and buffer names that are considered to be related to the current buffer. +Related buffers can be cycled through via :R and :P commands." + :type 'boolean + :group 'viper) (put 'vip-related-files-and-buffers-ring 'permanent-local t) ;; Used to find out if we are done with searching the current buffer. @@ -599,16 +708,15 @@ These buffers can be cycled through via :R and :P commands.") (defvar vip-inhibit-startup-message nil "Whether Viper startup message should be inhibited.") -(defvar vip-custom-file-name (vip-convert-standard-file-name "~/.viper") - "Viper customisation file. -This variable must be set _before_ loading Viper.") - +(defcustom vip-spell-function 'ispell-region + "Spell function used by #s<move> command to spell." + :type 'function + :group 'viper) -(defvar vip-spell-function 'ispell-region - "Spell function used by #s<move> command to spell.") - -(defvar vip-tags-file-name "TAGS" - "The tags file used by Viper.") +(defcustom vip-tags-file-name "TAGS" + "The tags file used by Viper." + :type 'string + :group 'viper) ;; Indicates if we are in the middle of executing a command that takes another ;; command as an argument, e.g., cw, dw, etc. @@ -616,9 +724,11 @@ This variable must be set _before_ loading Viper.") ;; Minibuffer -(defvar vip-vi-style-in-minibuffer t +(defcustom vip-vi-style-in-minibuffer t "If t, use vi-style editing in minibuffer. -Should be set in `~/.vip' file.") +Should be set in `~/.vip' file." + :type 'boolean + :group 'viper) ;; overlay used in the minibuffer to indicate which state it is in (vip-deflocalvar vip-minibuffer-overlay nil) @@ -640,16 +750,31 @@ Should be set in `~/.vip' file.") "Mode line tag identifying the Replace mode of Viper.") -(defvar vip-vi-state-hook nil - "*Hooks run just before the switch to Vi mode is completed.") -(defvar vip-insert-state-hook nil - "*Hooks run just before the switch to Insert mode is completed.") -(defvar vip-replace-state-hook nil - "*Hooks run just before the switch to Replace mode is completed.") -(defvar vip-emacs-state-hook nil - "*Hooks run just before the switch to Emacs mode is completed.") +(defcustom vip-vi-state-hook nil + "*Hooks run just before the switch to Vi mode is completed." + :type 'hook + :group 'viper) +(defcustom vip-insert-state-hook nil + "*Hooks run just before the switch to Insert mode is completed." + :type 'hook + :group 'viper) +(defcustom vip-replace-state-hook nil + "*Hooks run just before the switch to Replace mode is completed." + :type 'hook + :group 'viper) +(defcustom vip-emacs-state-hook nil + "*Hooks run just before the switch to Emacs mode is completed." + :type 'hook + :group 'viper) -(defvar vip-load-hook nil - "Hooks run just after loading Viper.") +(defcustom vip-load-hook nil + "Hooks run just after loading Viper." + :type 'hook + :group 'viper) + +;;; Local Variables: +;;; eval: (put 'vip-deflocalvar 'lisp-indent-hook 'defun) +;;; End: + ;;; viper-ex.el ends here diff --git a/lisp/emulation/viper-keym.el b/lisp/emulation/viper-keym.el index 9c1f50158b9..c2dd794f851 100644 --- a/lisp/emulation/viper-keym.el +++ b/lisp/emulation/viper-keym.el @@ -27,7 +27,7 @@ (defvar viper-always) (defvar vip-current-state) (defvar vip-mode-string) -(defvar vip-expert-level) +(defvar viper-expert-level) (defvar vip-ex-style-editing-in-insert) (defvar vip-ex-style-motion) @@ -59,26 +59,34 @@ This setting cannot be changed interactively.") ;;; Emacs keys in other states. -(defvar vip-want-emacs-keys-in-insert t +(defcustom vip-want-emacs-keys-in-insert t "*Set to nil if you want complete Vi compatibility in insert mode. -Complete compatibility with Vi is not recommended for power use of Viper.") +Complete compatibility with Vi is not recommended for power use of Viper." + :type 'boolean + :group 'viper) -(defvar vip-want-emacs-keys-in-vi t +(defcustom vip-want-emacs-keys-in-vi t "*Set to nil if you want complete Vi compatibility in Vi mode. -Full Vi compatibility is not recommended for power use of Viper.") +Full Vi compatibility is not recommended for power use of Viper." + :type 'boolean + :group 'viper) -(defvar vip-no-multiple-ESC t +(defcustom vip-no-multiple-ESC t "*If true, multiple ESC in Vi mode will cause bell to ring. This is set to t on a windowing terminal and to 'twice on a dumb terminal (unless the user level is 1, 2, or 5). On a dumb terminal, this enables cursor keys and is generally more convenient, as terminals usually don't have a convenient Meta key. Setting vip-no-multiple-ESC to nil will allow as many multiple ESC, -as is allowed by the major mode in effect.") +as is allowed by the major mode in effect." + :type 'boolean + :group 'viper) -(defvar vip-want-ctl-h-help nil +(defcustom vip-want-ctl-h-help nil "*If t then C-h is bound to help-command in insert mode, if nil then it is -bound to delete-backward-char.") +bound to delete-backward-char." + :type 'boolean + :group 'viper) ;;; Keymaps @@ -114,7 +122,7 @@ This map is global, shared by all buffers.") (defvar vip-vi-diehard-map (make-sparse-keymap) "This keymap is in use when the user asks Viper to simulate Vi very closely. -This happens when vip-expert-level is 1 or 2. See vip-set-expert-level.") +This happens when viper-expert-level is 1 or 2. See viper-set-expert-level.") (vip-deflocalvar vip-insert-local-user-map (make-sparse-keymap) @@ -584,7 +592,7 @@ Arguments: (major-mode vip-state keymap)" (princ (format "vip-emacs-state-modifier-minor-mode: %S\n" vip-emacs-state-modifier-minor-mode)) - (princ (format "\nvip-expert-level %S\n" vip-expert-level)) + (princ (format "\nviper-expert-level %S\n" viper-expert-level)) (princ (format "vip-no-multiple-ESC %S\n" vip-no-multiple-ESC)) (princ (format "viper-always %S\n" viper-always)) (princ (format "vip-ex-style-motion %S\n" @@ -627,4 +635,9 @@ form ((key . function) (key . function) ... )." alist)) +;;; Local Variables: +;;; eval: (put 'vip-deflocalvar 'lisp-indent-hook 'defun) +;;; End: + + ;;; viper-keym.el ends here diff --git a/lisp/emulation/viper-macs.el b/lisp/emulation/viper-macs.el index 07e39038b47..7f98bfb0008 100644 --- a/lisp/emulation/viper-macs.el +++ b/lisp/emulation/viper-macs.el @@ -27,6 +27,7 @@ (defvar vip-ex-work-buf) (defvar vip-custom-file-name) (defvar vip-current-state) +(defvar vip-fast-keyseq-timeout) ;; loading happens only in non-interactive compilation ;; in order to spare non-viperized emacs from being viperized @@ -71,19 +72,17 @@ (defvar vip-last-kbd-macro nil "Vector of keys representing the name of last Viper keyboard macro.") -(defconst vip-fast-keyseq-timeout 200 - "*Key sequence separated by no more than this many milliseconds is viewed as a macro, if such a macro is defined. -This also controls ESC-keysequences generated by keyboard function keys.") +(defcustom vip-repeat-from-history-key 'f12 + "Prefix key for accessing previously typed Vi commands. - -(defvar vip-repeat-from-history-key 'f12 - "Prefix key for invocation of vip-repeat-from-history function, -which repeats previous destructive commands from the history of such -commands. -This function can then be invoked as <this-key> 1 or <this-key> 2. +The previous command is accessible, as usual, via `.'. The command before this +can be invoked as `<this key> 1', and the command before that, and the command +before that one is accessible as `<this key> 2'. The notation for these keys is borrowed from XEmacs. Basically, a key is a symbol, e.g., `a', `\\1', `f2', etc., or a list, e.g., -`(meta control f1)'.") +`(meta control f1)'." + :type 'key + :group 'viper) @@ -544,7 +543,7 @@ there." (vip-display-macro macro-name) state-name major-mode)) ((cdr (setq macro-pair (vip-kbd-global-pair macro-entry))) (message - "Global mapping of %S for %s is removed" + "Global mapping for %S in %s is removed" (vip-display-macro macro-name) state-name)) (t (error "%S is not mapped to a macro for %s in `%s'" (vip-display-macro macro-name) diff --git a/lisp/emulation/viper-mous.el b/lisp/emulation/viper-mous.el index 4ba05c1790c..7d9590d98df 100644 --- a/lisp/emulation/viper-mous.el +++ b/lisp/emulation/viper-mous.el @@ -47,6 +47,11 @@ (require 'viper-util) +(defgroup viper-mouse nil + "Support for Viper special mouse-bound commands" + :prefix "vip-" + :group 'viper) + ;;; Variables @@ -58,21 +63,25 @@ ;; Frame that was selected before the switch-frame event. (defconst vip-current-frame-saved (selected-frame)) -(defvar vip-surrounding-word-function 'vip-surrounding-word +(defcustom vip-surrounding-word-function 'vip-surrounding-word "*Function that determines what constitutes a word for clicking events. Takes two parameters: a COUNT, indicating how many words to return, and CLICK-COUNT, telling whether this is the first click, a double-click, -or a tripple-click.") +or a tripple-click." + :type 'boolean + :group 'viper-mouse) ;; time interval in millisecond within which successive clicks are ;; considered related -(defconst vip-multiclick-timeout (if (vip-window-display-p) - (if vip-xemacs-p - mouse-track-multi-click-time - double-click-time) - 500) - "*Time interval in millisecond within which successive clicks are -considered related.") +(defcustom vip-multiclick-timeout (if (vip-window-display-p) + (if vip-xemacs-p + mouse-track-multi-click-time + double-click-time) + 500) + "*Time interval in millisecond within which successive mouse clicks are +considered related." + :type 'integer + :group 'viper-mouse) ;; current event click count; XEmacs only (defvar vip-current-click-count 0) @@ -432,5 +441,9 @@ bindings in the Viper manual." vip-current-frame-saved (selected-frame))) +;;; Local Variables: +;;; eval: (put 'vip-deflocalvar 'lisp-indent-hook 'defun) +;;; End: + ;;; viper-mous.el ends here diff --git a/lisp/emulation/viper-util.el b/lisp/emulation/viper-util.el index efcb637fe25..404501f3c33 100644 --- a/lisp/emulation/viper-util.el +++ b/lisp/emulation/viper-util.el @@ -1065,11 +1065,22 @@ to write a custom function, similar to `vip-ex-nontrivial-find-file-unix'." (defun vip-key-to-emacs-key (key) (let (key-name char-p modifiers mod-char-list base-key base-key-name) (cond (vip-xemacs-p key) + ((symbolp key) (setq key-name (symbol-name key)) - (if (= (length key-name) 1) ; character event - (string-to-char key-name) - key)) + (cond ((= (length key-name) 1) ; character event + (string-to-char key-name)) + ;; Emacs doesn't recognize `return' and `escape' as events on + ;; dumb terminals, so we translate them into characters + ((and vip-emacs-p (not (vip-window-display-p)) + (string= key-name "return")) + ?\C-m) + ((and vip-emacs-p (not (vip-window-display-p)) + (string= key-name "escape")) + ?\e) + ;; pass symbol-event as is + (t key))) + ((listp key) (setq modifiers (subseq key 0 (1- (length key))) base-key (vip-seq-last-elt key) @@ -1129,8 +1140,13 @@ to write a custom function, similar to `vip-ex-nontrivial-find-file-unix'." "")) +;; Uses different timeouts for ESC-sequences and others (defsubst vip-fast-keysequence-p () - (not (vip-sit-for-short vip-fast-keyseq-timeout t))) + (not (vip-sit-for-short + (if (vip-ESC-event-p last-input-event) + vip-ESC-keyseq-timeout + vip-fast-keyseq-timeout) + t))) (defun vip-read-char-exclusive () (let (char @@ -1174,7 +1190,7 @@ the `Local variables' section of a file." ;;; Movement utilities -(defvar vip-syntax-preference 'strict-vi +(defcustom vip-syntax-preference 'strict-vi "*Syntax type characterizing Viper's alphanumeric symbols. `emacs' means only word constituents are considered to be alphanumeric. Word constituents are symbols specified as word constituents by the current @@ -1183,7 +1199,10 @@ syntax table. `reformed-vi' means Vi-ish behavior: word constituents and the symbol `_'. However, word constituents are determined according to Emacs syntax tables, which may be different from Vi in some major modes. -`strict-vi' means Viper words are exactly as in Vi.") +`strict-vi' means Viper words are exactly as in Vi." + :type '(radio (const strict-vi) (const reformed-vi) + (const extended) (const emacs)) + :group 'viper) (vip-deflocalvar vip-ALPHA-char-class "w" "String of syntax classes characterizing Viper's alphanumeric symbols. @@ -1311,7 +1330,11 @@ Must be called in order for changes to `vip-syntax-preference' to take effect." - (provide 'viper-util) + + +;;; Local Variables: +;;; eval: (put 'vip-deflocalvar 'lisp-indent-hook 'defun) +;;; End: ;;; viper-util.el ends here diff --git a/lisp/emulation/viper.el b/lisp/emulation/viper.el index 2736f50ca35..ec5b21407e5 100644 --- a/lisp/emulation/viper.el +++ b/lisp/emulation/viper.el @@ -8,7 +8,7 @@ ;; Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc. -(defconst viper-version "2.94 of June 12, 1997" +(defconst viper-version "2.95 of July 9, 1997" "The current version of Viper") ;; This file is part of GNU Emacs. @@ -150,24 +150,24 @@ ;; ;; The last vip-vi-basic-minor-mode contains most of the usual Vi bindings ;; in its edit mode. This mode provides access to all Emacs facilities. -;; Novice users, however, may want to set their vip-expert-level to 1 +;; Novice users, however, may want to set their viper-expert-level to 1 ;; in their .vip file. This will enable vip-vi-diehard-minor-mode. This ;; minor mode's bindings make Viper simulate the usual Vi very closely. ;; For instance, C-c will not have its standard Emacs binding ;; and so many of the goodies of Emacs are not available. ;; -;; A skilled user should set vip-expert-level to at least 3. This will +;; A skilled user should set viper-expert-level to at least 3. This will ;; enable `C-c' and many Emacs facilities will become available. ;; In this case, vip-vi-diehard-minor-mode is inactive. ;; ;; Viper gurus should have at least -;; (setq vip-expert-level 4) -;; in their ~/.vip files. This will unsuppress all Emacs keys that are not +;; (setq viper-expert-level 4) +;; in their ~/.viper files. This will unsuppress all Emacs keys that are not ;; essential for VI-style editing. ;; Pick-and-choose users may want to put -;; (setq vip-expert-level 5) -;; in ~/.vip. Viper will then leave it up to the user to set the variables -;; vip-want-* See vip-set-expert-level for details. +;; (setq viper-expert-level 5) +;; in ~/.viper. Viper will then leave it up to the user to set the variables +;; vip-want-* See viper-set-expert-level for details. ;; ;; The very first minor mode, vip-vi-intercept-minor-mode, is of no ;; concern for the user. It is needed to bind Viper's vital keys, such as @@ -302,6 +302,8 @@ ;; compiler pacifier (defvar mark-even-if-inactive) +(defvar viper-expert-level) +(defvar vip-expert-level) ;; loading happens only in non-interactive compilation ;; in order to spare non-viperized emacs from being viperized @@ -313,24 +315,49 @@ ))) ;; end pacifier +;; better be defined before Viper custom group. +(defvar vip-custom-file-name (vip-convert-standard-file-name "~/.viper") + "Viper customisation file. +If set by the user, this must be done _before_ Viper is loaded in `~/.emacs'.") + +(defgroup viper nil + "Vi emulation within Emacs. +NOTE: Viper customization should be saved in `vip-custom-file-name', which +defaults to `~/.viper'." + :prefix "vip-" + :group 'emulations) + (require 'viper-cmd) (defvar vip-always t "See `viper-always'. This variable is for compatibility with older Vipers.") -(defvar viper-always vip-always +(defcustom viper-always vip-always "Non-nil means, arrange for vi-state to be a default when appropriate. This is different from `viper-mode' variable in that `viper-mode' determines whether to use Viper in the first place, while `viper-always', if nil, lets -user decide when to invoke Viper in a major mode.") - -(defvar viper-mode (cond (noninteractive nil) - (t 'ask)) - "Viperize or not Viperize. +user decide when to invoke Viper in a major mode." + :type 'boolean + :tag "Always Invoke Viper" + :group 'viper) + +;; Non-viper variables that need to be saved in case the user decides to +;; de-viperize emacs. +(defvar viper-saved-non-viper-variables nil) +;; Contains user settings for vars affected by viper-set-expert-level function. +;; Not a user option. +(defvar viper-saved-user-settings nil) + +(defcustom viper-mode (cond (noninteractive nil) + (t 'ask)) + "To Viperize or not to Viperize. If t, viperize emacs. If nil -- don't. If `ask', ask the user. This variable is used primatily when Viper is being loaded. Must be set in `~/.emacs' before Viper is loaded. -DO NOT set this variable interactively.") +DO NOT set this variable interactively." + :type '(choice (const nil) (const t) (const ask)) + :tag "Set Viper Mode on Loading" + :group 'viper) ;; The following are provided for compatibility with older VIP's @@ -342,6 +369,7 @@ DO NOT set this variable interactively.") (defalias 'vip-change-mode-to-insert 'vip-change-state-to-insert) (defalias 'vip-change-mode-to-emacs 'vip-change-state-to-emacs) + ;;;###autoload @@ -367,11 +395,11 @@ DO NOT set this variable interactively.") (erase-buffer) (insert (substitute-command-keys - "Viper Is a Package for Emacs Rebels. -It is also a VI Plan for Emacs Rescue and a venomous VI PERil. + "Viper Is a Package for Emacs Rebels, +a VI Plan for Emacs Rescue, and a venomous VI PERil. -Technically speaking, Viper is a Vi emulation package for GNU Emacs 19 and -XEmacs 19. It supports virtually all of Vi and Ex functionality, extending +Incidentally, Viper emulates Vi under GNU Emacs 20 and XEmacs 20. +It supports all of what is good in Vi and Ex, while extending and improving upon much of it. 1. Viper supports Vi at several levels. Level 1 is the closest to Vi, @@ -383,26 +411,30 @@ and improving upon much of it. as in VI, to smooth transition to Viper for the beginners. However, to use Emacs productively, you are advised to reach user level 3 or higher. - If your user level is 2 or higher, ^X and ^C will invoke Emacs - functions,as usual in Emacs; ^Z will toggle vi/emacs modes, and - ^G will be the usual Emacs's keyboard-quit (something like ^C in VI). + At user level 2 or higher, ^X and ^C have Emacs, not Vi, bindings; + ^Z toggles Vi/Emacs states; ^G is Emacs' keyboard-quit (like ^C in Vi). 2. Vi exit functions (e.g., :wq, ZZ) work on INDIVIDUAL files -- they - do not cause Emacs to quit, except at user level 1 (a novice). + do not cause Emacs to quit, except at user level 1 (for a novice). 3. ^X^C EXITS EMACS. 4. Viper supports multiple undo: `u' will undo. Typing `.' will repeat undo. Another `u' changes direction. - 6. Emacs Meta functions are invoked by typing `C-\\' or `\\ ESC'. - On a window system, the best way is to use the Meta-key. + 6. Emacs Meta key is `C-\\' (in all modes) or `\\ ESC' (in Vi command mode). + On a window system, the best way is to use the Meta-key on your keyboard. 7. Try \\[keyboard-quit] and \\[abort-recursive-edit] repeatedly,if something funny happens. This would abort the current editing command. -You can get more information on Viper by: +For more information on Viper: - a. Typing `:help' in Vi state - b. Printing Viper manual, found in ./etc/viper.dvi - c. Printing ViperCard, the Quick Reference, found in ./etc/viperCard.dvi + a. Type `:help' in Vi command mode + b. Print Viper manual, found in ./etc/viper.dvi + c. Print the Quick Reference, found in ./etc/viperCard.dvi + +To submit a bug report or to contact the author, type :submitReport in Vi +command mode. To shoo Viper away and return to pure Emacs (horror!), type: + + M-x viper-go-away This startup message appears whenever you load Viper, unless you type `y' now." )) @@ -417,7 +449,7 @@ This startup message appears whenever you load Viper, unless you type `y' now." "The last message is in buffer `Viper Startup Message'") (sit-for 4) )) - (vip-set-expert-level 'dont-change-unless))) + (viper-set-expert-level 'dont-change-unless))) (vip-change-state-to-vi)))) @@ -429,6 +461,134 @@ This startup message appears whenever you load Viper, unless you type `y' now." (vip-change-state-to-insert)) +;; remove viper hooks from SYMBOL +(defun viper-remove-hooks (symbol) + (cond ((not (boundp symbol)) nil) + ((not (listp (eval symbol))) nil) + ((string-match "-hook" (symbol-name symbol)) + (remove-hook symbol 'viper-mode) + (remove-hook symbol 'vip-change-state-to-emacs) + (remove-hook symbol 'vip-change-state-to-insert) + (remove-hook symbol 'vip-change-state-to-vi) + ))) + +;; Remove local value in all existing buffers +;; This doesn't delocalize vars (which would have been desirable) +(defun viper-delocalize-var (symbol) + (mapcar (function (lambda (buf) + (save-excursion + (set-buffer buf) + (kill-local-variable symbol)))) + (buffer-list))) + + +(defun viper-go-away () + "De-Viperize Emacs. +This function tries to do as good a job as possible. However, it may undo some +user customization, unrelated to Viper. For instance, if the user advised +`read-file-name', `describe-key', and some others, then this advice will be +undone. +It also doesn't undo some Viper settings. For instance, `minor-mode-map-alist' +remains buffer-local." + (interactive) + + ;; restore non-viper vars + (setq-default + default-major-mode + (viper-standard-value 'default-major-mode viper-saved-non-viper-variables) + next-line-add-newlines + (viper-standard-value + 'next-line-add-newlines viper-saved-non-viper-variables) + require-final-newline + (viper-standard-value + 'require-final-newline viper-saved-non-viper-variables) + mark-even-if-inactive + (viper-standard-value + 'mark-even-if-inactive viper-saved-non-viper-variables) + scroll-step + (viper-standard-value 'scroll-step viper-saved-non-viper-variables) + global-mode-string + (viper-standard-value 'global-mode-string viper-saved-non-viper-variables) ) + + (setq-default + mode-line-buffer-identification + (viper-standard-value + 'mode-line-buffer-identification viper-saved-non-viper-variables)) + + ;; Ideally, we would like to be able to de-localize local variables + (viper-delocalize-var 'minor-mode-map-alist) + (viper-delocalize-var 'require-final-newline) + + + ;; deactivate all advices done by Viper. + (ad-deactivate-regexp "vip-") + + (setq viper-mode nil) + + (viper-delocalize-var 'vip-vi-minibuffer-minor-mode) + (viper-delocalize-var 'vip-insert-minibuffer-minor-mode) + (viper-delocalize-var 'vip-vi-intercept-minor-mode) + (viper-delocalize-var 'vip-insert-intercept-minor-mode) + + (viper-delocalize-var 'vip-vi-local-user-minor-mode) + (viper-delocalize-var 'vip-vi-kbd-minor-mode) + (viper-delocalize-var 'vip-vi-global-user-minor-mode) + (viper-delocalize-var 'vip-vi-state-modifier-minor-mode) + (viper-delocalize-var 'vip-vi-diehard-minor-mode) + (viper-delocalize-var 'vip-vi-basic-minor-mode) + + (viper-delocalize-var 'vip-replace-minor-mode) + + (viper-delocalize-var 'vip-insert-local-user-minor-mode) + (viper-delocalize-var 'vip-insert-kbd-minor-mode) + (viper-delocalize-var 'vip-insert-global-user-minor-mode) + (viper-delocalize-var 'vip-insert-state-modifier-minor-mode) + (viper-delocalize-var 'vip-insert-diehard-minor-mode) + (viper-delocalize-var 'vip-insert-basic-minor-mode) + + (viper-delocalize-var 'vip-emacs-intercept-minor-mode) + (viper-delocalize-var 'vip-emacs-local-user-minor-mode) + (viper-delocalize-var 'vip-emacs-kbd-minor-mode) + (viper-delocalize-var 'vip-emacs-global-user-minor-mode) + (viper-delocalize-var 'vip-emacs-state-modifier-minor-mode) + + (setq-default vip-vi-minibuffer-minor-mode nil + vip-insert-minibuffer-minor-mode nil + vip-vi-intercept-minor-mode nil + vip-insert-intercept-minor-mode nil + + vip-vi-local-user-minor-mode nil + vip-vi-kbd-minor-mode nil + vip-vi-global-user-minor-mode nil + vip-vi-state-modifier-minor-mode nil + vip-vi-diehard-minor-mode nil + vip-vi-basic-minor-mode nil + + vip-replace-minor-mode nil + + vip-insert-local-user-minor-mode nil + vip-insert-kbd-minor-mode nil + vip-insert-global-user-minor-mode nil + vip-insert-state-modifier-minor-mode nil + vip-insert-diehard-minor-mode nil + vip-insert-basic-minor-mode nil + + vip-emacs-intercept-minor-mode nil + vip-emacs-local-user-minor-mode nil + vip-emacs-kbd-minor-mode nil + vip-emacs-global-user-minor-mode nil + vip-emacs-state-modifier-minor-mode nil + ) + + ;; remove all hooks set by viper + (mapatoms 'viper-remove-hooks) + (remove-hook 'comint-mode-hook 'vip-comint-mode-hook) + (remove-hook 'minibuffer-setup-hook 'vip-minibuffer-setup-sentinel) + ) + + + + ;; This sets major mode hooks to make them come up in vi-state. (defun vip-set-hooks () @@ -461,6 +621,9 @@ This startup message appears whenever you load Viper, unless you type `y' now." (defvar java-mode-hook) (add-hook 'java-mode-hook 'viper-mode) + (defvar javascript-mode-hook) + (add-hook 'javascript-mode-hook 'viper-mode) + (defvar emacs-lisp-mode-hook) (add-hook 'emacs-lisp-mode-hook 'viper-mode) (defvar lisp-mode-hook) @@ -502,8 +665,14 @@ This startup message appears whenever you load Viper, unless you type `y' now." (add-hook 'completion-list-mode-hook 'viper-mode) (add-hook 'compilation-mode-hook 'viper-mode) - (add-hook 'perl-mode-hook 'viper-mode) - (add-hook 'tcl-mode-hook 'viper-mode) + (defvar perl-mode-hook) + (add-hook 'perl-mode-hook 'viper-mode) + + (defvar tcl-mode-hook) + (add-hook 'tcl-mode-hook 'viper-mode) + + (defvar python-mode-hook) + (add-hook 'python-mode-hook 'viper-mode) (defvar emerge-startup-hook) (add-hook 'emerge-startup-hook 'vip-change-state-to-emacs) @@ -568,26 +737,26 @@ This startup message appears whenever you load Viper, unless you type `y' now." ;; Dired (vip-modify-major-mode 'dired-mode 'emacs-state vip-dired-modifier-map) - (vip-set-emacs-search-style-macros nil 'dired-mode) + (vip-set-emacs-state-search-style-macros nil 'dired-mode) (add-hook 'dired-mode-hook 'vip-change-state-to-emacs) ;; Tar (vip-modify-major-mode 'tar-mode 'emacs-state vip-slash-and-colon-map) - (vip-set-emacs-search-style-macros nil 'tar-mode) + (vip-set-emacs-state-search-style-macros nil 'tar-mode) ;; MH-E (vip-modify-major-mode 'mh-folder-mode 'emacs-state vip-slash-and-colon-map) - (vip-set-emacs-search-style-macros nil 'mh-folder-mode) + (vip-set-emacs-state-search-style-macros nil 'mh-folder-mode) ;; changing state to emacs is needed so the preceding will take hold (add-hook 'mh-folder-mode-hook 'vip-change-state-to-emacs) (add-hook 'mh-show-mode-hook 'viper-mode) ;; Gnus (vip-modify-major-mode 'gnus-group-mode 'emacs-state vip-slash-and-colon-map) - (vip-set-emacs-search-style-macros nil 'gnus-group-mode) + (vip-set-emacs-state-search-style-macros nil 'gnus-group-mode) (vip-modify-major-mode 'gnus-summary-mode 'emacs-state vip-slash-and-colon-map) - (vip-set-emacs-search-style-macros nil 'gnus-summary-mode) + (vip-set-emacs-state-search-style-macros nil 'gnus-summary-mode) ;; changing state to emacs is needed so the preceding will take hold (add-hook 'gnus-group-mode-hook 'vip-change-state-to-emacs) (add-hook 'gnus-summary-mode-hook 'vip-change-state-to-emacs) @@ -595,7 +764,7 @@ This startup message appears whenever you load Viper, unless you type `y' now." ;; Info (vip-modify-major-mode 'Info-mode 'emacs-state vip-slash-and-colon-map) - (vip-set-emacs-search-style-macros nil 'Info-mode) + (vip-set-emacs-state-search-style-macros nil 'Info-mode) ;; Switching to emacs is needed so the above will take hold (defadvice Info-mode (after vip-Info-ad activate) "Switch to emacs mode." @@ -604,7 +773,7 @@ This startup message appears whenever you load Viper, unless you type `y' now." ;; Buffer menu (vip-modify-major-mode 'Buffer-menu-mode 'emacs-state vip-slash-and-colon-map) - (vip-set-emacs-search-style-macros nil 'Buffer-menu-mode) + (vip-set-emacs-state-search-style-macros nil 'Buffer-menu-mode) ;; Switching to emacs is needed so the above will take hold (defadvice Buffer-menu-mode (after vip-Buffer-menu-ad activate) "Switch to emacs mode." @@ -709,11 +878,16 @@ This startup message appears whenever you load Viper, unless you type `y' now." "Use `read-file-name' for reading arguments." (interactive (cons (read-file-name "Find file: " nil default-directory) ;; if Mule and prefix argument, ask for coding system - (if (or (boundp 'MULE) ; mule integrated Emacs 19 - (featurep 'mule)) ; mule integrated XEmacs 20 - (list - (and current-prefix-arg - (read-coding-system "Coding-system: ")))) + (cond ((and vip-emacs-p + (boundp 'MULE)) ; Emacs 20 with MULE + nil) + ((and vip-xemacs-p + (featurep 'mule)) ; XEmacs 20 with MULE + (list + (and current-prefix-arg + (read-coding-system + "Coding-system: ")))) + ) ))) (defadvice find-file-other-window (before vip-add-suffix-advice activate) @@ -721,24 +895,36 @@ This startup message appears whenever you load Viper, unless you type `y' now." (interactive (cons (read-file-name "Find file in other window: " nil default-directory) ;; if Mule and prefix argument, ask for coding system - (if (or (boundp 'MULE) ; mule integrated Emacs 19 - (featurep 'mule)) ; mule integrated XEmacs 20 - (list - (and current-prefix-arg - (read-coding-system "Coding-system: ")))) + (cond ((and vip-emacs-p + (boundp 'MULE)) ; Emacs 20 with MULE + nil) + ((and vip-xemacs-p + (featurep 'mule)) ; XEmacs 20 with MULE + (list + (and current-prefix-arg + (read-coding-system + "Coding-system: ")))) + ) ))) + (defadvice find-file-other-frame (before vip-add-suffix-advice activate) "Use `read-file-name' for reading arguments." (interactive (cons (read-file-name "Find file in other frame: " nil default-directory) ;; if Mule and prefix argument, ask for coding system - (if (or (boundp 'MULE) ; mule integrated Emacs 19 - (featurep 'mule)) ; mule integrated XEmacs 20 - (list - (and current-prefix-arg - (read-coding-system "Coding-system: ")))) + (cond ((and vip-emacs-p + (boundp 'MULE)) ; Emacs 20 with MULE + nil) + ((and vip-xemacs-p + (featurep 'mule)) ; XEmacs 20 with MULE + (list + (and current-prefix-arg + (read-coding-system + "Coding-system: ")))) + ) ))) + (defadvice read-file-name (around vip-suffix-advice activate) "Tell `exit-minibuffer' to run `vip-file-add-suffix' as a hook." @@ -815,7 +1001,7 @@ If you wish to Viperize AND make this your way of life, please put in your .emacs file (preferably, close to the top). These two lines must come in the order given. -Also, the startup file name has changed from .vip to .viper")) +Also, the startup file name has been changed from .vip to .viper")) (if (y-or-n-p "Viperize? ") (setq viper-mode t) (setq viper-mode nil)) @@ -825,10 +1011,34 @@ Also, the startup file name has changed from .vip to .viper")) +;; Get viper standard value of SYMBOL. If symbol is customized, get its +;; standard value. Otherwise, get the value saved in the alist STORAGE. If +;; STORAGE is nil, use viper-saved-user-settings. +(defun viper-standard-value (symbol &optional storage) + (or (eval (car (get symbol 'customized-value))) + (eval (car (get symbol 'saved-value))) + (nth 1 (assoc symbol (or storage viper-saved-user-settings))))) + + + +;; save non-viper vars that Viper might change +(if (null viper-saved-non-viper-variables) + (setq viper-saved-non-viper-variables + (list + (cons 'default-major-mode (list default-major-mode)) + (cons 'next-line-add-newlines (list next-line-add-newlines)) + (cons 'require-final-newline (list require-final-newline)) + (cons 'mark-even-if-inactive (list mark-even-if-inactive)) + (cons 'scroll-step (list scroll-step)) + (cons 'mode-line-buffer-identification + (list (default-value 'mode-line-buffer-identification))) + (cons 'global-mode-string (list global-mode-string)) + ))) + ;; Set some useful macros, advices -;; These must be BEFORE we ~/.vip is loaded, -;; so the user can unrecord them in ~/.vip. +;; These must be BEFORE ~/.viper is loaded, +;; so the user can unrecord them in ~/.viper. (if viper-mode (progn ;; set advices and some variables that give emacs Vi look. @@ -843,18 +1053,14 @@ Also, the startup file name has changed from .vip to .viper")) (vector vip-repeat-from-history-key '\2) 'vi-state [(meta x) v i p - r e p e a t - f r o m - h i s t o r y return] 't) - ;; set the toggle case sensitivity and regexp search macros - (vip-set-vi-search-style-macros nil) - + ;; set macros for toggling case sensitivity and regexp search + (vip-set-search-style-toggling-macros nil) ;; Make %%% toggle parsing comments for matching parentheses - (vip-record-kbd-macro - "%%%" 'vi-state - [(meta x) v i p - t o g g l e - p a r s e - s e x p - i g n o r e - c o m m e n t s return] - 't) + (vip-set-parsing-style-toggling-macro nil) )) -;; ~/.vip is loaded if it exists +;; ~/.viper is loaded if it exists (if (and (file-exists-p vip-custom-file-name) viper-mode (not noninteractive)) @@ -864,21 +1070,29 @@ Also, the startup file name has changed from .vip to .viper")) ;; Viper's basic map. (vip-add-keymap vip-mode-map vip-vi-global-user-map) +(if (boundp 'vip-expert-level) + (setq viper-expert-level vip-expert-level)) + + ;; Applying Viper customization -- runs after (load .vip) -;; Save user settings or Viper defaults for vars controled by vip-expert-level -(setq vip-saved-user-settings - (list (cons 'vip-want-ctl-h-help vip-want-ctl-h-help) - (cons 'viper-always viper-always) - (cons 'vip-no-multiple-ESC vip-no-multiple-ESC) - (cons 'vip-ex-style-motion vip-ex-style-motion) - (cons 'vip-ex-style-editing-in-insert - vip-ex-style-editing-in-insert) - (cons 'vip-want-emacs-keys-in-vi vip-want-emacs-keys-in-vi) - (cons 'vip-electric-mode vip-electric-mode) - (cons 'vip-want-emacs-keys-in-insert vip-want-emacs-keys-in-insert) - (cons 'vip-re-search vip-re-search))) +;; Save user settings or Viper defaults for vars controled by +;; viper-expert-level +(if (null viper-saved-user-settings) + (setq viper-saved-user-settings + (list (cons 'vip-want-ctl-h-help (list vip-want-ctl-h-help)) + (cons 'viper-always (list viper-always)) + (cons 'vip-no-multiple-ESC (list vip-no-multiple-ESC)) + (cons 'vip-ex-style-motion (list vip-ex-style-motion)) + (cons 'vip-ex-style-editing-in-insert + (list vip-ex-style-editing-in-insert)) + (cons 'vip-want-emacs-keys-in-vi + (list vip-want-emacs-keys-in-vi)) + (cons 'vip-electric-mode (list vip-electric-mode)) + (cons 'vip-want-emacs-keys-in-insert + (list vip-want-emacs-keys-in-insert)) + (cons 'vip-re-search (list vip-re-search))))) (if viper-mode @@ -909,7 +1123,7 @@ Also, the startup file name has changed from .vip to .viper")) ;; Intercept maps could go in viper-keym.el -;; We keep them here in case someone redefines them in ~/.vip +;; We keep them here in case someone redefines them in ~/.viper (define-key vip-vi-intercept-map vip-ESC-key 'vip-intercept-ESC-key) (define-key vip-insert-intercept-map vip-ESC-key 'vip-intercept-ESC-key) @@ -926,7 +1140,7 @@ Also, the startup file name has changed from .vip to .viper")) (if (and viper-mode (or viper-always - (and (< vip-expert-level 5) (> vip-expert-level 0)))) + (and (< viper-expert-level 5) (> viper-expert-level 0)))) (vip-set-hooks)) ;; Let all minor modes take effect after loading @@ -946,4 +1160,9 @@ Also, the startup file name has changed from .vip to .viper")) (provide 'vip) (provide 'viper) + +;;; Local Variables: +;;; eval: (put 'vip-deflocalvar 'lisp-indent-hook 'defun) +;;; End: + ;;; viper.el ends here |