[comp.emacs] GNU Emacs' vip-mode improvments wanted

ascott@fws214.intel.com, Dan_Jacobson@ATT.COM (02/23/91)

[This e-mail is much more appropriately answered by real VIP mode
users, and as not to waste all Andy's keystrokes, I must forward it to
the net... please forgive if necessary. -Dan J.]

> On Thu, 21 Feb 91 17:43:17 PST, ascott@fws214.intel.com (Andy Scott ~) said:

################################# beginning of Andy's message
Dan,
I have been using emacs for a while (VM5.22, gnus, calc, etc.)
and have noticed your plugs for it (I heartily agree, by the
way.)  

I have vip-mode mapped to Control-Z as suggested.

[^Z was a bad astetic coice if you ask me, as it usually means
"suspend" in UNIX... but I'm not a VI[P] guy -Dan J.]

Question: I am looking for better customization via the .vip
file.  Having such would help me personally, and help others
migrate to the emacs environment (I like elements of both.  I
use emacs-mode for mail and freeform text entry, and vip-mode
for heavy text editing.  I'm very proficient/confortable with
vi, and end up using it on the platforms here that don't have
emacs yet (I use elvis on the dept laptop.)

Attached at the end is my .vip file.  I arranged it the way
I did to document the difference between my setup and the
default.

My questions, which maybe could form a .vip FAQ start, if
any such animal exists:

Major desires:
1. I miss the strict vi "R" command a lot (see my .vip code comments);
have you found a better solution?

2. :wq blows away the whole emacs session.  Very nasty for
the new user.  Could it be changed to save-and-kill-buffer or
save-and-bury-buffer?  The prefix key code intimidates me.

3. ESC key annoyance.  I've developed a bad habit of sometimes
hitting the ESC key one time too many (just to *make sure*) in
vi, and carried that over to vip.  Then I end of capitalizing
some entire region by mistake.  Any suggestions? (Change normal
emacs ESC prefix to something else locally?)

Minor desires:
4. Some uses have complained that if the cursor is at the
top/bottom of a window and scrolls, it scrolls by more than
vi's one line.  Personally, I like it, but I'd like to know
how to defeat it.

Things I noticed along the way:
5. Use with VM.  With VM4.41 I could toggle Control-Z and
the emacs mode-line would change to ** Vi **.  In VM5.22
it doesn't, but seems to still work otherwise.

6. Have you or anyone else further embellished vip-mode?

Thanks for listening to my drivel :-)

Andy Scott

;;; .vip
;;; Customization file for EMACS vip-mode
;;; 02/13/90 A. Scott, ascott@fws214.intel.com
;;; This makes EMACs look very close to standard
;;; unix vi mode.
;;; 01/09/91 AMS Modified binding to be closer to
;;; strict vi.
;;;
;;;Customizing Key Bindings
;;;========================
;;;
;;;
;;;VIP uses `vip-command-mode-map' as the "local keymap" for vi mode.
;;;For example, in vi mode, SPC is bound to the function
;;;`vip-scroll'.  But, if you wish to make SPC and some other keys
;;; behave like Vi, you can include the following lines in your `.vip'
;;;file.
;;;
(setq vip-inhibit-startup-message t)
(setq vip-shift-width 8)
(setq vip-re-replace nil)
(setq vip-search-wrap-around t)
(setq vip-re-search nil)
(setq vip-case-fold-search t)
(setq vip-re-query-replace nil)
(setq vip-open-with-indent t)
(setq vip-tags-filename "TAGS")
;(define-key vip-mode-map "\C-h" 'vip-backward-char)
(setq vip-help-in-insert-mode t)

;; The following mapping is for Emacs conformance, where
;; C-g is the standard "abort command" function
(define-key vip-mode-map "\C-g" 'vip-keyboard-quit) ;default vip
(define-key vip-mode-map "g" 'vip-info-on-file)     ;default vip
;(define-key vip-mode-map "g" 'vip-goto-line)       ;optional vip

;; The following mapping is for strict vi conformance
;(define-key vip-mode-map "\C-g" 'vip-info-on-file) ;strict vi
;(define-key vip-mode-map "g" 'vip-keyboard-quit)   ;unused in vi

(define-key vip-mode-map "\C-m" 'vip-next-line-at-bol) ;strict vi
;(define-key vip-mode-map "\C-m" 'vip-scroll-back) ;default vip

(define-key vip-mode-map " " 'vip-forward-char)    ;strict vi
;(define-key vip-mode-map " " 'vip-scroll)         ;default vip

(define-key vip-mode-map "s" 'vip-substitute)      ;strict vi
(define-key vip-mode-map "S" 'vip-substitute-line) ;strict vi
;(define-key vip-mode-map "s" 'vip-switch-to-buffer) ;default vip
;(define-key vip-mode-map "S" 'vip-switch-to-buffer-other-window) ;default vip

(define-key vip-mode-map "C" 'vip-change-to-eol)  ;strict vi
;(define-key vip-mode-map "C" 'vip-ctl-c-equivalent)  ;default vip

;; 01/09/91 AMS - Fixing R to be like strict vi isn't easy.  The ESC
;; prefix would probably have to be changed to that if it was hit
;; after R mode, it would return to command mode. Hmm, maybe this
;; means that R mode should invoke something similar to "insert
;; mode"; I should check that out sometime.  I use R mode a lot in
;; real vi.  R mode could also be 'overwrite-mode if ESC would
;; terminate it.
;(define-key vip-mode-map "R" 'vip-replace-string) ;default vip
;(define-key vip-mode-map "R" 'vip-change-to-eol) ;"C" in strict vi
;(define-key vip-mode-map "R" 'overwrite-mode)    ;emacs mode option 
(define-key vip-mode-map "R" 'vip-substitute)    ;closest to strict vi

(define-key vip-mode-map "X" 'vip-delete-backward-char) ;strict vi
;(define-key vip-mode-map "X" 'vip-ctl-x-equivalent)    ;default vip

;(define-key vip-mode-map "Q" 'vip-query-replace)  ;default vip
                                                   ;unused in vi

;(define-key vip-mode-map "\C-q" 'quoted-insert)   ;default emacs
;(define-key vip-mode-map "\C-v" 'scroll-up)       ;default vip & emacs
(define-key vip-mode-map "\C-v" 'quoted-insert)   ;strict vi

;; Unused in vip and available for mapping
;(define-key vip-mode-map "~" 'vip-goto-line)
;(define-key vip-mode-map "_" 'vip-goto-line)
;(define-key vip-mode-map "]" 'vip-goto-line)
;(define-key vip-mode-map "[" 'vip-goto-line)
;(define-key vip-mode-map "&" 'vip-goto-line)
;(define-key vip-mode-map "@" 'vip-goto-line)
;(define-key vip-mode-map "q" 'vip-goto-line)
;; How about unused ctl- sequences?


;Nate Hess's configuration  (He was at Intel, now nhess@oracle.com)
;(define-key vip-mode-map "\C-r" 'name-last-kbd-macro)
;(define-key vip-mode-map "\C-r" 'isearch-backward) ;default emacs
;(define-key vip-mode-map "~" 'upcase-region)
;(define-key vip-mode-map "`" 'downcase-region)
;(define-key vip-mode-map "t" 'transpose-chars)
;(define-key vip-mode-map "v" 'set-mark-command)
;(define-key vip-mode-map "y" 'kill-region) ;emacs kill definition
;(define-key vip-mode-map "Y" 'yank) ;emacs yank definition
;(define-key vip-mode-map "Q" 'spell-buffer)
;(define-key vip-mode-map "F" 'fill-paragraph)
;(define-key vip-mode-map "Z" 'suspend-emacs)
;(define-key vip-mode-map "B" 'electric-buffer-list)
;(define-key vip-mode-map "M" 'rmail)
-------------------------------------------------------------
Andrew M. Scott               Intel Corporation, M/S FM2-26
ascott@fws214.intel.com       1900 Prairie City Road
(916) 351-6369                Folsom, CA 95630, USA

################################# end of Andy's message
-- 
Dan_Jacobson@ATT.COM  Naperville IL USA  +1 708-979-6364

sane@m.cs.uiuc.edu (Aamod Sane) (02/23/91)

	ascott@fws214.intel.com, Dan_Jacobson@ATT.COM writes:

	>[This e-mail is much more appropriately answered by real VIP mode
	>users, and as not to waste all Andy's keystrokes, I must forward it to
	>the net... please forgive if necessary. -Dan J.]

	>> On Thu, 21 Feb 91 17:43:17 PST, ascott@fws214.intel.com (Andy Scott ~) said:

	>################################# beginning of Andy's message
	>Dan,
	>I have been using emacs for a while (VM5.22, gnus, calc, etc.)
	>and have noticed your plugs for it (I heartily agree, by the
	>way.)  

	>I have vip-mode mapped to Control-Z as suggested.

	>[^Z was a bad astetic coice if you ask me, as it usually means
	>"suspend" in UNIX... but I'm not a VI[P] guy -Dan J.]

	>Question: I am looking for better customization via the .vip
	>file.  Having such would help me personally, and help others
	>migrate to the emacs environment (I like elements of both.  I

	>Major desires:
	>1. I miss the strict vi "R" command a lot (see my .vip code comments);
	>have you found a better solution?

Yes - see below

	>2. :wq blows away the whole emacs session.  Very nasty for
	>the new user.  Could it be changed to save-and-kill-buffer or
	>save-and-bury-buffer?  The prefix key code intimidates me.

Yes I have that fix too, and it will also fix problems with auto-save-files

Also I never allow emacs to just exit

This is how to take care of that

(defun save-buffers-kill-emacs (&optional arg)
  (interactive "P")
    (save-some-buffers arg t)
      (if (yes-or-no-p "Do you really want to exit? ")
	    (kill-emacs)))

	>3. ESC key annoyance.  I've developed a bad habit of sometimes
	>hitting the ESC key one time too many (just to *make sure*) in
	>vi, and carried that over to vip.  Then I end of capitalizing
	>some entire region by mistake.  Any suggestions? (Change normal
	>emacs ESC prefix to something else locally?)

I do not have this problem, so did not fix it. I'll see what I  can do.

	>Minor desires:
	>4. Some uses have complained that if the cursor is at the
	>top/bottom of a window and scrolls, it scrolls by more than
	>vi's one line.  Personally, I like it, but I'd like to know
	>how to defeat it.
	>-------------------------------------------------------------
	>Andrew M. Scott               Intel Corporation, M/S FM2-26
	>ascott@fws214.intel.com       1900 Prairie City Road
	>(916) 351-6369                Folsom, CA 95630, USA

	>################################# end of Andy's message
	>-- 
	>Dan_Jacobson@ATT.COM  Naperville IL USA  +1 708-979-6364

Here are the changes.


Here is my customisation file for Vi. It fixes many of the problems
that vip has.

1. "~" is a case toggle
2. "R" works as in vi
3. "/" does not toggle. It always searches regular expression
    /RET will repeat the previous search as in vi.
4. :wq saves and kills only the file on which you do it.


Bad news:
	1 does not (yet) get put into the history set. As soon
		as I figure those out, I will add the history
	2 R works with history not quite correctly. When
		you do ".", it just inserts, instead of replacing
	3. The prompt for / and ? remains the same one of these days
		I'll change that. (ONLY prompt appears same. it works
			otherwise)

NOTE: I DO NOT USE THE .VIP AT ALL. There are changes to vip.el in a file
of the same name in my local load path. This vip.el contains only the 
modified functions It loads the default using the my-default-load 
function below

You can try using the .vip if you wish. Just put the code into .vip
instead of doing it my way. Please let me kow if that works

Aamod Sane
sane@cs.uiuc.edu

;; Methods for incremental additions to existing packages
;; Copyright (C) Aamod Sane (sane@cs.uiuc.edu)
;; Author: Aamod Sane
;; This file is not part of GNU Emacs yet.
;; The FSF copyright below applies to this file.
;; Generated from a net discussion. The only person I remember
;; from the discussion is Dan LaLiberte.

;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY.  No author or distributor
;; accepts responsibility to anyone for the consequences of using it
;; or for whether it serves any particular purpose or works at all,
;; unless he says so in writing.  Refer to the GNU Emacs General Public
;; License for full details.

;; Everyone is granted permission to copy, modify and redistribute
;; GNU Emacs, but only under the conditions described in the
;; GNU Emacs General Public License.   A copy of this license is
;; supposed to have been given to you along with GNU Emacs so you
;; can know your rights and responsibilities.  It should be in a
;; file named COPYING.  Among other things, the copyright notice
;; and this notice must be preserved on all copies.

;; put the following functions in your .emacs file

(setq load-path
      (append
       (list "/your/system/load/path")
       load-path))

(defvar my-default-load-path load-path)

(setq load-path
      (append
       (list nil
	     (expand-file-name"~/emacs") ;; your local load path
             )
       load-path))

;; now simply use (my-default-load "package-name")
;; as the first line in a package of the same name
;; in your file

(defun my-default-load(name)
  (let ((save-path load-path))
       (progn
	(setq load-path my-default-load-path)
	(load name)
	(setq load-path save-path)))) 

;;;---------------------------------------------------

;; vip.el fixes
;; Copyright (C) Aamod Sane (sane@cs.uiuc.edu)
;; Author: Aamod Sane
;; This file is not part of GNU Emacs yet.
;; The FSF copyright below applies to this file

;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY.  No author or distributor
;; accepts responsibility to anyone for the consequences of using it
;; or for whether it serves any particular purpose or works at all,
;; unless he says so in writing.  Refer to the GNU Emacs General Public
;; License for full details.

;; Everyone is granted permission to copy, modify and redistribute
;; GNU Emacs, but only under the conditions described in the
;; GNU Emacs General Public License.   A copy of this license is
;; supposed to have been given to you along with GNU Emacs so you
;; can know your rights and responsibilities.  It should be in a
;; file named COPYING.  Among other things, the copyright notice
;; and this notice must be preserved on all copies.
;;;-------------------------
;;; vip modifications
;;;------------------------
;;; put these in a file vip.el in your local load path if you use
;;; my-default-load for incremental additions

(my-default-load "vip")

(defun vip-if-string()
  (let ((my-vip-s-string (vip-read-string (if vip-re-search "RE-/" "/"))))
    (if (not (string= my-vip-s-string ""))
	(setq vip-s-string my-vip-s-string))))

(defun vip-search-forward (arg)
  "Search a string forward.  ARG is used to find the ARG's occurence
of the string.  Default is vanilla search.  Search mode can be toggled by
giving null search string."
  (interactive "P")
  (let ((val (vip-P-val arg)) (com (vip-getcom arg)))
    (setq vip-s-forward t)
    (vip-if-string)
    (vip-search vip-s-string t val)
    (if com
	(progn
	  (move-marker vip-com-point (mark))
	  (vip-execute-com 'vip-search-next val com)))))

(defun vip-search-backward (arg)
  "Search a string backward.  ARG is used to find the ARG's occurence
of the string.  Default is vanilla search.  Search mode can be toggled by
giving null search string."
  (interactive "P")
  (let ((val (vip-P-val arg)) (com (vip-getcom arg)))
    (setq vip-s-forward nil)
    (vip-if-string)
    (vip-search vip-s-string nil val)
    (if com
	(progn
	  (move-marker vip-com-point (mark))
	  (vip-execute-com 'vip-search-next val com)))))

(defun vip-overwrite-escape()
  (interactive)
  (overwrite-mode 0)
  (vip-change-mode-to-vi)
  (define-key vip-mode-map "\e" 'vip-ESC))
  
(defun vip-overwrite()
  (interactive)
  (vip-insert nil)
  (define-key vip-insert-local-map "\e" 'vip-overwrite-escape)
  (if (eq overwrite-mode nil) 
      (overwrite-mode 1)
    (message "Already in overwrite mode...changing to insert")))
    
(define-key vip-mode-map "R" 'vip-overwrite)

(defun vip-toggle-case()
 (interactive)
 (let ((c (following-char)))
   (delete-char 1 nil)
   (if (eq c (upcase c))
       (insert-char (downcase c) 1)
       (insert-char (upcase c) 1))))

(define-key vip-mode-map "~" 'vip-toggle-case)

(setq vip-inhibit-startup-message t)
(setq vip-open-with-indent t)
(setq vip-re-search t)
(setq vip-re-replace t)

(define-key vip-mode-map "\C-o" 'vip-nil)
(define-key vip-mode-map "C" 'vip-change-to-eol)
(define-key vip-mode-map "s" 'vip-substitute)
(define-key vip-mode-map "S" 'vip-substitute-line)

;; to fix the wq and auto-save problem
;; fix vip-execute instead of ex-write for future dispatcher
;; changes.

(defun vip-execute-ex-command ()
  "execute ex command using the value of addresses."
  (cond ((string= ex-token "goto") (ex-goto))
	((string= ex-token "copy") (ex-copy nil))
	((string= ex-token "delete") (ex-delete))
	((string= ex-token "edit") (ex-edit))
	((string= ex-token "file") (vip-info-on-file))
	;((string= ex-token "global") (ex-global nil))
	((string= ex-token "join") (ex-line "join"))
	((string= ex-token "k") (ex-mark))
	((string= ex-token "mark") (ex-mark))
	((string= ex-token "map") (ex-map))
	((string= ex-token "move") (ex-copy t))
	((string= ex-token "put") (ex-put))
	((string= ex-token "quit") (ex-quit))
	((string= ex-token "read") (ex-read))
	((string= ex-token "set") (ex-set))
	((string= ex-token "shell") (ex-shell))
	((string= ex-token "substitute") (ex-substitute))
	((string= ex-token "stop") (suspend-emacs))
	((string= ex-token "t") (ex-copy nil))
	((string= ex-token "tag") (ex-tag))
	((string= ex-token "undo") (vip-undo))
	((string= ex-token "unmap") (ex-unmap))
	;((string= ex-token "v") (ex-global t))
	((string= ex-token "version") (vip-version))
	((string= ex-token "visual") (ex-edit))
	((string= ex-token "write") (ex-write nil))
	((string= ex-token "wq") (vip-ex-write-and-kill-buffer))
	((string= ex-token "yank") (ex-yank))
	((string= ex-token "!") (ex-command))
	((string= ex-token "=") (ex-line-no))
	((string= ex-token ">") (ex-line "right"))
	((string= ex-token "<") (ex-line "left"))
	((string= ex-token "&") (ex-substitute t))
	((string= ex-token "~") (ex-substitute t t))
	((or (string= ex-token "append")
	     (string= ex-token "args")
	     (string= ex-token "change")
	     (string= ex-token "insert")
	     (string= ex-token "open")
	     )
	 (error (format "%s: no such command from VIP" ex-token)))
	((or (string= ex-token "abbreviate")
	     (string= ex-token "list")
	     (string= ex-token "next")
	     (string= ex-token "print")
	     (string= ex-token "preserve")
	     (string= ex-token "recover")
	     (string= ex-token "rewind")
	     (string= ex-token "source")
	     (string= ex-token "unabbreviate")
	     (string= ex-token "xit")
	     (string= ex-token "z")
	     )
	 (error (format "%s: not implemented in VIP" ex-token)))
	(t (error (format "%s: Not an editor command" ex-token)))))

(defun vip-ex-write-and-kill-buffer()
	(ex-write nil)
	(delete-auto-save-file-if-necessary)
	(kill-buffer (current-buffer)))