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