-;;; vi.el --- major mode for emulating "vi" editor under GNU Emacs.
+;;; vi.el --- major mode for emulating "vi" editor under GNU Emacs
+
+;; This file is in the public domain because the authors distributed it
+;; without a copyright notice before the US signed the Bern Convention.
+
+;; This file is part of GNU Emacs.
;; Author: Neal Ziring <nz@rsch.wisc.edu>
;; Felix S. T. Wu <wu@crys.wisc.edu>
;; Keywords: emulations
-;;; Commentary:
-
-; Originally written by : seismo!wucs!nz@rsch.wisc.edu (Neal Ziring)
-; Extensively redesigned and rewritten by wu@crys.wisc.edu (Felix S.T. Wu)
-; Last revision: 01/07/87 Wed (for GNU Emacs 18.33)
-;
-; INSTALLATION PROCEDURE:
-; 1) Add a global key binding for command "vi-mode" (I use ESC ESC instead of
-; the single ESC used in real "vi", so I can access other ESC prefixed emacs
-; commands while I'm in "vi"), say, by putting the following line in your
-; ".emacs" file:
-; (define-key global-map "\e\e" 'vi-mode) ;quick switch into vi-mode
-; 2) If you wish you can define "find-file-hooks" to enter "vi" automatically
-; after a file is loaded into the buffer. For example, I defined it as:
-; (setq find-file-hooks (list
-; (function (lambda ()
-; (if (not (or (eq major-mode 'Info-mode)
-; (eq major-mode 'vi-mode)))
-; (vi-mode))))))
-; 3) In your .emacs file you can define the command "vi-mode" to be "autoload"
-; or you can execute the "load" command to load "vi" directly.
-; 4) Read the comments for command "vi-mode" before you start using it.
-;
-; COULD DO
-; 1). A general 'define-operator' function to replace current hack
-; 2). In operator handling, should allow other point moving Emacs commands
-; (such as ESC <, ESC >) to be used as arguments.
-;
+;;; Commentary:
+
+;; Originally written by : seismo!wucs!nz@rsch.wisc.edu (Neal Ziring)
+;; Extensively redesigned and rewritten by wu@crys.wisc.edu (Felix S.T. Wu)
+;; Last revision: 01/07/87 Wed (for GNU Emacs 18.33)
+
+;; INSTALLATION PROCEDURE:
+;; 1) Add a global key binding for command "vi-mode" (I use ESC ESC instead of
+;; the single ESC used in real "vi", so I can access other ESC prefixed emacs
+;; commands while I'm in "vi"), say, by putting the following line in your
+;; ".emacs" file:
+;; (define-key global-map "\e\e" 'vi-mode) ;quick switch into vi-mode
+;; 2) If you wish you can define "find-file-hook" to enter "vi" automatically
+;; after a file is loaded into the buffer. For example, I defined it as:
+;; (setq find-file-hook (list
+;; (function (lambda ()
+;; (if (not (or (eq major-mode 'Info-mode)
+;; (eq major-mode 'vi-mode)))
+;; (vi-mode))))))
+;; 3) In your .emacs file you can define the command "vi-mode" to be "autoload"
+;; or you can execute the "load" command to load "vi" directly.
+;; 4) Read the comments for command "vi-mode" before you start using it.
+
+;; COULD DO
+;; 1). A general 'define-operator' function to replace current hack
+;; 2). In operator handling, should allow other point moving Emacs commands
+;; (such as ESC <, ESC >) to be used as arguments.
+
;;; Code:
-(defun vi-switch-mode (arg mode-char)
- "Switch the major mode of current buffer as specified by the following char \\{vi-tilde-map}"
- (interactive "P\nc")
- (let ((mode-cmd (lookup-key vi-tilde-map (char-to-string mode-char))))
- (if (null mode-cmd)
- (with-output-to-temp-buffer "*Help*"
- (princ (substitute-command-keys "Possible major modes to switch to: \\{vi-tilde-map}"))
- (save-excursion
- (set-buffer standard-output)
- (help-mode)))
- (setq prefix-arg arg) ; prefix arg will be passed down
- (command-execute mode-cmd nil) ; may need to save mode-line-format etc
- (set-buffer-modified-p (buffer-modified-p))))) ; just in case
+(defvar vi-mode-old-major-mode)
+(defvar vi-mode-old-mode-name)
+(defvar vi-mode-old-local-map)
+(defvar vi-mode-old-case-fold)
-\f
(if (null (where-is-internal 'vi-switch-mode (current-local-map)))
(define-key ctl-x-map "~" 'vi-switch-mode))
(define-key vi-tilde-map "v" 'vi-mode)
(define-key vi-tilde-map "x" 'tex-mode)
(define-key vi-tilde-map "~" 'vi-back-to-old-mode))
+\f
+(defun vi-switch-mode (arg mode-char)
+ "Switch the major mode of current buffer as specified by the following char \\{vi-tilde-map}"
+ (interactive "P\nc")
+ (let ((mode-cmd (lookup-key vi-tilde-map (char-to-string mode-char))))
+ (if (null mode-cmd)
+ (with-output-to-temp-buffer "*Help*"
+ (princ (substitute-command-keys "Possible major modes to switch to: \\{vi-tilde-map}"))
+ (save-excursion
+ (set-buffer standard-output)
+ (help-mode)))
+ (setq prefix-arg arg) ; prefix arg will be passed down
+ (command-execute mode-cmd nil) ; may need to save mode-line-format etc
+ (force-mode-line-update)))) ; just in case
+\f
(defun vi-debugging (arg)
"Toggle debug-on-error flag. If prefix arg is given, set t."
(interactive "P")
(use-local-map vi-mode-old-local-map)
(setq major-mode vi-mode-old-major-mode)
(setq case-fold-search vi-mode-old-case-fold)
- (set-buffer-modified-p (buffer-modified-p)))))
+ (force-mode-line-update))))
(defun vi-readonly-mode ()
"Toggle current buffer's readonly flag."
;;(fillarray vi-com-map 'vi-undefined)
(define-key vi-com-map "\C-@" 'vi-mark-region) ; extension
(define-key vi-com-map "\C-a" 'vi-ask-for-info) ; extension
- (define-key vi-com-map "\C-b" 'vi-backward-windowfull)
+ (define-key vi-com-map "\C-b" 'vi-backward-windowful)
(define-key vi-com-map "\C-c" 'vi-do-old-mode-C-c-command) ; extension
(define-key vi-com-map "\C-d" 'vi-scroll-down-window)
(define-key vi-com-map "\C-e" 'vi-expose-line-below)
- (define-key vi-com-map "\C-f" 'vi-forward-windowfull)
+ (define-key vi-com-map "\C-f" 'vi-forward-windowful)
(define-key vi-com-map "\C-g" 'keyboard-quit)
(define-key vi-com-map "\C-i" 'indent-relative-maybe) ; TAB
(define-key vi-com-map "\C-j" 'vi-next-line) ; LFD
(define-key vi-com-map "\C-\\" 'vi-unimplemented)
(define-key vi-com-map "\C-]" 'find-tag)
(define-key vi-com-map "\C-^" 'vi-locate-def) ; extension
- (define-key vi-com-map "\C-_" 'vi-undefined)
+ (define-key vi-com-map "\C-_" 'vi-undefined)
(define-key vi-com-map " " 'forward-char)
(define-key vi-com-map "!" 'vi-operator)
(define-key vi-com-map "H" 'vi-home-window-line)
(define-key vi-com-map "I" 'vi-insert-before-first-nonwhite)
(define-key vi-com-map "J" 'vi-join-lines)
- (define-key vi-com-map "K" 'vi-undefined)
+ (define-key vi-com-map "K" 'vi-undefined)
(define-key vi-com-map "L" 'vi-last-window-line)
(define-key vi-com-map "M" 'vi-middle-window-line)
(define-key vi-com-map "N" 'vi-reverse-last-search)
(define-key vi-com-map "S" 'vi-substitute-lines)
(define-key vi-com-map "T" 'vi-backward-upto-char)
(define-key vi-com-map "U" 'vi-unimplemented)
- (define-key vi-com-map "V" 'vi-undefined)
+ (define-key vi-com-map "V" 'vi-undefined)
(define-key vi-com-map "W" 'vi-forward-blank-delimited-word)
(define-key vi-com-map "X" 'call-last-kbd-macro) ; modification/extension
(define-key vi-com-map "Y" 'vi-yank-line)
(define-key vi-com-map "s" 'vi-substitute-chars)
(define-key vi-com-map "t" 'vi-forward-upto-char)
(define-key vi-com-map "u" 'undo)
- (define-key vi-com-map "v" 'vi-verify-spelling)
+ (define-key vi-com-map "v" 'vi-verify-spelling)
(define-key vi-com-map "w" 'vi-forward-word)
(define-key vi-com-map "x" 'vi-kill-char)
(define-key vi-com-map "y" 'vi-operator)
(put 'mark-defun 'point-moving-unit 'region)
(put 'mark-whole-buffer 'point-moving-unit 'region)
(put 'mark-end-of-sentence 'point-moving-unit 'region)
-(put 'mark-c-function 'point-moving-unit 'region)
+(put 'c-mark-function 'point-moving-unit 'region)
;;;
(defvar vi-mark-alist nil
"Alist of (NAME . MARK), marks are local to each buffer.")
(defvar vi-scroll-amount (/ (window-height) 2)
- "Default amount of lines for scrolling (used by "^D"/"^U").")
+ "Default amount of lines for scrolling (used by \"^D\"/\"^U\").")
(defvar vi-shift-width 4
- "Shift amount for "<"/">" operators.")
+ "Shift amount for \"<\"/\">\" operators.")
(defvar vi-ins-point nil ; integer
- "Last insertion point. Should use 'mark' instead.")
+ "Last insertion point. Should use `mark' instead.")
(defvar vi-ins-length nil ; integer
"Length of last insertion.")
(defvar vi-last-change-command nil ; cons cell
"Save commands for redoing last changes. Each command is in (FUNC . ARGS)
-form that is ready to be 'apply'ed.")
+form that is ready to be `apply'ed.")
(defvar vi-last-shell-command nil ; last shell op command line
"Save last shell command given for \"!\" operator.")
(defvar vi-insert-state nil ; boolean
- "T if it is in insert state.")
+ "Non-nil if it is in insert state.")
; in "loaddefs.el"
-;(defvar search-last-string ""
+;(defvar search-last-string ""
; "Last string search for by a search command.")
(defvar vi-search-last-command nil ; (re-)search-forward(backward)
(defvar vi-mode-old-mode-name nil
"Save the mode-name before entering vi-mode.")
-
+
(defvar vi-mode-old-major-mode nil
"Save the major-mode before entering vi-mode.")
(defvar vi-mode-old-case-fold nil)
-
+
;(defconst vi-add-to-mode-line-1
; '(overwrite-mode nil " Insert"))
(make-local-variable 'vi-mode-old-mode-name)
(make-local-variable 'vi-mode-old-major-mode)
(make-local-variable 'vi-mode-old-case-fold)
- (run-hooks 'vi-mode-hook))
-
+ (run-mode-hooks 'vi-mode-hook))
+
;;;###autoload
(defun vi-mode ()
"Major mode that acts like the `vi' editor.
`vi-name-last-change-or-macro', `vi-verify-spelling', `vi-locate-def',
`vi-mark-region', and 'vi-quote-words'. Some of them are quite handy.
- Use \\[vi-switch-mode] to switch among different modes quickly.
-
+
Syntax table and abbrevs while in vi mode remain as they were in Emacs."
(interactive)
(if (null vi-mode-old-major-mode) ; very first call for current buffer
(vi-mode-setup))
(if (eq major-mode 'vi-mode)
- (message "Already in vi-mode." (ding))
+ (progn (ding) (message "Already in vi-mode."))
(setq vi-mode-old-local-map (current-local-map))
(setq vi-mode-old-mode-name mode-name)
(setq vi-mode-old-major-mode major-mode)
(use-local-map vi-com-map)
(setq major-mode 'vi-mode)
(setq mode-name "VI")
- (set-buffer-modified-p (buffer-modified-p)) ; force mode line update
+ (force-mode-line-update) ; force mode line update
(if vi-insert-state ; this is a return from insertion
(vi-end-of-insert-state))))
"Go into insert state, the text entered will be repeated if REPETITION > 1.
If PREFIX-CODE is given, do it before insertion begins if DO-IT-NOW-P is T.
In any case, the prefix-code will be done before each 'redo-insert'.
-This function expects 'overwrite-mode' being set properly beforehand."
+This function expects `overwrite-mode' being set properly beforehand."
(if do-it-now-p (apply (car prefix-code) (cdr prefix-code)))
(setq vi-ins-point (point))
(setq vi-ins-repetition repetition)
(setq case-fold-search vi-mode-old-case-fold)
(use-local-map vi-mode-old-local-map)
(setq major-mode vi-mode-old-major-mode)
- (set-buffer-modified-p (buffer-modified-p)) ; force mode line update
+ (force-mode-line-update)
(setq vi-insert-state t))
(defun vi-end-of-insert-state ()
(<= vi-ins-repetition 0))
(vi-goto-command-state t)
(if (> vi-ins-repetition 1)
- (progn
+ (progn
(let ((str (buffer-substring vi-ins-point (point))))
(while (> vi-ins-repetition 1)
(insert str)
(kill-line arg)
(vi-set-last-change-command 'kill-line arg))
-(defun vi-kill-region ()
- (interactive)
- (kill-region)
+(defun vi-kill-region (start end)
+ (interactive "*r")
+ (kill-region start end)
(vi-set-last-change-command 'kill-region))
-
+
(defun vi-append-at-end-of-line (arg)
"go to end of line and then go into vi insert state."
(interactive "*p")
"Go to ARGth line."
(interactive "P")
(if (null (vi-raw-numeric-prefix arg))
- (end-of-buffer)
+ (with-no-warnings
+ (end-of-buffer))
(goto-line (vi-prefix-numeric-value arg))))
(defun vi-beginning-of-buffer ()
;;;;;
(defun vi-isearch-forward (arg)
- "Incremental search forward. Use regexp version if ARG is non-nil."
+ "Incremental search forward. Use regexp version if ARG is non-nil."
(interactive "P")
(let ((scmd (if arg 'isearch-forward-regexp 'isearch-forward))
(opoint (point)))
(list t (read-string "regexp/" nil))
(list nil (read-string "/" nil))))
(setq vi-search-last-command (if arg 're-search-forward 'search-forward))
- (if (> (length string) 0) (setq search-last-string string))
- (funcall vi-search-last-command search-last-string nil nil 1))
+ (if (> (length string) 0)
+ (isearch-update-ring string arg))
+ (funcall vi-search-last-command string nil nil 1))
(defun vi-search-backward (arg string)
"Nonincremental search backward. Use regexp version if ARG is non-nil."
(list t (read-string "regexp?" nil))
(list nil (read-string "?" nil))))
(setq vi-search-last-command (if arg 're-search-backward 'search-backward))
- (if (> (length string) 0) (setq search-last-string string))
- (funcall vi-search-last-command search-last-string nil nil 1))
+ (if (> (length string) 0)
+ (isearch-update-ring string arg))
+ (funcall vi-search-last-command string nil nil 1))
(defun vi-repeat-last-search (arg &optional search-command search-string)
- "Repeat last search command. If optional search-command/string are given,
+ "Repeat last search command.
+If optional search-command/string are given,
use those instead of the ones saved."
- (interactive "p")
- (if (null search-command) (setq search-command vi-search-last-command))
- (if (null search-string) (setq search-string search-last-string))
- (if (null search-command)
- (message "No last search command to repeat." (ding))
- (funcall search-command search-string nil nil arg)))
+ (interactive "p")
+ (if (null search-command) (setq search-command vi-search-last-command))
+ (if (null search-string)
+ (setq search-string
+ (car (if (memq search-command
+ '(re-search-forward re-search-backward))
+ regexp-search-ring
+ search-ring))))
+ (if (null search-command)
+ (progn (ding) (message "No last search command to repeat."))
+ (funcall search-command search-string nil nil arg)))
(defun vi-reverse-last-search (arg &optional search-command search-string)
- "Redo last search command in reverse direction. If the optional search args
-are given, use those instead of the ones saved."
+ "Redo last search command in reverse direction.
+If the optional search args are given, use those instead of the ones saved."
(interactive "p")
(if (null search-command) (setq search-command vi-search-last-command))
- (if (null search-string) (setq search-string search-last-string))
+ (if (null search-string)
+ (setq search-string
+ (car (if (memq search-command
+ '(re-search-forward re-search-backward))
+ regexp-search-ring
+ search-ring))))
(if (null search-command)
- (message "No last search command to repeat." (ding))
+ (progn (ding) (message "No last search command to repeat."))
(funcall (cond ((eq search-command 're-search-forward) 're-search-backward)
((eq search-command 're-search-backward) 're-search-forward)
((eq search-command 'search-forward) 'search-backward)
((eq search-command 'search-backward) 'search-forward))
search-string nil nil arg)))
-
+
(defun vi-join-lines (arg)
"join ARG lines from current line (default 2), cleaning up white space."
(interactive "P")
(if (null (vi-raw-numeric-prefix arg))
(delete-indentation t)
- (setq count (vi-prefix-numeric-value arg))
- (while (>= count 2)
- (delete-indentation t)
- (setq count (1- count))))
+ (let ((count (vi-prefix-numeric-value arg)))
+ (while (>= count 2)
+ (delete-indentation t)
+ (setq count (1- count)))))
(vi-set-last-change-command 'vi-join-lines arg))
(defun vi-backward-kill-line ()
(kill-region vi-ins-point (point)))
(vi-goto-command-state t)))
-(defun vi-backward-windowfull (count)
- "Backward COUNT windowfulls. Default is one."
+(defun vi-backward-windowful (count)
+ "Backward COUNT windowfuls. Default is one."
(interactive "p")
; (set-mark-command nil)
(while (> count 0)
(interactive "p")
(scroll-up count))
-(defun vi-forward-windowfull (count)
- "Forward COUNT windowfulls. Default is one."
+(defun vi-forward-windowful (count)
+ "Forward COUNT windowfuls. Default is one."
(interactive "p")
; (set-mark-command nil)
(while (> count 0)
"Go down count lines, try to keep at the same column."
(interactive "p")
(setq this-command 'next-line) ; this is a needed trick
- (if (= (point) (or (line-move count) (point)))
+ (if (= (point) (progn (line-move count) (point)))
(ding) ; no moving, already at end of buffer
(setq last-command 'next-line)))
(defun vi-previous-line-first-nonwhite (count)
"Go up COUNT lines. Stop at first non-white."
(interactive "p")
- (previous-line count)
+ (forward-line (- count))
(back-to-indentation))
(defun vi-scroll-up-window (count)
(defun vi-char-argument (arg)
"Get following character (could be any CHAR) as part of the prefix argument.
-Possible prefix-arg cases are NIL, INTEGER, (NIL . CHAR) or (INTEGER . CHAR)."
+Possible prefix-arg cases are nil, INTEGER, (nil . CHAR) or (INTEGER . CHAR)."
(interactive "P")
(let ((char (read-char)))
(cond ((null arg) (setq prefix-arg (cons nil char)))
(t
(let ((mark (vi-get-mark mark-char)))
(if (null mark)
- (message "Mark register undefined." (vi-ding))
+ (progn (vi-ding) (message "Mark register undefined."))
(set-mark-command nil)
(goto-char mark)
(if line-flag (back-to-indentation)))))))
-
+
(defun vi-goto-line-mark (char)
"Go to the line (at first non-white) marked by next char."
(interactive "c")
(interactive "p")
(if (null find-arg) (setq find-arg vi-last-find-char))
(if (null find-arg)
- (message "No last find char to repeat." (ding))
+ (progn (ding) (message "No last find char to repeat."))
(vi-find-char (cons (* (car find-arg) -1) (cdr find-arg)) count))) ;6/13/86
(defun vi-find-char (arg count)
(interactive "p")
(if (null find-arg) (setq find-arg vi-last-find-char))
(if (null find-arg)
- (message "No last find char to repeat." (ding))
+ (progn (ding) (message "No last find char to repeat."))
(vi-find-char find-arg count)))
(defun vi-backward-find-char (count char)
(setq end (1+ end)))
((eq moving-unit 'line)
(goto-char begin) (beginning-of-line) (setq begin (point))
- (goto-char end) (next-line 1) (beginning-of-line) (setq end (point))))
- (if (> end (point-max)) (setq end (point-max))) ; force in buffer region
+ (goto-char end) (forward-line 1) (beginning-of-line) (setq end (point))))
+ (if (> end (point-max)) (setq end (point-max))) ; force in buffer region
(cons begin end)))))
(defun vi-delete-op (motion-command arg)
(= (aref string (1- (length string))) ?\n))
(defun vi-put-before (arg &optional after-p)
- "Put yanked (in vi sense) text back before/above cursor.
+ "Put yanked (in vi sense) text back before/above cursor.
If a numeric prefix value (currently it should be >1) is given, put back
text as lines. If the optional after-p is given, put after/below the cursor."
(interactive "P")
(t (error "Register %c is not containing text string" reg))))
(if (vi-string-end-with-nl-p put-text) ; put back text as lines
(if after-p
- (progn (next-line 1) (beginning-of-line))
+ (progn (forward-line 1) (beginning-of-line))
(beginning-of-line))
(if after-p (forward-char 1)))
(push-mark (point))
(interactive "*P")
(let ((rcmd (if arg 'replace-regexp 'replace-string)))
(call-interactively rcmd nil)))
-
+
(defun vi-adjust-window (arg position)
"Move current line to the top/center/bottom of the window."
(interactive "p\nc")
(ding))))
(defun vi-name-last-change-or-macro (arg char)
- "Give name to the last change command or just defined kbd macro.
+ "Give name to the last change command or just defined kbd macro.
If prefix ARG is given, name last macro, otherwise name last change command.
The following CHAR will be the name for the command or macro."
(interactive "P\nc")
(vi-set-last-change-command 'vi-more-redo-insertion str
overwrite-p prefix-code)))
(fset (intern (char-to-string char)) vi-last-change-command)))
-
+
(defun vi-call-named-change-or-macro (count char)
"Execute COUNT times the keyboard macro definition named by the following CHAR."
(interactive "p\nc")
(setq char (read-char))
(vi-ask-for-info char))))
+(declare-function c-mark-function "cc-cmds" ())
+
(defun vi-mark-region (arg region)
"Mark region appropriately. The next char REGION is d(efun),s(-exp),b(uffer),
p(aragraph), P(age), f(unction in C/Pascal etc.), w(ord), e(nd of sentence),
l(ines)."
(interactive "p\nc")
- (cond ((char-equal region ?d) (mark-defun arg))
+ (cond ((char-equal region ?d) (mark-defun))
((char-equal region ?s) (mark-sexp arg))
((char-equal region ?b) (mark-whole-buffer))
- ((char-equal region ?p) (mark-paragraph arg))
+ ((char-equal region ?p) (mark-paragraph))
((char-equal region ?P) (mark-page arg))
- ((char-equal region ?f) (mark-c-function arg))
+ ((char-equal region ?f) (c-mark-function))
((char-equal region ?w) (mark-word arg))
((char-equal region ?e) (mark-end-of-sentence arg))
((char-equal region ?l) (vi-mark-lines arg))
(goto-char (point-min))
(if (re-search-forward (concat "^(def[unvarconst ]*" name) nil t)
nil
- (message "No definition for \"%s\" in current file." name (ding))
+ (ding)
+ (message "No definition for \"%s\" in current file." name)
(set-mark-command t))))
(defun vi-split-open-line (arg)
(if flag (forward-char 1))))) arg)
t))
+(provide 'vi)
+
+;; arch-tag: ac9bdac3-8acb-4ddd-bdae-c6dd873153b3
;;; vi.el ends here