Annotation of 43BSDReno/contrib/emacs-18.55/lisp/vi.el, revision 1.1.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.