Annotation of 43BSDReno/contrib/emacs-18.55/lisp/vi.el, revision 1.1

1.1     ! root        1: ; Evi: Major mode for emulating "vi" editor under GNU Emacs.
        !             2: ; Originally written by : [email protected] (Neal Ziring)
        !             3: ; Extensively redesigned and rewritten by [email protected] (Felix S.T. Wu)
        !             4: ; Last revision: 01/07/87 Wed (for GNU Emacs 18.33)
        !             5: ;
        !             6: ; INSTALLATION PROCEDURE:
        !             7: ; 1) Add a global key binding for command "vi-mode" (I use ESC ESC instead of
        !             8: ;    the single ESC used in real "vi", so I can access other ESC prefixed emacs
        !             9: ;    commands while I'm in "vi"), say, by putting the following line in your
        !            10: ;    ".emacs" file:
        !            11: ;    (define-key global-map "\e\e" 'vi-mode) ;quick switch into vi-mode
        !            12: ; 2) If you wish you can define "find-file-hooks" to enter "vi" automatically
        !            13: ;    after a file is loaded into the buffer. For example, I defined it as:
        !            14: ;    (setq find-file-hooks (list
        !            15: ;                            (function (lambda ()
        !            16: ;                                (if (not (or (eq major-mode 'Info-mode)
        !            17: ;                                            (eq major-mode 'vi-mode)))
        !            18: ;                                    (vi-mode))))))
        !            19: ; 3) In your .emacs file you can define the command "vi-mode" to be "autoload"
        !            20: ;    or you can execute the "load" command to load "vi" directly.
        !            21: ; 4) Read the comments for command "vi-mode" before you start using it.   
        !            22: ;
        !            23: ; COULD DO
        !            24: ; 1). A general 'define-operator' function to replace current hack
        !            25: ; 2). In operator handling, should allow other point moving Emacs commands
        !            26: ;     (such as ESC <, ESC >) to be used as arguments.
        !            27: ;
        !            28: 
        !            29: (defun vi-switch-mode (arg mode-char)
        !            30:   "Switch the major mode of current buffer as specified by the following char \\{vi-tilde-map}"
        !            31:   (interactive "P\nc")
        !            32:   (let ((mode-cmd (lookup-key vi-tilde-map (char-to-string mode-char))))
        !            33:     (if (null mode-cmd)
        !            34:        (with-output-to-temp-buffer "*Help*"
        !            35:          (princ (substitute-command-keys "Possible major modes to switch to: \\{vi-tilde-map}")))
        !            36:       (setq prefix-arg arg)            ; prefix arg will be passed down
        !            37:       (command-execute mode-cmd nil)   ; may need to save mode-line-format etc
        !            38:       (set-buffer-modified-p (buffer-modified-p))))) ; just in case
        !            39: 
        !            40: 
        !            41: (if (null (where-is-internal 'vi-switch-mode (current-local-map)))
        !            42:     (define-key ctl-x-map "~" 'vi-switch-mode))
        !            43: 
        !            44: (defvar vi-tilde-map nil
        !            45:   "Keymap used for \\[vi-switch-mode] prefix key.  Link to various major modes.")
        !            46: 
        !            47: (if vi-tilde-map
        !            48:     nil
        !            49:   (setq vi-tilde-map (make-keymap))
        !            50:   (define-key vi-tilde-map "a" 'abbrev-mode)
        !            51:   (define-key vi-tilde-map "c" 'c-mode)
        !            52:   (define-key vi-tilde-map "d" 'vi-debugging)
        !            53:   (define-key vi-tilde-map "e" 'emacs-lisp-mode)
        !            54:   (define-key vi-tilde-map "f" 'auto-fill-mode)
        !            55:   (define-key vi-tilde-map "g" 'prolog-mode)
        !            56:   (define-key vi-tilde-map "h" 'hanoi)
        !            57:   (define-key vi-tilde-map "i" 'info-mode)
        !            58:   (define-key vi-tilde-map "l" 'lisp-mode)
        !            59:   (define-key vi-tilde-map "n" 'nroff-mode)
        !            60:   (define-key vi-tilde-map "o" 'overwrite-mode)
        !            61:   (define-key vi-tilde-map "O" 'outline-mode)
        !            62:   (define-key vi-tilde-map "P" 'picture-mode)
        !            63:   (define-key vi-tilde-map "r" 'vi-readonly-mode)
        !            64:   (define-key vi-tilde-map "t" 'text-mode)
        !            65:   (define-key vi-tilde-map "v" 'vi-mode)
        !            66:   (define-key vi-tilde-map "x" 'tex-mode)
        !            67:   (define-key vi-tilde-map "~" 'vi-back-to-old-mode))
        !            68: 
        !            69: (defun vi-debugging (arg)
        !            70:   "Toggle debug-on-error flag.  If prefix arg is given, set t."
        !            71:   (interactive "P")
        !            72:   (if arg
        !            73:       (setq debug-on-error t)
        !            74:     (setq debug-on-error (not debug-on-error)))
        !            75:   (if debug-on-error
        !            76:       (message "Debug-on-error ...")
        !            77:     (message "NO more debug-on-error")))
        !            78: 
        !            79: (defun vi-back-to-old-mode ()
        !            80:   "Go back to the previous mode without setting up for insertion."
        !            81:   (interactive)
        !            82:   (if vi-mode-old-major-mode
        !            83:       (progn
        !            84:        (setq mode-name vi-mode-old-mode-name)
        !            85:        (use-local-map vi-mode-old-local-map)
        !            86:        (setq major-mode vi-mode-old-major-mode)
        !            87:        (setq case-fold-search vi-mode-old-case-fold)
        !            88:        (set-buffer-modified-p (buffer-modified-p)))))
        !            89: 
        !            90: (defun vi-readonly-mode ()
        !            91:   "Toggle current buffer's readonly flag."
        !            92:   (interactive)
        !            93:   (setq buffer-read-only (not buffer-read-only)))
        !            94: 
        !            95: (defvar vi-com-map nil
        !            96:    "Keymap used in Evi's command state
        !            97: Command state includes most of the vi editing commands, with some Emacs
        !            98: command extensions.")
        !            99: 
        !           100: (put 'vi-undefined 'suppress-keymap t)
        !           101: (if vi-com-map nil
        !           102:   (setq vi-com-map (make-keymap))
        !           103: ;;(fillarray vi-com-map 'vi-undefined)
        !           104:   (define-key vi-com-map "\C-@" 'vi-mark-region) ; extension
        !           105:   (define-key vi-com-map "\C-a" 'vi-ask-for-info)  ; extension
        !           106:   (define-key vi-com-map "\C-b" 'vi-backward-windowfull)
        !           107:   (define-key vi-com-map "\C-c" 'vi-do-old-mode-C-c-command) ; extension
        !           108:   (define-key vi-com-map "\C-d" 'vi-scroll-down-window)
        !           109:   (define-key vi-com-map "\C-e" 'vi-expose-line-below)
        !           110:   (define-key vi-com-map "\C-f" 'vi-forward-windowfull)
        !           111:   (define-key vi-com-map "\C-g" 'keyboard-quit)
        !           112:   (define-key vi-com-map "\C-i" 'indent-relative-maybe) ; TAB
        !           113:   (define-key vi-com-map "\C-j" 'vi-next-line) ; LFD
        !           114:   (define-key vi-com-map "\C-k" 'vi-kill-line) ; extension
        !           115:   (define-key vi-com-map "\C-l" 'recenter)
        !           116:   (define-key vi-com-map "\C-m" 'vi-next-line-first-nonwhite) ; RET
        !           117:   (define-key vi-com-map "\C-n" 'vi-next-line)
        !           118:   (define-key vi-com-map "\C-o" 'vi-split-open-line)
        !           119:   (define-key vi-com-map "\C-p" 'previous-line)
        !           120:   (define-key vi-com-map "\C-q" 'vi-query-replace) ; extension
        !           121:   (define-key vi-com-map "\C-r" 'vi-isearch-backward) ; modification
        !           122:   (define-key vi-com-map "\C-s" 'vi-isearch-forward)  ; extension
        !           123:   (define-key vi-com-map "\C-t" 'vi-transpose-objects) ; extension
        !           124:   (define-key vi-com-map "\C-u" 'vi-scroll-up-window)
        !           125:   (define-key vi-com-map "\C-v" 'scroll-up) ; extension
        !           126:   (define-key vi-com-map "\C-w" 'vi-kill-region)   ; extension
        !           127:   (define-key vi-com-map "\C-x" 'Control-X-prefix) ; extension
        !           128:   (define-key vi-com-map "\C-y" 'vi-expose-line-above)
        !           129:   (define-key vi-com-map "\C-z" 'suspend-emacs)
        !           130: 
        !           131:   (define-key vi-com-map "\e"   'ESC-prefix); C-[ (ESC)
        !           132:   (define-key vi-com-map "\C-\\" 'vi-unimplemented)
        !           133:   (define-key vi-com-map "\C-]" 'find-tag)
        !           134:   (define-key vi-com-map "\C-^" 'vi-locate-def)  ; extension
        !           135:   (define-key vi-com-map "\C-_" 'vi-undefined) 
        !           136: 
        !           137:   (define-key vi-com-map " " 'forward-char)
        !           138:   (define-key vi-com-map "!"  'vi-operator)
        !           139:   (define-key vi-com-map "\"" 'vi-char-argument)
        !           140:   (define-key vi-com-map "#"  'universal-argument) ; extension
        !           141:   (define-key vi-com-map "$"  'end-of-line)
        !           142:   (define-key vi-com-map "%"  'vi-find-matching-paren)
        !           143:   (define-key vi-com-map "&"  'vi-unimplemented)
        !           144:   (define-key vi-com-map "'"  'vi-goto-line-mark)
        !           145:   (define-key vi-com-map "("  'backward-sexp)
        !           146:   (define-key vi-com-map ")"  'forward-sexp)
        !           147:   (define-key vi-com-map "*"  'vi-name-last-change-or-macro) ; extension
        !           148:   (define-key vi-com-map "+"  'vi-next-line-first-nonwhite)
        !           149:   (define-key vi-com-map ","  'vi-reverse-last-find-char)
        !           150:   (define-key vi-com-map "-"  'vi-previous-line-first-nonwhite)
        !           151:   (define-key vi-com-map "."  'vi-redo-last-change-command)
        !           152:   (define-key vi-com-map "/"  'vi-search-forward)
        !           153:   (define-key vi-com-map "0"  'beginning-of-line)
        !           154: 
        !           155:   (define-key vi-com-map "1"  'vi-digit-argument)
        !           156:   (define-key vi-com-map "2"  'vi-digit-argument)
        !           157:   (define-key vi-com-map "3"  'vi-digit-argument)
        !           158:   (define-key vi-com-map "4"  'vi-digit-argument)
        !           159:   (define-key vi-com-map "5"  'vi-digit-argument)
        !           160:   (define-key vi-com-map "6"  'vi-digit-argument)
        !           161:   (define-key vi-com-map "7"  'vi-digit-argument)
        !           162:   (define-key vi-com-map "8"  'vi-digit-argument)
        !           163:   (define-key vi-com-map "9"  'vi-digit-argument)
        !           164: 
        !           165:   (define-key vi-com-map ":"  'vi-ex-cmd)
        !           166:   (define-key vi-com-map ";"  'vi-repeat-last-find-char)
        !           167:   (define-key vi-com-map "<"  'vi-operator)
        !           168:   (define-key vi-com-map "="  'vi-operator)
        !           169:   (define-key vi-com-map ">"  'vi-operator)
        !           170:   (define-key vi-com-map "?"  'vi-search-backward)
        !           171:   (define-key vi-com-map "@"  'vi-call-named-change-or-macro) ; extension
        !           172: 
        !           173:   (define-key vi-com-map "A"  'vi-append-at-end-of-line)
        !           174:   (define-key vi-com-map "B"  'vi-backward-blank-delimited-word)
        !           175:   (define-key vi-com-map "C"  'vi-change-rest-of-line)
        !           176:   (define-key vi-com-map "D"  'vi-kill-line)
        !           177:   (define-key vi-com-map "E"  'vi-end-of-blank-delimited-word)
        !           178:   (define-key vi-com-map "F"  'vi-backward-find-char)
        !           179:   (define-key vi-com-map "G"  'vi-goto-line)
        !           180:   (define-key vi-com-map "H"  'vi-home-window-line)
        !           181:   (define-key vi-com-map "I"  'vi-insert-before-first-nonwhite)
        !           182:   (define-key vi-com-map "J"  'vi-join-lines)
        !           183:   (define-key vi-com-map "K"  'vi-undefined) 
        !           184:   (define-key vi-com-map "L"  'vi-last-window-line)
        !           185:   (define-key vi-com-map "M"  'vi-middle-window-line)
        !           186:   (define-key vi-com-map "N"  'vi-reverse-last-search)
        !           187:   (define-key vi-com-map "O"  'vi-open-above)
        !           188:   (define-key vi-com-map "P"  'vi-put-before)
        !           189:   (define-key vi-com-map "Q"  'vi-quote-words) ; extension
        !           190:   (define-key vi-com-map "R"  'vi-replace-chars)
        !           191:   (define-key vi-com-map "S"  'vi-substitute-lines)
        !           192:   (define-key vi-com-map "T"  'vi-backward-upto-char)
        !           193:   (define-key vi-com-map "U"  'vi-unimplemented)
        !           194:   (define-key vi-com-map "V"  'vi-undefined) 
        !           195:   (define-key vi-com-map "W"  'vi-forward-blank-delimited-word)
        !           196:   (define-key vi-com-map "X"  'call-last-kbd-macro) ; modification/extension
        !           197:   (define-key vi-com-map "Y"  'vi-yank-line)
        !           198:   (define-key vi-com-map "Z" (make-sparse-keymap)) ;allow below prefix command
        !           199:   (define-key vi-com-map "ZZ" 'vi-save-all-and-exit)
        !           200: 
        !           201:   (define-key vi-com-map "["  'vi-unimplemented)
        !           202:   (define-key vi-com-map "\\" 'vi-operator) ; extension for vi-narrow-op
        !           203:   (define-key vi-com-map "]"  'vi-unimplemented)
        !           204:   (define-key vi-com-map "^"  'back-to-indentation)
        !           205:   (define-key vi-com-map "_"  'vi-undefined)
        !           206:   (define-key vi-com-map "`"  'vi-goto-char-mark)
        !           207: 
        !           208:   (define-key vi-com-map "a"  'vi-insert-after)
        !           209:   (define-key vi-com-map "b"  'backward-word)
        !           210:   (define-key vi-com-map "c"  'vi-operator)
        !           211:   (define-key vi-com-map "d"  'vi-operator)
        !           212:   (define-key vi-com-map "e"  'vi-end-of-word)
        !           213:   (define-key vi-com-map "f"  'vi-forward-find-char)
        !           214:   (define-key vi-com-map "g"  'vi-beginning-of-buffer) ; extension
        !           215:   (define-key vi-com-map "h"  'backward-char)
        !           216:   (define-key vi-com-map "i"  'vi-insert-before)
        !           217:   (define-key vi-com-map "j"  'vi-next-line)
        !           218:   (define-key vi-com-map "k"  'previous-line)
        !           219:   (define-key vi-com-map "l"  'forward-char)
        !           220:   (define-key vi-com-map "m"  'vi-set-mark)
        !           221:   (define-key vi-com-map "n"  'vi-repeat-last-search)
        !           222:   (define-key vi-com-map "o"  'vi-open-below)
        !           223:   (define-key vi-com-map "p"  'vi-put-after)
        !           224:   (define-key vi-com-map "q"  'vi-replace)
        !           225:   (define-key vi-com-map "r"  'vi-replace-1-char)
        !           226:   (define-key vi-com-map "s"  'vi-substitute-chars)
        !           227:   (define-key vi-com-map "t"  'vi-forward-upto-char)
        !           228:   (define-key vi-com-map "u"  'undo)
        !           229:   (define-key vi-com-map "v"  'vi-verify-spelling) 
        !           230:   (define-key vi-com-map "w"  'vi-forward-word)
        !           231:   (define-key vi-com-map "x"  'vi-kill-char)
        !           232:   (define-key vi-com-map "y"  'vi-operator)
        !           233:   (define-key vi-com-map "z"  'vi-adjust-window)
        !           234: 
        !           235:   (define-key vi-com-map "{"  'backward-paragraph)
        !           236:   (define-key vi-com-map "|"  'vi-goto-column)
        !           237:   (define-key vi-com-map "}"  'forward-paragraph)
        !           238:   (define-key vi-com-map "~"  'vi-change-case)
        !           239:   (define-key vi-com-map "\177" 'delete-backward-char))
        !           240: 
        !           241: (put 'backward-char 'point-moving-unit 'char)
        !           242: (put 'vi-next-line 'point-moving-unit 'line)
        !           243: (put 'next-line 'point-moving-unit 'line)
        !           244: (put 'forward-line 'point-moving-unit 'line)
        !           245: (put 'previous-line 'point-moving-unit 'line)
        !           246: (put 'vi-isearch-backward 'point-moving-unit 'search)
        !           247: (put 'vi-search-backward 'point-moving-unit 'search)
        !           248: (put 'vi-isearch-forward 'point-moving-unit 'search)
        !           249: (put 'vi-search-forward 'point-moving-unit 'search)
        !           250: (put 'forward-char 'point-moving-unit 'char)
        !           251: (put 'end-of-line 'point-moving-unit 'char)
        !           252: (put 'vi-find-matching-paren 'point-moving-unit 'match)
        !           253: (put 'vi-goto-line-mark 'point-moving-unit 'line)
        !           254: (put 'backward-sexp 'point-moving-unit 'sexp)
        !           255: (put 'forward-sexp 'point-moving-unit 'sexp)
        !           256: (put 'vi-next-line-first-nonwhite 'point-moving-unit 'line)
        !           257: (put 'vi-previous-line-first-nonwhite 'point-moving-unit 'line)
        !           258: (put 'vi-reverse-last-find-char 'point-moving-unit 'rev-find)
        !           259: (put 'vi-re-search-forward 'point-moving-unit 'search)
        !           260: (put 'beginning-of-line 'point-moving-unit 'char)
        !           261: (put 'vi-beginning-of-buffer 'point-moving-unit 'char)
        !           262: (put 'vi-repeat-last-find-char 'point-moving-unit 'find)
        !           263: (put 'vi-re-search-backward 'point-moving-unit 'search)
        !           264: (put 'vi-backward-blank-delimited-word 'point-moving-unit 'WORD)
        !           265: (put 'vi-end-of-blank-delimited-word 'point-moving-unit 'match)
        !           266: (put 'vi-backward-find-char 'point-moving-unit 'find)
        !           267: (put 'vi-goto-line 'point-moving-unit 'line)
        !           268: (put 'vi-home-window-line 'point-moving-unit 'line)
        !           269: (put 'vi-last-window-line 'point-moving-unit 'line)
        !           270: (put 'vi-middle-window-line 'point-moving-unit 'line)
        !           271: (put 'vi-reverse-last-search 'point-moving-unit 'rev-search)
        !           272: (put 'vi-backward-upto-char 'point-moving-unit 'find)
        !           273: (put 'vi-forward-blank-delimited-word 'point-moving-unit 'WORD)
        !           274: (put 'back-to-indentation 'point-moving-unit 'char)
        !           275: (put 'vi-goto-char-mark 'point-moving-unit 'char)
        !           276: (put 'backward-word 'point-moving-unit 'word)
        !           277: (put 'vi-end-of-word 'point-moving-unit 'match)
        !           278: (put 'vi-forward-find-char 'point-moving-unit 'find)
        !           279: (put 'backward-char 'point-moving-unit 'char)
        !           280: (put 'vi-forward-char 'point-moving-unit 'char)
        !           281: (put 'vi-repeat-last-search 'point-moving-unit 'search)
        !           282: (put 'vi-forward-upto-char 'point-moving-unit 'find)
        !           283: (put 'vi-forward-word 'point-moving-unit 'word)
        !           284: (put 'vi-goto-column 'point-moving-unit 'match)
        !           285: (put 'forward-paragraph 'point-moving-unit 'paragraph)
        !           286: (put 'backward-paragraph 'point-moving-unit 'paragraph)
        !           287: 
        !           288: ;;; region mark commands
        !           289: (put 'mark-page 'point-moving-unit 'region)
        !           290: (put 'mark-paragraph 'point-moving-unit 'region)
        !           291: (put 'mark-word 'point-moving-unit 'region)
        !           292: (put 'mark-sexp 'point-moving-unit 'region)
        !           293: (put 'mark-defun 'point-moving-unit 'region)
        !           294: (put 'mark-whole-buffer 'point-moving-unit 'region)
        !           295: (put 'mark-end-of-sentence 'point-moving-unit 'region)
        !           296: (put 'mark-c-function 'point-moving-unit 'region)
        !           297: ;;;
        !           298: 
        !           299: (defvar vi-mark-alist nil
        !           300:   "Alist of (NAME . MARK), marks are local to each buffer.")
        !           301: 
        !           302: (defvar vi-scroll-amount (/ (window-height) 2)
        !           303:   "Default amount of lines for scrolling (used by "^D"/"^U").")
        !           304: 
        !           305: (defvar vi-shift-width 4
        !           306:   "Shift amount for "<"/">" operators.")
        !           307: 
        !           308: (defvar vi-ins-point nil               ; integer
        !           309:   "Last insertion point.  Should use 'mark' instead.")
        !           310: 
        !           311: (defvar vi-ins-length nil              ; integer
        !           312:   "Length of last insertion.")
        !           313: 
        !           314: (defvar vi-ins-repetition nil          ; integer
        !           315:   "The repetition required for last insertion.")
        !           316: 
        !           317: (defvar vi-ins-overwrt-p nil           ; boolean
        !           318:   "T if last insertion was a replace actually.")
        !           319: 
        !           320: (defvar vi-ins-prefix-code nil         ; ready-to-eval sexp
        !           321:   "Code to be eval'ed before (redo-)insertion begins.")
        !           322: 
        !           323: (defvar vi-last-find-char nil          ; cons cell
        !           324:   "Save last direction, char and upto-flag used for char finding.")
        !           325: 
        !           326: (defvar vi-last-change-command nil     ; cons cell
        !           327:   "Save commmands for redoing last changes.  Each command is in (FUNC . ARGS)
        !           328: form that is ready to be 'apply'ed.")
        !           329: 
        !           330: (defvar vi-last-shell-command nil      ; last shell op command line
        !           331:   "Save last shell command given for \"!\" operator.")
        !           332: 
        !           333: (defvar vi-insert-state nil             ; boolean
        !           334:   "T if it is in insert state.")
        !           335: 
        !           336: ; in "loaddefs.el"
        !           337: ;(defvar search-last-string "" 
        !           338: ;  "Last string search for by a search command.")
        !           339: 
        !           340: (defvar vi-search-last-command nil     ; (re-)search-forward(backward)
        !           341:   "Save last search command for possible redo.")
        !           342: 
        !           343: (defvar vi-mode-old-local-map nil
        !           344:   "Save the local-map used before entering vi-mode.")
        !           345: 
        !           346: (defvar vi-mode-old-mode-name nil
        !           347:   "Save the mode-name before entering vi-mode.")
        !           348:   
        !           349: (defvar vi-mode-old-major-mode nil
        !           350:   "Save the major-mode before entering vi-mode.")
        !           351: 
        !           352: (defvar vi-mode-old-case-fold nil)
        !           353:   
        !           354: ;(defconst vi-add-to-mode-line-1
        !           355: ;  '(overwrite-mode nil " Insert"))
        !           356: 
        !           357: ;; Value is same as vi-add-to-mode-line-1 when in vi mode,
        !           358: ;; but nil in other buffers.
        !           359: ;(defvar vi-add-to-mode-line nil)
        !           360: 
        !           361: (defun vi-mode-setup ()
        !           362:   "Setup a buffer for vi-mode by creating necessary buffer-local variables."
        !           363: ;  (make-local-variable 'vi-add-to-mode-line)
        !           364: ;  (setq vi-add-to-mode-line vi-add-to-mode-line-1)
        !           365: ;  (or (memq vi-add-to-mode-line minor-mode-alist)
        !           366: ;      (setq minor-mode-alist (cons vi-add-to-mode-line minor-mode-alist)))
        !           367:   (make-local-variable 'vi-scroll-amount)
        !           368:   (setq vi-scroll-amount (/ (window-height) 2))
        !           369:   (make-local-variable 'vi-shift-width)
        !           370:   (setq vi-shift-width 4)
        !           371:   (make-local-variable 'vi-ins-point)
        !           372:   (make-local-variable 'vi-ins-length)
        !           373:   (make-local-variable 'vi-ins-repetition)
        !           374:   (make-local-variable 'vi-ins-overwrt-p)
        !           375:   (make-local-variable 'vi-ins-prefix-code)
        !           376:   (make-local-variable 'vi-last-change-command)
        !           377:   (make-local-variable 'vi-last-shell-command)
        !           378:   (make-local-variable 'vi-last-find-char)
        !           379:   (make-local-variable 'vi-mark-alist)
        !           380:   (make-local-variable 'vi-insert-state)
        !           381:   (make-local-variable 'vi-mode-old-local-map)
        !           382:   (make-local-variable 'vi-mode-old-mode-name)
        !           383:   (make-local-variable 'vi-mode-old-major-mode)
        !           384:   (make-local-variable 'vi-mode-old-case-fold)
        !           385:   (run-hooks 'vi-mode-hook))
        !           386:       
        !           387: (defun vi-mode ()
        !           388:   "Major mode that acts like the `vi' editor.
        !           389: The purpose of this mode is to provide you the combined power of vi (namely,
        !           390: the \"cross product\" effect of commands and repeat last changes) and Emacs.
        !           391: 
        !           392: This command redefines nearly all keys to look like vi commands.
        !           393: It records the previous major mode, and any vi command for input
        !           394: \(`i', `a', `s', etc.) switches back to that mode.
        !           395: Thus, ordinary Emacs (in whatever major mode you had been using)
        !           396: is \"input\" mode as far as vi is concerned.
        !           397: 
        !           398: To get back into vi from \"input\" mode, you must issue this command again.
        !           399: Therefore, it is recommended that you assign it to a key.
        !           400: 
        !           401: Major differences between this mode and real vi :
        !           402: 
        !           403: * Limitations and unsupported features
        !           404:   - Search patterns with line offset (e.g. /pat/+3 or /pat/z.) are
        !           405:     not supported.
        !           406:   - Ex commands are not implemented; try ':' to get some hints.
        !           407:   - No line undo (i.e. the 'U' command), but multi-undo is a standard feature.
        !           408: 
        !           409: * Modifications
        !           410:   - The stopping positions for some point motion commands (word boundary,
        !           411:     pattern search) are slightly different from standard 'vi'.
        !           412:     Also, no automatic wrap around at end of buffer for pattern searching.
        !           413:   - Since changes are done in two steps (deletion then insertion), you need
        !           414:     to undo twice to completely undo a change command.  But this is not needed
        !           415:     for undoing a repeated change command.
        !           416:   - No need to set/unset 'magic', to search for a string with regular expr
        !           417:     in it just put a prefix arg for the search commands.  Replace cmds too.
        !           418:   - ^R is bound to incremental backward search, so use ^L to redraw screen.
        !           419: 
        !           420: * Extensions
        !           421:   - Some standard (or modified) Emacs commands were integrated, such as
        !           422:     incremental search, query replace, transpose objects, and keyboard macros.
        !           423:   - In command state, ^X links to the 'ctl-x-map', and ESC can be linked to
        !           424:     esc-map or set undefined.  These can give you the full power of Emacs.
        !           425:   - See vi-com-map for those keys that are extensions to standard vi, e.g.
        !           426:     `vi-name-last-change-or-macro', `vi-verify-spelling', `vi-locate-def',
        !           427:     `vi-mark-region', and 'vi-quote-words'.  Some of them are quite handy.
        !           428:   - Use \\[vi-switch-mode] to switch among different modes quickly.
        !           429:   
        !           430: Syntax table and abbrevs while in vi mode remain as they were in Emacs."
        !           431:    (interactive)
        !           432:    (if (null vi-mode-old-major-mode)   ; very first call for current buffer
        !           433:        (vi-mode-setup))
        !           434: 
        !           435:    (if (eq major-mode 'vi-mode)
        !           436:        (message "Already in vi-mode." (ding))
        !           437:      (setq vi-mode-old-local-map (current-local-map))
        !           438:      (setq vi-mode-old-mode-name mode-name)
        !           439:      (setq vi-mode-old-major-mode major-mode)
        !           440:      (setq vi-mode-old-case-fold case-fold-search) ; this is needed !!
        !           441:      (setq case-fold-search nil)       ; exact case match in searching
        !           442:      (use-local-map vi-com-map)
        !           443:      (setq major-mode 'vi-mode)
        !           444:      (setq mode-name "VI")
        !           445:      (set-buffer-modified-p (buffer-modified-p))  ; force mode line update
        !           446:      (if vi-insert-state               ; this is a return from insertion
        !           447:          (vi-end-of-insert-state))))
        !           448: 
        !           449: (defun vi-ding()
        !           450:   "Ding !"
        !           451:   (interactive)
        !           452:   (ding))
        !           453: 
        !           454: (defun vi-save-all-and-exit ()
        !           455:   "Save all modified buffers without asking, then exits emacs."
        !           456:   (interactive)
        !           457:   (save-some-buffers t)
        !           458:   (kill-emacs))
        !           459: 
        !           460: ;; to be used by "ex" commands
        !           461: (defvar vi-replaced-string nil)
        !           462: (defvar vi-replacing-string nil)
        !           463: 
        !           464: (defun vi-ex-cmd ()
        !           465:   "Ex commands are not implemented in Evi mode.  For some commonly used ex
        !           466: commands, you can use the following alternatives for similar effect :
        !           467: w            C-x C-s (save-buffer)
        !           468: wq           C-x C-c (save-buffers-kill-emacs)
        !           469: w fname      C-x C-w (write-file)
        !           470: e fname      C-x C-f (find-file)
        !           471: r fname      C-x i   (insert-file)
        !           472: s/old/new    use q (vi-replace) to do unconditional replace
        !           473:              use C-q (vi-query-replace) to do query replace
        !           474: set sw=n     M-x set-variable vi-shift-width n "
        !           475:   (interactive)
        !           476: ;; (let ((cmd (read-string ":")) (lines 1))
        !           477: ;;  (cond ((string-match "s"))))
        !           478:   (with-output-to-temp-buffer "*Help*"
        !           479:     (princ (documentation 'vi-ex-cmd))))
        !           480: 
        !           481: (defun vi-undefined ()
        !           482:   (interactive)
        !           483:   (message "Command key \"%s\" is undefined in Evi."
        !           484:           (single-key-description last-command-char))
        !           485:   (ding))
        !           486: 
        !           487: (defun vi-unimplemented ()
        !           488:   (interactive)
        !           489:   (message "Command key \"%s\" is not implemented in Evi."
        !           490:           (single-key-description last-command-char))
        !           491:   (ding))
        !           492: 
        !           493: ;;;;;
        !           494: (defun vi-goto-insert-state (repetition &optional prefix-code do-it-now-p)
        !           495:   "Go into insert state, the text entered will be repeated if REPETITION > 1.
        !           496: If PREFIX-CODE is given, do it before insertion begins if DO-IT-NOW-P is T.
        !           497: In any case, the prefix-code will be done before each 'redo-insert'.
        !           498: This function expects 'overwrite-mode' being set properly beforehand."
        !           499:   (if do-it-now-p (apply (car prefix-code) (cdr prefix-code)))
        !           500:   (setq vi-ins-point (point))
        !           501:   (setq vi-ins-repetition repetition)
        !           502:   (setq vi-ins-prefix-code prefix-code)
        !           503:   (setq mode-name vi-mode-old-mode-name)
        !           504:   (setq case-fold-search vi-mode-old-case-fold)
        !           505:   (use-local-map vi-mode-old-local-map)
        !           506:   (setq major-mode vi-mode-old-major-mode)
        !           507:   (set-buffer-modified-p (buffer-modified-p))  ; force mode line update
        !           508:   (setq vi-insert-state t))
        !           509: 
        !           510: (defun vi-end-of-insert-state ()
        !           511:   "Terminate insertion and set up last change command."
        !           512:   (if (or (< (point) vi-ins-point)    ;Check if there is any effective change
        !           513:          (and (= (point) vi-ins-point) (null vi-ins-prefix-code))
        !           514:          (<= vi-ins-repetition 0))
        !           515:       (vi-goto-command-state t)
        !           516:     (if (> vi-ins-repetition 1)
        !           517:        (progn 
        !           518:          (let ((str (buffer-substring vi-ins-point (point))))
        !           519:            (while (> vi-ins-repetition 1)
        !           520:              (insert str)
        !           521:              (setq vi-ins-repetition (1- vi-ins-repetition))))))
        !           522:     (vi-set-last-change-command 'vi-first-redo-insertion vi-ins-point (point)
        !           523:                             overwrite-mode vi-ins-prefix-code)
        !           524:     (vi-goto-command-state t)))
        !           525: 
        !           526: (defun vi-first-redo-insertion (begin end &optional overwrite-p prefix-code)
        !           527:   "Redo last insertion the first time.  Extract the string and save it for
        !           528: future redoes.  Do prefix-code if it's given, use overwrite mode if asked."
        !           529:   (let ((str (buffer-substring begin end)))
        !           530:     (if prefix-code (apply (car prefix-code) (cdr prefix-code)))
        !           531:     (if overwrite-p (delete-region (point) (+ (point) (length str))))
        !           532:     (insert str)
        !           533:     (vi-set-last-change-command 'vi-more-redo-insertion str overwrite-p prefix-code)))
        !           534: 
        !           535: (defun vi-more-redo-insertion (str &optional overwrite-p prefix-code)
        !           536:   "Redo more insertion : copy string from STR to point, use overwrite mode
        !           537: if overwrite-p is T; apply prefix-code first if it's non-nil."
        !           538:   (if prefix-code (apply (car prefix-code) (cdr prefix-code)))
        !           539:   (if overwrite-p (delete-region (point) (+ (point) (length str))))
        !           540:   (insert str))
        !           541: 
        !           542: (defun vi-goto-command-state (&optional from-insert-state-p)
        !           543:   "Go to vi-mode command state.  If optional arg exists, means return from
        !           544: insert state."
        !           545:   (use-local-map vi-com-map)
        !           546:   (setq vi-insert-state nil)
        !           547:   (if from-insert-state-p
        !           548:       (if overwrite-mode
        !           549:          (overwrite-mode 0)
        !           550: ;      (set-minor-mode 'ins "Insert" nil)
        !           551:        )))
        !           552: 
        !           553: (defun vi-kill-line (arg)
        !           554:    "kill specified number of lines (=d$), text saved in the kill ring."
        !           555:    (interactive "*P")
        !           556:    (kill-line arg)
        !           557:    (vi-set-last-change-command 'kill-line arg))
        !           558: 
        !           559: (defun vi-kill-region ()
        !           560:   (interactive)
        !           561:   (kill-region)
        !           562:   (vi-set-last-change-command 'kill-region))
        !           563:   
        !           564: (defun vi-append-at-end-of-line (arg)
        !           565:    "go to end of line and then go into vi insert state."
        !           566:    (interactive "*p")
        !           567:    (vi-goto-insert-state arg '(end-of-line) t))
        !           568: 
        !           569: (defun vi-change-rest-of-line (arg)
        !           570:   "Change the rest of (ARG) lines (= c$ in vi)."
        !           571:   (interactive "*P")
        !           572:   (vi-goto-insert-state 1 (list 'kill-line arg) t))
        !           573: 
        !           574: (defun vi-insert-before-first-nonwhite (arg)
        !           575:   "(= ^i in vi)"
        !           576:   (interactive "*p")
        !           577:   (vi-goto-insert-state arg '(back-to-indentation) t))
        !           578: 
        !           579: (defun vi-open-above (arg)
        !           580:   "open new line(s) above current line and enter insert state."
        !           581:   (interactive "*p")
        !           582:   (vi-goto-insert-state 1
        !           583:                        (list (function (lambda (x)
        !           584:                                          (or (beginning-of-line)
        !           585:                                              (open-line x)))) arg)
        !           586:                        t))
        !           587: 
        !           588: (defun vi-open-below (arg)
        !           589:   "open new line(s) and go into insert mode on the last line."
        !           590:   (interactive "*p")
        !           591:   (vi-goto-insert-state 1
        !           592:                        (list (function (lambda (x)
        !           593:                                          (or (end-of-line)
        !           594:                                            (open-line x)
        !           595:                                            (forward-line x)))) arg)
        !           596:                        t))
        !           597: 
        !           598: (defun vi-insert-after (arg)
        !           599:    "start vi insert state after cursor."
        !           600:    (interactive "*p")
        !           601:    (vi-goto-insert-state arg
        !           602:                         (list (function (lambda ()
        !           603:                                           (if (not (eolp)) (forward-char)))))
        !           604:                         t))
        !           605: 
        !           606: (defun vi-insert-before (arg)
        !           607:   "enter insert state before the cursor."
        !           608:   (interactive "*p")
        !           609:   (vi-goto-insert-state arg))
        !           610: 
        !           611: (defun vi-goto-line (arg)
        !           612:    "Go to ARGth line."
        !           613:    (interactive "P")
        !           614:    (if (null (vi-raw-numeric-prefix arg))
        !           615:        (end-of-buffer)
        !           616:      (goto-line (vi-prefix-numeric-value arg))))
        !           617: 
        !           618: (defun vi-beginning-of-buffer ()
        !           619:   "Move point to the beginning of current buffer."
        !           620:   (interactive)
        !           621:   (goto-char (point-min)))
        !           622: 
        !           623: ;;;;; not used now
        !           624: ;;(defvar regexp-search t              ; string
        !           625: ;;  "*T if search string can contain regular expressions. (= set magic in vi)")
        !           626: ;;;;;
        !           627: 
        !           628: (defun vi-isearch-forward (arg)
        !           629:   "Incremental search forward.  Use regexp version if ARG is non-nil." 
        !           630:   (interactive "P")
        !           631:   (let ((scmd (if arg 'isearch-forward-regexp 'isearch-forward))
        !           632:        (opoint (point)))
        !           633:     (call-interactively scmd)
        !           634:     (if (= opoint (point))
        !           635:        nil
        !           636:       (setq vi-search-last-command (if arg 're-search-forward 'search-forward)))))
        !           637: 
        !           638: (defun vi-isearch-backward (arg)
        !           639:   "Incremental search backward.  Use regexp version if ARG is non-nil."
        !           640:   (interactive "P")
        !           641:   (let ((scmd (if arg 'isearch-backward-regexp 'isearch-backward))
        !           642:        (opoint (point)))
        !           643:     (call-interactively scmd)
        !           644:     (if (= opoint (point))
        !           645:        nil
        !           646:       (setq vi-search-last-command (if arg 're-search-backward 'search-backward)))))
        !           647: 
        !           648: (defun vi-search-forward (arg string)
        !           649:    "Nonincremental search forward. Use regexp version if ARG is non-nil."
        !           650:    (interactive (if current-prefix-arg
        !           651:                    (list t (read-string "regexp/" nil))
        !           652:                  (list nil (read-string "/" nil))))
        !           653:    (setq vi-search-last-command (if arg 're-search-forward 'search-forward))
        !           654:    (if (> (length string) 0) (setq search-last-string string)) 
        !           655:    (funcall vi-search-last-command search-last-string nil nil 1))
        !           656: 
        !           657: (defun vi-search-backward (arg string)
        !           658:    "Nonincremental search backward.  Use regexp version if ARG is non-nil."
        !           659:    (interactive (if current-prefix-arg
        !           660:                    (list t (read-string "regexp?" nil))
        !           661:                  (list nil (read-string "?" nil))))
        !           662:    (setq vi-search-last-command (if arg 're-search-backward 'search-backward))
        !           663:    (if (> (length string) 0) (setq search-last-string string)) 
        !           664:    (funcall vi-search-last-command search-last-string nil nil 1))
        !           665: 
        !           666: (defun vi-repeat-last-search (arg &optional search-command search-string)
        !           667:    "Repeat last search command.  If optional search-command/string are given,
        !           668: use those instead of the ones saved."
        !           669:    (interactive "p")
        !           670:    (if (null search-command) (setq search-command vi-search-last-command))
        !           671:    (if (null search-string) (setq search-string search-last-string))
        !           672:    (if (null search-command)
        !           673:        (message "No last search command to repeat." (ding))
        !           674:      (funcall search-command search-string nil nil arg)))
        !           675: 
        !           676: (defun vi-reverse-last-search (arg &optional search-command search-string)
        !           677:   "Redo last search command in reverse direction. If the optional search args
        !           678: are given, use those instead of the ones saved."
        !           679:   (interactive "p")
        !           680:   (if (null search-command) (setq search-command vi-search-last-command))
        !           681:   (if (null search-string) (setq search-string search-last-string))
        !           682:   (if (null search-command)
        !           683:       (message "No last search command to repeat." (ding))
        !           684:     (funcall (cond ((eq search-command 're-search-forward) 're-search-backward)
        !           685:                   ((eq search-command 're-search-backward) 're-search-forward)
        !           686:                   ((eq search-command 'search-forward) 'search-backward)
        !           687:                   ((eq search-command 'search-backward) 'search-forward))
        !           688:             search-string nil nil arg)))
        !           689:        
        !           690: (defun vi-join-lines (arg)
        !           691:    "join ARG lines from current line (default 2), cleaning up white space."
        !           692:    (interactive "P")
        !           693:    (if (null (vi-raw-numeric-prefix arg))
        !           694:        (delete-indentation t)
        !           695:      (setq count (vi-prefix-numeric-value arg))
        !           696:      (while (>= count 2)
        !           697:        (delete-indentation t)
        !           698:        (setq count (1- count))))
        !           699:    (vi-set-last-change-command 'vi-join-lines arg))
        !           700: 
        !           701: (defun vi-backward-kill-line ()
        !           702:    "kill the current line.  Only works in insert state."
        !           703:    (interactive)
        !           704:    (if (not vi-insert-state)
        !           705:        nil
        !           706:      (beginning-of-line 1)
        !           707:      (kill-line nil)))
        !           708: 
        !           709: (defun vi-abort-ins ()
        !           710:   "abort insert state, kill inserted text and go back to command state."
        !           711:   (interactive)
        !           712:   (if (not vi-insert-state)
        !           713:       nil
        !           714:     (if (> (point) vi-ins-point)
        !           715:           (kill-region vi-ins-point (point)))
        !           716:     (vi-goto-command-state t)))
        !           717: 
        !           718: (defun vi-backward-windowfull (count)
        !           719:   "Backward COUNT windowfulls. Default is one."
        !           720:   (interactive "p")
        !           721: ; (set-mark-command nil)
        !           722:   (while (> count 0)
        !           723:     (scroll-down nil)
        !           724:     (setq count (1- count))))
        !           725: 
        !           726: (defun vi-scroll-down-window (count)
        !           727:   "Scrolls down window COUNT lines.  If COUNT is nil (actually, non-integer),
        !           728: scrolls default amount.  The given COUNT is remembered for future scrollings."
        !           729:   (interactive "P")
        !           730:   (if (integerp count)
        !           731:       (setq vi-scroll-amount count))
        !           732:   (scroll-up vi-scroll-amount))
        !           733: 
        !           734: (defun vi-expose-line-below (count)
        !           735:   "Expose COUNT more lines below the current window.  Default COUNT is 1."
        !           736:   (interactive "p")
        !           737:   (scroll-up count))
        !           738: 
        !           739: (defun vi-forward-windowfull (count)
        !           740:   "Forward COUNT windowfulls. Default is one."
        !           741:   (interactive "p")
        !           742: ; (set-mark-command nil)
        !           743:   (while (> count 0)
        !           744:     (scroll-up nil)
        !           745:     (setq count (1- count))))
        !           746: 
        !           747: (defun vi-next-line (count)
        !           748:   "Go down count lines, try to keep at the same column."
        !           749:   (interactive "p")
        !           750:   (setq this-command 'next-line)       ; this is a needed trick
        !           751:   (if (= (point) (or (line-move count) (point)))
        !           752:       (ding)                           ; no moving, already at end of buffer
        !           753:     (setq last-command 'next-line)))
        !           754: 
        !           755: (defun vi-next-line-first-nonwhite (count)
        !           756:   "Go down COUNT lines.  Stop at first non-white."
        !           757:   (interactive "p")
        !           758:   (if (= (point) (progn (forward-line count) (back-to-indentation) (point)))
        !           759:       (ding)))                         ; no moving, already at end of buffer
        !           760: 
        !           761: (defun vi-previous-line-first-nonwhite (count)
        !           762:   "Go up COUNT lines.  Stop at first non-white."
        !           763:   (interactive "p")
        !           764:   (previous-line count)
        !           765:   (back-to-indentation))
        !           766: 
        !           767: (defun vi-scroll-up-window (count)
        !           768:   "Scrolls up window COUNT lines.  If COUNT is nil (actually, non-integer),
        !           769: scrolls default amount.  The given COUNT is remembered for future scrollings."
        !           770:   (interactive "P")
        !           771:   (if (integerp count)
        !           772:       (setq vi-scroll-amount count))
        !           773:   (scroll-down vi-scroll-amount))
        !           774: 
        !           775: (defun vi-expose-line-above (count)
        !           776:   "Expose COUNT more lines above the current window.  Default COUNT is 1."
        !           777:   (interactive "p")
        !           778:   (scroll-down count))
        !           779: 
        !           780: (defun vi-char-argument (arg)
        !           781:   "Get following character (could be any CHAR) as part of the prefix argument.
        !           782: Possible perfix-arg cases are NIL, INTEGER, (NIL . CHAR) or (INTEGER . CHAR)."
        !           783:   (interactive "P")
        !           784:   (let ((char (read-char)))
        !           785:     (cond ((null arg) (setq prefix-arg (cons nil char)))
        !           786:          ((integerp arg) (setq prefix-arg (cons arg char)))
        !           787:          ; This can happen only if the user changed his/her mind for CHAR,
        !           788:          ; Or there are some leading "universal-argument"s
        !           789:          (t (setq prefix-arg (cons (car arg) char))))))
        !           790: 
        !           791: (defun vi-goto-mark (mark-char &optional line-flag)
        !           792:   "Go to marked position or line (if line-flag is given). Goto mark '@' means
        !           793: jump into and pop the top mark on the mark ring."
        !           794:   (cond ((char-equal mark-char last-command-char)      ; `` or ''
        !           795:         (exchange-point-and-mark) (if line-flag (back-to-indentation)))
        !           796:        ((char-equal mark-char ?@)      ; jump and pop mark
        !           797:         (set-mark-command t) (if line-flag (back-to-indentation)))
        !           798:        (t
        !           799:         (let ((mark (vi-get-mark mark-char)))
        !           800:           (if (null mark)
        !           801:               (message "Mark register undefined." (vi-ding))
        !           802:             (set-mark-command nil)
        !           803:             (goto-char mark)
        !           804:             (if line-flag (back-to-indentation)))))))
        !           805:                     
        !           806: (defun vi-goto-line-mark (char)
        !           807:   "Go to the line (at first non-white) marked by next char."
        !           808:   (interactive "c")
        !           809:   (vi-goto-mark char t))
        !           810: 
        !           811: (defun vi-goto-char-mark (char)
        !           812:   "Go to the char position marked by next mark-char."
        !           813:   (interactive "c")
        !           814:   (vi-goto-mark char))
        !           815: 
        !           816: (defun vi-digit-argument (arg)
        !           817:   "Set numeric prefix argument."
        !           818:   (interactive "P")
        !           819:   (cond ((null arg) (digit-argument arg))
        !           820:        ((integerp arg) (digit-argument nil)
        !           821:                         (setq prefix-arg (* prefix-arg arg)))
        !           822:        (t (digit-argument nil)         ; in (NIL . CHAR) or (NUM . CHAR) form
        !           823:           (setq prefix-arg (cons (* prefix-arg
        !           824:                                     (if (null (car arg)) 1 (car arg)))
        !           825:                                  (cdr arg))))))
        !           826: 
        !           827: (defun vi-raw-numeric-prefix (arg)
        !           828:   "Return the raw value of numeric part prefix argument."
        !           829:   (if (consp arg) (car arg) arg))
        !           830: 
        !           831: (defun vi-prefix-numeric-value (arg)
        !           832:   "Return numeric meaning of the raw prefix argument.  This is a modification
        !           833: to the standard one provided in `callint.c' to handle (_ . CHAR) cases."
        !           834:   (cond ((null arg) 1)
        !           835:        ((integerp arg) arg)
        !           836:        ((consp arg) (if (car arg) (car arg) 1))))
        !           837: 
        !           838: (defun vi-reverse-last-find-char (count &optional find-arg)
        !           839:   "Reverse last f F t T operation COUNT times.  If the optional FIND-ARG
        !           840: is given, it is used instead of the saved one."
        !           841:   (interactive "p")
        !           842:   (if (null find-arg) (setq find-arg vi-last-find-char))
        !           843:   (if (null find-arg)
        !           844:       (message "No last find char to repeat." (ding))
        !           845:     (vi-find-char (cons (* (car find-arg) -1) (cdr find-arg)) count))) ;6/13/86
        !           846: 
        !           847: (defun vi-find-char (arg count)
        !           848:   "Find in DIRECTION (1/-1) for CHAR of COUNT'th times on current line.
        !           849: If UPTO-FLAG is T, stop before the char. ARG = (DIRECTION.CHAR.UPTO-FLAG."
        !           850:   (let* ((direction (car arg)) (char (car (cdr arg)))
        !           851:         (upto-flag (cdr (cdr arg))) (pos (+ (point) direction)))
        !           852:     (if (catch 'exit-find-char
        !           853:          (while t
        !           854:            (cond ((null (char-after pos)) (throw 'exit-find-char nil))
        !           855:                  ((char-equal (char-after pos) ?\n) (throw 'exit-find-char nil))
        !           856:                  ((char-equal char (char-after pos)) (setq count (1- count))
        !           857:                   (if (= count 0)
        !           858:                       (throw 'exit-find-char
        !           859:                              (if upto-flag
        !           860:                                  (setq pos (- pos direction))
        !           861:                                pos)))))
        !           862:            (setq pos (+ pos direction))))
        !           863:       (goto-char pos)
        !           864:     (ding))))
        !           865: 
        !           866: (defun vi-repeat-last-find-char (count &optional find-arg)
        !           867:   "Repeat last f F t T operation COUNT times.  If optional FIND-ARG is given,
        !           868: it is used instead of the saved one."
        !           869:   (interactive "p")
        !           870:   (if (null find-arg) (setq find-arg vi-last-find-char))
        !           871:   (if (null find-arg)
        !           872:       (message "No last find char to repeat." (ding))
        !           873:     (vi-find-char find-arg count)))
        !           874: 
        !           875: (defun vi-backward-find-char (count char)
        !           876:   "Find the COUNT'th CHAR backward on current line."
        !           877:   (interactive "p\nc")
        !           878:   (setq vi-last-find-char (cons -1 (cons char nil)))
        !           879:   (vi-repeat-last-find-char count))
        !           880: 
        !           881: (defun vi-forward-find-char (count char)
        !           882:   "Find the COUNT'th CHAR forward on current line."
        !           883:   (interactive "p\nc")
        !           884:   (setq vi-last-find-char (cons 1 (cons char nil)))
        !           885:   (vi-repeat-last-find-char count))
        !           886: 
        !           887: (defun vi-backward-upto-char (count char)
        !           888:   "Find upto the COUNT'th CHAR backward on current line."
        !           889:   (interactive "p\nc")
        !           890:   (setq vi-last-find-char (cons -1 (cons char t)))
        !           891:   (vi-repeat-last-find-char count))
        !           892: 
        !           893: (defun vi-forward-upto-char (count char)
        !           894:   "Find upto the COUNT'th CHAR forward on current line."
        !           895:   (interactive "p\nc")
        !           896:   (setq vi-last-find-char (cons 1 (cons char t)))
        !           897:   (vi-repeat-last-find-char count))
        !           898: 
        !           899: (defun vi-end-of-word (count)
        !           900:   "Move forward until encountering the end of a word.
        !           901: With argument, do this that many times."
        !           902:   (interactive "p")
        !           903:   (if (not (eobp)) (forward-char))
        !           904:   (if (re-search-forward "\\W*\\w+\\>" nil t count)
        !           905:       (backward-char)))
        !           906: 
        !           907: (defun vi-replace-1-char (count char)
        !           908:   "Replace char after point by CHAR.  Repeat COUNT times."
        !           909:   (interactive "p\nc")
        !           910:   (delete-char count nil)       ; don't save in kill ring
        !           911:   (setq last-command-char char)
        !           912:   (self-insert-command count)
        !           913:   (vi-set-last-change-command 'vi-replace-1-char count char))
        !           914: 
        !           915: (defun vi-replace-chars (arg)
        !           916:   "Replace chars over old ones."
        !           917:   (interactive "*p")
        !           918:   (overwrite-mode 1)
        !           919:   (vi-goto-insert-state arg))
        !           920: 
        !           921: (defun vi-substitute-chars (count)
        !           922:   "Substitute COUNT chars by the input chars, enter insert state."
        !           923:   (interactive "*p")
        !           924:   (vi-goto-insert-state 1 (list (function (lambda (c) ; this is a bit tricky
        !           925:                                            (delete-region (point)
        !           926:                                                           (+ (point) c))))
        !           927:                                count) t))
        !           928: 
        !           929: (defun vi-substitute-lines (count)
        !           930:   "Substitute COUNT lines by the input chars. (=cc in vi)"
        !           931:   (interactive "*p")
        !           932:   (vi-goto-insert-state 1 (list 'vi-delete-op 'next-line (1- count)) t))
        !           933: 
        !           934: (defun vi-prefix-char-value (arg)
        !           935:   "Get the char part of the current prefix argument."
        !           936:   (cond ((null arg) nil)
        !           937:        ((integerp arg) nil)
        !           938:        ((consp arg) (cdr arg))
        !           939:        (t nil)))
        !           940: 
        !           941: (defun vi-operator (arg)
        !           942:   "Handling vi operators (d/c/</>/!/=/y).  Current implementation requires
        !           943: the key bindings of the operators being fixed."
        !           944:   (interactive "P")
        !           945:   (catch 'vi-exit-op
        !           946:     (let ((this-op-char last-command-char))
        !           947:       (setq last-command-char (read-char))
        !           948:       (setq this-command (lookup-key vi-com-map (char-to-string last-command-char)))
        !           949:       (if (not (eq this-command 'vi-digit-argument))
        !           950:          (setq prefix-arg arg)
        !           951:        (vi-digit-argument arg)
        !           952:        (setq last-command-char (read-char))
        !           953:        (setq this-command (lookup-key vi-com-map (char-to-string last-command-char))))
        !           954:       (cond ((char-equal this-op-char last-command-char) ; line op
        !           955:             (vi-execute-op this-op-char 'next-line
        !           956:                            (cons (1- (vi-prefix-numeric-value prefix-arg))
        !           957:                                  (vi-prefix-char-value prefix-arg))))
        !           958:            ;; We assume any command that has no property 'point-moving-unit'
        !           959:            ;; as having that property with the value 'CHAR'.  3/12/86
        !           960:            (t   ;;  (get this-command 'point-moving-unit)
        !           961:             (vi-execute-op this-op-char this-command prefix-arg))))))
        !           962:            ;;   (t (throw 'vi-exit-op (ding)))))))
        !           963: 
        !           964: (defun vi-execute-op (op-char motion-command arg)
        !           965:   "Execute vi edit operator as specified by OP-CHAR, the operand is the region
        !           966: determined by the MOTION-COMMAND with ARG."
        !           967:   (cond ((= op-char ?d)
        !           968:         (if (vi-delete-op motion-command arg)
        !           969:             (vi-set-last-change-command 'vi-delete-op (vi-repeat-command-of motion-command) arg)))
        !           970:         ((= op-char ?c)
        !           971:          (if (vi-delete-op motion-command arg)
        !           972:              (vi-goto-insert-state 1 (list 'vi-delete-op
        !           973:                              (vi-repeat-command-of motion-command) arg) nil)))
        !           974:         ((= op-char ?y)
        !           975:          (if (vi-yank-op motion-command arg)
        !           976:              (vi-set-last-change-command 'vi-yank-op (vi-repeat-command-of motion-command) arg)))
        !           977:         ((= op-char ?!)
        !           978:          (if (vi-shell-op motion-command arg)
        !           979:              (vi-set-last-change-command 'vi-shell-op (vi-repeat-command-of motion-command) arg vi-last-shell-command)))
        !           980:         ((= op-char ?<)
        !           981:          (if (vi-shift-op motion-command arg (- vi-shift-width))
        !           982:              (vi-set-last-change-command 'vi-shift-op (vi-repeat-command-of motion-command) arg (- vi-shift-width))))
        !           983:         ((= op-char ?>)
        !           984:          (if (vi-shift-op motion-command arg vi-shift-width)
        !           985:              (vi-set-last-change-command 'vi-shift-op (vi-repeat-command-of motion-command) arg vi-shift-width)))
        !           986:         ((= op-char ?=)
        !           987:          (if (vi-indent-op motion-command arg)
        !           988:              (vi-set-last-change-command 'vi-indent-op (vi-repeat-command-of motion-command) arg)))
        !           989:         ((= op-char ?\\)
        !           990:          (vi-narrow-op motion-command arg))))
        !           991: 
        !           992: (defun vi-repeat-command-of (command)
        !           993:   "Return the command for redo the given command."
        !           994:   (let ((cmd-type (get command 'point-moving-unit)))
        !           995:     (cond ((eq cmd-type 'search) 'vi-repeat-last-search)
        !           996:          ((eq cmd-type 'find) 'vi-repeat-last-find-char)
        !           997:          (t command))))
        !           998: 
        !           999: (defun vi-effective-range (motion-command arg)
        !          1000:   "Return (begin . end) of the range spanned by executing the given
        !          1001: MOTION-COMMAND with ARG.
        !          1002:    MOTION-COMMAND in ready-to-eval list form is not yet supported."
        !          1003:   (save-excursion
        !          1004:     (let ((begin (point)) end opoint
        !          1005:          (moving-unit (get motion-command 'point-moving-unit)))
        !          1006:       (setq prefix-arg arg)
        !          1007:       (setq opoint (point))
        !          1008:       (command-execute motion-command nil)
        !          1009: ;; Check if there is any effective motion. Note that for single line operation
        !          1010: ;; the motion-command causes no effective point movement (since it moves up or
        !          1011: ;; down zero lines), but it should be counted as effectively moved.
        !          1012:       (if (and (= (point) opoint) (not (eq moving-unit 'line)))
        !          1013:          (cons opoint opoint)          ; no effective motion
        !          1014:        (if (eq moving-unit 'region)
        !          1015:            (setq begin (or (mark) (point))))
        !          1016:        (if (<= begin (point))
        !          1017:            (setq end (point))
        !          1018:          (setq end begin)
        !          1019:          (setq begin (point)))
        !          1020:        (cond ((or (eq moving-unit 'match) (eq moving-unit 'find))
        !          1021:               (setq end (1+ end)))
        !          1022:              ((eq moving-unit 'line)
        !          1023:               (goto-char begin) (beginning-of-line) (setq begin (point))
        !          1024:               (goto-char end) (next-line 1) (beginning-of-line) (setq end (point))))
        !          1025:        (if (> end (point-max)) (setq end (point-max))) ; force in buffer region 
        !          1026:        (cons begin end)))))
        !          1027: 
        !          1028: (defun vi-delete-op (motion-command arg)
        !          1029:   "Delete range specified by MOTION-COMMAND with ARG."
        !          1030:   (let* ((range (vi-effective-range motion-command arg))
        !          1031:         (begin (car range)) (end (cdr range)) reg)
        !          1032:     (if (= begin end)
        !          1033:        nil                             ; point not moved, abort op
        !          1034:       (setq reg (vi-prefix-char-value arg))
        !          1035:       (if (null reg)
        !          1036:          (kill-region begin end)       ; kill ring as unnamed registers
        !          1037:        (if (and (>= reg ?A) (<= reg ?Z))
        !          1038:            (append-to-register (downcase reg) begin end t)
        !          1039:          (copy-to-register reg begin end t)))
        !          1040:       t)))
        !          1041: 
        !          1042: (defun vi-yank-op (motion-command arg)
        !          1043:   "Yank (in vi sense) range specified by MOTION-COMMAND with ARG."
        !          1044:   (let* ((range (vi-effective-range motion-command arg))
        !          1045:         (begin (car range)) (end (cdr range)) reg)
        !          1046:     (if (= begin end)
        !          1047:        nil                             ; point not moved, abort op
        !          1048:       (setq reg (vi-prefix-char-value arg))
        !          1049:       (if (null reg)
        !          1050:          (copy-region-as-kill begin end); kill ring as unnamed registers
        !          1051:        (if (and (>= reg ?A) (<= reg ?Z))
        !          1052:            (append-to-register (downcase reg) begin end nil)
        !          1053:          (copy-to-register reg begin end nil)))
        !          1054:       t)))
        !          1055: 
        !          1056: (defun vi-yank-line (arg)
        !          1057:   "Yank (in vi sense) lines (= `yy' command)."
        !          1058:   (interactive "*P")
        !          1059:   (setq arg (cons (1- (vi-prefix-numeric-value arg)) (vi-prefix-char-value arg)))
        !          1060:   (if (vi-yank-op 'next-line arg)
        !          1061:       (vi-set-last-change-command 'vi-yank-op 'next-line arg)))
        !          1062: 
        !          1063: (defun vi-string-end-with-nl-p (string)
        !          1064:   "See if STRING ends with a newline char.  Used in checking whether the yanked
        !          1065: text should be put back as lines or not."
        !          1066:   (= (aref string (1- (length string))) ?\n))
        !          1067: 
        !          1068: (defun vi-put-before (arg &optional after-p)
        !          1069:   "Put yanked (in vi sense) text back before/above cursor.  If a numeric prefix
        !          1070: value (currently it should be >1) is given, put back text as lines.
        !          1071: If the optional after-p is given, put after/below the cursor."
        !          1072:   (interactive "P")
        !          1073:   (let ((reg (vi-prefix-char-value arg)) put-text)
        !          1074:     (if (and reg (or (< reg ?1) (> reg ?9)) (null (get-register reg)))
        !          1075:        (error "Nothing in register %c" reg)
        !          1076:       (if (null reg) (setq reg ?1))    ; the default is the last text killed
        !          1077:       (setq put-text
        !          1078:            (if (and (>= reg ?1) (<= reg ?9))
        !          1079:                (let ((ring-length (length kill-ring)))
        !          1080:                  (setq this-command 'yank) ; So we may yank-pop !!
        !          1081:                  (nth (% (+ (- reg ?0 1) (- ring-length
        !          1082:                                             (length kill-ring-yank-pointer)))
        !          1083:                          ring-length) kill-ring))
        !          1084:              (if (stringp (get-register reg))
        !          1085:                  (get-register reg)
        !          1086:                (error "Register %c is not containing text string" reg))))
        !          1087:       (if (vi-string-end-with-nl-p put-text) ; put back text as lines
        !          1088:          (if after-p
        !          1089:              (progn (next-line 1) (beginning-of-line))
        !          1090:            (beginning-of-line))
        !          1091:        (if after-p (forward-char 1)))
        !          1092:       (push-mark (point))
        !          1093:       (insert put-text)
        !          1094:       (exchange-point-and-mark)
        !          1095: ;;    (back-to-indentation)      ; this is not allowed if we allow yank-pop
        !          1096:       (vi-set-last-change-command 'vi-put-before arg after-p))))
        !          1097: 
        !          1098: (defun vi-put-after (arg)
        !          1099:   "Put yanked (in vi sense) text back after/below cursor."
        !          1100:   (interactive "P")
        !          1101:   (vi-put-before arg t))
        !          1102: 
        !          1103: (defun vi-shell-op (motion-command arg &optional shell-command)
        !          1104:   "Perform shell command (as filter) on range specified by MOTION-COMMAND
        !          1105: with ARG. If SHELL-COMMAND is not given, ask for one from minibuffer.
        !          1106: If char argument is given, it directs the output to a *temp* buffer."
        !          1107:   (let* ((range (vi-effective-range motion-command arg))
        !          1108:         (begin (car range)) (end (cdr range)))
        !          1109:     (if (= begin end)
        !          1110:        nil                             ; point not moved, abort op
        !          1111:       (cond ((null shell-command)
        !          1112:             (setq shell-command (read-string "!" nil))
        !          1113:             (setq vi-last-shell-command shell-command)))
        !          1114:       (shell-command-on-region begin end shell-command (not (vi-prefix-char-value arg)))
        !          1115:       t)))
        !          1116: 
        !          1117: (defun vi-shift-op (motion-command arg amount)
        !          1118:   "Perform shift command on range specified by MOTION-COMMAND with ARG for
        !          1119: AMOUNT on each line.  Negative amount means shift left.
        !          1120: SPECIAL FEATURE: char argument can be used to specify shift amount(1-9)."
        !          1121:   (let* ((range (vi-effective-range motion-command arg))
        !          1122:         (begin (car range)) (end (cdr range)))
        !          1123:     (if (= begin end)
        !          1124:        nil                             ; point not moved, abort op
        !          1125:       (if (vi-prefix-char-value arg)
        !          1126:          (setq amount (if (> amount 0)
        !          1127:                           (- (vi-prefix-char-value arg) ?0)
        !          1128:                         (- ?0 (vi-prefix-char-value arg)))))
        !          1129:       (indent-rigidly begin end amount)
        !          1130:       t)))
        !          1131: 
        !          1132: (defun vi-indent-op (motion-command arg)
        !          1133:   "Perform indent command on range specified by MOTION-COMMAND with ARG."
        !          1134:   (let* ((range (vi-effective-range motion-command arg))
        !          1135:         (begin (car range)) (end (cdr range)))
        !          1136:     (if (= begin end)
        !          1137:        nil                             ; point not moved, abort op
        !          1138:       (indent-region begin end nil)    ; insert TAB as indent command
        !          1139:       t)))
        !          1140: 
        !          1141: (defun vi-narrow-op (motion-command arg)
        !          1142:   "Narrow to region specified by MOTION-COMMAND with ARG."
        !          1143:   (let* ((range (vi-effective-range motion-command arg))
        !          1144:         (begin (car range)) (end (cdr range)) reg)
        !          1145:     (if (= begin end)
        !          1146:        nil                             ; point not moved, abort op
        !          1147:       (narrow-to-region begin end))))
        !          1148: 
        !          1149: (defun vi-get-mark (char)
        !          1150:   "Return contents of vi mark register named CHAR, or nil if undefined."
        !          1151:   (cdr (assq char vi-mark-alist)))
        !          1152: 
        !          1153: (defun vi-set-mark (char)
        !          1154:   "Set contents of vi mark register named CHAR to current point. '@' is the
        !          1155: special anonymous mark register."
        !          1156:   (interactive "c")
        !          1157:   (if (char-equal char ?@)
        !          1158:       (set-mark-command nil)
        !          1159:     (let ((aelt (assq char vi-mark-alist)))
        !          1160:       (if aelt
        !          1161:          (move-marker (cdr aelt) (point)) ; fixed 6/12/86
        !          1162:        (setq aelt (cons char (copy-marker (point))))
        !          1163:        (setq vi-mark-alist (cons aelt vi-mark-alist))))))
        !          1164: 
        !          1165: (defun vi-find-matching-paren ()
        !          1166:   "Locate the matching paren.  It's a hack right now."
        !          1167:   (interactive)
        !          1168:   (cond ((looking-at "[[({]") (forward-sexp 1) (backward-char 1))
        !          1169:        ((looking-at "[])}]") (forward-char 1) (backward-sexp 1))
        !          1170:         (t (ding))))
        !          1171: 
        !          1172: (defun vi-backward-blank-delimited-word (count)
        !          1173:   "Backward COUNT blank-delimited words."
        !          1174:   (interactive "p")
        !          1175:   (if (re-search-backward "[ \t\n\`][^ \t\n\`]+" nil t count)
        !          1176:       (if (not (bobp)) (forward-char 1))))
        !          1177: 
        !          1178: (defun vi-forward-blank-delimited-word (count)
        !          1179:   "Forward COUNT blank-delimited words."
        !          1180:   (interactive "p")
        !          1181:   (if (re-search-forward "[^ \t\n]*[ \t\n]+[^ \t\n]" nil t count)
        !          1182:       (if (not (eobp)) (backward-char 1))))
        !          1183: 
        !          1184: (defun vi-end-of-blank-delimited-word (count)
        !          1185:   "Forward to the end of the COUNT'th blank-delimited word."
        !          1186:   (interactive "p")
        !          1187:   (if (re-search-forward "[^ \t\n\']+[ \t\n\']" nil t count)
        !          1188:       (if (not (eobp)) (backward-char 2))))
        !          1189: 
        !          1190: (defun vi-home-window-line (arg)
        !          1191:   "To window home or arg'th line from the top of the window."
        !          1192:   (interactive "p")
        !          1193:   (move-to-window-line (1- arg))
        !          1194:   (back-to-indentation))
        !          1195: 
        !          1196: (defun vi-last-window-line (arg)
        !          1197:   "To window last line or arg'th line from the bottom of the window."
        !          1198:   (interactive "p")
        !          1199:   (move-to-window-line (- arg))
        !          1200:   (back-to-indentation))
        !          1201: 
        !          1202: (defun vi-middle-window-line ()
        !          1203:   "To the middle line of the window."
        !          1204:   (interactive)
        !          1205:   (move-to-window-line nil)
        !          1206:   (back-to-indentation))
        !          1207: 
        !          1208: (defun vi-forward-word (count)
        !          1209:   "Stop at the beginning of the COUNT'th words from point."
        !          1210:   (interactive "p")
        !          1211:   (if (re-search-forward "\\w*\\W+\\<" nil t count)
        !          1212:       t
        !          1213:     (vi-ding)))
        !          1214: 
        !          1215: (defun vi-set-last-change-command (fun &rest args)
        !          1216:   "Set (FUN . ARGS) as the last-change-command."
        !          1217:   (setq vi-last-change-command (cons fun args)))
        !          1218: 
        !          1219: (defun vi-redo-last-change-command (count &optional command)
        !          1220:   "Redo last change command COUNT times.  If the optional COMMAND is given,
        !          1221: it is used instead of the current last-change-command."
        !          1222:   (interactive "p")
        !          1223:   (if (null command)
        !          1224:       (setq command vi-last-change-command))
        !          1225:   (if (null command)
        !          1226:       (message "No last change command available.")
        !          1227:     (while (> count 0)
        !          1228:       (apply (car command) (cdr command))
        !          1229:       (setq count (1- count)))))
        !          1230: 
        !          1231: (defun vi-kill-char (count)
        !          1232:   "Kill COUNT chars from current point."
        !          1233:   (interactive "*p")
        !          1234:   (delete-char count t)                        ; save in kill ring
        !          1235:   (vi-set-last-change-command 'delete-char count t))
        !          1236: 
        !          1237: (defun vi-transpose-objects (arg unit)
        !          1238:   "Transpose objects, the following char specifies unit of objects to be
        !          1239: transposed -- \"c\" for chars, \"l\" for lines, \"w\" for words, \"s\" for
        !          1240:  sexp, \"p\" for paragraph.
        !          1241: For the use of the prefix-arg, refer to individual functions called."
        !          1242:   (interactive "*P\nc")
        !          1243:   (if (char-equal unit ??)
        !          1244:       (progn
        !          1245:        (message "Transpose: c(har), l(ine), p(aragraph), s(-exp), w(ord),")
        !          1246:        (setq unit (read-char))))
        !          1247:   (vi-set-last-change-command 'vi-transpose-objects arg unit)
        !          1248:   (cond ((char-equal unit ?c) (transpose-chars arg))
        !          1249:        ((char-equal unit ?l) (transpose-lines (vi-prefix-numeric-value arg)))
        !          1250:        ((char-equal unit ?p) (transpose-paragraphs (vi-prefix-numeric-value arg)))
        !          1251:        ((char-equal unit ?s) (transpose-sexps (vi-prefix-numeric-value arg)))
        !          1252:        ((char-equal unit ?w) (transpose-words (vi-prefix-numeric-value arg)))
        !          1253:        (t (vi-transpose-objects arg ??))))
        !          1254: 
        !          1255: (defun vi-query-replace (arg)
        !          1256:   "Query replace, use regexp version if ARG is non-nil."
        !          1257:   (interactive "*P")
        !          1258:   (let ((rcmd (if arg 'query-replace-regexp 'query-replace)))
        !          1259:     (call-interactively rcmd nil)))
        !          1260: 
        !          1261: (defun vi-replace (arg)
        !          1262:   "Replace strings, use regexp version if ARG is non-nil."
        !          1263:   (interactive "*P")
        !          1264:   (let ((rcmd (if arg 'replace-regexp 'replace-string)))
        !          1265:     (call-interactively rcmd nil)))
        !          1266:        
        !          1267: (defun vi-adjust-window (arg position)
        !          1268:   "Move current line to the top/center/bottom of the window."
        !          1269:   (interactive "p\nc")
        !          1270:   (cond ((char-equal position ?\r) (recenter 0))
        !          1271:        ((char-equal position ?-) (recenter -1))
        !          1272:        ((char-equal position ?.) (recenter (/ (window-height) 2)))
        !          1273:        (t (message "Move current line to: \\r(top) -(bottom) .(middle)")
        !          1274:           (setq position (read-char))
        !          1275:           (vi-adjust-window arg position))))
        !          1276: 
        !          1277: (defun vi-goto-column (col)
        !          1278:   "Go to given column of the current line."
        !          1279:   (interactive "p")
        !          1280:   (let ((opoint (point)))
        !          1281:     (beginning-of-line)
        !          1282:     (while (> col 1)
        !          1283:       (if (eolp)
        !          1284:          (setq col 0)
        !          1285:        (forward-char 1)
        !          1286:        (setq col (1- col))))
        !          1287:     (if (= col 1)
        !          1288:        t
        !          1289:       (goto-char opoint)
        !          1290:       (ding))))
        !          1291: 
        !          1292: (defun vi-name-last-change-or-macro (arg char)
        !          1293:   "Give name to the last change command or just defined kbd macro.  If prefix
        !          1294: ARG is given, name last macro, otherwise name last change command.  The
        !          1295: following CHAR will be the name for the command or macro."
        !          1296:   (interactive "P\nc")
        !          1297:   (if arg
        !          1298:       (name-last-kbd-macro (intern (char-to-string char)))
        !          1299:     (if (eq (car vi-last-change-command) 'vi-first-redo-insertion)
        !          1300:        (let* ((args (cdr vi-last-change-command)) ; save the insertion text
        !          1301:               (str (buffer-substring (nth 0 args) (nth 1 args)))
        !          1302:               (overwrite-p (nth 2 args))
        !          1303:               (prefix-code (nth 3 args)))
        !          1304:          (vi-set-last-change-command 'vi-more-redo-insertion str
        !          1305:                                   overwrite-p prefix-code)))
        !          1306:     (fset (intern (char-to-string char)) vi-last-change-command)))
        !          1307:   
        !          1308: (defun vi-call-named-change-or-macro (count char)
        !          1309:   "Execute COUNT times the keyboard macro definition named by the following CHAR."
        !          1310:   (interactive "p\nc")
        !          1311:   (if (stringp (symbol-function (intern (char-to-string char))))
        !          1312:       (execute-kbd-macro (intern (char-to-string char)) count)
        !          1313:     (vi-redo-last-change-command count (symbol-function (intern (char-to-string char))))))
        !          1314: 
        !          1315: (defun vi-change-case (arg)            ; could be made as an operator ?
        !          1316:   "Change the case of the char after point."
        !          1317:   (interactive "*p")
        !          1318:   (catch 'exit
        !          1319:     (if (looking-at "[a-z]")
        !          1320:        (upcase-region (point) (+ (point) arg))
        !          1321:       (if (looking-at "[A-Z]")
        !          1322:          (downcase-region (point) (+ (point) arg))
        !          1323:        (ding)
        !          1324:        (throw 'exit nil)))
        !          1325:     (vi-set-last-change-command 'vi-change-case arg) ;should avoid redundant save
        !          1326:     (forward-char arg)))
        !          1327: 
        !          1328: (defun vi-ask-for-info (char)
        !          1329:   "Inquire status info. The next CHAR will specify the particular info requested."
        !          1330:   (interactive "c")
        !          1331:   (cond ((char-equal char ?l) (what-line))
        !          1332:        ((char-equal char ?c) (what-cursor-position))
        !          1333:        ((char-equal char ?p) (what-page))
        !          1334:        (t (message "Ask for: l(ine number), c(ursor position), p(age number)")
        !          1335:           (setq char (read-char))
        !          1336:           (vi-ask-for-info char))))
        !          1337: 
        !          1338: (defun vi-mark-region (arg region)
        !          1339:   "Mark region approriately.  The next char REGION is d(efun),s(-exp),b(uffer),
        !          1340: p(aragraph), P(age), f(unction in C/Pascal etc.), w(ord), e(nd of sentence),
        !          1341: l(ines)."
        !          1342:   (interactive "p\nc")
        !          1343:   (cond ((char-equal region ?d) (mark-defun arg))
        !          1344:        ((char-equal region ?s) (mark-sexp arg))
        !          1345:        ((char-equal region ?b) (mark-whole-buffer))
        !          1346:        ((char-equal region ?p) (mark-paragraph arg))
        !          1347:        ((char-equal region ?P) (mark-page arg))
        !          1348:        ((char-equal region ?f) (mark-c-function arg))
        !          1349:        ((char-equal region ?w) (mark-word arg))
        !          1350:        ((char-equal region ?e) (mark-end-of-sentence arg))
        !          1351:        ((char-equal region ?l) (vi-mark-lines arg))
        !          1352:        (t (message "Mark: d(efun),s(-exp),b(uf),p(arag),P(age),f(unct),w(ord),e(os),l(ines)")
        !          1353:           (setq region (read-char))
        !          1354:           (vi-mark-region arg region))))
        !          1355: 
        !          1356: (defun vi-mark-lines (num)
        !          1357:   "Mark NUM of lines from current line as current region."
        !          1358:   (beginning-of-line 1)
        !          1359:   (push-mark)
        !          1360:   (end-of-line num))
        !          1361: 
        !          1362: (defun vi-verify-spelling (arg unit)
        !          1363:   "Verify spelling for the objects specified by char UNIT : [b(uffer),
        !          1364: r(egion), s(tring), w(ord) ]."
        !          1365:   (interactive "P\nc")
        !          1366:   (setq prefix-arg arg)                        ; seems not needed
        !          1367:   (cond ((char-equal unit ?b) (call-interactively 'spell-buffer))
        !          1368:        ((char-equal unit ?r) (call-interactively 'spell-region))
        !          1369:        ((char-equal unit ?s) (call-interactively 'spell-string))
        !          1370:        ((char-equal unit ?w) (call-interactively 'spell-word))
        !          1371:        (t (message "Spell check: b(uffer), r(egion), s(tring), w(ord)")
        !          1372:           (setq unit (read-char))
        !          1373:           (vi-verify-spelling arg unit))))
        !          1374: 
        !          1375: (defun vi-do-old-mode-C-c-command (arg)
        !          1376:   "This is a hack for accessing mode specific C-c commands in vi-mode."
        !          1377:   (interactive "P")
        !          1378:   (let ((cmd (lookup-key vi-mode-old-local-map
        !          1379:                         (concat "\C-c" (char-to-string (read-char))))))
        !          1380:     (if (catch 'exit-vi-mode   ; kludge hack due to dynamic binding
        !          1381:                                ; of case-fold-search
        !          1382:          (if (null cmd)
        !          1383:              (progn (ding) nil)
        !          1384:            (let ((case-fold-search vi-mode-old-case-fold)) ; a hack
        !          1385:              (setq prefix-arg arg)
        !          1386:              (command-execute cmd nil)
        !          1387:              nil)))
        !          1388:        (progn
        !          1389:          (vi-back-to-old-mode)
        !          1390:          (setq prefix-arg arg)
        !          1391:          (command-execute cmd nil)))))
        !          1392: 
        !          1393: (defun vi-quote-words (arg char)
        !          1394:   "Quote ARG words from the word point is on with the pattern specified by the
        !          1395: CHAR. Currently, CHAR could be [,{,(,\",',`,<,*, etc."
        !          1396:   (interactive "*p\nc")
        !          1397:   (while (not (string-match "[[({<\"'`*]" (char-to-string char)))
        !          1398:     (message "Enter any of [,{,(,<,\",',`,* as quoting character.")
        !          1399:     (setq char (read-char)))
        !          1400:   (vi-set-last-change-command 'vi-quote-words arg char)
        !          1401:   (if (not (looking-at "\\<")) (forward-word -1))
        !          1402:   (insert char)
        !          1403:   (cond ((char-equal char ?[) (setq char ?]))
        !          1404:        ((char-equal char ?{) (setq char ?}))
        !          1405:        ((char-equal char ?<) (setq char ?>))
        !          1406:        ((char-equal char ?() (setq char ?)))
        !          1407:        ((char-equal char ?`) (setq char ?')))
        !          1408:   (vi-end-of-word arg)
        !          1409:   (forward-char 1)
        !          1410:   (insert char))
        !          1411: 
        !          1412: (defun vi-locate-def ()
        !          1413:   "Locate definition in current file for the name before the point. It assumes
        !          1414: a `(def..' always starts at the beginning of a line."
        !          1415:   (interactive)
        !          1416:   (let (name)
        !          1417:     (save-excursion
        !          1418:       (setq name (buffer-substring (progn (vi-backward-blank-delimited-word 1)
        !          1419:                                          (skip-chars-forward "^a-zA-Z")
        !          1420:                                          (point))
        !          1421:                                   (progn (vi-end-of-blank-delimited-word 1)
        !          1422:                                          (forward-char)
        !          1423:                                          (skip-chars-backward "^a-zA-Z")
        !          1424:                                          (point)))))
        !          1425:     (set-mark-command nil)
        !          1426:     (goto-char (point-min))
        !          1427:     (if (re-search-forward (concat "^(def[unvarconst ]*" name) nil t)
        !          1428:        nil
        !          1429:       (message "No definition for \"%s\" in current file." name (ding))
        !          1430:       (set-mark-command t))))
        !          1431: 
        !          1432: (defun vi-split-open-line (arg)
        !          1433:   "Insert a newline and leave point before it.
        !          1434: With arg, inserts that many newlines."
        !          1435:   (interactive "*p")
        !          1436:   (vi-goto-insert-state 1
        !          1437:     (list (function (lambda (arg)
        !          1438:                      (let ((flag (and (bolp) (not (bobp)))))
        !          1439:                        (if flag (forward-char -1))
        !          1440:                        (while (> arg 0)
        !          1441:                          (save-excursion
        !          1442:                            (insert ?\n)
        !          1443:                            (if fill-prefix (insert fill-prefix)))
        !          1444:                          (setq arg (1- arg)))
        !          1445:                        (if flag (forward-char 1))))) arg)
        !          1446:     t))

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.