ViperMode

Viper is a built-in Emacs package that provides a full-featured vi emulator.

If you want Vim features too, use Evil instead.

Tips

Colorizing Viper's Mode Line Indicator

Here is how to colorize Viper’s mode-line mode indicator to make it more prominent.

  (eval-after-load 'viper
    '(progn
       (setq viper-vi-state-id (concat (propertize "<V>" 'face 'hi-blue-b) " "))
       (setq viper-emacs-state-id (concat (propertize "<E>" 'face 'hi-red-b) " "))
       (setq viper-insert-state-id (concat (propertize "<I>" 'face 'hi-blue-b) " "))
       (setq viper-replace-state-id (concat (propertize "<R>" 'face 'hi-blue-b) " "))
       ;; The property `risky-local-variable' is a security measure
       ;; for mode line variables that have properties
       (put 'viper-mode-string 'risky-local-variable t)))

Using different color themes for Viper

The above didn’t work for me so well. Here is a method to use different color themes for Viper’s different insertion modes (also supports Vimpulse’s Visual mode):

    (require 'color-theme)
    (when (not (commandp 'color-theme-snapshot))
      (fset 'color-theme-snapshot (color-theme-make-snapshot)))
    (defgroup esn-viper nil
      "* Options for Viper Color theme.")
    (defvar esn-viper-last-mode 0
      "* Defines the last mode for Viper")
    (defcustom esn-viper-insert-color-theme "(color-theme-shaman)"
      "* Defines the color-theme used for Insert mode."
      :type 'string
      :group 'esn-viper)
    (defcustom esn-viper-emacs-color-theme "(color-theme-robin-hood)"
      "* Defines the color-theme used for Emacs mode."
      :type 'string
      :group 'esn-viper)
    (defcustom esn-viper-vi-color-theme "(color-theme-vim-colors)"
      "* Defines the color-theme used for VI mode."
      :type 'string
      :group 'esn-viper)
    (defcustom esn-viper-vi-visual-color-theme "(color-theme-vim-colors)"
      "* Defines the color-theme used for VI visual mode."
      :type 'string
      :group 'esn-viper)
    (defun esn-viper-pre-command-hook ()
      (interactive)
      (let ((deactivate-mark nil) (esn-keybinding 2) )
        (when (not (minibufferp))
          (when (and (= 2 esn-keybinding) (boundp 'viper-current-state) viper-current-state)
            (when (and (not (= 1 esn-viper-last-mode))
                       (eq viper-current-state 'emacs-state))
              ;; Emacs
              (setq esn-viper-last-mode 1)
              (color-theme-snapshot)
              (with-temp-buffer
                (insert esn-viper-emacs-color-theme)
                (eval-buffer)))
            (when (and (not (= 2 esn-viper-last-mode))
                       (eq viper-current-state 'insert-state))
              ;; Insert
              (setq esn-viper-last-mode 2)
              (color-theme-snapshot)
              (with-temp-buffer
                (insert esn-viper-insert-color-theme)
                (eval-buffer)))
            (when (and (not (= 3 esn-viper-last-mode))
                       (eq viper-current-state 'vi-state)
                       (or (not (boundp 'viper-visual-mode))
                           (not viper-visual-mode)))
              ;; vi Normal
              (setq esn-viper-last-mode 3)
              (color-theme-snapshot)
              (with-temp-buffer
                (insert esn-viper-vi-color-theme)
                (eval-buffer)))
            (when (and (not (= 4 esn-viper-last-mode))
                       (eq viper-current-state 'vi-state)
                       (boundp 'viper-visual-mode)
                       viper-visual-mode)
              ;; vi visual
              (setq esn-viper-last-mode 4)
              (color-theme-snapshot)
              (with-temp-buffer
                (insert esn-viper-vi-visual-color-theme)
                (eval-buffer)))))))
    (add-hook 'pre-command-hook 'esn-viper-pre-command-hook)
    (add-hook 'post-command-hook 'esn-viper-pre-command-hook)

MatthewFidler

I also put this in a key selection package. It provides a menu for possible keys and also provides the different color themes for Viper. It requires ColorTheme as well as Lisp:key-choices.el, Lisp:color-theme-vim-insert-mode.el, Lisp:color-theme-emacs-revert-theme.el. If you want ErgoEmacs support is requires the ErgoEmacs keybinding package. It is provided in EmacsPortable

Viper and CUA, deleting region

When using CuaMode, the delete and backspace keys normally deletes the region if it is active. However, when using Viper, this does not work. Put this in your .emacs if you want it to work:

    (defun viper-cua-region-fix()
      (define-key viper-vi-global-user-map [backspace] 'backward-delete-char-untabify)
      (define-key viper-vi-global-user-map "\C-d" 'delete-char)
      (define-key viper-insert-global-user-map [backspace] 'backward-delete-char-untabify)
      (define-key viper-insert-global-user-map "\C-d" 'delete-char))
    (eval-after-load 'viper '(viper-cua-region-fix))

I hope this will be fixed in the CVS soon. The fix there will be different, however (the above is not entirely correct, but maybe a good workaround).

vi keys in dired-mode

From a Reddit discussion:

    (define-key dired-mode-map "v" 'dired-x-find-file)
    (define-key dired-mode-map "V" 'dired-view-file)
    (define-key dired-mode-map "j" 'dired-next-line)
    (define-key dired-mode-map "J" 'dired-goto-file)
    (define-key dired-mode-map "k" 'dired-previous-line)
    (define-key dired-mode-map "K" 'dired-do-kill-lines)

From a Stackoverflow post:

        ;; A way to activate and deactivate vi-state when toggling the wdired-mode
        (eval-after-load "wdired"
          '(progn
             (eval-after-load "viper"
               '(progn
                  (defadvice wdired-change-to-wdired-mode (after viper activate)
                    (unless (eq viper-current-state 'emacs-state)
                      (viper-change-state 'vi-state)))
                  (defadvice wdired-finish-edit (after viper activate)
                    (unless (eq viper-current-state 'emacs-state)
                      (viper-change-state-to-vi)) ; back to normal state
                    (viper-modify-major-mode    ; back to dired map
                     'dired-mode 'vi-state dired-mode-map)))))

vi Tutorial for Viper

There is now a Viper/vi tutorial included in nXhtml. You find it in nxml/util/viper-tut.el.

Eh, yes. It is a rather strange place to put it in.

Switching buffers

There is a way to make Viper state and Viper insert state global, like in Vim (and probably vi). In Vim (and probably vi), you start in Normal Mode. You can switch buffer, and Vim stays in Normal Mode. Pressing “i” puts Vim in Insert Mode. Then if you switch buffers by clicking on another window, Vim stays in Insert Mode. You don’t have to remember which buffer is in what mode, you only need to remember in which mode Vim is.

In Viper, you start in Viper state. Pressing “i” puts Viper in Insert state. But this state is buffer local: if you switch buffers, Viper switches to whatever state the other buffer is. So when you switch buffers a lot, you can quickly lose track of which buffer is in what state, and start messing up buffers, inserting “:w” everywhere – or unwillingly executing commands like ‘i’ or ‘a’

Some don’t want modes to be changed stealthily. Additionally, Viper also has a replacement mode, which Vim does not have (but vi used to have).

However, some like the idea since:

One workaround is binding “:b” to ‘anything’ (see Anything), thus allowing me to use “:b” to switch buffers.

This ensures me that I leave every buffer in Normal Mode.

Questions

Is there a way to deactivate Viper for a single buffer in a function? That is, why doesn’t the following work?

    (defun test ()
      (interactive)
      (text-mode)
      (viper-change-state-to-emacs))

M-x test

How to skip "File ... is checked. Check it out? (y or n)" on :w for SVN files?

Hi, we use SVN, and everytime I write a version controled file (with “:w”), Viper asks me if I want to check it out.

Since it doesn’t make sense for SVN files, I added:

        (not (memq (vc-backend file) '(nil SVN)))

under the line:

        (not (memq (vc-backend file) '(nil CVS)))

in the function ‘viper-file-checked-in-p’.

I’m not really satisfied with this, since I’ll silently loose this change next time I update my Emacs. Is there a cleaner way?

Thanks! – SebastienRoccaSerra

Here:

    (defadvice viper-maybe-checkout (around viper-svn-checkin-fix activate)
      "Advise viper-maybe-checkout to ignore svn files."
      (let ((file (expand-file-name (buffer-file-name buf))))
        (when (and (featurep 'vc-hooks)
                   (not (memq (vc-backend file) '(nil SVN))))
          ad-do-it)))

This seems to work for me, at least. Until upstream Viper gets fixed. – JeremyHankins

"Inner Word" commands?

How do you get Vim’s “ciw” (= Change Inner Word) command?

I mean, you are in Normal Mode, in an EmacsLispMode buffer, ‘viper-syntax-preference’ is set to ‘extended’ and, in the following code:

    (change-inner-word)

the Cursor is over the “i”. Then, ‘cw’ will kill “inner-word”, whilst ‘ciw’ will kill “inner” only.

Vimpulse provides text objects (e.g., ‘ciw’) for Viper.

Bugs

`==’ doesn’t work in Viper 3.14 (“Viper Bell” in minibuffer and no effect). You can fix it modifying viper-prefix-arg-com:

      (if (atom com)
      ;; `com' is a single char, so we construct the command argument
      ;; and if `char' is `?', we describe the arg; otherwise
      ;; we prepare the command that will be executed at the end.
      (progn
        (setq cmd-info (cons value com))
        (while (viper= char ?U)
          (viper-describe-arg cmd-info)
          (setq char (read-char)))
        ;; `char' is a movement cmd, a digit arg cmd, or a register cmd---so
        ;; we execute it at the very end
        (or (viper-movement-command-p char)
        (viper-digit-command-p char)
        (viper-regsuffix-command-p char)
        (viper= char ?!) ; bang command
        (viper= char ?g) ; the gg command (like G0)
        (viper= char ?=) ; the == command  <<<<<<<<<< ADD THIS LINE
        (error "Viper bell"))
        (setq cmd-to-exec-at-end
          (viper-exec-form-in-vi
           `(key-binding (char-to-string ,char)))))

How can you remap prefix keys like `c' and `d'?

This doesn’t seem to be possible with simple configuration, as the prefix keys have been hardcoded into Viper source (http://stackoverflow.com/questions/2145562/how-can-i-remap-the-prefix-keys-c-d-etc-in-emacs-viper-mode)

Changing viper-toggle-key

I’ve set

(setq viper-toggle-key "\C-q")

in .viper in order to use C-z as undo. However, it only seems to work in Insert mode: in both Vi and Emacs modes C-z is still bound to viper-toggle-key-action. Neither of these lines in .viper (after setting viper-toggle-key) seems to have any effect:

(define-key viper-vi-global-user-map "\C-z" 'undo)
(set-global-key "\C-z" 'undo)

AlexeyRomanov

I have never looked at setting C-z separately but some years ago we got cua-mode and viper to work together. So I turn on both cua-mode and viper and move viper-toggle-key (to f6) and then C-z will be undo. (Which I hardly use since it is easier to use vipers undo most of the time.) – LennartBorgman

I am in fact using cua-mode. I wonder why I am not getting the same result… I’ve just tried moving cua-mode loading after viper is loaded, but it didn’t help. – AlexeyRomanov

What version of Emacs are you using?

The last patched EmacsW32 (see TabCompletion for a link to my setup).

Then maybe something has changed that I am not aware of. I am going to release a new version of Emacs+Emacsw32 as soon as I have fixed some problems with nXhtml. However that may take some time.


CategoryEmulation CategoryKeys CategoryModalEditing