|
|
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))
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.