Annotation of GNUtools/emacs/lisp/vip.el, revision 1.1.1.1

1.1       root        1: ;; VIP: A VI Package for GNU Emacs (version 3.5 of September 15, 1987)
                      2: 
                      3: ;; Author: Masahiko Sato ([email protected]).  In Japan, the author's
                      4: ;; address is: [email protected]
                      5: ;; Send suggestions and bug reports to one of the above addresses.
                      6: ;; When you report a bug, be sure to include the version number of VIP and
                      7: ;; Emacs you are using.
                      8: 
                      9: ;; Execute info command by typing "M-x info" to get information on VIP.
                     10: 
                     11: ;; external variables
                     12: 
                     13: (defvar vip-emacs-local-map nil
                     14:   "Local map used in emacs mode. \(buffer specific\)")
                     15: 
                     16: (defvar vip-emacs-old-commands nil
                     17:   "Old Emacs definitions of C-x 3 and C-x TAB.")
                     18: 
                     19: (defvar vip-insert-local-map nil
                     20:   "Local map used in insert command mode. \(buffer specific\)")
                     21:   
                     22: (make-variable-buffer-local 'vip-emacs-local-map)
                     23: (make-variable-buffer-local 'vip-emacs-old-commands)
                     24: (make-variable-buffer-local 'vip-insert-local-map)
                     25: 
                     26: (defvar vip-insert-point nil
                     27:   "Remember insert point as a marker. \(buffer specific\)")
                     28: 
                     29: (set-default 'vip-insert-point (make-marker))
                     30: (make-variable-buffer-local 'vip-insert-point)
                     31: 
                     32: (defvar vip-com-point nil
                     33:   "Remember com point as a marker. \(buffer specific\)")
                     34: 
                     35: (set-default 'vip-com-point (make-marker))
                     36: (make-variable-buffer-local 'vip-com-point)
                     37: 
                     38: (defvar vip-current-mode nil
                     39:   "Current mode.  One of emacs-mode, vi-mode, insert-mode.")
                     40: 
                     41: (make-variable-buffer-local 'vip-current-mode)
                     42: (setq-default vip-current-mode 'emacs-mode)
                     43: 
                     44: (defvar vip-emacs-mode-line-buffer-identification nil
                     45:   "value of mode-line-buffer-identification in emacs-mode.")
                     46: (make-variable-buffer-local 'vip-emacs-mode-line-buffer-identification)
                     47: (setq-default vip-emacs-mode-line-buffer-identification
                     48:              '("Emacs: %17b"))
                     49: 
                     50: (defvar vip-current-major-mode nil
                     51:   "vip-current-major-mode is the major-mode vi considers it is now.
                     52: \(buffer specific\)")
                     53: 
                     54: (make-variable-buffer-local 'vip-current-major-mode)
                     55: 
                     56: (defvar vip-last-shell-com nil
                     57:   "last shell command executed by ! command")
                     58: 
                     59: (defvar vip-use-register nil
                     60:   "name of register to store deleted or yanked strings.")
                     61: 
                     62: (defvar vip-d-com nil
                     63:   "If non-nil, it's value is a list (M-COM VAL COM), and is used to
                     64: re-execute last destrcutive command")
                     65: 
                     66: (defconst vip-shift-width 8
                     67:   "*The number of colums shifted by > and < command.")
                     68: 
                     69: (defconst vip-re-replace nil
                     70:   "*If t then do regexp replace, if nil then do string replace.")
                     71: 
                     72: (defvar vip-d-char nil
                     73:   "The character remenbered by the vi \"r\" command")
                     74: 
                     75: (defvar vip-f-char nil
                     76:   "for use by \";\" command")
                     77: 
                     78: (defvar vip-F-char nil
                     79:   "for use by \".\" command")
                     80: 
                     81: (defvar vip-f-forward nil
                     82:   "for use by \";\" command")
                     83:   
                     84: (defvar vip-f-offset nil
                     85:   "for use by \";\" command")
                     86: 
                     87: (defconst vip-search-wrap-around t
                     88:   "*if t, search wraps around")
                     89: 
                     90: (defconst vip-re-search nil
                     91:   "*if t, search is reg-exp search, otherwise vanilla search.")
                     92: 
                     93: (defvar vip-s-string nil
                     94:   "last search string")
                     95: 
                     96: (defvar vip-s-forward nil
                     97:   "if t, search is forward.")
                     98: 
                     99: (defconst vip-case-fold-search nil
                    100:   "*if t, search ignores cases.")
                    101: 
                    102: (defconst vip-re-query-replace nil
                    103:   "*If t then do regexp replace, if nil then do string replace.")
                    104: 
                    105: (defconst vip-open-with-indent nil
                    106:   "*if t, indent when open a new line.")
                    107: 
                    108: (defconst vip-help-in-insert-mode nil
                    109:   "*if t then C-h is bound to help-command in insert mode, if nil then it is
                    110: bound to delete-backward-char.")
                    111: 
                    112: (defvar vip-quote-string "> "
                    113:   "string inserted at the beginning of region")
                    114: 
                    115: (defvar vip-tags-file-name "TAGS")
                    116: 
                    117: (defvar vip-inhibit-startup-message nil)
                    118: 
                    119: ;; basic set up
                    120: 
                    121: (global-set-key "\C-z" 'vip-change-mode-to-vi)
                    122: 
                    123: (defmacro vip-loop (count body)
                    124:   "(COUNT BODY) Execute BODY COUNT times."
                    125:   (list 'let (list (list 'count count))
                    126:        (list 'while (list '> 'count 0)
                    127:              body
                    128:              (list 'setq 'count (list '1- 'count)))))
                    129: 
                    130: (defun vip-push-mark-silent (&optional location)
                    131:   "Set mark at LOCATION (point, by default) and push old mark on mark ring.
                    132: No message."
                    133:   (if (null (mark))
                    134:       nil
                    135:     (setq mark-ring (cons (copy-marker (mark-marker)) mark-ring))
                    136:     (if (> (length mark-ring) mark-ring-max)
                    137:        (progn
                    138:          (move-marker (car (nthcdr mark-ring-max mark-ring)) nil)
                    139:          (setcdr (nthcdr (1- mark-ring-max) mark-ring) nil))))
                    140:   (set-mark (or location (point))))
                    141: 
                    142: (defun vip-goto-col (arg)
                    143:   "Go to ARG's column."
                    144:   (interactive "P")
                    145:   (let ((val (vip-p-val arg))
                    146:        (com (vip-getcom arg)))
                    147:     (save-excursion
                    148:       (end-of-line)
                    149:       (if (> val (1+ (current-column))) (error "")))
                    150:     (if com (move-marker vip-com-point (point)))
                    151:     (beginning-of-line)
                    152:     (forward-char (1- val))
                    153:     (if com (vip-execute-com 'vip-goto-col val com))))
                    154: 
                    155: (defun vip-refresh-mode-line ()
                    156:   "Redraw mode line."
                    157:   (set-buffer-modified-p (buffer-modified-p)))
                    158: 
                    159: (defun vip-copy-keymap (map)
                    160:   (if (null map) (make-sparse-keymap) (copy-keymap map)))
                    161: 
                    162: 
                    163: ;; changing mode
                    164: 
                    165: (defun vip-change-mode (new-mode)
                    166:   "Change mode to NEW-MODE.  NEW-MODE is either emacs-mode, vi-mode,
                    167: or insert-mode."
                    168:   (or (eq new-mode vip-current-mode)
                    169:       (progn
                    170:        (cond ((eq new-mode 'vi-mode)
                    171:               (if (eq vip-current-mode 'insert-mode)
                    172:                   (progn
                    173:                     (vip-copy-region-as-kill (point) vip-insert-point)
                    174:                     (vip-repeat-insert-command))
                    175:                 (setq vip-emacs-local-map (current-local-map)
                    176:                       vip-emacs-old-commands
                    177:                       (cons (lookup-key ctl-x-map "3")
                    178:                             (lookup-key ctl-x-map "\C-i"))
                    179:                       vip-emacs-mode-line-buffer-identification
                    180:                       mode-line-buffer-identification
                    181:                       vip-insert-local-map (vip-copy-keymap
                    182:                                             (current-local-map)))
                    183:                 (define-key ctl-x-map "3" 'vip-buffer-in-two-windows)
                    184:                 (define-key ctl-x-map "\C-i" 'insert-file))
                    185:               (vip-change-mode-line "Vi:   ")
                    186:               (use-local-map vip-mode-map))
                    187:              ((eq new-mode 'insert-mode)
                    188:               (move-marker vip-insert-point (point))
                    189:               (if (eq vip-current-mode 'emacs-mode)
                    190:                   (progn
                    191:                     (setq vip-emacs-local-map (current-local-map)
                    192:                           vip-emacs-old-commands
                    193:                           (cons (lookup-key ctl-x-map "3")
                    194:                                 (lookup-key ctl-x-map "\C-i"))
                    195:                           vip-emacs-mode-line-buffer-identification
                    196:                           mode-line-buffer-identification
                    197:                           vip-insert-local-map (vip-copy-keymap
                    198:                                                 (current-local-map)))
                    199:                     (define-key ctl-x-map "3" 'vip-buffer-in-two-windows)
                    200:                     (define-key ctl-x-map "\C-i" 'insert-file))
                    201:                 (setq vip-insert-local-map (vip-copy-keymap
                    202:                                             vip-emacs-local-map)))
                    203:               (vip-change-mode-line "Insert")
                    204:               (use-local-map vip-insert-local-map)
                    205:               (define-key vip-insert-local-map "\e" 'vip-change-mode-to-vi)
                    206:               (define-key vip-insert-local-map "\C-z" 'vip-ESC)
                    207:               (define-key vip-insert-local-map "\C-h"
                    208:                 (if vip-help-in-insert-mode 'help-command
                    209:                   'delete-backward-char))
                    210:               (define-key vip-insert-local-map "\C-w"
                    211:                 'vip-delete-backward-word))
                    212:              ((eq new-mode 'emacs-mode) 
                    213:               (vip-change-mode-line "Emacs:")
                    214:               (define-key ctl-x-map "3" (car vip-emacs-old-commands))
                    215:               (define-key ctl-x-map "\C-i" (cdr vip-emacs-old-commands))
                    216:               (use-local-map vip-emacs-local-map)))
                    217:        (setq vip-current-mode new-mode)
                    218:        (vip-refresh-mode-line))))
                    219: 
                    220: (defun vip-copy-region-as-kill (beg end)
                    221:   "If BEG and END do not belong to the same buffer, it copies empty region."
                    222:   (condition-case nil
                    223:       (copy-region-as-kill beg end)
                    224:     (error (copy-region-as-kill beg beg))))
                    225: 
                    226: (defun vip-change-mode-line (string)
                    227:   "Assuming that the mode line format contains the string \"Emacs:\", this
                    228: function replaces the string by \"Vi:   \" etc."
                    229:   (setq mode-line-buffer-identification
                    230:        (if (string= string "Emacs:")
                    231:            vip-emacs-mode-line-buffer-identification
                    232:          (list (concat string " %17b")))))
                    233: 
                    234: (defun vip-mode ()
                    235:   "Turn on VIP emulation of VI."
                    236:   (interactive)
                    237:   (if (not vip-inhibit-startup-message)
                    238:       (progn
                    239:        (switch-to-buffer "VIP Startup Message")
                    240:        (erase-buffer)
                    241:        (insert
                    242:         "VIP is a Vi emulation package for GNU Emacs.  VIP provides most Vi commands
                    243: including Ex commands.  VIP is however different from Vi in several points.
                    244: You can get more information on VIP by:
                    245:     1.  Typing `M-x info' and selecting menu item \"vip\".
                    246:     2.  Typing `C-h k' followed by a key whose description you want.
                    247:     3.  Printing VIP manual which can be found as GNU/man/vip.texinfo
                    248:     4.  Printing VIP Reference Card which can be found as GNU/etc/vipcard.tex
                    249: 
                    250: This startup message appears whenever you load VIP unless you type `y' now.
                    251: Type `n' to quit this window for now.\n")
                    252:        (goto-char (point-min))
                    253:        (if (y-or-n-p "Inhibit VIP startup message? ")
                    254:            (progn
                    255:              (save-excursion
                    256:                (set-buffer
                    257:                 (find-file-noselect (substitute-in-file-name "~/.vip")))
                    258:                (goto-char (point-max))
                    259:                (insert "\n(setq vip-inhibit-startup-message t)\n")
                    260:                (save-buffer)
                    261:                (kill-buffer (current-buffer)))
                    262:              (message "VIP startup message inhibited.")
                    263:              (sit-for 2)))
                    264:        (kill-buffer (current-buffer))
                    265:        (message "")
                    266:        (setq vip-inhibit-startup-message t)))
                    267:   (vip-change-mode-to-vi))
                    268: 
                    269: (defun vip-change-mode-to-vi ()
                    270:   "Change mode to vi mode."
                    271:   (interactive)
                    272:   (vip-change-mode 'vi-mode))
                    273: 
                    274: (defun vip-change-mode-to-insert ()
                    275:   "Change mode to insert mode."
                    276:   (interactive)
                    277:   (vip-change-mode 'insert-mode))
                    278: 
                    279: (defun vip-change-mode-to-emacs ()
                    280:   "Change mode to emacs mode."
                    281:   (interactive)
                    282:   (vip-change-mode 'emacs-mode))
                    283: 
                    284: 
                    285: ;; escape to emacs mode termporarilly
                    286: 
                    287: (defun vip-get-editor-command (l-map g-map &optional str)
                    288:   "Read characters from keyboard until an editor command is formed, using
                    289: local keymap L-MAP and global keymap G-MAP.  If the command is a
                    290: self-insert-command, the character just read is returned instead.  Optional
                    291: string STR is used as initial input string."
                    292:   (let (char l-bind g-bind)
                    293:     (setq char
                    294:          (if (or (null str) (string= str ""))
                    295:              (read-char)
                    296:            (string-to-char str)))
                    297:     (setq last-command-char char)
                    298:     (setq l-bind (vip-binding-of char l-map))
                    299:     (if (null l-bind)
                    300:        ;; since local binding is empty, we concentrate on global one.
                    301:        (progn
                    302:          (setq g-bind (vip-binding-of char g-map))
                    303:          (if (null g-bind)
                    304:              nil ;; return nil, since both bindings are void.
                    305:            (if (keymapp g-bind)
                    306:                (vip-get-editor-command nil g-bind (vip-string-tail str))
                    307:              (if (eq g-bind 'self-insert-command) char g-bind))))
                    308:       ;; local binding is nonvoid
                    309:       (if (keymapp l-bind)
                    310:          ;; since l-bind is a keymap, we consider g-bind as well.
                    311:          (progn
                    312:            (setq g-bind (vip-binding-of char g-map))
                    313:            (if (null g-bind)
                    314:                (vip-get-editor-command l-bind nil (vip-string-tail str))
                    315:              (if (keymapp g-bind)
                    316:                  ;; both bindings are keymap
                    317:                  (vip-get-editor-command l-bind g-bind (vip-string-tail str))
                    318:                ;; l-bind is a keymap, so we neglect g-bind
                    319:                (vip-get-editor-command l-bind nil (vip-string-tail str)))))
                    320:        ;; l-bind is a command
                    321:        (if (eq l-bind 'self-insert-command) char l-bind)))))
                    322: 
                    323: (defun vip-binding-of (char map)
                    324:   "Return key-binding of CHAR under keymap MAP.  It is nil if the binding
                    325: is void, or a command, or a keymap"
                    326:   (let ((val (if (listp map)
                    327:                 (cdr (assq char map))
                    328:               (aref map char))))
                    329:     (cond ((null val) nil)
                    330:          ((keymapp val)
                    331:           (if (symbolp val) (symbol-function val) val))
                    332:          (t
                    333:           ;; otherwise, it is a function which is either a real function or
                    334:           ;; a keymap fset to val.
                    335:           (let ((fun (symbol-function val)))
                    336:             (if (or (null fun) (keymapp fun)) fun val))))))
                    337: 
                    338: (defun vip-escape-to-emacs (arg &optional char)
                    339:   "Escape to emacs mode and execute one emacs command and then return to
                    340: vi mode.  ARG is used as the prefix value for the executed command.  If
                    341: CHAR is given it becomes the first character of the command."
                    342:   (interactive "P")
                    343:   (let (com (buff (current-buffer)) (first t))
                    344:     (if char (setq unread-command-char char))
                    345:     (setq prefix-arg arg)
                    346:     (while (or first (>= unread-command-char 0))
                    347:       ;; this while loop is executed until unread command char will be
                    348:       ;; exhausted.
                    349:       (setq first nil)
                    350:       (setq com (vip-get-editor-command vip-emacs-local-map global-map))
                    351:       (if (numberp com)
                    352:          (vip-loop (vip-p-val prefix-arg)
                    353:                    (insert (char-to-string com)))
                    354:        (command-execute com prefix-arg)))
                    355:     (setq prefix-arg nil)  ;; reset prefix arg
                    356:     ))
                    357: 
                    358: (defun vip-message-conditions (conditions)
                    359:   "Print CONDITIONS as a message."
                    360:   (let ((case (car conditions)) (msg (cdr conditions)))
                    361:     (if (null msg)
                    362:        (message "%s" case)
                    363:       (message "%s %s" case (prin1-to-string msg)))
                    364:     (ding)))
                    365: 
                    366: (defun vip-ESC (arg)
                    367:   "Emulate ESC key in Emacs mode."
                    368:   (interactive "P")
                    369:   (vip-escape-to-emacs arg ?\e))
                    370: 
                    371: (defun vip-ctl-c (arg)
                    372:   "Emulate C-c key in Emacs mode."
                    373:   (interactive "P")
                    374:   (vip-escape-to-emacs arg ?\C-c))
                    375: 
                    376: (defun vip-ctl-x (arg)
                    377:   "Emulate C-x key in Emacs mode."
                    378:   (interactive "P")
                    379:   (vip-escape-to-emacs arg ?\C-x))
                    380: 
                    381: (defun vip-ctl-h (arg)
                    382:   "Emulate C-h key in Emacs mode."
                    383:   (interactive "P")
                    384:   (vip-escape-to-emacs arg ?\C-h))
                    385: 
                    386: 
                    387: ;; prefix argmument for vi mode
                    388: 
                    389: ;; In vi mode, prefix argument is a dotted pair (NUM . COM) where NUM
                    390: ;; represents the numeric value of the prefix argument and COM represents
                    391: ;; command prefix such as "c", "d", "m" and "y".
                    392: 
                    393: (defun vip-prefix-arg-value (char value com)
                    394:   "Compute numeric prefix arg value.  Invoked by CHAR.  VALUE is the value
                    395: obtained so far, and COM is the command part obtained so far."
                    396:   (while (and (>= char ?0) (<= char ?9))
                    397:     (setq value (+ (* (if (numberp value) value 0) 10) (- char ?0)))       
                    398:     (setq char (read-char)))
                    399:   (setq prefix-arg value)
                    400:   (if com (setq prefix-arg (cons prefix-arg com)))
                    401:   (while (= char ?U)
                    402:     (vip-describe-arg prefix-arg)
                    403:     (setq char (read-char)))
                    404:   (setq unread-command-char char))
                    405: 
                    406: (defun vip-prefix-arg-com (char value com)
                    407:   "Vi operator as prefix argument."
                    408:   (let ((cont t))
                    409:     (while (and cont
                    410:                (or (= char ?c) (= char ?d) (= char ?y)
                    411:                    (= char ?!) (= char ?<) (= char ?>) (= char ?=)
                    412:                    (= char ?#) (= char ?r) (= char ?R) (= char ?\")))
                    413:       (if com
                    414:          ;; this means that we already have a command character, so we
                    415:          ;; construct a com list and exit while.  however, if char is "
                    416:          ;; it is an error.
                    417:          (progn
                    418:            ;; new com is (CHAR . OLDCOM)
                    419:            (if (or (= char ?#) (= char ?\")) (error ""))
                    420:            (setq com (cons char com))
                    421:            (setq cont nil))
                    422:        ;; if com is nil we set com as char, and read more.  again, if char
                    423:        ;; is ", we read the name of register and store it in vip-use-register.
                    424:        ;; if char is !, =, or #, a copmlete com is formed so we exit while.
                    425:        (cond ((or (= char ?!) (= char ?=))
                    426:               (setq com char)
                    427:               (setq char (read-char))
                    428:               (setq cont nil))
                    429:              ((= char ?#)
                    430:               ;; read a char and encode it as com
                    431:               (setq com (+ 128 (read-char)))
                    432:               (setq char (read-char))
                    433:               (setq cont nil))
                    434:              ((or (= char ?<) (= char ?>))
                    435:               (setq com char)
                    436:               (setq char (read-char))
                    437:               (if (= com char) (setq com (cons char com)))
                    438:               (setq cont nil))
                    439:              ((= char ?\")
                    440:               (let ((reg (read-char)))
                    441:                 (if (or (and (<= ?A reg) (<= reg ?z))
                    442:                         (and (<= ?1 reg) (<= reg ?9)))
                    443:                     (setq vip-use-register reg)
                    444:                   (error ""))
                    445:                 (setq char (read-char))))
                    446:              (t
                    447:               (setq com char)
                    448:               (setq char (read-char)))))))
                    449:   (if (atom com)
                    450:       ;; com is a single char, so we construct prefix-arg 
                    451:       ;; and if char is ?, describe prefix arg, otherwise exit by
                    452:       ;; pushing the char back
                    453:       (progn
                    454:        (setq prefix-arg (cons value com))
                    455:        (while (= char ?U)
                    456:          (vip-describe-arg prefix-arg)
                    457:          (setq char (read-char)))
                    458:        (setq unread-command-char char))
                    459:     ;; as com is non-nil, this means that we have a command to execute
                    460:     (if (or (= (car com) ?r) (= (car com) ?R))
                    461:        ;; execute apropriate region command.
                    462:        (let ((char (car com)) (com (cdr com)))
                    463:          (setq prefix-arg (cons value com))
                    464:          (if (= char ?r) (vip-region prefix-arg)
                    465:            (vip-Region prefix-arg))
                    466:          ;; reset prefix-arg
                    467:          (setq prefix-arg nil))
                    468:       ;; otherwise, reset prefix arg and call appropriate command
                    469:       (setq value (if (null value) 1 value))
                    470:       (setq prefix-arg nil)
                    471:       (cond ((equal com '(?c . ?c)) (vip-line (cons value ?C)))
                    472:            ((equal com '(?d . ?d)) (vip-line (cons value ?D)))
                    473:            ((equal com '(?d . ?y)) (vip-yank-defun))
                    474:            ((equal com '(?y . ?y)) (vip-line (cons value ?Y)))
                    475:            ((equal com '(?< . ?<)) (vip-line (cons value ?<)))
                    476:            ((equal com '(?> . ?>)) (vip-line (cons value ?>)))
                    477:            ((equal com '(?! . ?!)) (vip-line (cons value ?!)))
                    478:            ((equal com '(?= . ?=)) (vip-line (cons value ?=)))
                    479:            (t (error ""))))))
                    480: 
                    481: (defun vip-describe-arg (arg)
                    482:   (let (val com)
                    483:     (setq val (vip-P-val arg)
                    484:          com (vip-getcom arg))
                    485:     (if (null val)
                    486:        (if (null com)
                    487:            (message "Value is nil, and commmand is nil.")
                    488:          (message "Value is nil, and command is %c." com))
                    489:       (if (null com)
                    490:          (message "Value is %d, and command is nil." val)
                    491:        (message "Value is %d, and command is %c." val com)))))
                    492: 
                    493: (defun vip-digit-argument (arg)
                    494:   "Begin numeric argument for the next command."
                    495:   (interactive "P")
                    496:   (vip-prefix-arg-value last-command-char nil
                    497:                        (if (consp arg) (cdr arg) nil)))
                    498: 
                    499: (defun vip-command-argument (arg)
                    500:   "Accept a motion command as an argument."
                    501:   (interactive "P")
                    502:   (condition-case conditions
                    503:       (vip-prefix-arg-com
                    504:        last-command-char   
                    505:        (cond ((null arg) nil)
                    506:             ((consp arg) (car arg))
                    507:             ((numberp arg) arg)
                    508:             (t (error "strange arg")))
                    509:        (cond ((null arg) nil)
                    510:             ((consp arg) (cdr arg))
                    511:             ((numberp arg) nil)
                    512:             (t (error "strange arg"))))
                    513:     (quit
                    514:      (setq vip-use-register nil)
                    515:      (signal 'quit nil))))
                    516: 
                    517: (defun vip-p-val (arg)
                    518:   "Get value part of prefix-argument ARG."
                    519:   (cond ((null arg) 1)
                    520:        ((consp arg) (if (null (car arg)) 1 (car arg)))
                    521:        (t arg)))
                    522: 
                    523: (defun vip-P-val (arg)
                    524:   "Get value part of prefix-argument ARG."
                    525:   (cond ((consp arg) (car arg))
                    526:        (t arg)))
                    527: 
                    528: (defun vip-getcom (arg)
                    529:   "Get com part of prefix-argument ARG."
                    530:   (cond ((null arg) nil)
                    531:        ((consp arg) (cdr arg))
                    532:        (t nil)))
                    533: 
                    534: (defun vip-getCom (arg)
                    535:   "Get com part of prefix-argument ARG and modify it."
                    536:   (let ((com (vip-getcom arg)))
                    537:     (cond ((equal com ?c) ?C)
                    538:          ((equal com ?d) ?D)
                    539:          ((equal com ?y) ?Y)
                    540:          (t com))))
                    541: 
                    542: 
                    543: ;; repeat last destructive command
                    544: 
                    545: (defun vip-append-to-register (reg start end)
                    546:   "Append region to text in register REG.
                    547: START and END are buffer positions indicating what to append."
                    548:   (set-register reg (concat (or (get-register reg) "")
                    549:                            (buffer-substring start end))))
                    550: 
                    551: (defun vip-execute-com (m-com val com)
                    552:   "(M-COM VAL COM)  Execute command COM. The list (M-COM VAL COM) is set
                    553: to vip-d-com for later use by vip-repeat"
                    554:   (let ((reg vip-use-register))
                    555:     (if com
                    556:        (cond ((= com ?c) (vip-change vip-com-point (point)))
                    557:              ((= com (- ?c)) (vip-change-subr vip-com-point (point)))
                    558:              ((or (= com ?C) (= com (- ?C)))
                    559:               (save-excursion
                    560:                 (set-mark vip-com-point)
                    561:                 (vip-enlarge-region (mark) (point))
                    562:                 (if vip-use-register
                    563:                     (progn
                    564:                       (cond ((and (<= ?a vip-use-register)
                    565:                                   (<= vip-use-register ?z))
                    566:                              (copy-to-register
                    567:                               vip-use-register (mark) (point) nil))
                    568:                             ((and (<= ?A vip-use-register)
                    569:                                   (<= vip-use-register ?Z))
                    570:                              (vip-append-to-register
                    571:                               (+ vip-use-register 32) (mark) (point)))
                    572:                             (t (setq vip-use-register nil)
                    573:                                (error "")))
                    574:                       (setq vip-use-register nil)))
                    575:                 (delete-region (mark) (point)))
                    576:               (open-line 1)
                    577:               (if (= com ?C) (vip-change-mode-to-insert) (yank)))
                    578:              ((= com ?d)
                    579:               (if vip-use-register
                    580:                   (progn
                    581:                     (cond ((and (<= ?a vip-use-register)
                    582:                                 (<= vip-use-register ?z))
                    583:                            (copy-to-register
                    584:                             vip-use-register vip-com-point (point) nil))
                    585:                           ((and (<= ?A vip-use-register)
                    586:                                 (<= vip-use-register ?Z))
                    587:                            (vip-append-to-register
                    588:                             (+ vip-use-register 32) vip-com-point (point)))
                    589:                           (t (setq vip-use-register nil)
                    590:                              (error "")))
                    591:                     (setq vip-use-register nil)))
                    592:               (setq last-command
                    593:                     (if (eq last-command 'd-command) 'kill-region nil))
                    594:               (kill-region vip-com-point (point))
                    595:               (setq this-command 'd-command))
                    596:              ((= com ?D)
                    597:               (save-excursion
                    598:                 (set-mark vip-com-point)
                    599:                 (vip-enlarge-region (mark) (point))
                    600:                 (if vip-use-register
                    601:                     (progn
                    602:                       (cond ((and (<= ?a vip-use-register)
                    603:                                   (<= vip-use-register ?z))
                    604:                              (copy-to-register
                    605:                               vip-use-register (mark) (point) nil))
                    606:                             ((and (<= ?A vip-use-register)
                    607:                                   (<= vip-use-register ?Z))
                    608:                              (vip-append-to-register
                    609:                               (+ vip-use-register 32) (mark) (point)))
                    610:                             (t (setq vip-use-register nil)
                    611:                                (error "")))
                    612:                       (setq vip-use-register nil)))
                    613:                 (setq last-command
                    614:                       (if (eq last-command 'D-command) 'kill-region nil))
                    615:                 (kill-region (mark) (point))
                    616:                 (if (eq m-com 'vip-line) (setq this-command 'D-command)))
                    617:               (back-to-indentation))
                    618:              ((= com ?y)
                    619:               (if vip-use-register
                    620:                   (progn
                    621:                     (cond ((and (<= ?a vip-use-register)
                    622:                                 (<= vip-use-register ?z))
                    623:                            (copy-to-register
                    624:                             vip-use-register vip-com-point (point) nil))
                    625:                           ((and (<= ?A vip-use-register)
                    626:                                 (<= vip-use-register ?Z))
                    627:                            (vip-append-to-register
                    628:                             (+ vip-use-register 32) vip-com-point (point)))
                    629:                           (t (setq vip-use-register nil)
                    630:                              (error "")))
                    631:                     (setq vip-use-register nil)))
                    632:               (setq last-command nil)
                    633:               (copy-region-as-kill vip-com-point (point))
                    634:               (goto-char vip-com-point))
                    635:              ((= com ?Y)
                    636:               (save-excursion
                    637:                 (set-mark vip-com-point)
                    638:                 (vip-enlarge-region (mark) (point))
                    639:                 (if vip-use-register
                    640:                     (progn
                    641:                       (cond ((and (<= ?a vip-use-register)
                    642:                                   (<= vip-use-register ?z))
                    643:                              (copy-to-register
                    644:                               vip-use-register (mark) (point) nil))
                    645:                             ((and (<= ?A vip-use-register)
                    646:                                   (<= vip-use-register ?Z))
                    647:                              (vip-append-to-register
                    648:                               (+ vip-use-register 32) (mark) (point)))
                    649:                             (t (setq vip-use-register nil)
                    650:                                (error "")))
                    651:                       (setq vip-use-register nil)))
                    652:                 (setq last-command nil)
                    653:                 (copy-region-as-kill (mark) (point)))
                    654:               (goto-char vip-com-point))
                    655:              ((or (= com ?!) (= com (- ?!)))
                    656:               (save-excursion
                    657:                 (set-mark vip-com-point)
                    658:                 (vip-enlarge-region (mark) (point))
                    659:                 (shell-command-on-region
                    660:                  (mark) (point)
                    661:                  (if (= com ?!)
                    662:                      (setq vip-last-shell-com (vip-read-string "!"))
                    663:                    vip-last-shell-com)
                    664:                  t)))
                    665:              ((= com ?=)
                    666:               (save-excursion
                    667:                 (set-mark vip-com-point)
                    668:                 (vip-enlarge-region (mark) (point))
                    669:                 (if (> (mark) (point)) (exchange-point-and-mark))
                    670:                 (indent-region (mark) (point) nil)))
                    671:              ((= com ?<)
                    672:               (save-excursion
                    673:                 (set-mark vip-com-point)
                    674:                 (vip-enlarge-region (mark) (point))
                    675:                 (indent-rigidly (mark) (point) (- vip-shift-width)))
                    676:               (goto-char vip-com-point))
                    677:              ((= com ?>)
                    678:               (save-excursion
                    679:                 (set-mark vip-com-point)
                    680:                 (vip-enlarge-region (mark) (point))
                    681:                 (indent-rigidly (mark) (point) vip-shift-width))
                    682:               (goto-char vip-com-point))
                    683:              ((>= com 128)
                    684:               ;; this is special command #
                    685:               (vip-special-prefix-com (- com 128)))))
                    686:     (setq vip-d-com (list m-com val (if (or (= com ?c) (= com ?C) (= com ?!))
                    687:                                        (- com) com)
                    688:                          reg))))
                    689: 
                    690: (defun vip-repeat (arg)
                    691:   "(ARG)  Re-excute last destructive command.  vip-d-com has the form
                    692: (COM ARG CH REG), where COM is the command to be re-executed, ARG is the
                    693: argument for COM, CH is a flag for repeat, and REG is optional and if exists
                    694: is the name of the register for COM."
                    695:   (interactive "P")
                    696:   (if (eq last-command 'vip-undo)
                    697:       ;; if the last command was vip-undo, then undo-more
                    698:       (vip-undo-more)
                    699:     ;; otherwise execute the command stored in vip-d-com.  if arg is non-nil
                    700:     ;; its prefix value is used as new prefix value for the command.
                    701:     (let ((m-com (car vip-d-com))
                    702:          (val (vip-P-val arg))
                    703:          (com (car (cdr (cdr vip-d-com))))
                    704:          (reg (nth 3 vip-d-com)))
                    705:       (if (null val) (setq val (car (cdr vip-d-com))))
                    706:       (if (null m-com) (error "No previous command to repeat."))
                    707:       (setq vip-use-register reg)
                    708:       (funcall m-com (cons val com)))))
                    709: 
                    710: (defun vip-special-prefix-com (char)
                    711:   "This command is invoked interactively by the key sequence #<char>"
                    712:   (cond ((= char ?c)
                    713:         (downcase-region (min vip-com-point (point))
                    714:                          (max vip-com-point (point))))
                    715:        ((= char ?C)
                    716:         (upcase-region (min vip-com-point (point))
                    717:                        (max vip-com-point (point))))
                    718:        ((= char ?g)
                    719:         (set-mark vip-com-point)
                    720:         (vip-global-execute))
                    721:        ((= char ?q)
                    722:         (set-mark vip-com-point)
                    723:         (vip-quote-region))
                    724:        ((= char ?s) (spell-region vip-com-point (point)))))
                    725: 
                    726: 
                    727: ;; undoing
                    728: 
                    729: (defun vip-undo ()
                    730:   "Undo previous change."
                    731:   (interactive)
                    732:   (message "undo!")
                    733:   (undo-start)
                    734:   (undo-more 2)
                    735:   (setq this-command 'vip-undo))
                    736: 
                    737: (defun vip-undo-more ()
                    738:   "Continue undoing previous changes."
                    739:   (message "undo more!")
                    740:   (undo-more 1)
                    741:   (setq this-command 'vip-undo))
                    742: 
                    743: 
                    744: ;; utilities
                    745: 
                    746: (defun vip-string-tail (str)
                    747:   (if (or (null str) (string= str "")) nil
                    748:     (substring str 1)))
                    749: 
                    750: (defun vip-yank-defun ()
                    751:   (mark-defun)
                    752:   (copy-region-as-kill (point) (mark)))
                    753: 
                    754: (defun vip-enlarge-region (beg end)
                    755:   "Enlarge region between BEG and END."
                    756:   (if (< beg end)
                    757:       (progn (goto-char beg) (set-mark end))
                    758:     (goto-char end)
                    759:     (set-mark beg))
                    760:   (beginning-of-line)
                    761:   (exchange-point-and-mark)
                    762:   (if (or (not (eobp)) (not (bolp))) (next-line 1))
                    763:   (beginning-of-line)
                    764:   (if (> beg end) (exchange-point-and-mark)))
                    765: 
                    766: (defun vip-global-execute ()
                    767:   "Call last keyboad macro for each line in the region."
                    768:   (if (> (point) (mark)) (exchange-point-and-mark))
                    769:   (beginning-of-line)
                    770:   (call-last-kbd-macro)
                    771:   (while (< (point) (mark))
                    772:     (forward-line 1)
                    773:     (beginning-of-line)
                    774:     (call-last-kbd-macro)))
                    775: 
                    776: (defun vip-quote-region ()
                    777:   "Quote region by inserting the user supplied string at the beginning of
                    778: each line in the region."
                    779:   (setq vip-quote-string
                    780:        (let ((str
                    781:               (vip-read-string (format "quote string \(default \"%s\"\): "
                    782:                                        vip-quote-string))))
                    783:          (if (string= str "") vip-quote-string str)))
                    784:   (vip-enlarge-region (point) (mark))
                    785:   (if (> (point) (mark)) (exchange-point-and-mark))
                    786:   (insert vip-quote-string)
                    787:   (beginning-of-line)
                    788:   (forward-line 1)
                    789:   (while (and (< (point) (mark)) (bolp))
                    790:     (insert vip-quote-string)
                    791:     (beginning-of-line)
                    792:     (forward-line 1)))
                    793: 
                    794: (defun vip-end-with-a-newline-p (string)
                    795:   "Check if the string ends with a newline."
                    796:   (or (string= text "")
                    797:       (= (aref string (1- (length string))) ?\n)))
                    798: 
                    799: (defun vip-read-string (prompt &optional init)
                    800:   (setq save-minibuffer-local-map (copy-keymap minibuffer-local-map))
                    801:   (define-key minibuffer-local-map "\C-h" 'backward-char)
                    802:   (define-key minibuffer-local-map "\C-w" 'backward-word)
                    803:   (define-key minibuffer-local-map "\e" 'exit-minibuffer)
                    804:   (let (str)
                    805:     (condition-case conditions
                    806:        (setq str (read-string prompt init))
                    807:       (quit
                    808:        (setq minibuffer-local-map save-minibuffer-local-map)
                    809:        (signal 'quit nil)))
                    810:     (setq minibuffer-local-map save-minibuffer-local-map)
                    811:     str))
                    812: 
                    813: 
                    814: ;; insertion commands
                    815: 
                    816: (defun vip-repeat-insert-command ()
                    817:   "This function is called when mode changes from insertion mode to
                    818: vi command mode.  It will repeat the insertion command if original insertion
                    819: command was invoked with argument > 1."
                    820:   (let ((i-com (car vip-d-com)) (val (car (cdr vip-d-com))))
                    821:     (if (and val (> val 1)) ;; first check that val is non-nil
                    822:        (progn        
                    823:          (setq vip-d-com (list i-com (1- val) ?r))
                    824:          (vip-repeat nil)
                    825:          (setq vip-d-com (list i-com val ?r))))))
                    826: 
                    827: (defun vip-insert (arg) ""
                    828:   (interactive "P")
                    829:   (let ((val (vip-p-val arg)) (com (vip-getcom arg)))
                    830:     (setq vip-d-com (list 'vip-insert val ?r))
                    831:     (if com (vip-loop val (yank))
                    832:       (vip-change-mode-to-insert))))
                    833: 
                    834: (defun vip-append (arg)
                    835:   "Append after point."
                    836:   (interactive "P")
                    837:   (let ((val (vip-p-val arg)) (com (vip-getcom arg)))
                    838:     (setq vip-d-com (list 'vip-append val ?r))
                    839:     (if (not (eolp)) (forward-char))
                    840:     (if (equal com ?r)
                    841:        (vip-loop val (yank))
                    842:       (vip-change-mode-to-insert))))
                    843: 
                    844: (defun vip-Append (arg)
                    845:   "Append at end of line."
                    846:   (interactive "P")
                    847:   (let ((val (vip-p-val arg)) (com (vip-getcom arg)))
                    848:     (setq vip-d-com (list 'vip-Append val ?r))
                    849:     (end-of-line)
                    850:     (if (equal com ?r)
                    851:        (vip-loop val (yank))
                    852:       (vip-change-mode-to-insert))))
                    853: 
                    854: (defun vip-Insert (arg)
                    855:   "Insert before first non-white."
                    856:   (interactive "P")
                    857:   (let ((val (vip-p-val arg)) (com (vip-getcom arg)))
                    858:     (setq vip-d-com (list 'vip-Insert val ?r))
                    859:     (back-to-indentation)
                    860:     (if (equal com ?r)
                    861:        (vip-loop val (yank))
                    862:       (vip-change-mode-to-insert))))
                    863: 
                    864: (defun vip-open-line (arg)
                    865:   "Open line below."
                    866:   (interactive "P")
                    867:   (let ((val (vip-p-val arg)) (com (vip-getcom arg)))
                    868:     (setq vip-d-com (list 'vip-open-line val ?r))
                    869:     (let ((col (current-indentation)))
                    870:       (if (equal com ?r)
                    871:          (vip-loop val
                    872:                (progn
                    873:                  (end-of-line)
                    874:                  (newline 1)
                    875:                  (if vip-open-with-indent (indent-to col))
                    876:                  (yank)))
                    877:        (end-of-line)
                    878:        (newline 1)
                    879:        (if vip-open-with-indent (indent-to col))
                    880:        (vip-change-mode-to-insert)))))
                    881: 
                    882: (defun vip-Open-line (arg)
                    883:   "Open line above."
                    884:   (interactive "P")
                    885:   (let ((val (vip-p-val arg)) (com (vip-getcom arg)))
                    886:   (setq vip-d-com (list 'vip-Open-line val ?r))
                    887:   (let ((col (current-indentation)))
                    888:     (if (equal com ?r)
                    889:        (vip-loop val
                    890:              (progn
                    891:                (beginning-of-line)
                    892:                (open-line 1)
                    893:                (if vip-open-with-indent (indent-to col))
                    894:                (yank)))
                    895:       (beginning-of-line)
                    896:       (open-line 1)
                    897:       (if vip-open-with-indent (indent-to col))
                    898:       (vip-change-mode-to-insert)))))
                    899: 
                    900: (defun vip-open-line-at-point (arg)
                    901:   "Open line at point."
                    902:   (interactive "P")
                    903:   (let ((val (vip-p-val arg)) (com (vip-getcom arg)))
                    904:     (setq vip-d-com (list 'vip-open-line-at-point val ?r))
                    905:     (if (equal com ?r)
                    906:        (vip-loop val
                    907:              (progn
                    908:                (open-line 1)
                    909:                (yank)))
                    910:       (open-line 1)
                    911:       (vip-change-mode-to-insert))))
                    912: 
                    913: (defun vip-substitute (arg)
                    914:   "Substitute characters."
                    915:   (interactive "P")
                    916:   (let ((val (vip-p-val arg)) (com (vip-getcom arg)))
                    917:     (save-excursion
                    918:       (set-mark (point))
                    919:       (forward-char val)
                    920:       (if (equal com ?r)
                    921:          (vip-change-subr (mark) (point))
                    922:        (vip-change (mark) (point))))
                    923:     (setq vip-d-com (list 'vip-substitute val ?r))))
                    924:   
                    925: (defun vip-substitute-line (arg)
                    926:   "Substitute lines."
                    927:   (interactive "p")
                    928:   (vip-line (cons arg ?C)))
                    929: 
                    930: 
                    931: ;; line command
                    932: 
                    933: (defun vip-line (arg)
                    934:   (let ((val (car arg)) (com (cdr arg)))
                    935:     (move-marker vip-com-point (point))
                    936:     (next-line (1- val))
                    937:     (vip-execute-com 'vip-line val com)))
                    938: 
                    939: (defun vip-yank-line (arg)
                    940:   "Yank ARG lines (in vi's sense)"
                    941:   (interactive "P")
                    942:   (let ((val (vip-p-val arg)))
                    943:     (vip-line (cons val ?Y))))
                    944:     
                    945: 
                    946: ;; region command
                    947: 
                    948: (defun vip-region (arg)
                    949:   (interactive "P")
                    950:   (let ((val (vip-P-val arg))
                    951:        (com (vip-getcom arg)))
                    952:     (move-marker vip-com-point (point))
                    953:     (exchange-point-and-mark)
                    954:     (vip-execute-com 'vip-region val com)))
                    955: 
                    956: (defun vip-Region (arg)
                    957:   (interactive "P")
                    958:   (let ((val (vip-P-val arg))
                    959:        (com (vip-getCom arg)))
                    960:     (move-marker vip-com-point (point))
                    961:     (exchange-point-and-mark)
                    962:     (vip-execute-com 'vip-Region val com)))
                    963:   
                    964: (defun vip-replace-char (arg)
                    965:   "Replace the following ARG chars by the character read."
                    966:   (interactive "P")
                    967:   (let ((val (vip-p-val arg)) (com (vip-getcom arg)))
                    968:     (setq vip-d-com (list 'vip-replace-char val ?r))
                    969:     (vip-replace-char-subr (if (equal com ?r) vip-d-char (read-char)) val)))
                    970: 
                    971: (defun vip-replace-char-subr (char arg)
                    972:   (delete-char arg t)
                    973:   (setq vip-d-char char)
                    974:   (vip-loop (if (> arg 0) arg (- arg)) (insert char))
                    975:   (backward-char arg))
                    976: 
                    977: (defun vip-replace-string ()
                    978:   "Replace string.  If you supply null string as the string to be replaced,
                    979: the query replace mode will toggle between string replace and regexp replace."
                    980:   (interactive)
                    981:   (let (str)
                    982:     (setq str (vip-read-string
                    983:               (if vip-re-replace "Replace regexp: " "Replace string: ")))
                    984:     (if (string= str "")
                    985:        (progn
                    986:          (setq vip-re-replace (not vip-re-replace))
                    987:          (message (format "Replace mode changed to %s."
                    988:                           (if vip-re-replace "regexp replace"
                    989:                             "string replace"))))
                    990:       (if vip-re-replace
                    991:          (replace-regexp
                    992:           str
                    993:           (vip-read-string (format "Replace regexp \"%s\" with: " str)))
                    994:        (replace-string
                    995:         str
                    996:         (vip-read-string (format "Replace \"%s\" with: " str)))))))
                    997: 
                    998: 
                    999: ;; basic cursor movement.  j, k, l, m commands.
                   1000: 
                   1001: (defun vip-forward-char (arg)
                   1002:   "Move point right ARG characters (left if ARG negative).On reaching end
                   1003: of buffer, stop and signal error."
                   1004:   (interactive "P")
                   1005:   (let ((val (vip-p-val arg)) (com (vip-getcom arg)))
                   1006:     (if com (move-marker vip-com-point (point)))
                   1007:     (forward-char val)
                   1008:     (if com (vip-execute-com 'vip-forward-char val com))))
                   1009: 
                   1010: (defun vip-backward-char (arg)
                   1011:   "Move point left ARG characters (right if ARG negative).  On reaching
                   1012: beginning of buffer, stop and signal error."
                   1013:   (interactive "P")
                   1014:   (let ((val (vip-p-val arg)) (com (vip-getcom arg)))
                   1015:     (if com (move-marker vip-com-point (point)))
                   1016:     (backward-char val)
                   1017:     (if com (vip-execute-com 'vip-backward-char val com))))
                   1018: 
                   1019: 
                   1020: ;; word command
                   1021: 
                   1022: (defun vip-forward-word (arg)
                   1023:   "Forward word."
                   1024:   (interactive "P")
                   1025:   (let ((val (vip-p-val arg))
                   1026:        (com (vip-getcom arg)))
                   1027:     (if com (move-marker vip-com-point (point)))
                   1028:     (forward-word val)
                   1029:     (skip-chars-forward " \t\n")
                   1030:     (if com
                   1031:        (progn
                   1032:          (if (or (= com ?c) (= com (- ?c)))
                   1033:              (progn (backward-word 1) (forward-word 1)))
                   1034:          (if (or (= com ?d) (= com ?y))
                   1035:              (progn
                   1036:                (backward-word 1)
                   1037:                (forward-word 1)
                   1038:                (skip-chars-forward " \t")))
                   1039:          (vip-execute-com 'vip-forward-word val com)))))
                   1040: 
                   1041: (defun vip-end-of-word (arg)
                   1042:   "Move point to end of current word."
                   1043:   (interactive "P")
                   1044:   (let ((val (vip-p-val arg))
                   1045:        (com (vip-getcom arg)))
                   1046:     (if com (move-marker vip-com-point (point)))
                   1047:     (forward-char)
                   1048:     (forward-word val)
                   1049:     (backward-char)
                   1050:     (if com
                   1051:        (progn
                   1052:          (forward-char)
                   1053:          (vip-execute-com 'vip-end-of-word val com)))))
                   1054:                         
                   1055: (defun vip-backward-word (arg)
                   1056:   "Backward word."
                   1057:   (interactive "P")
                   1058:   (let ((val (vip-p-val arg))
                   1059:        (com (vip-getcom arg)))
                   1060:     (if com (move-marker vip-com-point (point)))
                   1061:     (backward-word val)
                   1062:     (if com (vip-execute-com 'vip-backward-word val com))))
                   1063: 
                   1064: (defun vip-forward-Word (arg)
                   1065:   "Forward word delimited by white character."
                   1066:   (interactive "P")
                   1067:   (let ((val (vip-p-val arg))
                   1068:        (com (vip-getcom arg)))
                   1069:     (if com (move-marker vip-com-point (point)))
                   1070:     (re-search-forward "[^ \t\n]*[ \t\n]+" nil t val)
                   1071:     (if com
                   1072:        (progn
                   1073:          (if (or (= com ?c) (= com (- ?c)))
                   1074:              (progn (backward-word 1) (forward-word 1)))
                   1075:          (if (or (= com ?d) (= com ?y))
                   1076:              (progn
                   1077:                (backward-word 1)
                   1078:                (forward-word 1)
                   1079:                (skip-chars-forward " \t")))
                   1080:          (vip-execute-com 'vip-forward-Word val com)))))
                   1081: 
                   1082: (defun vip-end-of-Word (arg)
                   1083:   "Move forward to end of word delimited by white character."
                   1084:   (interactive "P")
                   1085:   (let ((val (vip-p-val arg))
                   1086:        (com (vip-getcom arg)))
                   1087:     (if com (move-marker vip-com-point (point)))
                   1088:     (forward-char)
                   1089:     (if (re-search-forward "[^ \t\n]+" nil t val) (backward-char))
                   1090:     (if com
                   1091:        (progn
                   1092:          (forward-char)
                   1093:          (vip-execute-com 'vip-end-of-Word val com)))))
                   1094: 
                   1095: (defun vip-backward-Word (arg)
                   1096:   "Backward word delimited by white character."
                   1097:   (interactive "P")
                   1098:   (let ((val (vip-p-val arg))
                   1099:        (com (vip-getcom arg)))
                   1100:     (if com (move-marker vip-com-point (point)))
                   1101:     (if (re-search-backward "[ \t\n]+[^ \t\n]+" nil t val)
                   1102:        (forward-char)
                   1103:       (goto-char (point-min)))
                   1104:     (if com (vip-execute-com 'vip-backward-Word val com))))
                   1105: 
                   1106: (defun vip-beginning-of-line (arg)
                   1107:   "Go to beginning of line."
                   1108:   (interactive "P")
                   1109:   (let ((val (vip-p-val arg)) (com (vip-getcom arg)))
                   1110:     (if com (move-marker vip-com-point (point)))
                   1111:     (beginning-of-line val)
                   1112:     (if com (vip-execute-com 'vip-beginning-of-line val com))))
                   1113: 
                   1114: (defun vip-bol-and-skip-white (arg)
                   1115:   "Beginning of line at first non-white character."
                   1116:   (interactive "P")
                   1117:   (let ((val (vip-p-val arg)) (com (vip-getcom arg)))
                   1118:     (if com (move-marker vip-com-point (point)))
                   1119:     (back-to-indentation)
                   1120:     (if com (vip-execute-com 'vip-bol-and-skip-white val com))))
                   1121: 
                   1122: (defun vip-goto-eol (arg)
                   1123:   "Go to end of line."
                   1124:   (interactive "P")
                   1125:   (let ((val (vip-p-val arg)) (com (vip-getcom arg)))
                   1126:     (if com (move-marker vip-com-point (point)))
                   1127:     (end-of-line val)
                   1128:     (if com (vip-execute-com 'vip-goto-eol val com))))
                   1129: 
                   1130: (defun vip-next-line (arg)
                   1131:   "Go to next line."
                   1132:   (interactive "P")
                   1133:   (let ((val (vip-p-val arg)) (com (vip-getCom arg)))
                   1134:     (if com (move-marker vip-com-point (point)))
                   1135:     (next-line-internal val)
                   1136:     (setq this-command 'next-line)
                   1137:     (if com (vip-execute-com 'vip-next-line val com))))
                   1138: 
                   1139: (defun vip-next-line-at-bol (arg)
                   1140:   "Next line at beginning of line."
                   1141:   (interactive "P")
                   1142:   (let ((val (vip-p-val arg)) (com (vip-getCom arg)))
                   1143:     (if com (move-marker vip-com-point (point)))
                   1144:     (next-line val)
                   1145:     (back-to-indentation)
                   1146:     (if com (vip-execute-com 'vip-next-line-at-bol val com))))
                   1147: 
                   1148: (defun vip-previous-line (arg)
                   1149:   "Go to previous line."
                   1150:   (interactive "P")
                   1151:   (let ((val (vip-p-val arg)) (com (vip-getCom arg)))
                   1152:     (if com (move-marker vip-com-point (point)))
                   1153:     (next-line (- val))
                   1154:     (setq this-command 'previous-line)
                   1155:     (if com (vip-execute-com 'vip-previous-line val com))))
                   1156: 
                   1157: (defun vip-previous-line-at-bol (arg)
                   1158:   "Previous line at beginning of line."
                   1159:   (interactive "P")
                   1160:   (let ((val (vip-p-val arg)) (com (vip-getCom arg)))
                   1161:     (if com (move-marker vip-com-point (point)))
                   1162:     (next-line (- val))
                   1163:     (back-to-indentation)
                   1164:     (if com (vip-execute-com 'vip-previous-line val com))))
                   1165: 
                   1166: (defun vip-change-to-eol (arg)
                   1167:   "Change to end of line."
                   1168:   (interactive "P")
                   1169:   (vip-goto-eol (cons arg ?c)))
                   1170: 
                   1171: (defun vip-kill-line (arg)
                   1172:   "Delete line."
                   1173:   (interactive "P")
                   1174:   (vip-goto-eol (cons arg ?d)))
                   1175: 
                   1176: 
                   1177: ;; moving around
                   1178: 
                   1179: (defun vip-goto-line (arg)
                   1180:   "Go to ARG's line.  Without ARG go to end of buffer."
                   1181:   (interactive "P")
                   1182:   (let ((val (vip-P-val arg)) (com (vip-getCom arg)))
                   1183:     (move-marker vip-com-point (point))
                   1184:     (set-mark (point))
                   1185:     (if (null val)
                   1186:        (goto-char (point-max))
                   1187:       (goto-char (point-min))
                   1188:       (forward-line (1- val)))
                   1189:     (back-to-indentation)
                   1190:     (if com (vip-execute-com 'vip-goto-line val com))))
                   1191: 
                   1192: (defun vip-find-char (arg char forward offset)
                   1193:   "Find ARG's occurence of CHAR on the current line.  If FORWARD then
                   1194: search is forward, otherwise backward.  OFFSET is used to adjust point
                   1195: after search."
                   1196:   (let ((arg (if forward arg (- arg))) point)
                   1197:     (save-excursion
                   1198:       (save-restriction
                   1199:        (if (> arg 0)
                   1200:            (narrow-to-region
                   1201:             ;; forward search begins here
                   1202:             (if (eolp) (error "") (point))
                   1203:             ;; forward search ends here
                   1204:             (progn (next-line 1) (beginning-of-line) (point)))
                   1205:          (narrow-to-region
                   1206:           ;; backward search begins from here
                   1207:           (if (bolp) (error "") (point))
                   1208:           ;; backward search ends here
                   1209:           (progn (beginning-of-line) (point))))
                   1210:        ;; if arg > 0, point is forwarded before search.
                   1211:        (if (> arg 0) (goto-char (1+ (point-min)))
                   1212:          (goto-char (point-max)))
                   1213:        (let ((case-fold-search nil))
                   1214:          (search-forward (char-to-string char) nil 0 arg))
                   1215:        (setq point (point))
                   1216:        (if (or (and (> arg 0) (= point (point-max)))
                   1217:                (and (< arg 0) (= point (point-min))))
                   1218:            (error ""))))
                   1219:     (goto-char (+ point (if (> arg 0) (if offset -2 -1) (if offset 1 0))))))
                   1220: 
                   1221: (defun vip-find-char-forward (arg)
                   1222:   "Find char on the line.  If called interactively read the char to find
                   1223: from the terminal, and if called from vip-repeat, the char last used is
                   1224: used.  This behaviour is controlled by the sign of prefix numeric value."
                   1225:   (interactive "P")
                   1226:   (let ((val (vip-p-val arg)) (com (vip-getcom arg)))
                   1227:     (if (> val 0)
                   1228:        ;; this means that the function was called interactively
                   1229:        (setq vip-f-char (read-char)
                   1230:              vip-f-forward t
                   1231:              vip-f-offset nil)
                   1232:       (setq val (- val)))
                   1233:     (if com (move-marker vip-com-point (point)))
                   1234:     (vip-find-char val (if (> (vip-p-val arg) 0) vip-f-char vip-F-char) t nil)
                   1235:     (setq val (- val))
                   1236:     (if com
                   1237:        (progn
                   1238:          (setq vip-F-char vip-f-char);; set new vip-F-char
                   1239:          (forward-char)
                   1240:          (vip-execute-com 'vip-find-char-forward val com)))))
                   1241: 
                   1242: (defun vip-goto-char-forward (arg)
                   1243:   "Go up to char ARG forward on line."
                   1244:   (interactive "P")
                   1245:   (let ((val (vip-p-val arg)) (com (vip-getcom arg)))
                   1246:     (if (> val 0)
                   1247:        ;; this means that the function was called interactively
                   1248:        (setq vip-f-char (read-char)
                   1249:              vip-f-forward t
                   1250:              vip-f-offset t)
                   1251:       (setq val (- val)))
                   1252:     (if com (move-marker vip-com-point (point)))
                   1253:     (vip-find-char val (if (> (vip-p-val arg) 0) vip-f-char vip-F-char) t t)
                   1254:     (setq val (- val))
                   1255:     (if com
                   1256:        (progn
                   1257:          (setq vip-F-char vip-f-char);; set new vip-F-char
                   1258:          (forward-char)
                   1259:          (vip-execute-com 'vip-goto-char-forward val com)))))
                   1260: 
                   1261: (defun vip-find-char-backward (arg)
                   1262:   "Find char ARG on line backward."
                   1263:   (interactive "P")
                   1264:   (let ((val (vip-p-val arg)) (com (vip-getcom arg)))
                   1265:     (if (> val 0)
                   1266:        ;; this means that the function was called interactively
                   1267:        (setq vip-f-char (read-char)
                   1268:              vip-f-forward nil
                   1269:              vip-f-offset nil)
                   1270:       (setq val (- val)))
                   1271:     (if com (move-marker vip-com-point (point)))
                   1272:     (vip-find-char
                   1273:      val (if (> (vip-p-val arg) 0) vip-f-char vip-F-char) nil nil)
                   1274:     (setq val (- val))
                   1275:     (if com
                   1276:        (progn
                   1277:          (setq vip-F-char vip-f-char);; set new vip-F-char
                   1278:          (vip-execute-com 'vip-find-char-backward val com)))))
                   1279: 
                   1280: (defun vip-goto-char-backward (arg)
                   1281:   "Go up to char ARG backward on line."
                   1282:   (interactive "P")
                   1283:   (let ((val (vip-p-val arg)) (com (vip-getcom arg)))
                   1284:     (if (> val 0)
                   1285:        ;; this means that the function was called interactively
                   1286:        (setq vip-f-char (read-char)
                   1287:              vip-f-forward nil
                   1288:              vip-f-offset t)
                   1289:       (setq val (- val)))
                   1290:     (if com (move-marker vip-com-point (point)))
                   1291:     (vip-find-char val (if (> (vip-p-val arg) 0) vip-f-char vip-F-char) nil t)
                   1292:     (setq val (- val))
                   1293:     (if com
                   1294:        (progn
                   1295:          (setq vip-F-char vip-f-char);; set new vip-F-char
                   1296:          (vip-execute-com 'vip-goto-char-backward val com)))))
                   1297: 
                   1298: (defun vip-repeat-find (arg)
                   1299:   "Repeat previous find command."
                   1300:   (interactive "P")
                   1301:   (let ((val (vip-p-val arg)) (com (vip-getcom arg)))
                   1302:     (if com (move-marker vip-com-point (point)))
                   1303:     (vip-find-char val vip-f-char vip-f-forward vip-f-offset)
                   1304:     (if com
                   1305:        (progn
                   1306:          (if vip-f-forward (forward-char))
                   1307:          (vip-execute-com 'vip-repeat-find val com)))))
                   1308: 
                   1309: (defun vip-repeat-find-opposite (arg)
                   1310:   "Repeat previous find command in the opposite direction."
                   1311:   (interactive "P")
                   1312:   (let ((val (vip-p-val arg)) (com (vip-getcom arg)))
                   1313:     (if com (move-marker vip-com-point (point)))
                   1314:     (vip-find-char val vip-f-char (not vip-f-forward) vip-f-offset)
                   1315:     (if com
                   1316:        (progn
                   1317:          (if vip-f-forward (forward-char))
                   1318:          (vip-execute-com 'vip-repeat-find-opposite val com)))))
                   1319: 
                   1320: 
                   1321: ;; window scrolling etc.
                   1322: 
                   1323: (defun vip-other-window (arg)
                   1324:   "Switch to other window."
                   1325:   (interactive "p")
                   1326:   (other-window arg)
                   1327:   (or (not (eq vip-current-mode 'emacs-mode))
                   1328:       (string= (buffer-name (current-buffer)) " *Minibuf-1*")
                   1329:       (vip-change-mode-to-vi)))
                   1330: 
                   1331: (defun vip-window-top (arg)
                   1332:   "Go to home window line."
                   1333:   (interactive "P")
                   1334:   (let ((val (vip-p-val arg))
                   1335:        (com (vip-getCom arg)))
                   1336:     (if com (move-marker vip-com-point (point)))
                   1337:     (move-to-window-line (1- val))
                   1338:     (if com (vip-execute-com 'vip-window-top val com))))
                   1339: 
                   1340: (defun vip-window-middle (arg)
                   1341:   "Go to middle window line."
                   1342:   (interactive "P")
                   1343:   (let ((val (vip-p-val arg))
                   1344:        (com (vip-getCom arg)))
                   1345:     (if com (move-marker vip-com-point (point)))
                   1346:     (move-to-window-line (+ (/ (1- (window-height)) 2) (1- val)))
                   1347:     (if com (vip-execute-com 'vip-window-middle val com))))
                   1348: 
                   1349: (defun vip-window-bottom (arg)
                   1350:   "Go to last window line."
                   1351:   (interactive "P")
                   1352:   (let ((val (vip-p-val arg))
                   1353:        (com (vip-getCom arg)))
                   1354:     (if com (move-marker vip-com-point (point)))
                   1355:     (move-to-window-line (- val))
                   1356:     (if com (vip-execute-com 'vip-window-bottom val com))))
                   1357: 
                   1358: (defun vip-line-to-top (arg)
                   1359:   "Put current line on the home line."
                   1360:   (interactive "p")
                   1361:   (recenter (1- arg)))
                   1362: 
                   1363: (defun vip-line-to-middle (arg)
                   1364:   "Put current line on the middle line."
                   1365:   (interactive "p")
                   1366:   (recenter (+ (1- arg) (/ (1- (window-height)) 2))))
                   1367: 
                   1368: (defun vip-line-to-bottom (arg)
                   1369:   "Put current line on the last line."
                   1370:   (interactive "p")
                   1371:   (recenter (- (window-height) (1+ arg))))
                   1372: 
                   1373: 
                   1374: ;; paren match
                   1375: 
                   1376: (defun vip-paren-match (arg)
                   1377:   "Go to the matching parenthesis."
                   1378:   (interactive "P")
                   1379:   (let ((com (vip-getcom arg)))
                   1380:     (if (numberp arg)
                   1381:        (if (or (> arg 99) (< arg 1))
                   1382:            (error "Prefix must be between 1 and 99.")
                   1383:          (goto-char
                   1384:           (if (> (point-max) 80000)
                   1385:               (* (/ (point-max) 100) arg)
                   1386:             (/ (* (point-max) arg) 100)))
                   1387:          (back-to-indentation))
                   1388:     (cond ((looking-at "[\(\[{]")
                   1389:           (if com (move-marker vip-com-point (point)))
                   1390:           (forward-sexp 1)
                   1391:           (if com
                   1392:               (vip-execute-com 'vip-paren-match nil com)
                   1393:             (backward-char)))
                   1394:          ((looking-at "[])}]")
                   1395:           (forward-char)
                   1396:           (if com (move-marker vip-com-point (point)))
                   1397:           (backward-sexp 1)
                   1398:           (if com (vip-execute-com 'vip-paren-match nil com)))
                   1399:          (t (error ""))))))
                   1400: 
                   1401: 
                   1402: ;; sentence and paragraph
                   1403: 
                   1404: (defun vip-forward-sentence (arg)
                   1405:   "Forward sentence."
                   1406:   (interactive "P")
                   1407:   (let ((val (vip-p-val arg))
                   1408:        (com (vip-getcom arg)))
                   1409:     (if com (move-marker vip-com-point (point)))
                   1410:     (forward-sentence val)
                   1411:     (if com (vip-execute-com 'vip-forward-sentence nil com))))
                   1412: 
                   1413: (defun vip-backward-sentence (arg)
                   1414:   "Backward sentence."
                   1415:   (interactive "P")
                   1416:   (let ((val (vip-p-val arg))
                   1417:        (com (vip-getcom arg)))
                   1418:     (if com (move-marker vip-com-point (point)))
                   1419:     (backward-sentence val)
                   1420:     (if com (vip-execute-com 'vip-backward-sentence nil com))))
                   1421: 
                   1422: (defun vip-forward-paragraph (arg)
                   1423:   "Forward paragraph."
                   1424:   (interactive "P")
                   1425:   (let ((val (vip-p-val arg))
                   1426:        (com (vip-getCom arg)))
                   1427:     (if com (move-marker vip-com-point (point)))
                   1428:     (forward-paragraph val)
                   1429:     (if com (vip-execute-com 'vip-forward-paragraph nil com))))
                   1430: 
                   1431: (defun vip-backward-paragraph (arg)
                   1432:   "Backward paragraph."
                   1433:   (interactive "P")
                   1434:   (let ((val (vip-p-val arg))
                   1435:        (com (vip-getCom arg)))
                   1436:     (if com (move-marker vip-com-point (point)))
                   1437:     (backward-paragraph val)
                   1438:     (if com (vip-execute-com 'vip-backward-paragraph nil com))))
                   1439: 
                   1440: 
                   1441: ;; scrolling
                   1442: 
                   1443: (defun vip-scroll (arg)
                   1444:   "Scroll to next screen."
                   1445:   (interactive "p")
                   1446:   (if (> arg 0)
                   1447:       (while (> arg 0)
                   1448:        (scroll-up)
                   1449:        (setq arg (1- arg)))
                   1450:     (while (> 0 arg)
                   1451:       (scroll-down)
                   1452:       (setq arg (1+ arg)))))
                   1453: 
                   1454: (defun vip-scroll-back (arg)
                   1455:   "Scroll to previous screen."
                   1456:   (interactive "p")
                   1457:   (vip-scroll (- arg)))
                   1458: 
                   1459: (defun vip-scroll-down (arg)
                   1460:   "Scroll up half screen."
                   1461:   (interactive "P")
                   1462:   (if (null arg) (scroll-down (/ (window-height) 2))
                   1463:     (scroll-down arg)))
                   1464: 
                   1465: (defun vip-scroll-down-one (arg)
                   1466:   "Scroll up one line."
                   1467:   (interactive "p")
                   1468:   (scroll-down arg))
                   1469: 
                   1470: (defun vip-scroll-up (arg)
                   1471:   "Scroll down half screen."
                   1472:   (interactive "P")
                   1473:   (if (null arg) (scroll-up (/ (window-height) 2))
                   1474:     (scroll-up arg)))
                   1475: 
                   1476: (defun vip-scroll-up-one (arg)
                   1477:   "Scroll down one line."
                   1478:   (interactive "p")
                   1479:   (scroll-up arg))
                   1480: 
                   1481: 
                   1482: ;; splitting window
                   1483: 
                   1484: (defun vip-buffer-in-two-windows ()
                   1485:   "Show current buffer in two windows."
                   1486:   (interactive)
                   1487:   (delete-other-windows)
                   1488:   (split-window-vertically nil))
                   1489: 
                   1490: 
                   1491: ;; searching
                   1492: 
                   1493: (defun vip-search-forward (arg)
                   1494:   "Search a string forward.  ARG is used to find the ARG's occurence
                   1495: of the string.  Default is vanilla search.  Search mode can be toggled by
                   1496: giving null search string."
                   1497:   (interactive "P")
                   1498:   (let ((val (vip-P-val arg)) (com (vip-getcom arg)))
                   1499:     (setq vip-s-forward t
                   1500:          vip-s-string (vip-read-string (if vip-re-search "RE-/" "/")))
                   1501:     (if (string= vip-s-string "")
                   1502:        (progn
                   1503:          (setq vip-re-search (not vip-re-search))
                   1504:          (message (format "Search mode changed to %s search."
                   1505:                           (if vip-re-search "regular expression"
                   1506:                             "vanilla"))))
                   1507:       (vip-search vip-s-string t val)
                   1508:       (if com
                   1509:          (progn
                   1510:            (move-marker vip-com-point (mark))
                   1511:            (vip-execute-com 'vip-search-next val com))))))
                   1512: 
                   1513: (defun vip-search-backward (arg)
                   1514:   "Search a string backward.  ARG is used to find the ARG's occurence
                   1515: of the string.  Default is vanilla search.  Search mode can be toggled by
                   1516: giving null search string."
                   1517:   (interactive "P")
                   1518:   (let ((val (vip-P-val arg)) (com (vip-getcom arg)))
                   1519:     (setq vip-s-forward nil
                   1520:          vip-s-string (vip-read-string (if vip-re-search "RE-?" "?")))
                   1521:     (if (string= vip-s-string "")
                   1522:        (progn
                   1523:          (setq vip-re-search (not vip-re-search))
                   1524:          (message (format "Search mode changed to %s search."
                   1525:                           (if vip-re-search "regular expression"
                   1526:                             "vanilla"))))
                   1527:       (vip-search vip-s-string nil val)
                   1528:       (if com
                   1529:          (progn
                   1530:            (move-marker vip-com-point (mark))
                   1531:            (vip-execute-com 'vip-search-next val com))))))
                   1532: 
                   1533: (defun vip-search (string forward arg &optional no-offset init-point)
                   1534:   "(STRING FORWARD COUNT &optional NO-OFFSET) Search COUNT's occurrence of
                   1535: STRING.  Search will be forward if FORWARD, otherwise backward."
                   1536:   (let ((val (vip-p-val arg)) (com (vip-getcom arg))
                   1537:        (null-arg (null (vip-P-val arg))) (offset (not no-offset))
                   1538:        (case-fold-search vip-case-fold-search)
                   1539:        (start-point (or init-point (point))))
                   1540:     (if forward
                   1541:        (condition-case conditions
                   1542:            (progn
                   1543:              (if (and offset (not (eobp))) (forward-char))
                   1544:              (if vip-re-search
                   1545:                  (progn
                   1546:                    (re-search-forward string nil nil val)
                   1547:                    (re-search-backward string))
                   1548:                (search-forward string nil nil val)
                   1549:                (search-backward string))
                   1550:              (push-mark start-point))
                   1551:          (search-failed
                   1552:           (if (and null-arg vip-search-wrap-around)
                   1553:               (progn
                   1554:                 (goto-char (point-min))
                   1555:                 (vip-search string forward (cons 1 com) t start-point))
                   1556:             (goto-char start-point)
                   1557:             (signal 'search-failed (cdr conditions)))))
                   1558:       (condition-case conditions
                   1559:            (progn
                   1560:              (if vip-re-search
                   1561:                    (re-search-backward string nil nil val)
                   1562:                (search-backward string nil nil val))
                   1563:              (push-mark start-point))
                   1564:          (search-failed
                   1565:           (if (and null-arg vip-search-wrap-around)
                   1566:               (progn
                   1567:                 (goto-char (point-max))
                   1568:                 (vip-search string forward (cons 1 com) t start-point))
                   1569:             (goto-char start-point)
                   1570:             (signal 'search-failed (cdr conditions))))))))
                   1571: 
                   1572: (defun vip-search-next (arg)
                   1573:   "Repeat previous search."
                   1574:   (interactive "P")
                   1575:   (let ((val (vip-p-val arg)) (com (vip-getcom arg)))
                   1576:     (if (null vip-s-string) (error "No previous search string."))
                   1577:     (vip-search vip-s-string vip-s-forward arg)
                   1578:     (if com (vip-execute-com 'vip-search-next val com))))
                   1579: 
                   1580: (defun vip-search-Next (arg)
                   1581:   "Repeat previous search in the reverse direction."
                   1582:   (interactive "P")
                   1583:   (let ((val (vip-p-val arg)) (com (vip-getcom arg)))
                   1584:     (if (null vip-s-string) (error "No previous search string."))
                   1585:     (vip-search vip-s-string (not vip-s-forward) arg)
                   1586:     (if com (vip-execute-com 'vip-search-Next val com))))
                   1587: 
                   1588: 
                   1589: ;; visiting and killing files, buffers
                   1590: 
                   1591: (defun vip-switch-to-buffer ()
                   1592:   "Switch to buffer in the current window."
                   1593:   (interactive)
                   1594:   (let (buffer)
                   1595:     (setq buffer
                   1596:          (read-buffer
                   1597:           (format "switch to buffer \(%s\): "
                   1598:                   (buffer-name (other-buffer (current-buffer))))))
                   1599:     (switch-to-buffer buffer)
                   1600:     (vip-change-mode-to-vi)))
                   1601: 
                   1602: (defun vip-switch-to-buffer-other-window ()
                   1603:   "Switch to buffer in another window."
                   1604:   (interactive)
                   1605:   (let (buffer)
                   1606:     (setq buffer
                   1607:          (read-buffer
                   1608:           (format "Switch to buffer \(%s\): "
                   1609:                   (buffer-name (other-buffer (current-buffer))))))
                   1610:     (switch-to-buffer-other-window buffer)
                   1611:     (vip-change-mode-to-vi)))
                   1612: 
                   1613: (defun vip-kill-buffer ()
                   1614:   "Kill a buffer."
                   1615:   (interactive)
                   1616:   (let (buffer buffer-name)
                   1617:     (setq buffer-name
                   1618:          (read-buffer
                   1619:           (format "Kill buffer \(%s\): "
                   1620:                   (buffer-name (current-buffer)))))
                   1621:     (setq buffer
                   1622:          (if (null buffer-name)
                   1623:              (current-buffer)
                   1624:            (get-buffer buffer-name)))
                   1625:     (if (null buffer) (error "Buffer %s nonexistent." buffer-name))
                   1626:     (if (or (not (buffer-modified-p buffer))
                   1627:            (y-or-n-p "Buffer is modified, are you sure? "))
                   1628:        (kill-buffer buffer)
                   1629:       (error "Buffer not killed."))))
                   1630: 
                   1631: (defun vip-find-file ()
                   1632:   "Visit file in the current window."
                   1633:   (interactive)
                   1634:   (let (file)
                   1635:     (setq file (read-file-name "visit file: "))
                   1636:     (switch-to-buffer (find-file-noselect file))
                   1637:     (vip-change-mode-to-vi)))
                   1638: 
                   1639: (defun vip-find-file-other-window ()
                   1640:   "Visit file in another window."
                   1641:   (interactive)
                   1642:   (let (file)
                   1643:     (setq file (read-file-name "Visit file: "))
                   1644:     (switch-to-buffer-other-window (find-file-noselect file))
                   1645:     (vip-change-mode-to-vi)))
                   1646: 
                   1647: (defun vip-info-on-file ()
                   1648:   "Give information of the file associated to the current buffer."
                   1649:   (interactive)
                   1650:   (message "\"%s\" line %d of %d"
                   1651:           (if (buffer-file-name) (buffer-file-name) "")
                   1652:           (1+ (count-lines (point-min) (point)))
                   1653:           (1+ (count-lines (point-min) (point-max)))))
                   1654: 
                   1655: 
                   1656: ;; yank and pop
                   1657: 
                   1658: (defun vip-yank (text)
                   1659:   "yank TEXT silently."
                   1660:   (save-excursion
                   1661:     (vip-push-mark-silent (point))
                   1662:     (insert text)
                   1663:     (exchange-point-and-mark))
                   1664:   (skip-chars-forward " \t"))
                   1665: 
                   1666: (defun vip-put-back (arg)
                   1667:   "Put back after point/below line."
                   1668:   (interactive "P")
                   1669:   (let ((val (vip-p-val arg))
                   1670:        (text (if vip-use-register
                   1671:                  (if (and (<= ?1 vip-use-register) (<= vip-use-register ?9))
                   1672:                      (nth (- vip-use-register 49) kill-ring-yank-pointer)
                   1673:                    (get-register vip-use-register))
                   1674:                (car kill-ring-yank-pointer))))
                   1675:     (if (null text)
                   1676:        (if vip-use-register
                   1677:            (let ((reg vip-use-register))
                   1678:              (setq vip-use-register nil)
                   1679:              (error "Nothing in register %c" reg))
                   1680:          (error "")))
                   1681:     (setq vip-use-register nil)
                   1682:     (if (vip-end-with-a-newline-p text)
                   1683:        (progn
                   1684:          (next-line 1)
                   1685:          (beginning-of-line))
                   1686:       (if (and (not (eolp)) (not (eobp))) (forward-char)))
                   1687:     (setq vip-d-com (list 'vip-put-back val nil vip-use-register))
                   1688:     (vip-loop val (vip-yank text))))
                   1689: 
                   1690: (defun vip-Put-back (arg)
                   1691:   "Put back at point/above line."
                   1692:   (interactive "P")
                   1693:   (let ((val (vip-p-val arg))
                   1694:        (text (if vip-use-register
                   1695:                  (if (and (<= ?1 vip-use-register) (<= vip-use-register ?9))
                   1696:                      (nth (- vip-use-register 49) kill-ring-yank-pointer)
                   1697:                    (get-register vip-use-register))
                   1698:                (car kill-ring-yank-pointer))))
                   1699:     (if (null text)
                   1700:        (if vip-use-register
                   1701:            (let ((reg vip-use-register))
                   1702:              (setq vip-use-register nil)
                   1703:              (error "Nothing in register %c" reg))
                   1704:          (error "")))
                   1705:     (setq vip-use-register nil)
                   1706:     (if (vip-end-with-a-newline-p text) (beginning-of-line))
                   1707:     (setq vip-d-com (list 'vip-Put-back val nil vip-use-register))
                   1708:     (vip-loop val (vip-yank text))))
                   1709: 
                   1710: (defun vip-delete-char (arg)
                   1711:   "Delete character."
                   1712:   (interactive "P")
                   1713:   (let ((val (vip-p-val arg)))
                   1714:     (setq vip-d-com (list 'vip-delete-char val nil))
                   1715:     (if vip-use-register
                   1716:        (progn
                   1717:          (if (and (<= ?A vip-use-register) (<= vip-use-register ?Z))
                   1718:              (vip-append-to-register
                   1719:               (+ vip-use-register 32) (point) (- (point) val) nil)
                   1720:            (copy-to-register vip-use-register (point) (- (point) val) nil))
                   1721:          (setq vip-use-register nil)))
                   1722:     (delete-char val t)))
                   1723: 
                   1724: (defun vip-delete-backward-char (arg)
                   1725:   "Delete previous character."
                   1726:   (interactive "P")
                   1727:   (let ((val (vip-p-val arg)))
                   1728:     (setq vip-d-com (list 'vip-delete-backward-char val nil))
                   1729:     (if vip-use-register
                   1730:        (progn
                   1731:          (if (and (<= ?A vip-use-register) (<= vip-use-register ?Z))
                   1732:              (vip-append-to-register
                   1733:               (+ vip-use-register 32) (point) (+ (point) val) nil)
                   1734:            (copy-to-register vip-use-register (point) (+ (point) val) nil))
                   1735:          (setq vip-use-register nil)))
                   1736:     (delete-backward-char val t)))
                   1737: 
                   1738: 
                   1739: ;; join lines.
                   1740: 
                   1741: (defun vip-join-lines (arg)
                   1742:   "Join this line to next, if ARG is nil.  Otherwise, join ARG lines"
                   1743:   (interactive "*P")
                   1744:   (let ((val (vip-P-val arg)))
                   1745:     (setq vip-d-com (list 'vip-join-lines val nil))
                   1746:     (vip-loop (if (null val) 1 (1- val))
                   1747:          (progn
                   1748:            (end-of-line)
                   1749:            (if (not (eobp))
                   1750:                (progn
                   1751:                  (forward-line 1)
                   1752:                  (delete-region (point) (1- (point)))
                   1753:                  (fixup-whitespace)))))))
                   1754: 
                   1755: 
                   1756: ;; making small changes
                   1757: 
                   1758: (defun vip-change (beg end)
                   1759:   (setq c-string
                   1760:        (vip-read-string (format "%s => " (buffer-substring beg end))))
                   1761:   (vip-change-subr beg end))
                   1762: 
                   1763: (defun vip-change-subr (beg end)
                   1764:   (if vip-use-register
                   1765:       (progn
                   1766:        (copy-to-register vip-use-register beg end nil)
                   1767:        (setq vip-use-register nil)))
                   1768:   (kill-region beg end)
                   1769:   (setq this-command 'vip-change)
                   1770:   (insert c-string))
                   1771: 
                   1772: 
                   1773: ;; query replace
                   1774: 
                   1775: (defun vip-query-replace ()
                   1776:   "Query replace.  If you supply null string as the string to be replaced,
                   1777: the query replace mode will toggle between string replace and regexp replace."
                   1778:   (interactive)
                   1779:   (let (str)
                   1780:     (setq str (vip-read-string
                   1781:               (if vip-re-query-replace "Query replace regexp: "
                   1782:                 "Query replace: ")))
                   1783:     (if (string= str "")
                   1784:        (progn
                   1785:          (setq vip-re-query-replace (not vip-re-query-replace))
                   1786:          (message "Query replace mode changed to %s."
                   1787:                   (if vip-re-query-replace "regexp replace"
                   1788:                     "string replace")))
                   1789:       (if vip-re-query-replace
                   1790:          (query-replace-regexp
                   1791:           str
                   1792:           (vip-read-string (format "Query replace regexp \"%s\" with: " str)))
                   1793:        (query-replace
                   1794:         str
                   1795:         (vip-read-string (format "Query replace \"%s\" with: " str)))))))
                   1796: 
                   1797: 
                   1798: ;; marking
                   1799: 
                   1800: (defun vip-mark-beginning-of-buffer ()
                   1801:   (interactive)
                   1802:   (set-mark (point))
                   1803:   (goto-char (point-min))
                   1804:   (exchange-point-and-mark)
                   1805:   (message "mark set at the beginning of buffer"))
                   1806: 
                   1807: (defun vip-mark-end-of-buffer ()
                   1808:   (interactive)
                   1809:   (set-mark (point))
                   1810:   (goto-char (point-max))
                   1811:   (exchange-point-and-mark)
                   1812:   (message "mark set at the end of buffer"))
                   1813: 
                   1814: (defun vip-mark-point (char)
                   1815:   (interactive "c")
                   1816:   (cond ((and (<= ?a char) (<= char ?z))
                   1817:         (point-to-register (- char (- ?a ?\C-a))))
                   1818:        ((= char ?<) (vip-mark-beginning-of-buffer))
                   1819:        ((= char ?>) (vip-mark-end-of-buffer))
                   1820:        ((= char ?.) (push-mark))
                   1821:        ((= char ?,) (set-mark-command 1))
                   1822:        ((= char ?D) (mark-defun))
                   1823:        (t (error ""))))
                   1824: 
                   1825: (defun vip-goto-mark (arg)
                   1826:   "Go to mark."
                   1827:   (interactive "P")
                   1828:   (let ((char (read-char)) (com (vip-getcom arg)))
                   1829:     (vip-goto-mark-subr char com nil)))
                   1830: 
                   1831: (defun vip-goto-mark-and-skip-white (arg)
                   1832:   "Go to mark and skip to first non-white on line."
                   1833:   (interactive "P")
                   1834:   (let ((char (read-char)) (com (vip-getCom arg)))
                   1835:     (vip-goto-mark-subr char com t)))
                   1836: 
                   1837: (defun vip-goto-mark-subr (char com skip-white)
                   1838:   (cond ((and (<= ?a char) (<= char ?z))
                   1839:         (let ((buff (current-buffer)))
                   1840:           (if com (move-marker vip-com-point (point)))
                   1841:           (goto-char (register-to-point (- char (- ?a ?\C-a))))
                   1842:           (if skip-white (back-to-indentation))
                   1843:           (vip-change-mode-to-vi)
                   1844:           (if com
                   1845:               (if (equal buff (current-buffer))
                   1846:                   (vip-execute-com (if skip-white
                   1847:                                        'vip-goto-mark-and-skip-white
                   1848:                                      'vip-goto-mark)
                   1849:                                    nil com)
                   1850:                 (switch-to-buffer buff)
                   1851:                 (goto-char vip-com-point)
                   1852:                 (vip-change-mode-to-vi)
                   1853:                 (error "")))))
                   1854:        ((and (not skip-white) (= char ?`))
                   1855:         (if com (move-marker vip-com-point (point)))
                   1856:         (exchange-point-and-mark)
                   1857:         (if com (vip-execute-com 'vip-goto-mark nil com)))
                   1858:        ((and skip-white (= char ?'))
                   1859:         (if com (move-marker vip-com-point (point)))
                   1860:         (exchange-point-and-mark)
                   1861:         (back-to-indentation)
                   1862:         (if com (vip-execute-com 'vip-goto-mark-and-skip-white nil com)))
                   1863:        (t (error ""))))
                   1864: 
                   1865: (defun vip-exchange-point-and-mark ()
                   1866:   (interactive)
                   1867:   (exchange-point-and-mark)
                   1868:   (back-to-indentation))
                   1869: 
                   1870: (defun vip-keyboard-quit ()
                   1871:   "Abort partially formed or running command."
                   1872:   (interactive)
                   1873:   (setq vip-use-register nil)
                   1874:   (keyboard-quit))
                   1875: 
                   1876: (defun vip-ctl-c-equivalent (arg)
                   1877:   "Emulate C-c in Emacs mode."
                   1878:   (interactive "P")
                   1879:   (vip-ctl-key-equivalent "\C-c" arg))
                   1880: 
                   1881: (defun vip-ctl-x-equivalent (arg)
                   1882:   "Emulate C-x in Emacs mode."
                   1883:   (interactive "P")
                   1884:   (vip-ctl-key-equivalent "\C-x" arg))
                   1885: 
                   1886: (defun vip-ctl-key-equivalent (key arg)
                   1887:   (let ((char (read-char)))
                   1888:     (if (and (<= ?A char) (<= char ?Z))
                   1889:        (setq char (- char (- ?A ?\C-a))))
                   1890:          (setq prefix-arg arg)
                   1891:          (command-execute
                   1892:           (vip-get-editor-command
                   1893:            vip-emacs-local-map global-map
                   1894:            (format "%s%s" key (char-to-string char))))))
                   1895:   
                   1896: 
                   1897: ;; commands in insertion mode
                   1898: 
                   1899: (defun vip-delete-backward-word (arg)
                   1900:   "Delete previous word."
                   1901:   (interactive "p")
                   1902:   (save-excursion
                   1903:     (set-mark (point))
                   1904:     (backward-word arg)
                   1905:     (delete-region (point) (mark))))
                   1906: 
                   1907: 
                   1908: ;; key bindings
                   1909: 
                   1910: (set 'vip-mode-map (make-keymap))
                   1911: 
                   1912: (define-key vip-mode-map "\C-a" 'beginning-of-line)
                   1913: (define-key vip-mode-map "\C-b" 'vip-scroll-back)
                   1914: (define-key vip-mode-map "\C-c" 'vip-ctl-c)
                   1915: (define-key vip-mode-map "\C-d" 'vip-scroll-up)
                   1916: (define-key vip-mode-map "\C-e" 'vip-scroll-up-one)
                   1917: (define-key vip-mode-map "\C-f" 'vip-scroll)
                   1918: (define-key vip-mode-map "\C-g" 'vip-keyboard-quit)
                   1919: (define-key vip-mode-map "\C-h" 'help-command)
                   1920: (define-key vip-mode-map "\C-m" 'vip-scroll-back)
                   1921: (define-key vip-mode-map "\C-n" 'vip-other-window)
                   1922: (define-key vip-mode-map "\C-o" 'vip-open-line-at-point)
                   1923: (define-key vip-mode-map "\C-u" 'vip-scroll-down)
                   1924: (define-key vip-mode-map "\C-x" 'vip-ctl-x)
                   1925: (define-key vip-mode-map "\C-y" 'vip-scroll-down-one)
                   1926: (define-key vip-mode-map "\C-z" 'vip-change-mode-to-emacs)
                   1927: (define-key vip-mode-map "\e" 'vip-ESC)
                   1928: 
                   1929: (define-key vip-mode-map " " 'vip-scroll)
                   1930: (define-key vip-mode-map "!" 'vip-command-argument)
                   1931: (define-key vip-mode-map "\"" 'vip-command-argument)
                   1932: (define-key vip-mode-map "#" 'vip-command-argument)
                   1933: (define-key vip-mode-map "$" 'vip-goto-eol)
                   1934: (define-key vip-mode-map "%" 'vip-paren-match)
                   1935: (define-key vip-mode-map "&" 'vip-nil)
                   1936: (define-key vip-mode-map "'" 'vip-goto-mark-and-skip-white)
                   1937: (define-key vip-mode-map "(" 'vip-backward-sentence)
                   1938: (define-key vip-mode-map ")" 'vip-forward-sentence)
                   1939: (define-key vip-mode-map "*" 'call-last-kbd-macro)
                   1940: (define-key vip-mode-map "+" 'vip-next-line-at-bol)
                   1941: (define-key vip-mode-map "," 'vip-repeat-find-opposite)
                   1942: (define-key vip-mode-map "-" 'vip-previous-line-at-bol)
                   1943: (define-key vip-mode-map "." 'vip-repeat)
                   1944: (define-key vip-mode-map "/" 'vip-search-forward)
                   1945: 
                   1946: (define-key vip-mode-map "0" 'vip-beginning-of-line)
                   1947: (define-key vip-mode-map "1" 'vip-digit-argument)
                   1948: (define-key vip-mode-map "2" 'vip-digit-argument)
                   1949: (define-key vip-mode-map "3" 'vip-digit-argument)
                   1950: (define-key vip-mode-map "4" 'vip-digit-argument)
                   1951: (define-key vip-mode-map "5" 'vip-digit-argument)
                   1952: (define-key vip-mode-map "6" 'vip-digit-argument)
                   1953: (define-key vip-mode-map "7" 'vip-digit-argument)
                   1954: (define-key vip-mode-map "8" 'vip-digit-argument)
                   1955: (define-key vip-mode-map "9" 'vip-digit-argument)
                   1956: 
                   1957: (define-key vip-mode-map ":" 'vip-ex)
                   1958: (define-key vip-mode-map ";" 'vip-repeat-find)
                   1959: (define-key vip-mode-map "<" 'vip-command-argument)
                   1960: (define-key vip-mode-map "=" 'vip-command-argument)
                   1961: (define-key vip-mode-map ">" 'vip-command-argument)
                   1962: (define-key vip-mode-map "?" 'vip-search-backward)
                   1963: (define-key vip-mode-map "@" 'vip-nil)
                   1964: 
                   1965: (define-key vip-mode-map "A" 'vip-Append)
                   1966: (define-key vip-mode-map "B" 'vip-backward-Word)
                   1967: (define-key vip-mode-map "C" 'vip-ctl-c-equivalent)
                   1968: (define-key vip-mode-map "D" 'vip-kill-line)
                   1969: (define-key vip-mode-map "E" 'vip-end-of-Word)
                   1970: (define-key vip-mode-map "F" 'vip-find-char-backward)
                   1971: (define-key vip-mode-map "G" 'vip-goto-line)
                   1972: (define-key vip-mode-map "H" 'vip-window-top)
                   1973: (define-key vip-mode-map "I" 'vip-Insert)
                   1974: (define-key vip-mode-map "J" 'vip-join-lines)
                   1975: (define-key vip-mode-map "K" 'vip-kill-buffer)
                   1976: (define-key vip-mode-map "L" 'vip-window-bottom)
                   1977: (define-key vip-mode-map "M" 'vip-window-middle)
                   1978: (define-key vip-mode-map "N" 'vip-search-Next)
                   1979: (define-key vip-mode-map "O" 'vip-Open-line)
                   1980: (define-key vip-mode-map "P" 'vip-Put-back)
                   1981: (define-key vip-mode-map "Q" 'vip-query-replace)
                   1982: (define-key vip-mode-map "R" 'vip-replace-string)
                   1983: (define-key vip-mode-map "S" 'vip-switch-to-buffer-other-window)
                   1984: (define-key vip-mode-map "T" 'vip-goto-char-backward)
                   1985: (define-key vip-mode-map "U" 'vip-nil)
                   1986: (define-key vip-mode-map "V" 'vip-find-file-other-window)
                   1987: (define-key vip-mode-map "W" 'vip-forward-Word)
                   1988: (define-key vip-mode-map "X" 'vip-ctl-x-equivalent)
                   1989: (define-key vip-mode-map "Y" 'vip-yank-line)
                   1990: (define-key vip-mode-map "ZZ" 'save-buffers-kill-emacs)
                   1991: 
                   1992: (define-key vip-mode-map "[" 'vip-nil)
                   1993: (define-key vip-mode-map "\\" 'vip-escape-to-emacs)
                   1994: (define-key vip-mode-map "]" 'vip-nil)
                   1995: (define-key vip-mode-map "^" 'vip-bol-and-skip-white)
                   1996: (define-key vip-mode-map "_" 'vip-nil)
                   1997: (define-key vip-mode-map "`" 'vip-goto-mark)
                   1998: 
                   1999: (define-key vip-mode-map "a" 'vip-append)
                   2000: (define-key vip-mode-map "b" 'vip-backward-word)
                   2001: (define-key vip-mode-map "c" 'vip-command-argument)
                   2002: (define-key vip-mode-map "d" 'vip-command-argument)
                   2003: (define-key vip-mode-map "e" 'vip-end-of-word)
                   2004: (define-key vip-mode-map "f" 'vip-find-char-forward)
                   2005: (define-key vip-mode-map "g" 'vip-info-on-file)
                   2006: (define-key vip-mode-map "h" 'vip-backward-char)
                   2007: (define-key vip-mode-map "i" 'vip-insert)
                   2008: (define-key vip-mode-map "j" 'vip-next-line)
                   2009: (define-key vip-mode-map "k" 'vip-previous-line)
                   2010: (define-key vip-mode-map "l" 'vip-forward-char)
                   2011: (define-key vip-mode-map "m" 'vip-mark-point)
                   2012: (define-key vip-mode-map "n" 'vip-search-next)
                   2013: (define-key vip-mode-map "o" 'vip-open-line)
                   2014: (define-key vip-mode-map "p" 'vip-put-back)
                   2015: (define-key vip-mode-map "q" 'vip-nil)
                   2016: (define-key vip-mode-map "r" 'vip-replace-char)
                   2017: (define-key vip-mode-map "s" 'vip-switch-to-buffer)
                   2018: (define-key vip-mode-map "t" 'vip-goto-char-forward)
                   2019: (define-key vip-mode-map "u" 'vip-undo)
                   2020: (define-key vip-mode-map "v" 'vip-find-file)
                   2021: (define-key vip-mode-map "w" 'vip-forward-word)
                   2022: (define-key vip-mode-map "x" 'vip-delete-char)
                   2023: (define-key vip-mode-map "y" 'vip-command-argument)
                   2024: (define-key vip-mode-map "zH" 'vip-line-to-top)
                   2025: (define-key vip-mode-map "zM" 'vip-line-to-middle)
                   2026: (define-key vip-mode-map "zL" 'vip-line-to-bottom)
                   2027: (define-key vip-mode-map "z\C-m" 'vip-line-to-top)
                   2028: (define-key vip-mode-map "z." 'vip-line-to-middle)
                   2029: (define-key vip-mode-map "z-" 'vip-line-to-bottom)
                   2030: 
                   2031: (define-key vip-mode-map "{" 'vip-backward-paragraph)
                   2032: (define-key vip-mode-map "|" 'vip-goto-col)
                   2033: (define-key vip-mode-map "}" 'vip-forward-paragraph)
                   2034: (define-key vip-mode-map "~" 'vip-nil)
                   2035: (define-key vip-mode-map "\177" 'vip-delete-backward-char)
                   2036: 
                   2037: (defun vip-version ()
                   2038:   (interactive)
                   2039:   (message "VIP version 3.5 of September 15, 1987"))
                   2040: 
                   2041: 
                   2042: ;; implement ex commands
                   2043: 
                   2044: (defvar ex-token-type nil
                   2045:   "type of token.  if non-nil, gives type of address.  if nil, it
                   2046: is a command.")
                   2047: 
                   2048: (defvar ex-token nil
                   2049:   "value of token.")
                   2050: 
                   2051: (defvar ex-addresses nil
                   2052:   "list of ex addresses")
                   2053: 
                   2054: (defvar ex-flag nil
                   2055:   "flag for ex flag")
                   2056: 
                   2057: (defvar ex-buffer nil
                   2058:   "name of ex buffer")
                   2059: 
                   2060: (defvar ex-count nil
                   2061:   "value of ex count")
                   2062: 
                   2063: (defvar ex-g-flag nil
                   2064:   "flag for global command")
                   2065: 
                   2066: (defvar ex-g-variant nil
                   2067:   "if t global command is executed on lines not matching ex-g-pat")
                   2068: 
                   2069: (defvar ex-reg-exp nil
                   2070:   "save reg-exp used in substitute")
                   2071: 
                   2072: (defvar ex-repl nil
                   2073:   "replace pattern for substitute")
                   2074: 
                   2075: (defvar ex-g-pat nil
                   2076:   "pattern for global command")
                   2077: 
                   2078: (defvar ex-map (make-sparse-keymap)
                   2079:   "save commnads for mapped keys")
                   2080: 
                   2081: (defvar ex-tag nil
                   2082:   "save ex tag")
                   2083: 
                   2084: (defvar ex-file nil)
                   2085: 
                   2086: (defvar ex-variant nil)
                   2087: 
                   2088: (defvar ex-offset nil)
                   2089: 
                   2090: (defvar ex-append nil)
                   2091: 
                   2092: (defun vip-nil ()
                   2093:   (interactive)
                   2094:   (error ""))
                   2095: 
                   2096: (defun vip-looking-back (str)
                   2097:   "returns t if looking back reg-exp STR before point."
                   2098:   (and (save-excursion (re-search-backward str nil t))
                   2099:        (= (point) (match-end 0))))
                   2100: 
                   2101: (defun vip-check-sub (str)
                   2102:   "check if ex-token is an initial segment of STR"
                   2103:   (let ((length (length ex-token)))
                   2104:     (if (and (<= length (length str))
                   2105:             (string= ex-token (substring str 0 length)))
                   2106:        (setq ex-token str)
                   2107:       (setq ex-token-type "non-command"))))
                   2108: 
                   2109: (defun vip-get-ex-com-subr ()
                   2110:   "get a complete ex command"
                   2111:   (set-mark (point))
                   2112:   (re-search-forward "[a-z][a-z]*")
                   2113:   (setq ex-token-type "command")
                   2114:   (setq ex-token (buffer-substring (point) (mark)))
                   2115:   (exchange-point-and-mark)
                   2116:   (cond ((looking-at "a")
                   2117:         (cond ((looking-at "ab") (vip-check-sub "abbreviate"))
                   2118:               ((looking-at "ar") (vip-check-sub "args"))
                   2119:               (t (vip-check-sub "append"))))
                   2120:        ((looking-at "[bh]") (setq ex-token-type "non-command"))
                   2121:        ((looking-at "c")
                   2122:         (if (looking-at "co") (vip-check-sub "copy")
                   2123:           (vip-check-sub "change")))
                   2124:        ((looking-at "d") (vip-check-sub "delete"))
                   2125:        ((looking-at "e")
                   2126:         (if (looking-at "ex") (vip-check-sub "ex")
                   2127:           (vip-check-sub "edit")))
                   2128:        ((looking-at "f") (vip-check-sub "file"))
                   2129:        ((looking-at "g") (vip-check-sub "global"))
                   2130:        ((looking-at "i") (vip-check-sub "insert"))
                   2131:        ((looking-at "j") (vip-check-sub "join"))
                   2132:        ((looking-at "l") (vip-check-sub "list"))
                   2133:        ((looking-at "m")
                   2134:         (cond ((looking-at "map") (vip-check-sub "map"))
                   2135:               ((looking-at "mar") (vip-check-sub "mark"))
                   2136:               (t (vip-check-sub "move"))))
                   2137:        ((looking-at "n")
                   2138:         (if (looking-at "nu") (vip-check-sub "number")
                   2139:           (vip-check-sub "next")))
                   2140:        ((looking-at "o") (vip-check-sub "open"))
                   2141:        ((looking-at "p")
                   2142:         (cond ((looking-at "pre") (vip-check-sub "preserve"))
                   2143:               ((looking-at "pu") (vip-check-sub "put"))
                   2144:               (t (vip-check-sub "print"))))
                   2145:        ((looking-at "q") (vip-check-sub "quit"))
                   2146:        ((looking-at "r")
                   2147:         (cond ((looking-at "rec") (vip-check-sub "recover"))
                   2148:               ((looking-at "rew") (vip-check-sub "rewind"))
                   2149:               (t (vip-check-sub "read"))))
                   2150:        ((looking-at "s")
                   2151:         (cond ((looking-at "se") (vip-check-sub "set"))
                   2152:               ((looking-at "sh") (vip-check-sub "shell"))
                   2153:               ((looking-at "so") (vip-check-sub "source"))
                   2154:               ((looking-at "st") (vip-check-sub "stop"))
                   2155:               (t (vip-check-sub "substitute"))))
                   2156:        ((looking-at "t")
                   2157:         (if (looking-at "ta") (vip-check-sub "tag")
                   2158:           (vip-check-sub "t")))
                   2159:        ((looking-at "u")
                   2160:         (cond ((looking-at "una") (vip-check-sub "unabbreviate"))
                   2161:               ((looking-at "unm") (vip-check-sub "unmap"))
                   2162:               (t (vip-check-sub "undo"))))
                   2163:        ((looking-at "v")
                   2164:         (cond ((looking-at "ve") (vip-check-sub "version"))
                   2165:               ((looking-at "vi") (vip-check-sub "visual"))
                   2166:               (t (vip-check-sub "v"))))
                   2167:        ((looking-at "w")
                   2168:         (if (looking-at "wq") (vip-check-sub "wq")
                   2169:           (vip-check-sub "write")))
                   2170:        ((looking-at "x") (vip-check-sub "xit"))
                   2171:        ((looking-at "y") (vip-check-sub "yank"))
                   2172:        ((looking-at "z") (vip-check-sub "z")))
                   2173:   (exchange-point-and-mark))
                   2174: 
                   2175: (defun vip-get-ex-token ()
                   2176:   "get an ex-token which is either an address or a command.
                   2177: a token has type \(command, address, end-mark\) and value."
                   2178:   (save-window-excursion
                   2179:     (set-buffer " *ex-working-space*")
                   2180:     (skip-chars-forward " \t")
                   2181:     (cond ((looking-at "[k#]")
                   2182:           (setq ex-token-type "command")
                   2183:           (setq ex-token (char-to-string (following-char)))
                   2184:           (forward-char 1))
                   2185:          ((looking-at "[a-z]") (vip-get-ex-com-subr))
                   2186:          ((looking-at "\\.")
                   2187:           (forward-char 1)
                   2188:           (setq ex-token-type "dot"))
                   2189:          ((looking-at "[0-9]")
                   2190:           (set-mark (point))
                   2191:           (re-search-forward "[0-9]*")
                   2192:           (setq ex-token-type
                   2193:                 (cond ((string= ex-token-type "plus") "add-number")
                   2194:                       ((string= ex-token-type "minus") "sub-number")
                   2195:                       (t "abs-number")))
                   2196:           (setq ex-token (string-to-int (buffer-substring (point) (mark)))))
                   2197:          ((looking-at "\\$")
                   2198:           (forward-char 1)
                   2199:           (setq ex-token-type "end"))
                   2200:          ((looking-at "%")
                   2201:           (forward-char 1)
                   2202:           (setq ex-token-type "whole"))
                   2203:          ((looking-at "+")
                   2204:           (cond ((or (looking-at "+[-+]") (looking-at "+[\n|]"))
                   2205:                  (forward-char 1)
                   2206:                  (insert "1")
                   2207:                  (backward-char 1)
                   2208:                  (setq ex-token-type "plus"))
                   2209:                 ((looking-at "+[0-9]")
                   2210:                  (forward-char 1)
                   2211:                  (setq ex-token-type "plus"))
                   2212:                 (t
                   2213:                  (error "Badly formed address"))))
                   2214:          ((looking-at "-")
                   2215:           (cond ((or (looking-at "-[-+]") (looking-at "-[\n|]"))
                   2216:                  (forward-char 1)
                   2217:                  (insert "1")
                   2218:                  (backward-char 1)
                   2219:                  (setq ex-token-type "minus"))
                   2220:                 ((looking-at "-[0-9]")
                   2221:                  (forward-char 1)
                   2222:                  (setq ex-token-type "minus"))
                   2223:                 (t
                   2224:                  (error "Badly formed address"))))
                   2225:          ((looking-at "/")
                   2226:           (forward-char 1)
                   2227:           (set-mark (point))
                   2228:           (let ((cont t))
                   2229:             (while (and (not (eolp)) cont)
                   2230:               ;;(re-search-forward "[^/]*/")
                   2231:               (re-search-forward "[^/]*\\(/\\|\n\\)")
                   2232:               (if (not (vip-looking-back "[^\\\\]\\(\\\\\\\\\\)*\\\\/"))
                   2233:                   (setq cont nil))))
                   2234:           (backward-char 1)
                   2235:           (setq ex-token (buffer-substring (point) (mark)))
                   2236:           (if (looking-at "/") (forward-char 1))
                   2237:           (setq ex-token-type "search-forward"))
                   2238:          ((looking-at "\\?")
                   2239:           (forward-char 1)
                   2240:           (set-mark (point))
                   2241:           (let ((cont t))
                   2242:             (while (and (not (eolp)) cont)
                   2243:               ;;(re-search-forward "[^\\?]*\\?")
                   2244:               (re-search-forward "[^\\?]*\\(\\?\\|\n\\)")
                   2245:               (if (not (vip-looking-back "[^\\\\]\\(\\\\\\\\\\)*\\\\\\?"))
                   2246:                   (setq cont nil))
                   2247:               (backward-char 1)
                   2248:               (if (not (looking-at "\n")) (forward-char 1))))
                   2249:           (setq ex-token-type "search-backward")
                   2250:           (setq ex-token (buffer-substring (1- (point)) (mark))))
                   2251:          ((looking-at ",")
                   2252:           (forward-char 1)
                   2253:           (setq ex-token-type "comma"))
                   2254:          ((looking-at ";")
                   2255:           (forward-char 1)
                   2256:           (setq ex-token-type "semi-colon"))
                   2257:          ((looking-at "[!=><&~]")
                   2258:           (setq ex-token-type "command")
                   2259:           (setq ex-token (char-to-string (following-char)))
                   2260:           (forward-char 1))
                   2261:          ((looking-at "'")
                   2262:           (setq ex-token-type "goto-mark")
                   2263:           (forward-char 1)
                   2264:           (cond ((looking-at "'") (setq ex-token nil))
                   2265:                 ((looking-at "[a-z]") (setq ex-token (following-char)))
                   2266:                 (t (error "Marks are ' and a-z")))
                   2267:           (forward-char 1))
                   2268:          ((looking-at "\n")
                   2269:           (setq ex-token-type "end-mark")
                   2270:           (setq ex-token "goto"))
                   2271:          (t
                   2272:           (error "illegal token")))))
                   2273: 
                   2274: (defun vip-ex (&optional string)
                   2275:   "ex commands within VIP."
                   2276:   (interactive)
                   2277:   (or string
                   2278:       (setq ex-g-flag nil
                   2279:            ex-g-variant nil))
                   2280:   (let ((com-str (or string (vip-read-string ":")))
                   2281:        (address nil) (cont t) (dot (point)))
                   2282:     (save-window-excursion
                   2283:       (set-buffer (get-buffer-create " *ex-working-space*"))
                   2284:       (delete-region (point-min) (point-max))
                   2285:       (insert com-str "\n")
                   2286:       (goto-char (point-min)))
                   2287:     (setq ex-token-type "")
                   2288:     (setq ex-addresses nil)
                   2289:     (while cont
                   2290:       (vip-get-ex-token)
                   2291:       (cond ((or (string= ex-token-type "command")
                   2292:                 (string= ex-token-type "end-mark"))
                   2293:             (if address (setq ex-addresses (cons address ex-addresses)))
                   2294:             (cond ((string= ex-token "global")
                   2295:                    (ex-global nil)
                   2296:                    (setq cont nil))
                   2297:                   ((string= ex-token "v")
                   2298:                    (ex-global t)
                   2299:                    (setq cont nil))
                   2300:                   (t
                   2301:                    (vip-execute-ex-command)
                   2302:                    (save-window-excursion
                   2303:                      (set-buffer " *ex-working-space*")
                   2304:                      (skip-chars-forward " \t")
                   2305:                      (cond ((looking-at "|")
                   2306:                             (forward-char 1))
                   2307:                            ((looking-at "\n")
                   2308:                             (setq cont nil))
                   2309:                            (t (error "Extra character at end of a command")))))))
                   2310:            ((string= ex-token-type "non-command")
                   2311:             (error (format "%s: Not an editor command" ex-token)))
                   2312:            ((string= ex-token-type "whole")
                   2313:             (setq ex-addresses
                   2314:                   (cons (point-max) (cons (point-min) ex-addresses))))
                   2315:            ((string= ex-token-type "comma")
                   2316:             (setq ex-addresses
                   2317:                   (cons (if (null address) (point) address) ex-addresses)))
                   2318:            ((string= ex-token-type "semi-colon")
                   2319:             (if address (setq dot address))
                   2320:             (setq ex-addresses
                   2321:                   (cons (if (null address) (point) address) ex-addresses)))
                   2322:            (t (let ((ans (vip-get-ex-address-subr address dot)))
                   2323:                 (if ans (setq address ans))))))))
                   2324: 
                   2325: (defun vip-get-ex-pat ()
                   2326:   "get a regular expression and set ex-variant if found"
                   2327:   (save-window-excursion
                   2328:     (set-buffer " *ex-working-space*")
                   2329:     (skip-chars-forward " \t")
                   2330:     (if (looking-at "!")
                   2331:        (progn
                   2332:          (setq ex-g-variant (not ex-g-variant)
                   2333:                ex-g-flag (not ex-g-flag))
                   2334:          (forward-char 1)
                   2335:          (skip-chars-forward " \t")))
                   2336:     (if (looking-at "/")
                   2337:        (progn
                   2338:          (forward-char 1)
                   2339:          (set-mark (point))
                   2340:          (let ((cont t))
                   2341:            (while (and (not (eolp)) cont)
                   2342:              (re-search-forward "[^/]*\\(/\\|\n\\)")
                   2343:              ;;(re-search-forward "[^/]*/")
                   2344:              (if (not (vip-looking-back "[^\\\\]\\(\\\\\\\\\\)*\\\\/"))
                   2345:                  (setq cont nil))))
                   2346:          (setq ex-token
                   2347:                (if (= (mark) (point)) ""
                   2348:                  (buffer-substring (1- (point)) (mark))))
                   2349:          (backward-char 1))
                   2350:       (setq ex-token nil))))
                   2351: 
                   2352: (defun vip-get-ex-command ()
                   2353:   "get an ex command"
                   2354:   (save-window-excursion
                   2355:     (set-buffer " *ex-working-space*")
                   2356:     (if (looking-at "/") (forward-char 1))
                   2357:     (skip-chars-forward " \t")
                   2358:     (cond ((looking-at "[a-z]")
                   2359:           (vip-get-ex-com-subr)
                   2360:           (if (string= ex-token-type "non-command")
                   2361:               (error "%s: not an editor command" ex-token)))
                   2362:          ((looking-at "[!=><&~]")
                   2363:           (setq ex-token (char-to-string (following-char)))
                   2364:           (forward-char 1))
                   2365:          (t (error "Could not find an ex command")))))
                   2366: 
                   2367: (defun vip-get-ex-opt-gc ()
                   2368:   "get an ex option g or c"
                   2369:   (save-window-excursion
                   2370:     (set-buffer " *ex-working-space*")
                   2371:     (if (looking-at "/") (forward-char 1))
                   2372:     (skip-chars-forward " \t")
                   2373:     (cond ((looking-at "g")
                   2374:           (setq ex-token "g")
                   2375:           (forward-char 1)
                   2376:           t)
                   2377:          ((looking-at "c")
                   2378:           (setq ex-token "c")
                   2379:           (forward-char 1)
                   2380:           t)
                   2381:          (t nil))))
                   2382: 
                   2383: (defun vip-default-ex-addresses (&optional whole-flag)
                   2384:   "compute default addresses.  whole-flag means whole buffer."
                   2385:   (cond ((null ex-addresses)
                   2386:         (setq ex-addresses
                   2387:               (if whole-flag
                   2388:                   (cons (point-max) (cons (point-min) nil))
                   2389:                 (cons (point) (cons (point) nil)))))
                   2390:        ((null (cdr ex-addresses))
                   2391:         (setq ex-addresses
                   2392:               (cons (car ex-addresses) ex-addresses)))))
                   2393: 
                   2394: (defun vip-get-ex-address ()
                   2395:   "get an ex-address as a marker and set ex-flag if a flag is found"
                   2396:   (let ((address (point-marker)) (cont t))
                   2397:     (setq ex-token "")
                   2398:     (setq ex-flag nil)
                   2399:     (while cont
                   2400:       (vip-get-ex-token)
                   2401:       (cond ((string= ex-token-type "command")
                   2402:             (if (or (string= ex-token "print") (string= ex-token "list")
                   2403:                     (string= ex-token "#"))
                   2404:                 (progn
                   2405:                   (setq ex-flag t)
                   2406:                   (setq cont nil))
                   2407:             (error "address expected")))
                   2408:            ((string= ex-token-type "end-mark")
                   2409:             (setq cont nil))
                   2410:            ((string= ex-token-type "whole")
                   2411:             (error "a trailing address is expected"))
                   2412:            ((string= ex-token-type "comma")
                   2413:             (error "Extra characters after an address"))
                   2414:            (t (let ((ans (vip-get-ex-address-subr address (point-marker))))
                   2415:                 (if ans (setq address ans))))))
                   2416:     address))
                   2417: 
                   2418: (defun vip-get-ex-address-subr (old-address dot)
                   2419:   "returns an address as a point"
                   2420:   (let ((address nil))
                   2421:     (if (null old-address) (setq old-address dot))
                   2422:     (cond ((string= ex-token-type "dot")
                   2423:           (setq address dot))
                   2424:          ((string= ex-token-type "add-number")
                   2425:           (save-excursion
                   2426:             (goto-char old-address)
                   2427:             (forward-line (if (= old-address 0) (1- ex-token) ex-token))
                   2428:             (setq address (point-marker))))
                   2429:          ((string= ex-token-type "sub-number")
                   2430:           (save-excursion
                   2431:             (goto-char old-address)
                   2432:             (forward-line (- ex-token))
                   2433:             (setq address (point-marker))))
                   2434:          ((string= ex-token-type "abs-number")
                   2435:           (save-excursion
                   2436:             (goto-char (point-min))
                   2437:             (if (= ex-token 0) (setq address 0)
                   2438:               (forward-line (1- ex-token))
                   2439:               (setq address (point-marker)))))
                   2440:          ((string= ex-token-type "end")
                   2441:           (setq address (point-max-marker)))
                   2442:          ((string= ex-token-type "plus") t);; do nothing
                   2443:          ((string= ex-token-type "minus") t);; do nothing
                   2444:          ((string= ex-token-type "search-forward")
                   2445:           (save-excursion
                   2446:             (ex-search-address t)
                   2447:             (setq address (point-marker))))
                   2448:          ((string= ex-token-type "search-backward")
                   2449:           (save-excursion
                   2450:             (ex-search-address nil)
                   2451:             (setq address (point-marker))))
                   2452:          ((string= ex-token-type "goto-mark")
                   2453:           (save-excursion
                   2454:             (if (null ex-token)
                   2455:                 (exchange-point-and-mark)
                   2456:               (goto-char (register-to-point (- ex-token (- ?a ?\C-a)))))
                   2457:             (setq address (point-marker)))))
                   2458:     address))
                   2459: 
                   2460: (defun ex-search-address (forward)
                   2461:   "search pattern and set address"
                   2462:   (if (string= ex-token "")
                   2463:       (if (null vip-s-string) (error "No previous search string")
                   2464:        (setq ex-token vip-s-string))
                   2465:     (setq vip-s-string ex-token))
                   2466:   (if forward
                   2467:       (progn
                   2468:        (forward-line 1)
                   2469:        (re-search-forward ex-token))
                   2470:     (forward-line -1)
                   2471:     (re-search-backward ex-token)))
                   2472: 
                   2473: (defun vip-get-ex-buffer ()
                   2474:   "get a buffer name and set ex-count and ex-flag if found"
                   2475:   (setq ex-buffer nil)
                   2476:   (setq ex-count nil)
                   2477:   (setq ex-flag nil)
                   2478:   (save-window-excursion
                   2479:     (set-buffer " *ex-working-space*")
                   2480:     (skip-chars-forward " \t")
                   2481:     (if (looking-at "[a-zA-Z]")
                   2482:        (progn
                   2483:          (setq ex-buffer (following-char))
                   2484:          (forward-char 1)
                   2485:          (skip-chars-forward " \t")))
                   2486:     (if (looking-at "[0-9]")
                   2487:        (progn
                   2488:          (set-mark (point))
                   2489:          (re-search-forward "[0-9][0-9]*")
                   2490:          (setq ex-count (string-to-int (buffer-substring (point) (mark))))
                   2491:          (skip-chars-forward " \t")))
                   2492:     (if (looking-at "[pl#]")
                   2493:        (progn
                   2494:          (setq ex-flag t)
                   2495:          (forward-char 1)))
                   2496:     (if (not (looking-at "[\n|]"))
                   2497:        (error "Illegal extra characters"))))
                   2498: 
                   2499: (defun vip-get-ex-count ()
                   2500:   (setq ex-variant nil
                   2501:        ex-count nil
                   2502:        ex-flag nil)
                   2503:   (save-window-excursion
                   2504:     (set-buffer " *ex-working-space*")
                   2505:     (skip-chars-forward " \t")
                   2506:     (if (looking-at "!")
                   2507:        (progn
                   2508:          (setq ex-variant t)
                   2509:          (forward-char 1)))
                   2510:     (skip-chars-forward " \t")
                   2511:     (if (looking-at "[0-9]")
                   2512:        (progn
                   2513:          (set-mark (point))
                   2514:          (re-search-forward "[0-9][0-9]*")
                   2515:          (setq ex-count (string-to-int (buffer-substring (point) (mark))))
                   2516:          (skip-chars-forward " \t")))
                   2517:     (if (looking-at "[pl#]")
                   2518:        (progn
                   2519:          (setq ex-flag t)
                   2520:          (forward-char 1)))
                   2521:     (if (not (looking-at "[\n|]"))
                   2522:        (error "Illegal extra characters"))))
                   2523: 
                   2524: (defun vip-get-ex-file ()
                   2525:   "get a file name and set ex-variant, ex-append and ex-offset if found"
                   2526:   (setq ex-file nil
                   2527:        ex-variant nil
                   2528:        ex-append nil
                   2529:        ex-offset nil)
                   2530:   (save-window-excursion
                   2531:     (set-buffer " *ex-working-space*")
                   2532:     (skip-chars-forward " \t")
                   2533:     (if (looking-at "!")
                   2534:        (progn
                   2535:          (setq ex-variant t)
                   2536:          (forward-char 1)
                   2537:          (skip-chars-forward " \t")))
                   2538:     (if (looking-at ">>")
                   2539:        (progn
                   2540:          (setq ex-append t
                   2541:                ex-variant t)
                   2542:          (forward-char 2)
                   2543:          (skip-chars-forward " \t")))
                   2544:     (if (looking-at "+")
                   2545:        (progn
                   2546:          (forward-char 1)
                   2547:          (set-mark (point))
                   2548:          (re-search-forward "[ \t\n]")
                   2549:          (backward-char 1)
                   2550:          (setq ex-offset (buffer-substring (point) (mark)))
                   2551:          (forward-char 1)
                   2552:          (skip-chars-forward " \t")))
                   2553:     (set-mark (point))
                   2554:     (re-search-forward "[ \t\n]")
                   2555:     (backward-char 1)
                   2556:     (setq ex-file (buffer-substring (point) (mark)))))
                   2557: 
                   2558: (defun vip-execute-ex-command ()
                   2559:   "execute ex command using the value of addresses."
                   2560:   (cond ((string= ex-token "goto") (ex-goto))
                   2561:        ((string= ex-token "copy") (ex-copy nil))
                   2562:        ((string= ex-token "delete") (ex-delete))
                   2563:        ((string= ex-token "edit") (ex-edit))
                   2564:        ((string= ex-token "file") (vip-info-on-file))
                   2565:        ;((string= ex-token "global") (ex-global nil))
                   2566:        ((string= ex-token "join") (ex-line "join"))
                   2567:        ((string= ex-token "k") (ex-mark))
                   2568:        ((string= ex-token "mark") (ex-mark))
                   2569:        ((string= ex-token "map") (ex-map))
                   2570:        ((string= ex-token "move") (ex-copy t))
                   2571:        ((string= ex-token "put") (ex-put))
                   2572:        ((string= ex-token "quit") (ex-quit))
                   2573:        ((string= ex-token "read") (ex-read))
                   2574:        ((string= ex-token "set") (ex-set))
                   2575:        ((string= ex-token "shell") (ex-shell))
                   2576:        ((string= ex-token "substitute") (ex-substitute))
                   2577:        ((string= ex-token "stop") (suspend-emacs))
                   2578:        ((string= ex-token "t") (ex-copy nil))
                   2579:        ((string= ex-token "tag") (ex-tag))
                   2580:        ((string= ex-token "undo") (vip-undo))
                   2581:        ((string= ex-token "unmap") (ex-unmap))
                   2582:        ;((string= ex-token "v") (ex-global t))
                   2583:        ((string= ex-token "version") (vip-version))
                   2584:        ((string= ex-token "visual") (ex-edit))
                   2585:        ((string= ex-token "write") (ex-write nil))
                   2586:        ((string= ex-token "wq") (ex-write t))
                   2587:        ((string= ex-token "yank") (ex-yank))
                   2588:        ((string= ex-token "!") (ex-command))
                   2589:        ((string= ex-token "=") (ex-line-no))
                   2590:        ((string= ex-token ">") (ex-line "right"))
                   2591:        ((string= ex-token "<") (ex-line "left"))
                   2592:        ((string= ex-token "&") (ex-substitute t))
                   2593:        ((string= ex-token "~") (ex-substitute t t))
                   2594:        ((or (string= ex-token "append")
                   2595:             (string= ex-token "args")
                   2596:             (string= ex-token "change")
                   2597:             (string= ex-token "insert")
                   2598:             (string= ex-token "open")
                   2599:             )
                   2600:         (error (format "%s: no such command from VIP" ex-token)))
                   2601:        ((or (string= ex-token "abbreviate")
                   2602:             (string= ex-token "list")
                   2603:             (string= ex-token "next")
                   2604:             (string= ex-token "print")
                   2605:             (string= ex-token "preserve")
                   2606:             (string= ex-token "recover")
                   2607:             (string= ex-token "rewind")
                   2608:             (string= ex-token "source")
                   2609:             (string= ex-token "unabbreviate")
                   2610:             (string= ex-token "xit")
                   2611:             (string= ex-token "z")
                   2612:             )
                   2613:         (error (format "%s: not implemented in VIP" ex-token)))
                   2614:        (t (error (format "%s: Not an editor command" ex-token)))))
                   2615: 
                   2616: (defun ex-goto ()
                   2617:   "ex goto command"
                   2618:   (if (null ex-addresses)
                   2619:       (setq ex-addresses (cons (dot) nil)))
                   2620:   (push-mark (point))
                   2621:   (goto-char (car ex-addresses))
                   2622:   (beginning-of-line))
                   2623: 
                   2624: (defun ex-copy (del-flag)
                   2625:   "ex copy and move command.  DEL-FLAG means delete."
                   2626:   (vip-default-ex-addresses)
                   2627:   (let ((address (vip-get-ex-address))
                   2628:        (end (car ex-addresses)) (beg (car (cdr ex-addresses))))
                   2629:     (goto-char end)
                   2630:     (save-excursion
                   2631:       (set-mark beg)
                   2632:       (vip-enlarge-region (mark) (point))
                   2633:       (if del-flag (kill-region (point) (mark))
                   2634:        (copy-region-as-kill (point) (mark)))
                   2635:       (if ex-flag
                   2636:          (progn
                   2637:            (with-output-to-temp-buffer "*copy text*"
                   2638:              (princ
                   2639:               (if (or del-flag ex-g-flag ex-g-variant)
                   2640:                   (car kill-ring-yank-pointer)
                   2641:                 (buffer-substring (point) (mark)))))
                   2642:            (condition-case nil
                   2643:                (progn
                   2644:                  (vip-read-string "[Hit return to continue] ")
                   2645:                  (save-excursion (kill-buffer "*copy text*")))
                   2646:              (quit
                   2647:               (save-excursion (kill-buffer "*copy text*"))
                   2648:               (signal 'quit nil))))))
                   2649:       (if (= address 0)
                   2650:          (goto-char (point-min))
                   2651:        (goto-char address)
                   2652:        (forward-line 1))
                   2653:       (insert (car kill-ring-yank-pointer))))
                   2654: 
                   2655: (defun ex-delete ()
                   2656:   "ex delete"
                   2657:   (vip-default-ex-addresses)
                   2658:   (vip-get-ex-buffer)
                   2659:   (let ((end (car ex-addresses)) (beg (car (cdr ex-addresses))))
                   2660:     (if (> beg end) (error "First address exceeds second"))
                   2661:     (save-excursion
                   2662:       (vip-enlarge-region beg end)
                   2663:       (exchange-point-and-mark)
                   2664:       (if ex-count
                   2665:          (progn
                   2666:            (set-mark (point))
                   2667:            (forward-line (1- ex-count)))
                   2668:        (set-mark end))
                   2669:       (vip-enlarge-region (point) (mark))
                   2670:       (if ex-flag
                   2671:          ;; show text to be deleted and ask for confirmation
                   2672:          (progn
                   2673:            (with-output-to-temp-buffer " *delete text*"
                   2674:              (princ (buffer-substring (point) (mark))))
                   2675:            (condition-case conditions
                   2676:                (vip-read-string "[Hit return to continue] ")
                   2677:              (quit
                   2678:               (save-excursion (kill-buffer " *delete text*"))
                   2679:               (error "")))
                   2680:            (save-excursion (kill-buffer " *delete text*")))
                   2681:        (if ex-buffer
                   2682:            (if (and (<= ?A ex-buffer) (<= ex-buffer ?Z))
                   2683:                (vip-append-to-register
                   2684:                 (+ ex-buffer 32) (point) (mark) nil)
                   2685:              (copy-to-register ex-buffer (point) (mark) nil)))
                   2686:        (delete-region (point) (mark))))))
                   2687: 
                   2688: (defun ex-edit ()
                   2689:   "ex-edit"
                   2690:   (vip-get-ex-file)
                   2691:   (if (and (not ex-variant) (buffer-modified-p) buffer-file-name)
                   2692:       (error "No write since last change \(:e! overrides\)"))
                   2693:   (vip-change-mode-to-emacs)
                   2694:   (set-buffer
                   2695:    (find-file-noselect (concat default-directory ex-file)))
                   2696:   (vip-change-mode-to-vi)
                   2697:   (goto-char (point-min))
                   2698:   (if ex-offset
                   2699:       (progn
                   2700:        (save-window-excursion
                   2701:          (set-buffer " *ex-working-space*")
                   2702:          (delete-region (point-min) (point-max))
                   2703:          (insert ex-offset "\n")
                   2704:          (goto-char (point-min)))
                   2705:        (goto-char (vip-get-ex-address))
                   2706:        (beginning-of-line))))
                   2707: 
                   2708: (defun ex-global (variant)
                   2709:   "ex global command"
                   2710:   (if (or ex-g-flag ex-g-variant)
                   2711:       (error "Global within global not allowed")
                   2712:     (if variant
                   2713:        (setq ex-g-flag nil
                   2714:              ex-g-variant t)
                   2715:       (setq ex-g-flag t
                   2716:            ex-g-variant nil)))
                   2717:   (vip-get-ex-pat)
                   2718:   (if (null ex-token)
                   2719:       (error "Missing regular expression for global command"))
                   2720:   (if (string= ex-token "")
                   2721:       (if (null vip-s-string) (error "No previous search string")
                   2722:        (setq ex-g-pat vip-s-string))
                   2723:     (setq ex-g-pat ex-token
                   2724:          vip-s-string ex-token))
                   2725:   (if (null ex-addresses)
                   2726:       (setq ex-addresses (list (point-max) (point-min))))
                   2727:   (let ((marks nil) (mark-count 0)
                   2728:        com-str (end (car ex-addresses)) (beg (car (cdr ex-addresses))))
                   2729:     (if (> beg end) (error "First address exceeds second"))
                   2730:     (save-excursion
                   2731:       (vip-enlarge-region beg end)
                   2732:       (exchange-point-and-mark)
                   2733:       (let ((cont t) (limit (point-marker)))
                   2734:        (exchange-point-and-mark)
                   2735:        ;; skip the last line if empty
                   2736:        (beginning-of-line)
                   2737:        (if (and (eobp) (not (bobp))) (backward-char 1))
                   2738:        (while (and cont (not (bobp)) (>= (point) limit))
                   2739:          (beginning-of-line)
                   2740:          (set-mark (point))
                   2741:          (end-of-line)
                   2742:          (let ((found (re-search-backward ex-g-pat (mark) t)))
                   2743:            (if (or (and ex-g-flag found)
                   2744:                    (and ex-g-variant (not found)))
                   2745:                (progn
                   2746:                  (end-of-line)
                   2747:                  (setq mark-count (1+ mark-count))
                   2748:                  (setq marks (cons (point-marker) marks)))))
                   2749:          (beginning-of-line)
                   2750:          (if (bobp) (setq cont nil)
                   2751:            (forward-line -1)
                   2752:            (end-of-line)))))
                   2753:   (save-window-excursion
                   2754:     (set-buffer " *ex-working-space*")
                   2755:     (setq com-str (buffer-substring (1+ (point)) (1- (point-max)))))
                   2756:   (while marks
                   2757:     (goto-char (car marks))
                   2758:     ; report progress of execution on a slow machine.
                   2759:     ;(message "Executing global command...")
                   2760:     ;(if (zerop (% mark-count 10))
                   2761:        ;(message "Executing global command...%d" mark-count))
                   2762:     (vip-ex com-str)
                   2763:     (setq mark-count (1- mark-count))
                   2764:     (setq marks (cdr marks)))))
                   2765:   ;(message "Executing global command...done")))
                   2766: 
                   2767: (defun ex-line (com)
                   2768:   "ex line commands.  COM is join, shift-right or shift-left."
                   2769:   (vip-default-ex-addresses)
                   2770:   (vip-get-ex-count)
                   2771:   (let ((end (car ex-addresses)) (beg (car (cdr ex-addresses))) point)
                   2772:     (if (> beg end) (error "First address exceeds second"))
                   2773:     (save-excursion
                   2774:       (vip-enlarge-region beg end)
                   2775:       (exchange-point-and-mark)
                   2776:       (if ex-count
                   2777:          (progn
                   2778:            (set-mark (point))
                   2779:            (forward-line ex-count)))
                   2780:       (if ex-flag
                   2781:          ;; show text to be joined and ask for confirmation
                   2782:          (progn
                   2783:            (with-output-to-temp-buffer " *text*"
                   2784:              (princ (buffer-substring (point) (mark))))
                   2785:            (condition-case conditions
                   2786:                (progn
                   2787:                  (vip-read-string "[Hit return to continue] ")
                   2788:                  (ex-line-subr com (point) (mark)))
                   2789:              (quit
                   2790:               (ding)))
                   2791:            (save-excursion (kill-buffer " *text*")))
                   2792:        (ex-line-subr com (point) (mark)))
                   2793:       (setq point (point)))
                   2794:     (goto-char (1- point))
                   2795:     (beginning-of-line)))
                   2796: 
                   2797: (defun ex-line-subr (com beg end)
                   2798:   (cond ((string= com "join")
                   2799:         (goto-char (min beg end))
                   2800:         (while (and (not (eobp)) (< (point) (max beg end)))
                   2801:           (end-of-line)
                   2802:           (if (and (<= (point) (max beg end)) (not (eobp)))
                   2803:               (progn
                   2804:                 (forward-line 1)
                   2805:                 (delete-region (point) (1- (point)))
                   2806:                 (if (not ex-variant) (fixup-whitespace))))))
                   2807:        ((or (string= com "right") (string= com "left"))
                   2808:         (indent-rigidly
                   2809:          (min beg end) (max beg end)
                   2810:          (if (string= com "right") vip-shift-width (- vip-shift-width)))
                   2811:         (goto-char (max beg end))
                   2812:         (end-of-line)
                   2813:         (forward-char 1))))
                   2814: 
                   2815: (defun ex-mark ()
                   2816:   "ex mark"
                   2817:   (let (char)
                   2818:     (if (null ex-addresses)
                   2819:        (setq ex-addresses
                   2820:              (cons (point) nil)))
                   2821:     (save-window-excursion
                   2822:       (set-buffer " *ex-working-space*")
                   2823:       (skip-chars-forward " \t")
                   2824:       (if (looking-at "[a-z]")
                   2825:          (progn
                   2826:            (setq char (following-char))
                   2827:            (forward-char 1)
                   2828:            (skip-chars-forward " \t")
                   2829:            (if (not (looking-at "[\n|]"))
                   2830:                (error "Extra characters at end of \"k\" command")))
                   2831:        (if (looking-at "[\n|]")
                   2832:            (error "\"k\" requires a following letter")
                   2833:          (error "Mark must specify a letter"))))
                   2834:     (save-excursion
                   2835:       (goto-char (car ex-addresses))
                   2836:       (point-to-register (- char (- ?a ?\C-a))))))
                   2837: 
                   2838: (defun ex-map ()
                   2839:   "ex map"
                   2840:   (let (char string)
                   2841:     (save-window-excursion
                   2842:       (set-buffer " *ex-working-space*")
                   2843:       (skip-chars-forward " \t")
                   2844:       (setq char (char-to-string (following-char)))
                   2845:       (forward-char 1)
                   2846:       (skip-chars-forward " \t")
                   2847:       (if (looking-at "[\n|]") (error "Missing rhs"))
                   2848:       (set-mark (point))
                   2849:       (end-of-buffer)
                   2850:       (backward-char 1)
                   2851:       (setq string (buffer-substring (mark) (point))))
                   2852:     (if (not (lookup-key ex-map char))
                   2853:        (define-key ex-map char
                   2854:          (or (lookup-key vip-mode-map char) 'vip-nil)))
                   2855:     (define-key vip-mode-map char
                   2856:       (eval
                   2857:        (list 'quote
                   2858:             (cons 'lambda
                   2859:                   (list '(count)
                   2860:                         '(interactive "p")
                   2861:                         (list 'execute-kbd-macro string 'count))))))))
                   2862: 
                   2863: (defun ex-unmap ()
                   2864:   "ex unmap"
                   2865:   (let (char)
                   2866:     (save-window-excursion
                   2867:       (set-buffer " *ex-working-space*")
                   2868:       (skip-chars-forward " \t")
                   2869:       (setq char (char-to-string (following-char)))
                   2870:       (forward-char 1)
                   2871:       (skip-chars-forward " \t")
                   2872:       (if (not (looking-at "[\n|]")) (error "Macro must be a character")))
                   2873:     (if (not (lookup-key ex-map char))
                   2874:        (error "That macro wasn't mapped"))
                   2875:     (define-key vip-mode-map char (lookup-key ex-map char))
                   2876:     (define-key ex-map char nil)))
                   2877: 
                   2878: (defun ex-put ()
                   2879:   "ex put"
                   2880:   (let ((point (if (null ex-addresses) (point) (car ex-addresses))))
                   2881:     (vip-get-ex-buffer)
                   2882:     (setq vip-use-register ex-buffer)
                   2883:     (goto-char point)
                   2884:     (if (= point 0) (vip-Put-back 1) (vip-put-back 1))))
                   2885: 
                   2886: (defun ex-quit ()
                   2887:   "ex quit"
                   2888:   (let (char)
                   2889:     (save-window-excursion
                   2890:       (set-buffer " *ex-working-space*")
                   2891:       (skip-chars-forward " \t")
                   2892:       (setq char (following-char)))
                   2893:     (if (= char ?!) (kill-emacs t) (save-buffers-kill-emacs))))
                   2894: 
                   2895: (defun ex-read ()
                   2896:   "ex read"
                   2897:   (let ((point (if (null ex-addresses) (point) (car ex-addresses)))
                   2898:        (variant nil) command file)
                   2899:     (goto-char point)
                   2900:     (if (not (= point 0)) (next-line 1))
                   2901:     (beginning-of-line)
                   2902:     (save-window-excursion
                   2903:       (set-buffer " *ex-working-space*")
                   2904:       (skip-chars-forward " \t")
                   2905:       (if (looking-at "!")
                   2906:          (progn
                   2907:            (setq variant t)
                   2908:            (forward-char 1)
                   2909:            (skip-chars-forward " \t")
                   2910:            (set-mark (point))
                   2911:            (end-of-line)
                   2912:            (setq command (buffer-substring (mark) (point))))
                   2913:        (set-mark (point))
                   2914:        (re-search-forward "[ \t\n]")
                   2915:        (backward-char 1)
                   2916:        (setq file (buffer-substring (point) (mark)))))
                   2917:       (if variant
                   2918:          (shell-command command t)
                   2919:        (insert-file file))))
                   2920: 
                   2921: (defun ex-set ()
                   2922:   (eval (list 'setq
                   2923:              (read-variable "Variable: ")
                   2924:              (eval (read-minibuffer "Value: ")))))
                   2925: 
                   2926: (defun ex-shell ()
                   2927:   "ex shell"
                   2928:   (vip-change-mode-to-emacs)
                   2929:   (shell))
                   2930: 
                   2931: (defun ex-substitute (&optional repeat r-flag) 
                   2932:   "ex substitute. if REPEAT use previous reg-exp which is ex-reg-exp or
                   2933: vip-s-string"
                   2934:   (let (pat repl (opt-g nil) (opt-c nil) (matched-pos nil))
                   2935:     (if repeat (setq ex-token nil) (vip-get-ex-pat))
                   2936:     (if (null ex-token)
                   2937:        (setq pat (if r-flag vip-s-string ex-reg-exp)
                   2938:              repl ex-repl)
                   2939:       (setq pat (if (string= ex-token "") vip-s-string ex-token))
                   2940:       (setq vip-s-string pat
                   2941:            ex-reg-exp pat)
                   2942:       (vip-get-ex-pat)
                   2943:       (if (null ex-token)
                   2944:          (setq ex-token ""
                   2945:                ex-repl "")
                   2946:        (setq repl ex-token
                   2947:              ex-repl ex-token)))
                   2948:     (while (vip-get-ex-opt-gc)
                   2949:       (if (string= ex-token "g") (setq opt-g t) (setq opt-c t)))
                   2950:     (vip-get-ex-count)
                   2951:     (if ex-count
                   2952:        (save-excursion
                   2953:          (if ex-addresses (goto-char (car ex-addresses)))
                   2954:          (set-mark (point))
                   2955:          (forward-line (1- ex-count))
                   2956:          (setq ex-addresses (cons (point) (cons (mark) nil))))
                   2957:       (if (null ex-addresses)
                   2958:          (setq ex-addresses (cons (point) (cons (point) nil)))
                   2959:        (if (null (cdr ex-addresses))
                   2960:            (setq ex-addresses (cons (car ex-addresses) ex-addresses)))))
                   2961:     ;(setq G opt-g)
                   2962:     (let ((beg (car ex-addresses)) (end (car (cdr ex-addresses)))
                   2963:          (cont t) eol-mark)
                   2964:       (save-excursion
                   2965:        (vip-enlarge-region beg end)
                   2966:        (let ((limit (save-excursion
                   2967:                       (goto-char (max (point) (mark)))
                   2968:                       (point-marker))))
                   2969:          (goto-char (min (point) (mark)))
                   2970:          (while (< (point) limit)
                   2971:            (end-of-line)
                   2972:            (setq eol-mark (dot-marker))
                   2973:            (beginning-of-line)
                   2974:            (if opt-g
                   2975:                (progn
                   2976:                  (while (and (not (eolp))
                   2977:                              (re-search-forward pat eol-mark t))
                   2978:                    (if (or (not opt-c) (y-or-n-p "Replace? "))
                   2979:                        (progn
                   2980:                          (setq matched-pos (point))
                   2981:                          (replace-match repl))))
                   2982:                  (end-of-line)
                   2983:                  (forward-char))
                   2984:              (if (and (re-search-forward pat eol-mark t)
                   2985:                       (or (not opt-c) (y-or-n-p "Replace? ")))
                   2986:                  (progn
                   2987:                    (setq matched-pos (point))
                   2988:                    (replace-match repl)))
                   2989:              (end-of-line)
                   2990:              (forward-char))))))
                   2991:     (if matched-pos (goto-char matched-pos))
                   2992:     (beginning-of-line)
                   2993:     (if opt-c (message "done"))))
                   2994: 
                   2995: (defun ex-tag ()
                   2996:   "ex tag"
                   2997:   (let (tag)
                   2998:     (save-window-excursion
                   2999:       (set-buffer " *ex-working-space*")
                   3000:       (skip-chars-forward " \t")
                   3001:       (set-mark (point))
                   3002:       (skip-chars-forward "^ |\t\n")
                   3003:       (setq tag (buffer-substring (mark) (point))))
                   3004:     (if (not (string= tag "")) (setq ex-tag tag))
                   3005:     (vip-change-mode-to-emacs)
                   3006:     (condition-case conditions
                   3007:        (progn
                   3008:          (if (string= tag "")
                   3009:              (find-tag ex-tag t)
                   3010:            (find-tag-other-window ex-tag))
                   3011:          (vip-change-mode-to-vi))
                   3012:       (error
                   3013:        (vip-change-mode-to-vi)
                   3014:        (vip-message-conditions conditions)))))
                   3015: 
                   3016: (defun ex-write (q-flag)
                   3017:   "ex write"
                   3018:   (vip-default-ex-addresses t)
                   3019:   (vip-get-ex-file)
                   3020:   (if (string= ex-file "")
                   3021:       (progn
                   3022:        (if (null buffer-file-name)
                   3023:            (error "No file associated with this buffer"))
                   3024:        (setq ex-file buffer-file-name))
                   3025:     (setq ex-file (expand-file-name ex-file)))
                   3026:   (if (and (not (string= ex-file (buffer-file-name)))
                   3027:           (file-exists-p ex-file)
                   3028:           (not ex-variant))
                   3029:       (error (format "\"%s\" File exists - use w! to override" ex-file)))
                   3030:   (let ((end (car ex-addresses)) (beg (car (cdr ex-addresses))))
                   3031:     (if (> beg end) (error "First address exceeds second"))
                   3032:     (save-excursion
                   3033:       (vip-enlarge-region beg end)
                   3034:       (write-region (point) (mark) ex-file ex-append t)))
                   3035:   (if (null buffer-file-name) (setq buffer-file-name ex-file))
                   3036:   (if q-flag
                   3037:       (progn
                   3038:        (delete-auto-save-file-if-necessary)
                   3039:        (kill-buffer (current-buffer)))))
                   3040: 
                   3041: (defun ex-yank ()
                   3042:   "ex yank"
                   3043:   (vip-default-ex-addresses)
                   3044:   (vip-get-ex-buffer)
                   3045:   (let ((end (car ex-addresses)) (beg (car (cdr ex-addresses))))
                   3046:     (if (> beg end) (error "First address exceeds second"))
                   3047:     (save-excursion
                   3048:       (vip-enlarge-region beg end)
                   3049:       (exchange-point-and-mark)
                   3050:       (if (or ex-g-flag ex-g-variant) (error "Can't yank within global"))
                   3051:       (if ex-count
                   3052:          (progn
                   3053:            (set-mark (point))
                   3054:            (forward-line (1- ex-count)))
                   3055:        (set-mark end))
                   3056:       (vip-enlarge-region (point) (mark))
                   3057:       (if ex-flag (error "Extra chacters at end of command"))
                   3058:       (if ex-buffer
                   3059:          (copy-to-register ex-buffer (point) (mark) nil))
                   3060:       (copy-region-as-kill (point) (mark)))))
                   3061: 
                   3062: (defun ex-command ()
                   3063:   "execute shell command"
                   3064:   (let (command)
                   3065:     (save-window-excursion
                   3066:       (set-buffer " *ex-working-space*")
                   3067:       (skip-chars-forward " \t")
                   3068:       (set-mark (point))
                   3069:       (end-of-line)
                   3070:       (setq command (buffer-substring (mark) (point))))
                   3071:     (if (null ex-addresses)
                   3072:        (shell-command command)
                   3073:       (let ((end (car ex-addresses)) (beg (car (cdr ex-addresses))))
                   3074:        (if (null beg) (setq beg end))
                   3075:        (save-excursion
                   3076:          (goto-char beg)
                   3077:          (set-mark end)
                   3078:          (vip-enlarge-region (point) (mark))
                   3079:          (shell-command-on-region (point) (mark) command t))
                   3080:        (goto-char beg)))))
                   3081: 
                   3082: (defun ex-line-no ()
                   3083:   "print line number"
                   3084:   (message "%d"
                   3085:           (1+ (count-lines
                   3086:                (point-min)
                   3087:                (if (null ex-addresses) (point-max) (car ex-addresses))))))
                   3088: 
                   3089: (if (file-exists-p "~/.vip") (load "~/.vip"))
                   3090: 
                   3091: ;; End of VIP

unix.superglobalmegacorp.com

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