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