home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / languages / elisp / modes / evi / evi.el next >
Encoding:
Text File  |  1993-06-23  |  150.1 KB  |  4,549 lines

  1. ;; Copyright (c) 1992, 1993 Jeffrey R. Lewis
  2. ;; All rights reserved.
  3. ;;
  4. ;; Redistribution and use in source and compiled forms, with or without
  5. ;; modification, are permitted provided that the following conditions
  6. ;; are met:
  7. ;; 1. Redistributions of source code must retain the above copyright notice,
  8. ;;    this list of conditions and the following disclaimer.
  9. ;; 2. Redistributions in compiled form must either be accompanied by the
  10. ;;    source, or reproduce the above copyright notice, this list of conditions
  11. ;;    and the following disclaimer in the documentation and/or other materials
  12. ;;    provided with the distribution.
  13. ;;
  14. ;; THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
  15. ;; INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  16. ;; AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  17.  
  18. ;; Evi 0.99.8 - Emulate Vi
  19. ;; LCD Archive Entry:
  20. ;; evi|Jeffrey R. Lewis|jlewis@cse.ogi.edu
  21. ;; |Emulate Vi - enhanced emacs vi emulator for vi-heads
  22. ;; |6-23-93|0.99.8|~/modes/evi.tar.Z
  23. (defvar evi-version "Evi 0.99.8, 6-23-93")
  24.  
  25. ;; Here follows Evi 0.9, an even better vi emulator aimed at those who either
  26. ;; are well accustomed to vi, or who just simply happen to like its style of
  27. ;; editing better than emacs' default.  Evi's first goal is vi compatibility.
  28. ;; Its second goal is to be an extension of vi, taking advantage of features
  29. ;; supplied by the emacs environment, without simply becoming emacs with vi'ish
  30. ;; key bindings.
  31.  
  32. ;; You can get a copy of the evi documentation by sending an e-mail message to
  33. ;; mail-server@brandx.rain.com, with the following body:
  34. ;;    begin
  35. ;;    send evi.info.Z
  36. ;;    end
  37. ;; You can also pick up the TeXinfo source for the documentation by sending
  38. ;; for evi.tex.Z.  The latest version of evi can also be picked up this way:
  39. ;; send for evi.el.Z.
  40.  
  41. (defmacro evi-defbuffervar (name default-value documentation)
  42.   (list 'progn (list 'defvar name nil documentation)
  43.            (list 'make-variable-buffer-local (list 'quote name))
  44.            (list 'set-default (list 'quote name) default-value)))
  45.  
  46. (defvar evi-emacs-version
  47.   (let ((version (emacs-version)))
  48.     (cond ((string-match "Emacs 18\\|Epoch 4" version)
  49.             'emacs18)
  50.           ((string-match "Emacs 19\.[0-9]*\.[0-9]* Lucid" version)
  51.             'lucid19)
  52.           ((string-match "Emacs 19" version)
  53.         'emacs19))))
  54.  
  55. (cond
  56.   ((eq evi-emacs-version 'emacs18)
  57.     (defun evi-fill-keymap (keymap def)
  58.       (fillarray keymap def))
  59.  
  60.     (defun evi-keymap-bindings (map)
  61.       (evi-keymap-bindings2 map ""))
  62.  
  63.     (defun evi-keymap-bindings2 (map prefix)
  64.       (if (arrayp map)
  65.       (let ((i 0)
  66.         (len (length map))
  67.         (binding)
  68.         (keys)
  69.         (mappings nil))
  70.         (while (< i len)
  71.           (setq binding (aref map i))
  72.           (if binding
  73.           (progn
  74.             (setq keys (concat prefix (char-to-string i)))
  75.             (if (keymapp binding)
  76.             (setq mappings
  77.                   (nconc (evi-keymap-bindings2 binding keys)
  78.                      mappings))
  79.               (setq mappings (cons (cons keys binding) mappings)))))
  80.           (setq i (1+ i)))
  81.         mappings)
  82.     (let ((bindings (cdr map))
  83.           (mappings nil))
  84.       (while bindings
  85.         (let* ((binding (car bindings))
  86.            (keys (concat prefix (char-to-string (car binding)))))
  87.           (if (keymapp (cdr binding))
  88.           (setq mappings
  89.             (nconc (evi-keymap-bindings2 (cdr binding) keys)
  90.                    mappings))
  91.         (setq mappings (cons (cons keys (cdr binding)) mappings))))
  92.         (setq bindings (cdr bindings)))
  93.       mappings))))
  94.   ((eq evi-emacs-version 'emacs19)
  95.     (defun evi-fill-keymap (keymap def)
  96.       (fillarray (car (cdr keymap)) def))
  97.  
  98.     (defun evi-keymap-bindings (map)
  99.       (evi-keymap-bindings2 map ""))
  100.  
  101.     (defun evi-keymap-bindings2 (map prefix)
  102.       (let ((bindings (cdr map))
  103.         (mappings nil))
  104.     (while bindings
  105.       (if (vectorp (car bindings))
  106.           (setq mappings
  107.             (nconc (evi-vector-keymap-bindings (car bindings) prefix)
  108.                mappings))
  109.         (let* ((binding (car bindings))
  110.            (keys (concat prefix (char-to-string (car binding)))))
  111.           (if (keymapp (cdr binding))
  112.           (setq mappings
  113.             (nconc (evi-keymap-bindings2 (cdr binding) keys)
  114.                    mappings))
  115.         (setq mappings (cons (cons keys (cdr binding)) mappings)))))
  116.       (setq bindings (cdr bindings)))
  117.     mappings))
  118.  
  119.     (defun evi-vector-keymap-bindings (map prefix)
  120.       (let ((i 0)
  121.         (len (length map))
  122.         (binding)
  123.         (keys)
  124.         (mappings nil))
  125.     (while (< i len)
  126.       (setq binding (aref map i))
  127.       (if binding
  128.           (progn
  129.         (setq keys (concat prefix (char-to-string i)))
  130.         (if (keymapp binding)
  131.             (setq mappings
  132.               (nconc (evi-keymap-bindings2 binding keys)
  133.                  mappings))
  134.           (setq mappings (cons (cons keys binding) mappings)))))
  135.       (setq i (1+ i)))
  136.     mappings)))
  137.   ((eq evi-emacs-version 'lucid19)
  138.     (defun evi-fill-keymap (keymap def)
  139.       (let ((i 128))
  140.     (while (<= 0 (setq i (1- i)))
  141.       (define-key keymap (make-string 1 i) def))
  142.     keymap))
  143.  
  144.     (defun evi-keymap-bindings (map)
  145.       (let ((mappings nil))
  146.     (evi-keymap-bindings2 map "")
  147.     mappings))
  148.  
  149.     (defun evi-keymap-bindings2 (map prefix)
  150.       (map-keymap
  151.        (function
  152.      (lambda (key def)
  153.        (let* ((keys (concat prefix (single-key-description key))))
  154.          (if (keymapp def)
  155.          (setq mappings
  156.                (nconc (evi-keymap-bindings2 def keys) mappings))
  157.            (setq mappings
  158.              (cons (cons keys def) mappings)))))) map))))
  159.  
  160. (defvar evi-initialized nil)
  161.  
  162. (defvar evi-interactive t)
  163.  
  164. (defvar evi-mode-hook nil
  165.   "*Function or functions called upon entry to evi.")
  166.  
  167. (evi-defbuffervar evi-enabled nil
  168.   "If t, currently emulating vi in this buffer.")
  169.  
  170. (defvar evi-debug nil
  171.   "If t, errors generated by emacs are not handled.")
  172.  
  173. (defvar evi-supress-ex-startup nil
  174.   "If t, don't source .exrc or EXINIT at startup.")
  175.  
  176. (defvar evi-report-unsupported-options nil
  177.   "If t, give an error if a :set option is used that isn't supported.
  178. Otherwise, these are silently ignored.")
  179.  
  180. (evi-defbuffervar evi-mode 'vi
  181.   "Current vi mode, one of vi, insert or replace.")
  182.  
  183. (evi-defbuffervar evi-mode-string nil
  184.   "String describing current evi mode.  This is displayed in the mode line.")
  185.  
  186. (evi-defbuffervar evi-in-minibuf nil
  187.   "If t, we are currently editing in the minibuffer")
  188.  
  189. (defvar evi-enable-emacs-commands nil
  190.   "If t, emacs commands will be visible")
  191.  
  192. (defvar evi-meta-prefix-char nil
  193.   "Meta-prefix-char to use while in Evi buffers.")
  194.  
  195. (defvar evi-emacs-meta-prefix-char nil
  196.   "Meta-prefix-char that emacs uses.")
  197.  
  198. (defvar ex-input-escapes nil
  199.   "If t, backslash escapes in ex commands will be processed.")
  200.  
  201. (defvar evi-read-only-buffers nil
  202.   "If t, read-only files will have read-only buffers")
  203.  
  204. (defvar evi-last-point nil
  205.   "Used to calculate line number updates.")
  206.  
  207. (defvar evi-mark nil
  208.   "Used to define regions for operator commands.")
  209.  
  210. (defvar evi-global-directory t
  211.   "If t, a global current directory is used (this is the default).")
  212.  
  213. (defvar evi-directory-stack nil)
  214.  
  215. (defvar evi-process-buffer nil)
  216.  
  217. (defvar evi-abbrev-list nil)
  218.  
  219. (evi-defbuffervar evi-emacs-local-map nil
  220.   "Emacs' local map.  \(buffer specific\)")
  221.  
  222. (defvar evi-emacs-local-suppress-key-list '(?\b ?\t ?\e ?\C-?)
  223.   "Keys from emacs local map that are to be suppressed.")
  224.  
  225. (defvar evi-command-keys nil
  226.   "The keystrokes for the current command.")
  227.  
  228. (defvar evi-prompted nil
  229.   "If t, the current command was prompted for.")
  230.  
  231. (evi-defbuffervar evi-replace-max nil
  232.   "Maximum excursion of a replace, after which it switches to insert.")
  233.  
  234. (evi-defbuffervar evi-overstruck-char nil
  235.   "Value of the character overstruck by the `$' marking a partial line change.")
  236.  
  237. (evi-defbuffervar evi-context nil
  238.   "Current motion context.  One of to-end, to-next, whole-line, or nil.
  239. The value of this variable is passed to evi-motion-command, and is set by
  240. prefix operators like 'd' or '>' to control the type of region defined by
  241. the following motion command.")
  242.  
  243. (defvar evi-prefix-count nil
  244.   "Current prefix count.")
  245.  
  246. (defvar evi-prefix-count-multiplier 1
  247.   "Current prefix count multiplier.")
  248.  
  249. (defvar evi-register-spec nil
  250.   "Current register to use for deletes, yanks, puts, etc.")
  251.  
  252. (defvar evi-digit-register 8
  253.   "Current delete-ring register cursor.  Points to the register that
  254. will be register 1.")
  255.  
  256. (defvar evi-repeat-count 0
  257.   "The number of times the current command has been repeated via `.'.")
  258.  
  259. (defvar evi-hidden-repeat-count 0
  260.   "The hidden copy of evi-repeat-count, which isn't visible unless actually
  261. repeating a command.")
  262.  
  263. (defvar evi-last-macro-register nil
  264.   "Last register used to invoke a macro via \\[evi-register-macro].")
  265.  
  266. (defvar evi-registers (make-vector 72 nil)
  267.   "Vi registers.  0-8 are the delete ring, 9 is the unnamed text register,
  268. 10-35 are the alphabetic text registers, and 36-71 are the mark registers.
  269. Each text register is a cons cell with the car being the text in the register
  270. and the cdr being a flag indicating whether or not the text is whole lines.")
  271.  
  272. (defvar evi-register-unnamed 9
  273.   "Symbolic name for the unnamed register.  Shouldn't change.")
  274.  
  275. (defvar evi-region-shape 'chars
  276.   "Specifies the shape of the region for the current operation - one of
  277. chars, lines, or rectangle.  The value of this variable is stored in the cdr
  278. of any register that gets stored as a result of the current command.")
  279.  
  280. (evi-defbuffervar evi-current-indentation 0
  281.   "The indentation of the most recently auto-indented line.  Used by
  282. evi-newline to determine when to kill auto-indented whitespace.
  283. \(buffer specific\)")
  284.  
  285. (defvar evi-internal-command nil
  286.   "If t, next command will be executed in internal mode (certain interface
  287. features turned off)")
  288.  
  289. (evi-defbuffervar evi-goal-column 0
  290.   "The column that vertical cursor motion will try to preserve, if possible.")
  291.  
  292. (evi-defbuffervar evi-reset-goal-column t
  293.   "If t, a horizontal motion has been performed, thus goal column must be reset.")
  294.  
  295. (defvar evi-search-pattern nil
  296.   "The last pattern specified for searching.")
  297.  
  298. (defvar evi-search-forward t
  299.   "If t, the last search command was a forward search.")
  300.  
  301. (defvar evi-find-character nil
  302.   "The last character specified for finding.")
  303.  
  304. (defvar evi-find-forward t
  305.   "If t, the last find command was a forward search.")
  306.  
  307. (defvar evi-find-up-to nil
  308.   "If t, the last find command was a find up to command.")
  309.  
  310. (defvar ex-previous-re nil
  311.   "Last regular expression searched for in :subst command.")
  312.  
  313. (defvar ex-previous-replacement nil
  314.   "Last replacement used in :subst command.")
  315.  
  316. (evi-defbuffervar evi-context-ring (make-vector 10 nil)
  317.   "The last 10 contexts for this buffer.  A context is a location in the buffer
  318. where only relative motions were performed.  A new context is thus saved each
  319. time a non-relative motion is performed.")
  320.  
  321. (evi-defbuffervar evi-context-ring-cursor 0
  322.   "The cursor pointing to the last context in the context ring.")
  323.  
  324. (defvar evi-last-shell-command nil
  325.   "The last shell command run.")
  326.  
  327. (defvar ex-work-space (get-buffer-create " *ex-work-space*")
  328.   "Evi work space for parsing ex commands.")
  329.  
  330. (defvar ex-tag nil
  331.   "Last tag specified.")
  332.  
  333. (defun evi-make-keymap (name small &optional fill)
  334.   (let ((map (if small (make-sparse-keymap) (make-keymap))))
  335.     (if (fboundp 'set-keymap-name)
  336.     (set-keymap-name map name))
  337.     (if fill
  338.     (evi-fill-keymap map fill))
  339.     map))
  340.  
  341. (defconst evi-top-level-map
  342.   (evi-make-keymap 'evi-top-level-map nil 'evi-top-level-command))
  343.  
  344. (defconst evi-vi-map (evi-make-keymap 'evi-vi-map nil)
  345.   "The keymap used in vi mode.")
  346.  
  347. (defconst evi-internal-map (evi-make-keymap 'evi-internal-map nil)
  348.   "The keymap used for special command macro features.")
  349.  
  350. (defconst evi-motion-map (evi-make-keymap 'evi-motion-map nil)
  351.   "The keymap used for operand motions.")
  352.  
  353. (defconst evi-map-map (evi-make-keymap 'evi-map-map t)
  354.   "The keymap used for map macros.")
  355.  
  356. (defconst evi-input-map (evi-make-keymap 'evi-input-map nil 'evi-self-insert)
  357.   "The keymap used in input modes.")
  358.  
  359. (defconst evi-replace-map
  360.   (evi-make-keymap 'evi-replace-map nil 'evi-self-replace)
  361.   "The keymap used in replace mode.")
  362.  
  363. (defconst evi-insert-map (evi-make-keymap 'evi-insert-map t)
  364.   "The insert mode specific input map.")
  365.  
  366. (defconst evi-read-string-map (evi-make-keymap 'evi-read-string-map t)
  367.   "The evi-read-string specific command map.")
  368.  
  369. (defconst evi-read-string-input-map
  370.   (evi-make-keymap 'evi-read-string-input-map t)
  371.   "The evi-read-string specific input map.")
  372.  
  373. (defconst evi-ex-map (evi-make-keymap 'evi-ex-map t)
  374.   "The keymap used when reading ex commands from the minibuffer")
  375.  
  376. (defconst evi-ex-input-map (evi-make-keymap 'evi-ex-input-map t)
  377.   "The keymap used when reading ex commands from the minibuffer (insert-mode)")
  378.  
  379. (defconst evi-input-map-map (evi-make-keymap 'evi-input-map-map t)
  380.   "The keymap used for input map macros.")
  381.  
  382. (defconst evi-shell-map (evi-make-keymap 'evi-shell-map t)
  383.   "The local keymap used in command mode in a shell buffer.")
  384.  
  385. (evi-defbuffervar evi-buffer-local-vi-map 
  386.   (evi-make-keymap 'evi-buffer-local-vi-map t)
  387.   "The keymap for buffer specific additions to the vi command map")
  388.  
  389. (defconst evi-minibuf-input-map (evi-make-keymap 'evi-minibuf-input-map t))
  390.  
  391. ; it appears to be correct that this not include buffer-local-vi-map
  392. (defconst evi-default-keymap-list (list evi-map-map evi-vi-map))
  393.  
  394. (defconst evi-all-keymaps '(vi insert replace ex)
  395.   "All Evi keymaps.")
  396.  
  397. (evi-defbuffervar evi-register-parameter nil
  398.   "Register specification to the current parameterized macro.")
  399.  
  400. (evi-defbuffervar evi-prefix-count-parameter nil
  401.   "Prefix count to the current parameterized macro.")
  402.  
  403. (defvar evi-last-command-keys nil
  404.   "Command keys for the last complete vi command.")
  405.  
  406. (evi-defbuffervar evi-insert-point nil
  407.   "The point at which the current insert command began.")
  408.  
  409. ;; Vi option variables
  410. ;; ZZ - could/should make some of these buffer local after reading EXINIT
  411.  
  412. (defconst evi-option-list
  413.   '((("autoindent" "ai") . (bool . evi-auto-indent))
  414.     (("autoprint" "ap") . (bool . nil))
  415.     (("autowrite" "aw") . (bool . nil))
  416.     (("backslash-escapes" "be") . (bool . ex-input-escapes))
  417.     (("beautify") . (bool . nil))
  418.     (("command-line-editing" "cle") . (bool . evi-command-line-editing))
  419.     (("directory" "dir") . (string . nil))
  420.     (("edcompatible" "ed") . (bool . nil))
  421.     (("enable-emacs-commands" "ee") . (bool . evi-enable-emacs-commands))
  422.     (("errorbells" "eb") . (bool . evi-error-bell))
  423.     (("flash") . (bool . nil))
  424.     (("hardtabs" "ht") . (number . nil))
  425.     (("ignorecase" "ic") . (bool . evi-ignore-case))
  426.     (("ishell" "ish") . (string . explicit-shell-file-name))
  427.     (("lisp") . (bool . nil))
  428.     (("list") . (bool . nil))
  429.     (("magic") . (bool . evi-search-magic))
  430.     (("mesg") . (bool . nil))
  431.     (("meta-prefix" "mp") . (char . evi-meta-prefix-char))
  432.     (("modeline") . (bool . nil))
  433.     (("novice") . (bool . nil))
  434.     (("number" "nu") . (bool . evi-number))
  435.     (("optimize" "opt") . (bool . nil))
  436.     (("paragraphs" "para") . (string . nil))
  437.     (("prompt") . (bool . nil))
  438.     (("readonly" "ro") . (bool . evi-buffer-read-only))
  439.     (("readonly-buffers") . (bool . evi-read-only-buffers))
  440.     (("redraw") . (bool . nil))
  441.     (("remap") . (bool . nil))
  442.     (("report") . (number . nil))
  443.     (("scroll") . (number . evi-scroll-count))
  444.     (("sections" "sect") . (string . nil))
  445.     (("shell" "sh") . (string . shell-file-name))
  446.     (("shiftwidth" "sw") . (number . evi-shift-width))
  447.     (("showmatch" "sm") . (bool . evi-show-match))
  448.     (("showmode") . (bool . evi-show-mode))
  449.     (("slowopen" "slow") . (bool . nil))
  450.     (("sourceany") . (bool . nil))
  451.     (("tabstop" "ts") . (number . evi-tab-width))
  452.     (("tags") . (string . nil))
  453.     (("taglength" "tl") . (number . nil))
  454.     (("term") . (string . nil))
  455.     (("terse") . (bool . nil))
  456.     (("timeout") . (bool . evi-timeout))
  457.     (("timeoutlen") . (number . evi-timeout-length))
  458.     (("ttytype" "tty") . (string . nil))
  459.     (("warn") . (bool . nil))
  460.     (("word") . (string . evi-word))
  461.     (("Word") . (string . evi-Word))
  462.     (("wrapmargin" "wm") . (number . evi-wrap-margin))
  463.     (("wrapscan" "ws") . (bool . evi-search-wraparound))
  464.     (("writeany" "wa") . (bool . nil))))
  465.  
  466. (defvar evi-set-options nil
  467.   "List of options that have been set.")
  468.  
  469. (defconst evi-auto-indent nil
  470.   "*If t, automatically indents text inserted on a new line.")
  471.  
  472. (defconst evi-command-line-editing nil
  473.   "*If t, command-line editing is enabled.")
  474.  
  475. (defun evi-command-line-editing (enable)
  476.   (evi-define-key '(read-string read-string-input ex ex-input)
  477.           "\e" (if enable nil 'evi-exit-minibuf)))
  478.  
  479. (defconst evi-error-bell nil
  480.   "*If t, ring bell on error.")
  481.  
  482. (defconst evi-ignore-case nil
  483.   "*If t, ignore case in searches.")
  484.  
  485. (defconst evi-search-magic t
  486.   "*If t, search patterns are normal regular expressions.  This is the default.
  487. Otherwise, the `magic' characters `.' `[' and `*' are treated as literals and
  488. must be escaped to get their regular expression interpretation.")
  489.  
  490. (defconst evi-number nil
  491.   "*If t, tracks line and column number in status line.")
  492.  
  493. (defvar evi-number-string nil)
  494. (defvar evi-number-format " %d/%d")
  495. (defvar evi-line-number)
  496. (defvar evi-column-number)
  497.  
  498. (defun evi-calc-number ()
  499.   (setq evi-line-number (count-lines 1 (min (1+ (point)) (point-max)))
  500.     evi-column-number (1+ (current-column))
  501.     evi-number-string (format evi-number-format evi-line-number
  502.                             evi-column-number)
  503.     evi-last-point (point))
  504.   (evi-refresh-mode-line))
  505.  
  506. (defun evi-update-number (point)
  507.   (let* ((negative (< point evi-last-point))
  508.      (delta (1- (if negative
  509.             (count-lines point (min (1+ evi-last-point)
  510.                         (point-max)))
  511.               (count-lines evi-last-point
  512.                    (min (1+ point) (point-max)))))))
  513.     (setq evi-line-number (if negative
  514.                   (- evi-line-number delta)
  515.                 (+ evi-line-number delta))
  516.       evi-column-number (1+ (current-column))
  517.       evi-number-string (format evi-number-format evi-line-number
  518.                               evi-column-number)
  519.       evi-last-point (point))
  520.     (evi-refresh-mode-line)))
  521.  
  522. (defun evi-number (value)
  523.   (if value
  524.       (progn
  525.     (evi-install-in-mode-line 'evi-number-string)
  526.     (evi-calc-number))
  527.     (evi-deinstall-from-mode-line 'evi-number-string)
  528.     (evi-refresh-mode-line)))
  529.  
  530. (evi-defbuffervar evi-buffer-read-only nil
  531.   "*If t, the current buffer is read-only")
  532.  
  533. (defconst evi-scroll-count nil
  534.   "*The number of lines to scroll.")
  535.  
  536. (defconst evi-shift-width 8
  537.   "*The number of colums shifted by > and < command, and ^T and ^D
  538. in insert mode.")
  539.  
  540. (defconst evi-show-match nil
  541.   "*If t, show matching parentheses.")
  542.  
  543. (defconst evi-show-mode t
  544.   "*If t, show current vi mode.")
  545.  
  546. (defconst evi-tab-width 8
  547.   "*Distance between tab stops")
  548.  
  549. (defun evi-tab-width (width)
  550.   (setq tab-width width))
  551.  
  552. (defconst evi-timeout t
  553.   "*If t, keys in multi-character maps must be typed within one second of each
  554. other, otherwise the partial command aborted.")
  555.  
  556. (defconst evi-timeout-length 500
  557.   "*Not implemented.")
  558.  
  559. (defconst evi-word "[a-zA-Z0-9_]+\\|[^a-zA-Z0-9_ \t\n]+\\|^[ \t]*\n"
  560.   "*Regular expression to describe words for w, b and e commands.")
  561.  
  562. (defconst evi-Word "[^ \t\n]+\\|^[ \t]*\n"
  563.   "*Regular expression to describe words for W, B and E commands.")
  564.  
  565. (defconst evi-wrap-margin 0
  566.   "*If non-zero, the amount of right margin past which wraparound occurs.")
  567.  
  568. (defun evi-wrap-margin (margin)
  569.   (if (eq evi-emacs-version 'emacs18)
  570.       (if (= margin 0)
  571.       (setq auto-fill-hook nil)
  572.     (setq fill-column (- (window-width) margin)
  573.           auto-fill-hook 'do-auto-fill))
  574.     (if (= margin 0)
  575.     (setq auto-fill-function nil)
  576.       (setq fill-column (- (window-width) margin)
  577.         auto-fill-function 'do-auto-fill))))
  578.  
  579. (defconst evi-search-wraparound t
  580.   "*If t, search wraps around the end of the file.")
  581.  
  582. (defconst evi-insert-mode-local-bindings nil
  583.   "*If t, emacs buffer-local key bindings will be enabled in insert mode.")
  584.  
  585. ;; Ex commands
  586. ;; these are intended to be ordered roughly in order of frequency of use
  587.  
  588. (defvar ex-commands
  589.   '((("edit" . 1) . ((0 . ((nil . "!") (t . offset) (t . file))) . ex-edit))
  590.     (("buffer" . 1) . ((0 . ((nil . "!") (t . buffer))) . ex-change-buffer))
  591.     (("read" . 1) .
  592.      ((1 . ((t . (if "!" shell-command)) (t . file))) . ex-read))
  593.     (("write" . 1) . ((2 . ((nil . "!") (t . ">>") (t . file))) . ex-write))
  594.     (("kill" . 1) . ((0 . ((nil . "!") (t . buffer))) . ex-kill-buffer))
  595.     (("next" . 1) . ((0 . ((nil . "!") (t . files))) . ex-next))
  596.     (("Edit" . 1) .
  597.      ((0 . ((nil . "!") (nil . offset) (t . file))) . ex-edit-other-window))
  598.     (("Buffer" . 1) .
  599.      ((0 . ((nil . "!") (t . buffer))) . ex-change-buffer-other-window))
  600.     (("Kill" . 1) .
  601.      ((0 . ((nil . "!") (t . buffer))) . ex-kill-buffer-delete-windows))
  602.     (("Write" . 1) . ((0 . ((nil . "!"))) . ex-write-all-buffers))
  603.     (("Next" . 1) . ((0 . ((nil . "!") (t . files))) . ex-next-other-window))
  604.     (("set" . 2) . ((0 . ((nil . settings))) . ex-set))
  605.     (("substitute" . 1) .
  606.      ((2 . ((t . regular-expression) (backup . regular-expression2)
  607.         (nil . "g") (nil . "c"))) . ex-substitute))
  608.     (("global" . 1) .
  609.      ((2 . ((nil . "!") (t . regular-expression) (t . command))) . ex-global))
  610.     (("vglobal" . 1) .
  611.      ((2 . ((t . regular-expression) (t . command))) . ex-vglobal))
  612.     (("map" . 3) .
  613.      ((0 . ((nil . "!") (t . map) (t . words))) . ex-map))
  614.     (("gdb" . 2) . ((0 . ((t . file))) . ex-gdb))
  615.     (("wk" . 2) . ((0 . nil) . ex-write-kill))
  616.     (("wq" . 2) . ((0 . ((nil . "!"))) . ex-write-quit))
  617.     (("Wq" . 2) . ((0 . ((nil . "!"))) . ex-write-all-and-quit))
  618.     (("visual" . 2) . ((0 . ((nil . "!") (t . offset) (t . file))) . ex-edit))
  619.     (("Visual" . 2) .
  620.      ((0 . ((nil . "!") (nil . offset) (t . file))) . ex-edit-other-window))
  621.     (("abbreviate" . 2) .
  622.      ((0 . ((t . abbrev) (t . words))) . ex-abbrev))
  623.     (("append" . 1) . ((1 . nil) . ex-not-implemented))
  624.     (("args" . 2) . ((0 . nil) . ex-not-implemented))
  625.     (("bind" . 2) .
  626.      ((0 . ((nil . "!") (t . word) (t . rest-of-line))) . ex-elisp-bind))
  627.     (("bug" . 3) . ((0 . ((t . words))) . ex-report-bug))
  628.     (("cd" . 2) . ((0 . ((t . file))) . ex-change-directory))
  629.     (("change" . 1) . ((2 . nil) . ex-not-implemented))
  630.     (("chdir" . 3) . ((0 . ((t . file))) . ex-change-directory))
  631.     (("copy" . 2) . ((2 . ((t . address))) . ex-copy))
  632.     (("delete" . 1) . ((2 . ((t . register))) . ex-delete))
  633.     (("dirs" . 2) . ((0 . nil) . ex-directory-stack))
  634.     (("elisp" . 2) . ((0 . ((t . rest-of-line))) . ex-elisp-execute))
  635.     (("evilist" . 4) . ((0 . ((t . words))) . ex-mail-list))
  636.     (("file" . 1) . ((0 . ((t . file))) . ex-file))
  637.     (("insert" . 1) . ((1 . nil) . ex-not-implemented))
  638.     (("join" . 1) . ((2 . nil) . ex-not-implemented))
  639.     (("list" . 1) . ((2 . nil) . ex-not-implemented))
  640.     (("mail" . 3) . ((0 . ((t . words))) . ex-mail))
  641.     (("mark" . 2) . ((1 . ((t . mark))) . ex-mark))
  642.     (("move" . 1) . ((2 . ((t . address))) . ex-move))
  643.     (("number" . 2) . ((2 . nil) . ex-not-implemented))
  644.     (("popd" . 2) . ((0 . nil) . ex-pop-directory))
  645.     (("preserve" . 3) . ((0 . nil) . ex-preserve))
  646.     (("previous" . 4) . ((0 . nil) . ex-not-implemented))
  647.     (("print" . 1) . ((2 . nil) . ex-print))
  648.     (("pushd" . 4) . ((0 . ((t . file))) . ex-push-directory))
  649.     (("put" . 2) . ((1 . ((t . register))) . ex-put))
  650.     (("quit" . 1) . ((0 . ((nil . "!"))) . ex-quit))
  651.     (("recover" . 3) . ((0 . ((nil . "!") (t . file))) . ex-recover))
  652.     (("initialize" . 3) . ((0 . nil) . ex-initialize))
  653.     (("rewind" . 3) . ((0 . nil) . ex-not-implemented))
  654.     (("send" . 3) . ((0 . ((nil . "!"))) . ex-send-mail))
  655.     (("shell" . 2) . ((0 . nil) . ex-shell))
  656.     (("source" . 2) . ((0 . ((t . file))) . ex-source-file))
  657.     (("tag" . 1) . ((0 . ((t . word))) . ex-tag))
  658.     (("unabbreviate" . 3) . ((0 . ((t . abbrev))) . ex-unabbrev))
  659.     (("undo" . 1) . ((0 . nil) . ex-not-implemented))
  660.     (("unmap" . 3) . ((0 . ((nil . "!") (t . word))) . ex-unmap))
  661.     (("version" . 2) . ((0 . nil) . ex-evi-version))
  662.     (("xit" . 1) . ((0 . ((nil . "!"))) . ex-write-all-and-quit))
  663.     (("yank" . 1) . ((2 . ((t . register))) . ex-yank))
  664.     (("!" . 1) . ((2 . ((nil . "&") (t . shell-command))) . ex-shell-command))
  665.     (("<" . 1) . ((2 . nil) . ex-shift-left))
  666.     (("=" . 1) . ((2 . nil) . ex-not-implemented))
  667.     ((">" . 1) . ((2 . nil) . ex-shift-right))
  668.     (("&" . 1) . ((2 . nil) . ex-substitute-again))
  669.     (("@" . 1) . ((2 . nil) . ex-not-implemented))
  670.     (("" . 0) . ((2 . nil) . ex-null))))
  671.  
  672. ;; Macros
  673.  
  674. (defmacro evi-defmotion (&rest args)
  675.   (let* ((direction (car args))
  676.      (function (car (cdr args)))
  677.      (params (nth 2 args))
  678.      (documentation (nth 3 args))
  679.      (body (nthcdr 4 args))
  680.      (do-function (intern (concat "do-" (symbol-name function)))))
  681.     ; ZZ some rather narly hard-coding here, but does the trick for now
  682.     (cond ((eq (car params) '&char)
  683.         (` (progn (defun (, function) () (, documentation)
  684.             (interactive)
  685.             (evi-motion-command (quote (, do-function))
  686.                         (quote (, direction))
  687.                         evi-prefix-count evi-context
  688.                         (evi-read-command-char)))
  689.               (defun (, do-function) (, (cdr params)) (,@ body)))))
  690.       ((eq (car params) '&string)
  691.         (` (progn (defun (, function) () (, documentation)
  692.             (interactive)
  693.             (evi-motion-command
  694.               (quote (, do-function)) (quote (, direction))
  695.               evi-prefix-count evi-context
  696.               (evi-read-string (, (car (cdr params))))))
  697.               (defun (, do-function) (, (cdr (cdr params)))
  698.             (,@ body)))))
  699.       (t
  700.         (` (progn (defun (, function) () (, documentation)
  701.             (interactive)
  702.             (evi-motion-command
  703.               (quote (, do-function)) (quote (, direction))
  704.               evi-prefix-count evi-context))
  705.               (defun (, do-function) (, params) (,@ body))))))))
  706.  
  707. (defmacro evi-iterate (count &rest body)
  708.   (list 'let (list (list 'count count))
  709.       (append (list 'while (list '> 'count 0)) body
  710.           (list (list 'setq 'count (list '1- 'count))))
  711.       (list '= 'count 0)))
  712.  
  713. (defmacro evi-break ()
  714.   (list 'setq 'count -1))
  715.  
  716. (defmacro evi-enumerate-condition (item list condition &rest body)
  717.   (list 'let (list (list 'list list) (list item))
  718.     (append
  719.       (list 'while
  720.     (list 'and 'list
  721.           (list 'progn (list 'setq item '(car list)) condition)))
  722.       (if body
  723.     (append body '((setq list (cdr list))))
  724.     '((setq list (cdr list)))))
  725.     'list))
  726.  
  727. (defmacro evi-iterate-list (item list &rest body)
  728.   (list 'let (list (list 'list list) (list item) '(found))
  729.     (append
  730.       (list 'while 'list)
  731.       (append (list (list 'setq item '(car list)))
  732.           body '((setq list (cdr list)))))))
  733.  
  734. (defmacro evi-find (item list pred)
  735.   (list 'let (list (list 'list list) (list item) '(found))
  736.     (list 'while
  737.       (list 'and 'list
  738.         (list 'progn (list 'setq item '(car list) 'found pred)
  739.              '(not found)))
  740.       '(setq list (cdr list)))
  741.     'found))
  742.  
  743. (defmacro evi-set-goal-column ()
  744.   (` (if evi-reset-goal-column
  745.        (setq evi-goal-column (current-column)
  746.          evi-reset-goal-column nil))))
  747.  
  748. (defmacro evi-reset-goal-column ()
  749.   (` (setq evi-reset-goal-column t)))
  750.  
  751. (defmacro evi-register-text (register)
  752.   (list 'car register))
  753.  
  754. (defmacro evi-register-shape (register)
  755.   (list 'cdr register))
  756.  
  757. ;; Keymaps
  758.  
  759. (defun evi-define-key (maps key def)
  760.   (evi-enumerate-condition map maps t
  761.     (funcall 'define-key
  762.          (symbol-value (intern (concat "evi-" (symbol-name map) "-map")))
  763.          key def)))
  764.  
  765. (defun evi-define-macro (maps key macro)
  766.   (evi-enumerate-condition map maps t
  767.     (eval (list 'define-key
  768.         (intern (concat "evi-" (symbol-name map) "-map")) 'key
  769.         (list 'quote (list 'lambda ()
  770.           '(interactive) (list 'evi-internal-macro macro)))))))
  771.  
  772. (defun evi-make-local-keymap (keydefs)
  773.   (let ((keymap (make-sparse-keymap)))
  774.     (if (fboundp 'set-keymap-name)
  775.     (set-keymap-name keymap 'evi-local))
  776.     (mapcar '(lambda (keydef)
  777.            (define-key keymap (eval (car keydef)) (nth 1 keydef)))
  778.         keydefs)
  779.     keymap))
  780.  
  781. (defun evi-unbound ()
  782.   (interactive)
  783.   (evi-error "Nothing bound to `%c'" last-command-char))
  784.  
  785. ;                    "\C-a"
  786. (evi-define-key '(vi)            "\C-b" 'evi-scroll-page-backward)
  787. (evi-define-key '(vi)            "\C-c" 'keyboard-quit)
  788. (evi-define-key '(vi)            "\C-d" 'evi-scroll-text-forward)
  789. (evi-define-key '(vi)            "\C-e" 'evi-scroll-cursor-forward)
  790. (evi-define-key '(vi)            "\C-f" 'evi-scroll-page-forward)
  791. (evi-define-key '(vi)            "\C-g" 'evi-file-info)
  792. (evi-define-key '(vi motion)        "\C-h" 'evi-backward-char)
  793. (evi-define-key '(vi)            "\C-i" 'evi-unbound)
  794. (evi-define-key '(vi motion)        "\C-j" 'evi-next-line)
  795. ;                    "\C-k"
  796. (evi-define-key '(vi)            "\C-l" 'evi-redraw)
  797. (evi-define-key '(vi motion)        "\C-m" 'evi-beginning-of-next-line)
  798. (evi-define-key '(vi motion)        "\C-n" 'evi-next-line)
  799. ;                    "\C-o"
  800. (evi-define-key '(vi motion)        "\C-p" 'evi-previous-line)
  801. ;                    "\C-q"
  802. (evi-define-key '(vi)            "\C-r" 'evi-redraw)
  803. ;                    "\C-s"
  804. ;                    "\C-t"
  805. (evi-define-key '(vi)            "\C-u" 'evi-scroll-text-backward)
  806. ;                    "\C-v"
  807. ;                    "\C-w"
  808. ;                    "\C-x"
  809. (evi-define-key '(vi)            "\C-y" 'evi-scroll-cursor-backward)
  810. (evi-define-key '(vi)            "\C-z" 'suspend-emacs)
  811. ;                    "\C-[" (ESC)
  812. ;                    "\C-\"
  813. (evi-define-key '(vi)            "\C-]" 'evi-tag)
  814. (evi-define-macro '(vi)            "\C-^" ":e#\n")
  815.  
  816. (evi-define-key '(vi motion)        " " 'evi-forward-char)
  817. (evi-define-key '(vi)            "!" 'evi-shell-filter)
  818. (evi-define-key '(vi)            "\"" 'evi-prefix-register)
  819. (evi-define-key '(vi)            "#" 'evi-unbound)
  820. (evi-define-key '(vi motion)        "$" 'evi-end-of-line)
  821. (evi-define-key '(vi motion)        "%" 'evi-paren-match)
  822. (evi-define-macro '(vi)            "&" ":s\n")
  823. (evi-define-key '(vi motion)        "'" 'evi-goto-mark-vertical)
  824. (evi-define-key '(vi motion)        "(" 'evi-backward-sentence)
  825. (evi-define-key '(vi motion)        ")" 'evi-forward-sentence)
  826. (evi-define-key '(vi)            "*" 'evi-send-to-process)
  827. (evi-define-key '(vi motion)        "+" 'evi-beginning-of-next-line)
  828. (evi-define-key '(vi motion)        "," 'evi-find-next-character-reverse)
  829. (evi-define-key '(vi motion)        "-" 'evi-beginning-of-previous-line)
  830. (evi-define-key '(vi)            "." 'evi-repeat)
  831. (evi-define-key '(vi motion)        "/" 'evi-search-forward)
  832. (evi-define-key '(vi motion)        "0" 'evi-beginning-of-line)
  833. (evi-define-key '(vi motion)        "1" 'evi-prefix-digit)
  834. (evi-define-key '(vi motion)        "2" 'evi-prefix-digit)
  835. (evi-define-key '(vi motion)        "3" 'evi-prefix-digit)
  836. (evi-define-key '(vi motion)        "4" 'evi-prefix-digit)
  837. (evi-define-key '(vi motion)        "5" 'evi-prefix-digit)
  838. (evi-define-key '(vi motion)        "6" 'evi-prefix-digit)
  839. (evi-define-key '(vi motion)        "7" 'evi-prefix-digit)
  840. (evi-define-key '(vi motion)        "8" 'evi-prefix-digit)
  841. (evi-define-key '(vi motion)        "9" 'evi-prefix-digit)
  842. (evi-define-key '(vi)            ":" 'evi-ex-command)
  843. (evi-define-key '(vi motion)        ";" 'evi-find-next-character)
  844. (evi-define-key '(vi)            "<" 'evi-shift-left)
  845. (evi-define-key '(vi)            "=" 'evi-indent)
  846. (evi-define-key '(vi)            ">" 'evi-shift-right)
  847. (evi-define-key '(vi motion)        "?" 'evi-search-backward)
  848. (evi-define-key '(vi)            "@" 'evi-register-macro)
  849.  
  850. (evi-define-macro '(vi)            "A" "$#i")
  851. (evi-define-key '(vi motion)        "B" 'evi-backward-Word)
  852. (evi-define-macro '(vi)            "C" "&c#$")
  853. (evi-define-macro '(vi)            "D" "&d#$")
  854. (evi-define-key '(vi motion)        "E" 'evi-end-of-Word)
  855. (evi-define-key '(vi motion)        "F" 'evi-find-char-backwards)
  856. (evi-define-key '(vi motion)        "G" 'evi-goto-line)
  857. (evi-define-key '(vi motion)        "H" 'evi-goto-top-of-window)
  858. (evi-define-macro '(vi)            "I" "^#i")
  859. (evi-define-key '(vi)            "J" 'evi-join-lines)
  860. (evi-define-key '(vi)            "K" 'evi-unbound)
  861. (evi-define-key '(vi motion)        "L" 'evi-goto-bottom-of-window)
  862. (evi-define-key '(vi motion)        "M" 'evi-goto-middle-of-window)
  863. (evi-define-key '(vi motion)        "N" 'evi-search-next-reverse)
  864. (evi-define-key '(vi)            "O" 'evi-open-before)
  865. (evi-define-key '(vi)            "P" 'evi-put)
  866. (evi-define-key '(vi)            "Q" 'evi-quit-evi)
  867. (evi-define-key '(vi)            "R" 'evi-replace)
  868. (evi-define-macro '(vi)            "S" "&c#c")
  869. (evi-define-key '(vi motion)        "T" 'evi-find-char-backwards-after)
  870. (if (boundp 'buffer-undo-list)
  871.     (evi-define-key '(vi)        "U" 'evi-undo-line))
  872. (evi-define-key '(vi)            "V" 'evi-unbound)
  873. (evi-define-key '(vi motion)        "W" 'evi-forward-Word)
  874. (evi-define-macro '(vi)            "X" "&d#h")
  875. (evi-define-macro '(vi)            "Y" "&y#y")
  876. (evi-define-macro '(vi)            "ZZ" ":Wq!\n")
  877.  
  878. (evi-define-key '(vi)            "[\"" 'evi-register-string)
  879. (evi-define-key '(vi)            "['" 'evi-register-char)
  880. (evi-define-key '(vi motion)        "[(" 'evi-parameterized-macro)
  881. (evi-define-key '(vi motion)        "[[" 'evi-backward-section)
  882. (evi-define-key '(vi)            "[b" 'evi-buffer-name)
  883. (evi-define-key '(vi)            "[u" 'evi-undo-more)
  884. (evi-define-key '(vi)            "[{" 'evi-loop-over-lines-in-region)
  885. (evi-define-key '(vi)            "\\" 'evi-unbound)
  886. (evi-define-key '(vi motion)        "]]" 'evi-forward-section)
  887. (evi-define-key '(vi motion)        "^" 'evi-goto-indentation)
  888. (evi-define-key '(vi)            "_" 'evi-prompt-repeat)
  889. (evi-define-key '(vi motion)        "`" 'evi-goto-mark-horizontal)
  890.  
  891. (evi-define-macro '(vi)            "a" "l#i")
  892. (evi-define-key '(vi motion)        "b" 'evi-backward-word)
  893. (evi-define-key '(vi)            "c" 'evi-change)
  894. (evi-define-key '(vi)            "d" 'evi-delete)
  895. (evi-define-key '(vi motion)        "e" 'evi-end-of-word)
  896. (evi-define-key '(vi motion)        "f" 'evi-find-character)
  897. (evi-define-key '(vi)            "g" 'evi-unbound)
  898. (evi-define-key '(vi motion)        "h" 'evi-backward-char)
  899. (evi-define-key '(vi)            "i" 'evi-insert)
  900. (evi-define-key '(vi motion)        "j" 'evi-next-line)
  901. (evi-define-key '(vi motion)        "k" 'evi-previous-line)
  902. (evi-define-key '(vi motion)        "l" 'evi-forward-char)
  903. (evi-define-key '(vi)            "m" 'evi-set-mark)
  904. (evi-define-key '(vi motion)        "n" 'evi-search-next)
  905. (evi-define-key '(vi)            "o" 'evi-open-after)
  906. (evi-define-key '(vi)            "p" 'evi-put-after)
  907. (evi-define-key '(vi)            "q" 'evi-unbound)
  908. (evi-define-key '(vi)            "r" 'evi-replace-char)
  909. (evi-define-macro '(vi)            "s" "&c#l")
  910. (evi-define-key '(vi motion)        "t" 'evi-find-character-before)
  911. (evi-define-key '(vi)            "u" 'evi-undo)
  912. (evi-define-key '(vi)            "v" 'evi-unbound)
  913. (evi-define-key '(vi motion)        "w" 'evi-forward-word)
  914. (evi-define-macro '(vi)            "x" "&d#l")
  915. (evi-define-key '(vi)            "y" 'evi-yank)
  916. (evi-define-key '(vi)            "z" 'evi-window-control)
  917.  
  918. (evi-define-key '(vi motion)        "{" 'evi-backward-paragraph)
  919. (evi-define-key '(vi motion)        "|" 'evi-goto-column)
  920. (evi-define-key '(vi motion)        "}" 'evi-forward-paragraph)
  921. (evi-define-key '(vi)            "~" 'evi-toggle-case)
  922.  
  923. (evi-define-key '(internal)        "&" 'evi-register-parameter)
  924. (evi-define-key '(internal motion)    "#" 'evi-prefix-count-parameter)
  925. (evi-define-key '(internal)        "\n" 'evi-self-insert)
  926. (evi-define-key '(internal)        "\t" 'evi-maybe-indent)
  927.  
  928. (evi-define-key '(motion)        "a" 'evi-region-arbitrary)
  929. (evi-define-key '(motion)        "r" 'evi-region-rectangle)
  930. (evi-define-key '(motion)        "R" 'evi-region-rows)
  931. (evi-define-key '(motion)        "C" 'evi-region-columns)
  932.  
  933. ; ZZ should define for replace mode also?
  934. (evi-define-key '(input) "\C-q" 'evi-quoted-insert)
  935. (evi-define-key '(input) "\C-v" 'evi-quoted-insert)
  936.  
  937. (evi-define-key '(input replace) "\C-c" 'keyboard-quit)
  938. (evi-define-key '(input replace) "\e" 'evi-exit-command-loop)
  939.  
  940. (evi-define-key '(insert) "\C-d" 'evi-backward-indent)
  941. (evi-define-key '(insert) "\C-h" 'evi-insert-mode-delete-backward-char)
  942. (evi-define-key '(insert) "\C-j" 'evi-newline)
  943. (evi-define-key '(insert) "\C-m" 'evi-newline)
  944. (evi-define-key '(insert) "\C-t" 'evi-forward-indent)
  945. (evi-define-macro '(insert) "\C-w" "db")
  946. (evi-define-macro '(insert) "\C-x" "d0")
  947. (evi-define-key '(insert) "\177" 'evi-insert-mode-delete-backward-char)
  948.  
  949. ;(evi-define-key (replace) "\C-d" 'evi-backward-indent)
  950. (evi-define-key '(replace) "\C-h" 'evi-replace-mode-delete-backward-char)
  951. ;(evi-define-key (replace) "\C-t" 'evi-forward-indent)
  952. ;(evi-define-key (replace) "\C-w" 'evi-delete-backward-word)
  953. (evi-define-key '(replace) "\177" 'evi-replace-mode-delete-backward-char)
  954.  
  955. (evi-define-key '(read-string-input ex-input)
  956.                 "\C-h" 'evi-delete-backward-char-maybe-abort)
  957. (evi-define-key '(read-string read-string-input ex ex-input)
  958.                 "\C-j" 'evi-exit-minibuf)
  959. (evi-define-key '(read-string read-string-input ex ex-input)
  960.                 "\C-m" 'evi-exit-minibuf)
  961. (evi-define-key '(read-string read-string-input ex ex-input)
  962.                 "\e" 'evi-exit-minibuf)
  963. (evi-define-macro '(read-string-input ex-input)
  964.                 "\C-x" "d2|")
  965. (evi-define-key '(read-string-input ex-input)
  966.                 "\177" 'evi-delete-backward-char-maybe-abort)
  967.  
  968. (evi-define-key '(ex-input) "\C-i" 'ex-complete)
  969.  
  970. (evi-define-key '(shell) "\C-m" 'shell-send-input)
  971.  
  972. (cond
  973.   ((eq evi-emacs-version 'emacs19)
  974.     (let ((maps '(vi motion)))
  975.       (evi-define-key maps [down] 'evi-next-line)
  976.       (evi-define-key maps [up] 'evi-previous-line)
  977.       (evi-define-key maps [left] 'evi-backward-char)
  978.       (evi-define-key maps [right] 'evi-forward-char)))
  979.   ((eq evi-emacs-version 'lucid19)
  980.     ;; must find out how/if this interacts with the definition of ESC
  981.     (let ((maps '(vi motion)))
  982.       (evi-define-key maps 'down      'evi-next-line)
  983.       (evi-define-key maps 'up      'evi-previous-line)
  984.       (evi-define-key maps 'left      'evi-backward-char)
  985.       (evi-define-key maps 'right      'evi-forward-char)
  986.  
  987.       (evi-define-key maps 'button1 'evi-mouse-track)
  988.       (evi-define-key maps 'button2 'evi-x-set-point-and-insert-selection)
  989.       (evi-define-key maps '(control button1) 'evi-mouse-track-insert)
  990.       (evi-define-key maps '(control button2) 'evi-x-mouse-kill))
  991.  
  992.     (defun evi-mouse-track (event)
  993.       (interactive "e")
  994.       (mouse-track event)
  995.       (evi-fixup-cursor 'vertical))
  996.  
  997.     (defun evi-mouse-track-insert (event)
  998.       (interactive "e")
  999.       (mouse-track-insert event)
  1000.       (evi-fixup-cursor 'vertical))
  1001.  
  1002.     (defun evi-x-mouse-kill (event)
  1003.       (interactive "e")
  1004.       (x-mouse-kill event)
  1005.       (evi-fixup-cursor 'vertical))
  1006.  
  1007.     (defun evi-x-set-point-and-insert-selection (event)
  1008.       (interactive "e")
  1009.       (x-set-point-and-insert-selection event)
  1010.       (evi-fixup-cursor 'vertical)))
  1011.   (t
  1012.     ;; else version 18
  1013.     (define-key function-keymap "l" 'evi-backward-char)
  1014.     (define-key function-keymap "r" 'evi-forward-char)
  1015.     (define-key function-keymap "u" 'evi-previous-line)
  1016.     (define-key function-keymap "d" 'evi-next-line)))
  1017.  
  1018. ;; Command macros
  1019.  
  1020. (defun evi-parameterized-macro ()
  1021.   (interactive)
  1022.   (let* ((macro (evi-read-string "\("))
  1023.      (evi-register-parameter evi-register-spec)
  1024.      (evi-register-spec nil)
  1025.      (evi-prefix-count-parameter evi-prefix-count)
  1026.      (evi-prefix-count nil))
  1027.     (evi-execute-macro macro)
  1028.     (evi-fixup-cursor 'vertical)))
  1029.  
  1030. (defun evi-internal-macro (macro)
  1031.   (let ((evi-register-parameter evi-register-spec)
  1032.     (evi-register-spec nil)
  1033.     (evi-prefix-count-parameter evi-prefix-count)
  1034.     (evi-prefix-count nil)
  1035.     (evi-default-keymap-list (list evi-internal-map evi-vi-map))
  1036.     (evi-internal-command t))
  1037.     (evi-execute-macro macro))
  1038.   (if (eq evi-mode 'vi)
  1039.       (evi-fixup-cursor 'vertical)))
  1040.  
  1041. (defun evi-register-macro (char &optional count)
  1042.   (interactive (evi-character-arg))
  1043.   (let* ((evi-last-command-keys nil)
  1044.      (register-number (evi-register-number char))
  1045.      (macro (evi-register-text (aref evi-registers register-number))))
  1046.     (setq evi-last-macro-register register-number)
  1047.     (evi-push-macro macro)
  1048.     (evi-get-command)))
  1049.  
  1050. ;; And now we have to do our own keyboard macros...  emacs `keyboard' macros
  1051. ;; don't cut it as they don't believe in hierarchical commands - the macro
  1052. ;; has to terminate at the same lisp execution depth as it started.  This
  1053. ;; is OK for emacs 'cause emacs commands don't build on each other like vi
  1054. ;; commands do.  If anyone has any idea of how to make emacs `keyboard' macros
  1055. ;; behave in a manner independent of their execution context, please let me
  1056. ;; know.
  1057. (defvar evi-unread-command-char nil)
  1058. (defvar evi-macro-stack nil)
  1059. (defvar evi-current-macro nil)
  1060. (defvar evi-current-macro-index nil)
  1061.  
  1062. (defun evi-execute-macro (macro)
  1063.   (evi-push-macro macro)
  1064.   (while evi-current-macro
  1065.     (evi-get-command)))
  1066.  
  1067. (defun evi-read-string (prompt &optional initial vi-map input-map)
  1068.   (if evi-in-minibuf
  1069.       (evi-error "Can't use minibuffer inside minibuffer"))
  1070.   (or (save-window-excursion
  1071.     ;; this seems unduly complicated...
  1072.     (set-buffer (get-buffer-create (concat " *evi-" prompt "-Minibuf*")))
  1073.     ;; doesn't seem to work (or evi-current-macro ...)
  1074.     (set-window-buffer (minibuffer-window) (current-buffer))
  1075.     (select-window (minibuffer-window))
  1076.     (setq evi-in-minibuf t)
  1077.     (goto-char (point-max))
  1078.     (or (eq evi-emacs-version 'emacs18)
  1079.         (message nil))
  1080.     (insert prompt)
  1081.     ;;ZZ would be best if insert point could be set here
  1082.     (if initial
  1083.         (insert initial))
  1084.     (evi-unread-command-char ?i)
  1085.     (setq evi-minibuf-input-map (or input-map evi-read-string-input-map))
  1086.     (prog1
  1087.         (if (catch 'exit-minibuf
  1088.           (evi-command-loop (list (or vi-map evi-read-string-map)
  1089.                       evi-map-map evi-vi-map))
  1090.           t)
  1091.         (let ((start (+ (point) (length prompt))))
  1092.           (end-of-line)
  1093.           (buffer-substring start (point))))
  1094.       (goto-char (1- (point-max)))
  1095.       (beginning-of-line)
  1096.       (if (looking-at (concat prompt " *$"))
  1097.           (delete-region (point) (point-max))
  1098.         (goto-char (point-max)))))
  1099.       (throw 'abort t)))
  1100.  
  1101. (defun evi-exit-minibuf ()
  1102.   (interactive)
  1103.   (or evi-current-macro
  1104.       (progn (beginning-of-line)
  1105.          (sit-for 0)))
  1106.   (throw 'exit-minibuf t))
  1107.  
  1108. (if (eq evi-emacs-version 'lucid19)
  1109.     (defun evi-read-char ()
  1110.       (if evi-unread-command-char
  1111.       (prog1 evi-unread-command-char
  1112.         (setq evi-unread-command-char nil))
  1113.     (if evi-current-macro
  1114.         (prog1 (aref evi-current-macro evi-current-macro-index)
  1115.           (setq evi-current-macro-index (1+ evi-current-macro-index))
  1116.           (if (= evi-current-macro-index (length evi-current-macro))
  1117.           (evi-pop-macro)))
  1118.       (let ((event (allocate-event)))
  1119.         (while (progn
  1120.              (next-event event)
  1121.              (not (key-press-event-p event)))
  1122.           (dispatch-event event))
  1123.         (event-to-character event)))))
  1124.   (defun evi-read-char ()
  1125.     (if evi-unread-command-char
  1126.     (prog1 evi-unread-command-char
  1127.       (setq evi-unread-command-char nil))
  1128.       (if evi-current-macro
  1129.       (prog1 (aref evi-current-macro evi-current-macro-index)
  1130.         (setq evi-current-macro-index (1+ evi-current-macro-index))
  1131.         (if (= evi-current-macro-index (length evi-current-macro))
  1132.         (evi-pop-macro)))
  1133.     (read-char)))))
  1134.  
  1135. (defun evi-push-macro (macro)
  1136.   (setq evi-macro-stack (cons (cons evi-current-macro evi-current-macro-index)
  1137.                   evi-macro-stack)
  1138.     evi-current-macro macro
  1139.     evi-current-macro-index 0))
  1140.  
  1141. (defun evi-pop-macro ()
  1142.   (setq evi-current-macro (car (car evi-macro-stack))
  1143.     evi-current-macro-index (cdr (car evi-macro-stack))
  1144.     evi-macro-stack (cdr evi-macro-stack)))
  1145.  
  1146. (defun evi-internal-command ()
  1147.   (interactive)
  1148.   (let ((evi-internal-command t))
  1149.     (evi-get-command (list evi-internal-map evi-vi-map))))
  1150.  
  1151. (defun evi-register-parameter ()
  1152.   (interactive)
  1153.   (let ((evi-register-spec evi-register-parameter))
  1154.     (evi-get-command)))
  1155.  
  1156. (defun evi-prefix-count-parameter ()
  1157.   (interactive)
  1158.   (let ((evi-prefix-count evi-prefix-count-parameter))
  1159.     (evi-get-command)))
  1160.  
  1161. ;; Errors
  1162.  
  1163. (defun evi-error (&rest args)
  1164.   (throw 'abort (apply 'format args)))
  1165.  
  1166. (defun evi-warning (&rest args)
  1167.   (if evi-interactive
  1168.       (throw 'abort (apply 'format args))
  1169.     (princ (apply 'format args))
  1170.     (terpri)))
  1171.  
  1172. ;; Get command
  1173.  
  1174. (defun evi-command-loop (keymap-list)
  1175.   (let ((evi-default-keymap-list keymap-list)
  1176.     (loop-command-keys evi-command-keys))
  1177.     (prog1
  1178.       (catch 'exit
  1179.     (while t
  1180.       (setq evi-command-keys "")
  1181.       (let ((message
  1182.           (catch 'abort
  1183.             (evi-get-command keymap-list))))
  1184.         (if message
  1185.           (if (not (eq message t))
  1186.         (message message))
  1187.           (setq loop-command-keys
  1188.             (concat loop-command-keys evi-command-keys))))))
  1189.       (setq evi-command-keys (concat loop-command-keys evi-command-keys)))))
  1190.  
  1191. ; ZZ - if we don't set evi-default-keymap-list, it doesn't appear that macros
  1192. ; will be able to access emacs commands when appropriate
  1193. (defun evi-top-level-command ()
  1194.   (interactive)
  1195.   (setq evi-unread-command-char last-command-char)
  1196.   (let ((echo-keystrokes 0)
  1197.     (blink-matching-paren evi-show-match)
  1198.     (evi-command-keys "")
  1199.     (evi-prompted nil))
  1200.     (evi-do-command
  1201.       (if evi-enable-emacs-commands
  1202.       (list evi-map-map evi-buffer-local-vi-map evi-vi-map
  1203.         (cons nil (current-global-map)))
  1204.     (list evi-map-map evi-buffer-local-vi-map evi-vi-map)))
  1205.     (while evi-current-macro
  1206.       (setq evi-command-keys ""
  1207.         evi-prompted nil)
  1208.       (evi-do-command
  1209.        (if evi-enable-emacs-commands
  1210.        (list evi-map-map evi-buffer-local-vi-map evi-vi-map
  1211.          (cons nil (current-global-map)))
  1212.      (list evi-map-map evi-buffer-local-vi-map evi-vi-map))))))
  1213.  
  1214. (defun evi-do-command (maps)
  1215.   (let ((message (if evi-debug
  1216.              (catch 'abort
  1217.                (evi-get-command maps))
  1218.            (condition-case code
  1219.                (catch 'abort
  1220.              (evi-get-command maps))
  1221.              (error
  1222.                (evi-reset-top-level)
  1223.                (signal (car code) (cdr code)))
  1224.              (quit
  1225.                (evi-reset-top-level)
  1226.                (signal (car code) (cdr code)))))))
  1227.     (if message
  1228.     (progn (if (not (eq message t))
  1229.            (progn (if evi-error-bell (beep))
  1230.               (message message)))
  1231.            (evi-fixup-cursor 'horizontal)))
  1232.     (if evi-number
  1233.     (evi-update-number (point)))))
  1234.  
  1235. (defun evi-reset-top-level ()
  1236.   (if (not (eq evi-mode 'vi))
  1237.       (progn
  1238.     (if (or (eq evi-mode 'replace)
  1239.         (eq evi-mode 'change))
  1240.         (evi-exit-replace-mode))
  1241.     (evi-exit-input-mode)))
  1242.   (while evi-current-macro
  1243.     (evi-pop-macro))
  1244.   (evi-fixup-cursor 'horizontal))
  1245.  
  1246. (defun evi-emacs-command ()
  1247.   (interactive)
  1248.   (evi-unread-command-char last-command-char)
  1249.   (if evi-global-directory
  1250.       (let ((default-directory (evi-current-directory)))
  1251.     (evi-get-command (if evi-emacs-local-map
  1252.                 (list evi-emacs-local-map
  1253.                   (current-global-map))
  1254.               (list (current-global-map)))))
  1255.     (evi-get-command (if evi-emacs-local-map
  1256.             (list evi-emacs-local-map (current-global-map))
  1257.               (list (current-global-map))))))
  1258.  
  1259. (defun evi-exit-command-loop ()
  1260.   (interactive)
  1261.   (throw 'exit t))
  1262.  
  1263. (defun evi-db (string)
  1264.   (let ((buf (current-buffer))
  1265.     (dbuf (get-buffer-create "*debug*")))
  1266.     (or (eq buf dbuf)
  1267.     (progn
  1268.       (set-buffer dbuf)
  1269.       (insert string)
  1270.       (set-buffer buf)))))
  1271.  
  1272. (defun evi-get-command (&optional keymap-list)
  1273.   (let* ((current-keymap-list (or keymap-list evi-default-keymap-list))
  1274.      (inhibit-quit t)
  1275.      (char (evi-read-command-char))
  1276.      (keys (char-to-string char))
  1277.      (keydef))
  1278.     (evi-enumerate-condition keymap current-keymap-list
  1279.       (progn
  1280.     (if (keymapp keymap)
  1281.         (setq keydef (lookup-key keymap keys))
  1282.       ;; otherwise... we have a pair where the cdr is the keymap and
  1283.       ;; the car is a list of chars that we want to pass-thru this keymap
  1284.       ;; these are understood to always be emacs' keymaps, so we map
  1285.       ;; our meta-prefix to emacs' meta-prefix
  1286.       (if (memq (aref keys 0) (car keymap))
  1287.           (setq keydef nil)
  1288.         (setq keydef
  1289.           (lookup-key (cdr keymap)
  1290.               (if (= (aref keys 0) evi-meta-prefix-char)
  1291.                   (if (eq evi-emacs-version 'lucid19)
  1292.                   (if (= (length keys) 1)
  1293.                       (setq char (+ (evi-read-command-char)
  1294.                             128)
  1295.                         keys (char-to-string char))
  1296.                     (concat
  1297.                      (char-to-string (+ (aref keys 1) 128))
  1298.                      (substring keys 2)))
  1299.                 (concat
  1300.                   (char-to-string evi-emacs-meta-prefix-char)
  1301.                   (substring keys 1)))
  1302.                 keys)))))
  1303.     (while
  1304.       (cond ((keymapp keydef)
  1305.           (and evi-timeout
  1306.                (not evi-current-macro)
  1307.                (progn
  1308.              (or evi-current-macro (message ""))
  1309.              (if (evi-sit-for 1)
  1310.                  (evi-error "Timeout!"))))
  1311.           (setq char (evi-read-command-char)
  1312.             keys (concat keys (char-to-string char))
  1313.             keydef (lookup-key keydef (char-to-string char)))
  1314.           t)
  1315.         ((stringp keydef)
  1316.           (if evi-prompted (message ""))
  1317.           (setq last-command-char char
  1318.             evi-prompted nil)
  1319.           (let ((evi-last-command-keys nil))
  1320.             (setq quit-flag nil
  1321.               inhibit-quit nil)
  1322.             (evi-push-macro keydef)
  1323.             (evi-get-command))
  1324.           nil)
  1325.         ((commandp keydef)
  1326.           (if evi-prompted (message ""))
  1327.           (setq last-command-char char
  1328.             evi-prompted nil
  1329.             quit-flag nil
  1330.             inhibit-quit nil)
  1331.           (call-interactively keydef)
  1332.           nil)
  1333.         (t
  1334.           (setq keydef nil))))
  1335.     (not keydef)))
  1336.     (or keydef (progn (beep)
  1337.               (evi-error "Unknown command `%s'"
  1338.                  (key-description keys)))))
  1339.   
  1340.   nil)
  1341.  
  1342. (defun evi-read-command-char ()
  1343.   (if evi-current-macro
  1344.       ;; don't add the contents of a macro to evi-command-keys (test this now
  1345.       ;; because the current command char may be the last char in the macro)
  1346.       (evi-read-char)
  1347.     (progn
  1348.       (and evi-command-keys (> (length evi-command-keys) 0)
  1349.        (not evi-in-minibuf)
  1350.        (evi-sit-for 1)
  1351.        (progn (message "%s -"
  1352.             (mapconcat 'single-key-description evi-command-keys ""))
  1353.           (setq evi-prompted t)))
  1354.       (let ((char (evi-read-char)))
  1355.     ; probably lousy on garbage collection... 
  1356.     (if evi-command-keys
  1357.         (setq evi-command-keys
  1358.           (concat evi-command-keys (char-to-string char))))
  1359.     char))))
  1360.  
  1361. (defun evi-unread-command-char (char)
  1362.   (setq evi-unread-command-char char)
  1363.   (let ((length (length evi-command-keys)))
  1364.     (if (> length 0)
  1365.     (setq evi-command-keys (substring evi-command-keys 0 (1- length))))))
  1366.  
  1367. (defun evi-sit-for (count)
  1368.   (if evi-unread-command-char nil (sit-for count)))
  1369.  
  1370. ;; Interactive args
  1371.  
  1372. (defun evi-count-arg ()
  1373.   (list evi-prefix-count))
  1374.  
  1375. (defun evi-register-args ()
  1376.   (list (car evi-register-spec) (cdr evi-register-spec) evi-prefix-count))
  1377.  
  1378. (defun evi-character-arg ()
  1379.   (list (evi-read-command-char) evi-prefix-count))
  1380.  
  1381. (defun evi-string-arg (prompt)
  1382.   (list (evi-read-string prompt) evi-prefix-count))
  1383.  
  1384. (defun evi-context-arg ()
  1385.   (list evi-context))
  1386.  
  1387. ;; Mode line
  1388.  
  1389. (defvar evi-mode-line-format " Evi:%-6s")
  1390.  
  1391. (defun evi-in-mode-line-p (var)
  1392.   (if (listp mode-line-buffer-identification)
  1393.       (memq var mode-line-buffer-identification)
  1394.     nil))
  1395.  
  1396. (defun evi-install-in-mode-line (var)
  1397.   (or (evi-in-mode-line-p var)
  1398.       (setq mode-line-buffer-identification
  1399.         (if (listp mode-line-buffer-identification)
  1400.         (append mode-line-buffer-identification (list var))
  1401.           (cons mode-line-buffer-identification (list var))))))
  1402.  
  1403. (defun evi-deinstall-from-mode-line (var)
  1404.   (if (evi-in-mode-line-p var)
  1405.       (setq mode-line-buffer-identification
  1406.         (evi-filter (function (lambda (mode-var) (not (eq var mode-var))))
  1407.             mode-line-buffer-identification))))
  1408.  
  1409. (defun evi-change-mode-id (string)
  1410.   "Change Evi's mode identification string to STRING."
  1411.   (setq evi-mode-string (format evi-mode-line-format string)))
  1412.  
  1413. (defun evi-refresh-mode-line ()
  1414.   "Redraw mode line."
  1415.   (set-buffer-modified-p (buffer-modified-p)))
  1416.  
  1417. ;; Initializing
  1418.  
  1419. (defun evi-my-file (filename)
  1420.   (let ((attr (file-attributes filename)))
  1421.     (and attr
  1422.      (eq (car (cdr (cdr attr))) (user-uid)))))
  1423.  
  1424. (defun evi-initialize ()
  1425.   (setq evi-initialized t
  1426.     evi-directory-stack (list default-directory)
  1427.     evi-emacs-meta-prefix-char meta-prefix-char)
  1428.   (if (eq evi-emacs-version 'emacs18)
  1429.       (let ((temp-buffer-show-hook 'evi-startup-show-hook))
  1430.     (with-output-to-temp-buffer "*Startup*"
  1431.       (evi-customize)))
  1432.     (let ((temp-buffer-show-function 'evi-startup-show-hook))
  1433.       (with-output-to-temp-buffer "*Startup*"
  1434.     (evi-customize))))
  1435.   (or evi-meta-prefix-char
  1436.       (setq evi-meta-prefix-char evi-emacs-meta-prefix-char)))
  1437.  
  1438. (defun evi-startup-show-hook (buf)
  1439.   (let ((curbuf (current-buffer)))
  1440.     (set-buffer buf)
  1441.     (if (not (and (bobp) (eobp)))
  1442.     (progn
  1443.       (goto-char (point-min))
  1444.       (insert "The following problems were found at startup:\n")
  1445.       (display-buffer buf)
  1446.       (message "Use `z1=' to show only `%s'" (buffer-name curbuf))))
  1447.     (set-buffer curbuf)))
  1448.  
  1449. (defun evi-customize ()
  1450.   ; mimic emacs startup behaviour:
  1451.   ;   if su'd, use effective login name to find startup files (??)
  1452.   (let* ((user-name (user-login-name))
  1453.      (home (if (string= user-name (user-real-login-name))
  1454.          "~"
  1455.          (concat "~" user-name))))
  1456.     (if (file-readable-p "~/.evirc") (load-file (concat home "/.evirc")))
  1457.     (and (file-readable-p ".evirc") (evi-my-file ".evirc")
  1458.      (load-file ".evirc"))
  1459.     (let* ((evi-interactive nil)
  1460.        (source)
  1461.        (message (catch 'abort
  1462.               (or evi-supress-ex-startup
  1463.               (progn
  1464.                 (setq source "~/.exrc")
  1465.                 (evi-do-ex-command-file (concat home "/.exrc"))
  1466.                 (setq source "EXINIT")
  1467.                 (let ((exinit (getenv "EXINIT")))
  1468.                   (if exinit
  1469.                 (evi-do-ex-command-string exinit)))
  1470.                 (setq source ".exrc")
  1471.                 (if (evi-my-file ".exrc")
  1472.                 (evi-do-ex-command-file ".exrc"))))
  1473.               (setq source "~/.exrc.evi")
  1474.               (evi-do-ex-command-file (concat home "/.exrc.evi"))
  1475.               (setq source "EVIINIT")
  1476.               (let ((exinit (getenv "EVIINIT")))
  1477.             (if exinit
  1478.               (evi-do-ex-command-string exinit)))
  1479.               (setq source ".exrc.evi")
  1480.               (if (evi-my-file ".exrc.evi")
  1481.               (evi-do-ex-command-file ".exrc.evi"))
  1482.               nil)))
  1483.       (if message
  1484.     (progn
  1485.       (beep)
  1486.       (if (not (y-or-n-p (concat "Error in " source
  1487.                    (if (eq message t) "" (concat ": " message))
  1488.                    ". Continue? ")))
  1489.         (kill-emacs)))))))
  1490.  
  1491. ;; Startup & Shutdown
  1492.  
  1493. (defun evi ()
  1494.   "Start vi emulation in this buffer."
  1495.   (interactive)
  1496.   (if (not evi-enabled)
  1497.     (progn
  1498.       (or evi-initialized
  1499.       (evi-initialize))
  1500.       (setq evi-emacs-local-map (current-local-map))
  1501.       (evi-install-in-mode-line 'evi-mode-string)
  1502.       (if (eq evi-emacs-version 'lucid19)
  1503.       (set (make-local-variable 'interrupt-char) ?\C-c))
  1504.       (if evi-meta-prefix-char
  1505.     (set (make-local-variable 'meta-prefix-char) evi-meta-prefix-char))))
  1506.   (use-local-map evi-top-level-map)
  1507.   (and buffer-read-only (buffer-file-name)
  1508.        (progn (or evi-read-only-buffers
  1509.           (toggle-read-only))
  1510.           (setq evi-buffer-read-only t)))
  1511.   (evi-change-mode-id "Vi")
  1512.   (evi-number evi-number)
  1513.   (or evi-enabled
  1514.       (progn
  1515.     (evi-tab-width evi-tab-width)
  1516.     (evi-wrap-margin evi-wrap-margin)
  1517.     (run-hooks 'evi-mode-hook)))
  1518.   (setq evi-enabled t)
  1519.   (evi-refresh-mode-line))
  1520.  
  1521. (defun evi-quit-evi ()
  1522.   "Quit vi emulation in this buffer."
  1523.   (interactive)
  1524.   (setq evi-enabled nil)
  1525.   (evi-deinstall-from-mode-line 'evi-mode-string)
  1526.   (evi-deinstall-from-mode-line 'evi-number-string)
  1527.   (use-local-map evi-emacs-local-map)
  1528.   (kill-local-variable 'meta-prefix-char)
  1529.   (if (eq evi-emacs-version 'lucid19)
  1530.       (kill-local-variable 'interrupt-char))
  1531.   (evi-refresh-mode-line))
  1532.  
  1533. ;; Minibuffer
  1534.  
  1535. (defun evi-delete-backward-char-maybe-abort ()
  1536.   "Backup and delete previous character, aborting command if at
  1537. beginning of input."
  1538.   (interactive)
  1539.   (if (<= (point) evi-insert-point)
  1540.     (throw 'exit-minibuf nil))
  1541.   (delete-backward-char 1))
  1542.  
  1543. ;; Scrolling
  1544.  
  1545. (defun evi-scroll-page-forward (&optional count)
  1546.   "Scroll COUNT pages forward."
  1547.   (interactive (evi-count-arg))
  1548.   (scroll-up (if (eq (or count 1) 1)
  1549.            (- (window-height) 3)
  1550.            (* (1- (window-height)) (or count 1))))
  1551.   (evi-reset-goal-column))
  1552.  
  1553. (defun evi-scroll-page-backward (&optional count)
  1554.   "Scroll COUNT pages backward."
  1555.   (interactive (evi-count-arg))
  1556.   (scroll-down (if (eq (or count 1) 1)
  1557.          (- (window-height) 3)
  1558.          (* (1- (window-height)) (or count 1))))
  1559.   (evi-reset-goal-column))
  1560.  
  1561. (defun evi-scroll-text-forward (&optional count)
  1562.   "Scroll COUNT lines forward.  Default is one half of a page or the last COUNT
  1563. specified to either \\[evi-scroll-text-forward] or \\[evi-scroll-text-backward] if one was previously
  1564. given.  The position of the cursor on the screen is maintained."
  1565.   (interactive (evi-count-arg))
  1566.   (evi-set-goal-column)
  1567.   (let ((line-count (if count
  1568.               (setq evi-scroll-count count)
  1569.               (or evi-scroll-count (/ (1- (window-height)) 2))))
  1570.     (window-line (count-lines (window-start) (1+ (point)))))
  1571.     (scroll-up line-count)
  1572.     (forward-line (min (1- window-line) line-count))
  1573.     (evi-move-to-column evi-goal-column)))
  1574.  
  1575. (defun evi-scroll-text-backward (&optional count)
  1576.   "Scroll COUNT lines backward.  Default is one half of a page or the last COUNT
  1577. specified to either \\[evi-scroll-up] or \\[evi-scroll-down] if one was previously
  1578. given.  The position of the cursor on the screen is maintained."
  1579.   (interactive (evi-count-arg))
  1580.   (evi-set-goal-column)
  1581.   (let ((line-count (if count
  1582.               (setq evi-scroll-count count)
  1583.               (or evi-scroll-count (/ (1- (window-height)) 2))))
  1584.     (window-line (count-lines (window-start) (1+ (point)))))
  1585.     (scroll-down line-count)
  1586.     (forward-line (- (min (- (1- (window-height)) window-line) line-count)))
  1587.     (evi-move-to-column evi-goal-column)))
  1588.  
  1589. (defun evi-scroll-cursor-forward (&optional count)
  1590.   "Scroll COUNT lines forward.  Maintain cursor position in the file
  1591. if possible."
  1592.   (interactive (evi-count-arg))
  1593.   (evi-set-goal-column)
  1594.   (scroll-up (or count 1))
  1595.   (evi-move-to-column evi-goal-column))
  1596.  
  1597. (defun evi-scroll-cursor-backward (&optional count)
  1598.   "Scroll COUNT lines backward.  Maintain cursor position in the file
  1599. if possible."
  1600.   (interactive (evi-count-arg))
  1601.   (evi-set-goal-column)
  1602.   (scroll-down (or count 1))
  1603.   (evi-move-to-column evi-goal-column))
  1604.  
  1605. (defun evi-window-control (char &optional linenumber)
  1606.   "Position current line on the screen according to the following character.
  1607. With a prefix count, position that line."
  1608.   (interactive (evi-character-arg))
  1609.   (if linenumber
  1610.     (do-evi-goto-line linenumber))
  1611.   (cond ((and (>= char ?0) (<= char ?9))
  1612.       (let* ((count (evi-read-number (- char ?0)))
  1613.          (char (evi-read-command-char)))
  1614.         (cond ((= char ?.) (enlarge-window (- count (1- (window-height)))))
  1615.           ((= char ?+) (enlarge-window count))
  1616.           ((= char ?-) (shrink-window count))
  1617.           ((= char ?=) (cond ((= count 0) (delete-window))
  1618.                      ((= count 1) (delete-other-windows))
  1619.                      ((= count 2) (split-window-vertically))
  1620.                      (t (evi-error "Invalid window op"))))
  1621.           ((= char ?|) (cond ((= count 0) (delete-window))
  1622.                      ((= count 1) (delete-other-windows))
  1623.                      ((= count 2)
  1624.                     (split-window-horizontally)))))))
  1625.     ((or (= char ?f) (= char ?n)) (select-window (next-window)))
  1626.     ((or (= char ?b) (= char ?p)) (select-window (previous-window)))
  1627.     (t
  1628.       (let ((position
  1629.           (cond ((or (eq char ?\r) (eq char ?H)) 0)
  1630.             ((or (eq char ?.) (eq char ?M)) (/ (window-height) 2))
  1631.             ((or (eq char ?-) (eq char ?L)) (- (window-height) 2))
  1632.             (t (evi-error "Invalid window op")))))
  1633.         (recenter position))))
  1634.   (if evi-prompted (message "")))
  1635.  
  1636. ;; unlike the motion commands, the scroll commands have no wrapper function
  1637. ;; to fixup the cursor, soo...
  1638. (defun evi-move-to-column (column)
  1639.   (move-to-column column)
  1640.   (if (and (eolp) (not (bolp)))
  1641.     (backward-char)))
  1642.  
  1643. ;; Insert mode
  1644.  
  1645. (defun evi-insert (&optional count)
  1646.   "Enter insert mode."
  1647.   (interactive (evi-count-arg))
  1648.   (setq evi-insert-point (point))
  1649.   (evi-enter-insert count))
  1650.  
  1651. (defun evi-open-after (&optional count)
  1652.   "Open a new line below the current one and enter insert mode."
  1653.   (interactive (evi-count-arg))
  1654.   (end-of-line)
  1655.   (insert ?\n)
  1656.   (setq evi-insert-point (point))
  1657.   (evi-maybe-indent)
  1658.   (evi-enter-insert count))
  1659.  
  1660. (defun evi-open-before (&optional count)
  1661.   "Open a new line above the current one and enter insert mode."
  1662.   (interactive (evi-count-arg))
  1663.   (beginning-of-line)
  1664.   (insert ?\n)
  1665.   (backward-char)
  1666.   (setq evi-insert-point (point))
  1667.   (evi-maybe-indent t)
  1668.   (evi-enter-insert count))
  1669.  
  1670. (defun evi-enter-insert (&optional count)
  1671.   (evi-insert-mode count)
  1672.   (if (not (bolp)) (backward-char))
  1673.   (evi-reset-goal-column)
  1674.   (evi-save-command-keys))
  1675.  
  1676. (defun evi-insert-mode (&optional count)
  1677.   (setq evi-mode 'insert)
  1678.   (and (eobp) (not buffer-read-only)
  1679.        (progn (newline 1) (backward-char 1)))
  1680.   (or evi-in-minibuf
  1681.       (progn (evi-change-mode-id "Insert")
  1682.          (evi-refresh-mode-line)))
  1683.   (evi-command-loop
  1684.     (append (list evi-input-map-map)
  1685.         (if evi-in-minibuf
  1686.         (list evi-minibuf-input-map))
  1687.         (if (and evi-insert-mode-local-bindings evi-emacs-local-map)
  1688.         (list (cons evi-emacs-local-suppress-key-list
  1689.                 evi-emacs-local-map)))
  1690.         (list evi-insert-map evi-input-map)))
  1691.   (evi-maybe-kill-indentation)
  1692.   (evi-exit-input-mode count))
  1693.  
  1694. (defun evi-exit-input-mode (&optional count)
  1695.   "Exit from an input mode."
  1696.   (interactive)
  1697.   (ex-expand-abbrev)
  1698.   (if count
  1699.     (let ((input-string (buffer-substring evi-insert-point (point))))
  1700.       (evi-iterate (1- count)
  1701.     (insert input-string))))
  1702.   (setq evi-mode 'vi)
  1703.   (or evi-in-minibuf
  1704.       (progn (evi-change-mode-id "Vi")
  1705.          (evi-refresh-mode-line))))
  1706.  
  1707. (defun evi-insert-mode-delete-backward-char ()
  1708.   "Backup and delete previous character, but no further than insert point."
  1709.   (interactive)
  1710.   (if (> (point) evi-insert-point)
  1711.     (delete-backward-char 1)
  1712.     (message "Beginning of inserted text")))
  1713.  
  1714. (defun evi-maybe-indent (&optional forward)
  1715.   (interactive)
  1716.   (if evi-auto-indent
  1717.     (progn
  1718.       (let ((start (point)))
  1719.     (skip-chars-forward " \t")
  1720.     (delete-region start (point)))
  1721.       (if (or (not evi-insert-mode-local-bindings)
  1722.           (eq indent-line-function 'indent-to-left-margin))
  1723.     (indent-to (save-excursion
  1724.              (if forward (forward-char) (backward-char))
  1725.              (current-indentation)))
  1726.     (indent-according-to-mode))
  1727.       (setq evi-current-indentation (current-column)))))
  1728.  
  1729. (defun evi-maybe-kill-indentation ()
  1730.   (and evi-auto-indent (= evi-current-indentation (current-column))
  1731.     (let ((region
  1732.        (save-excursion
  1733.          (let ((start (if (progn (skip-chars-backward " \t") (bolp))
  1734.                 (point))))
  1735.            (if (and start (progn (skip-chars-forward " \t") (eolp)))
  1736.          (cons start (point)))))))
  1737.       (if region
  1738.     (delete-region (car region) (cdr region))))))
  1739.  
  1740. (defun evi-newline ()
  1741.   "Insert a newline, and indent to the current indentation level.
  1742. Kills indentation on current line if the line is otherwise empty."
  1743.   (interactive)
  1744.   (ex-expand-abbrev)
  1745.   (let ((start (point)))
  1746.     (insert ?\n)
  1747.     (evi-maybe-indent)
  1748.     (save-excursion
  1749.       (goto-char start)
  1750.       (evi-maybe-kill-indentation))))
  1751.  
  1752. (defun evi-forward-indent ()
  1753.   "Move forward to the next indentation level, defined by shiftwidth."
  1754.   (interactive)
  1755.   ; eat all preceeding blanks, then fill with tabs, and pad with spaces
  1756.   ; to reach the target column
  1757.   (let* ((start-column (current-column))
  1758.      (target-column (+ start-column (- evi-shift-width
  1759.                        (% start-column evi-shift-width))))
  1760.      (backup-point (save-excursion
  1761.              (skip-chars-backward " ")
  1762.              (point))))
  1763.     (delete-backward-char (- (point) backup-point))
  1764.     (if indent-tabs-mode
  1765.     (while (< (setq start-column (current-column)) target-column)
  1766.       (insert ?\t)))
  1767.     (if (> start-column target-column) (delete-backward-char 1))
  1768.     (insert-char ?\ (- target-column (current-column)))))
  1769.  
  1770. (defun evi-backward-indent ()
  1771.   "Move backward to the previous indentation level, defined by shiftwidth."
  1772.   (interactive)
  1773.   (let* ((start-column (current-column))
  1774.      (offset (let ((toffset (% start-column evi-shift-width)))
  1775.            (if (= toffset 0) evi-shift-width toffset)))
  1776.      (furthest (save-excursion
  1777.              (skip-chars-backward " \t" (max 0 (- (point) offset)))
  1778.              (- start-column (current-column)))))
  1779.     (backward-delete-char-untabify (min offset furthest) nil)))
  1780.  
  1781. (defun evi-quoted-insert ()
  1782.   (interactive)
  1783.   (insert (evi-read-char)))
  1784.  
  1785. ;; Replace mode
  1786.  
  1787. (defun evi-replace ()
  1788.   "Enter replace mode."
  1789.   (interactive)
  1790.   (setq evi-mode 'replace)
  1791.   (evi-replace-mode (1- (point-max)))
  1792.   (if (not (bolp)) (backward-char))
  1793.   (if evi-replace-max
  1794.     (set-marker evi-replace-max nil))
  1795.   (evi-reset-goal-column)
  1796.   (evi-save-command-keys))
  1797.  
  1798. ;(define-key evi-replace-map "\C-d" 'evi-backward-indent)
  1799. ;(define-key evi-replace-map "\C-t" 'evi-forward-indent)
  1800. ;(define-key evi-replace-map "\C-w" 'evi-delete-backward-word)
  1801.  
  1802. (defvar evi-replaced-string nil)
  1803. (defvar evi-replaced-string-index nil)
  1804.  
  1805. (defun evi-replace-mode (max-replace-position)
  1806.   (or evi-replace-max
  1807.       (setq evi-replace-max (make-marker)))
  1808.   (set-marker evi-replace-max max-replace-position)
  1809.   (setq evi-insert-point (point)
  1810.     evi-replaced-string ""
  1811.     evi-replaced-string-index 0)
  1812.   (evi-change-mode-id "Replce")
  1813.   (evi-refresh-mode-line)
  1814.   (if (catch 'switch-to-insert
  1815.     (evi-command-loop (list evi-input-map-map evi-replace-map))
  1816.     nil)
  1817.       (progn
  1818.     (set-marker evi-replace-max nil)
  1819.     (evi-insert-mode))
  1820.     (progn
  1821.       (evi-exit-replace-mode)
  1822.       (evi-exit-input-mode))))
  1823.  
  1824. (defun evi-exit-replace-mode ()
  1825.   (if (< evi-replaced-string-index (length evi-replaced-string))
  1826.     (let ((start (point)))
  1827.       (delete-region (point)
  1828.              (+ (point)
  1829.             (- (length evi-replaced-string)
  1830.                evi-replaced-string-index)))
  1831.       (insert-before-markers
  1832.        (substring evi-replaced-string evi-replaced-string-index))
  1833.       (goto-char start)))
  1834.   (if (eq evi-mode 'change)
  1835.     (evi-exit-change-mode))
  1836.   (setq evi-overstruck-char nil))
  1837.  
  1838. (defun evi-self-replace ()
  1839.   "Replace character under cursor with the command character."
  1840.   (interactive)
  1841.   (if (or (>= (point) evi-replace-max)
  1842.       (= (following-char) ?\n))
  1843.       (progn (setq evi-unread-command-char last-command-char)
  1844.          ;; ZZ this is gross... should be rewritten properly, if possible
  1845.          (setq evi-command-keys loop-command-keys)
  1846.          (throw 'switch-to-insert t))
  1847.     (if (= evi-replaced-string-index (length evi-replaced-string))
  1848.     (setq evi-replaced-string
  1849.           (concat evi-replaced-string
  1850.               (char-to-string (following-char)))))
  1851.     (setq evi-replaced-string-index (1+ evi-replaced-string-index))
  1852.     (let ((start (point)))
  1853.       (evi-replace-one-char last-command-char)
  1854.       ;; if auto-indenting happened...
  1855.       (if (> (- (point) start) 1)
  1856.       (setq evi-insert-point (1+ start)
  1857.         evi-replaced-string
  1858.         (buffer-substring (1+ start) (point))
  1859.         evi-replaced-string-index
  1860.         (length evi-replaced-string))))))
  1861.  
  1862. (defun evi-replace-one-char (char)
  1863.   (delete-region (point) (1+ (point)))
  1864.   (if (boundp 'buffer-undo-list)
  1865.       (if (and evi-overstruck-char (= (point) evi-replace-max))
  1866.     (progn (aset (car (car buffer-undo-list))
  1867.              0 evi-overstruck-char)
  1868.            (setq evi-overstruck-char nil))))
  1869.   ; ZZ unpleasantly hardcoded?
  1870.   (if (or (= char ?\n) (= char ?\r))
  1871.     (evi-newline)
  1872.     (insert char)))
  1873.  
  1874. (defun evi-replace-mode-delete-backward-char ()
  1875.   "Backup to previous character, undoing last replacement, but no further
  1876. than insert point."
  1877.   (interactive)
  1878.   (if (> (point) evi-insert-point)
  1879.     (progn (backward-char)
  1880.        (setq evi-replaced-string-index (1- evi-replaced-string-index)))
  1881.     (message "Beginning of replaced text")))
  1882.  
  1883. (defun evi-replace-char (char &optional count)
  1884.   "Replace the following COUNT characters with CHAR."
  1885.   (interactive (evi-character-arg))
  1886.   (if (catch 'abort
  1887.     (evi-motion-command 'do-evi-forward-char 'horizontal count 'to-end))
  1888.     (evi-error "Can't replace that many characters")
  1889.     (progn (evi-exchange-point-and-mark)
  1890.        (evi-iterate (or count 1)
  1891.          (evi-replace-one-char char))
  1892.        ; ZZ unpleasantly hard-coded?
  1893.        ; should be handled by a general purpose post-auto-indent func
  1894.        (if (or (= char ?\n) (= char ?\r))
  1895.          (evi-maybe-kill-indentation))
  1896.        (if (not (bolp)) (backward-char))))
  1897.   (evi-reset-goal-column)
  1898.   (evi-save-command-keys))
  1899.  
  1900. (defun evi-toggle-case (&optional count)
  1901.   "Toggle the case of the following COUNT characters."
  1902.   (interactive (evi-count-arg))
  1903.   (evi-motion-command 'do-evi-forward-char 'horizontal count 'to-end)
  1904.   (save-excursion
  1905.     (evi-iterate (- (point) evi-mark)
  1906.       (backward-char)
  1907.       (let ((char (following-char)))
  1908.     (cond ((and (>= char ?a) (<= char ?z))
  1909.         (upcase-region (point) (1+ (point))))
  1910.           ((and (>= char ?A) (<= char ?Z))
  1911.         (downcase-region (point) (1+ (point))))))))
  1912.   (evi-fixup-cursor 'horizontal)
  1913.   (evi-reset-goal-column)
  1914.   (evi-save-command-keys))
  1915.  
  1916. ;; Modification operators
  1917.  
  1918. (defun evi-change (&optional count)
  1919.   "Change operator."
  1920.   (interactive (evi-count-arg))
  1921.   (evi-operator-command (or count 1) 'to-end '(evi-change-internal) 1))
  1922.  
  1923. (defun evi-change-internal ()
  1924.   ; If the region is contained on one line, throw a `$' out to mark the
  1925.   ; end of the region, then enter replace mode and delete any un-replaced
  1926.   ; text when that is exited, with the replace-max set at the end of the
  1927.   ; region so that it will switch to insert mode if necessary.  Otherwise,
  1928.   ; delete the region first, and enter insert mode.
  1929.   (evi-copy-region-to-registers t)
  1930.   ; this makes the undo leave the point at the start of the undone text
  1931.   (evi-exchange-point-and-mark)
  1932.   (if (or (save-excursion (end-of-line) (> evi-mark (point)))
  1933.       (= (point) evi-mark))
  1934.       (progn (delete-region (point) evi-mark)
  1935.          (setq evi-insert-point (point))
  1936.          (evi-insert-mode))
  1937.     (progn (setq evi-overstruck-char (char-after (1- evi-mark)))
  1938.        (let ((here (point)))
  1939.          (goto-char evi-mark)
  1940.          (delete-region (1- evi-mark) evi-mark)
  1941.          (insert ?$)
  1942.          (if (boundp 'buffer-undo-list)
  1943.          ;; this is a bit of song and dance to get the cursor to
  1944.          ;; end up in the right place after an undo.  the problem
  1945.          ;; is these two previous statements, which are the first
  1946.          ;; things changed, and thus where the cursor will be left
  1947.          ;; after an undo.  first step: erase the fact that we put
  1948.          ;; the dollar sign there in the first place.
  1949.          (setq buffer-undo-list (cdr (cdr buffer-undo-list))))
  1950.          (goto-char here))
  1951.        (setq evi-mode 'change)
  1952.        (evi-replace-mode evi-mark)))
  1953.   (if (not (bolp)) (backward-char)))
  1954.  
  1955. (defun evi-exit-change-mode ()
  1956.   (if (and (marker-position evi-replace-max)
  1957.        (< (point) evi-replace-max))
  1958.     (let ((overstrike-offset (1- (- evi-replace-max (point)))))
  1959.       (and (eq evi-emacs-version 'lucid19)
  1960.        (null (car buffer-undo-list))
  1961.        ;; lemacs somehow sneaks in an undo boundary
  1962.        (setq buffer-undo-list (cdr buffer-undo-list)))
  1963.       (delete-region (point) (marker-position evi-replace-max))
  1964.       (set-marker evi-replace-max nil)
  1965.       (if (boundp 'buffer-undo-list)
  1966.       ;; second step: rewrite the undo record with the
  1967.       ;; original overstruck character
  1968.       (aset (car (car buffer-undo-list))
  1969.         overstrike-offset evi-overstruck-char)))))
  1970.  
  1971. (defun evi-delete (&optional count)
  1972.   "Delete operator."
  1973.   (interactive (evi-count-arg))
  1974.   (evi-operator-command (or count 1) 'to-next '(evi-delete-internal)))
  1975.  
  1976. (defun evi-delete-internal ()
  1977.   (evi-copy-region-to-registers t)
  1978.   (if evi-number
  1979.       (evi-update-number evi-mark))
  1980.   ; this makes the undo leave the point at the start of the undone text
  1981.   (evi-exchange-point-and-mark)
  1982.   (if (= (point) evi-mark)
  1983.     (message "Nothing deleted")
  1984.     (if (eq evi-region-shape 'rectangle)
  1985.     (delete-rectangle (point) (1+ evi-mark))
  1986.       (delete-region (point) evi-mark)))
  1987.   (evi-fixup-cursor (if (eq evi-region-shape 'chars) 'horizontal 'vertical)))
  1988.  
  1989. (defun evi-yank (&optional count)
  1990.   "Yank operator."
  1991.   (interactive (evi-count-arg))
  1992.   (save-excursion
  1993.     (evi-operator-command (or count 1) 'to-next '(evi-yank-internal))))
  1994.  
  1995. (defun evi-yank-internal ()
  1996.   (evi-copy-region-to-registers nil)
  1997.   (if (= evi-mark (point))
  1998.     (message "Nothing to yank")))
  1999.  
  2000. (defun evi-put-after (&optional register-number register-append count)
  2001.   "Put back yanked or deleted text after cursor."
  2002.   (interactive (evi-register-args))
  2003.   (let ((register
  2004.       (aref evi-registers (or register-number evi-register-unnamed))))
  2005.     (if register
  2006.     (if (eq (evi-register-shape register) 'lines)
  2007.         (progn (end-of-line)
  2008.            (if (not (eobp)) (forward-char))
  2009.            (save-excursion
  2010.              (evi-iterate (or count 1)
  2011.                (insert (evi-register-text register)))))
  2012.       (if (not (and (bolp) (eolp)))
  2013.           (forward-char))
  2014.       (evi-iterate (or count 1)
  2015.         (if (eq (evi-register-shape register) 'chars)
  2016.         (insert (evi-register-text register))
  2017.           (insert-rectangle (evi-register-text register))))
  2018.       (backward-char))
  2019.       (if register-number
  2020.       (message "Nothing in register %c"
  2021.            (evi-register-name register-number))
  2022.     (message "No text to put"))))
  2023.   (evi-reset-goal-column)
  2024.   (evi-save-command-keys))
  2025.  
  2026. (defun evi-put (&optional register-number register-append count)
  2027.   "Put back yanked or deleted text."
  2028.   (interactive (evi-register-args))
  2029.   (let ((register
  2030.       (aref evi-registers (or register-number evi-register-unnamed))))
  2031.     (if register
  2032.     (if (eq (evi-register-shape register) 'lines)
  2033.         (progn (beginning-of-line)
  2034.            (save-excursion
  2035.              (evi-iterate (or count 1)
  2036.                (insert (evi-register-text register)))))
  2037.       (evi-iterate (or count 1)
  2038.         (if (eq (evi-register-shape register) 'chars)
  2039.         (insert (evi-register-text register))
  2040.           (insert-rectangle (evi-register-text register))))
  2041.       (backward-char))
  2042.       (if register-number
  2043.       (message "Nothing in register %c"
  2044.            (evi-register-name register-number))
  2045.     (message "No text to put"))))
  2046.   (evi-reset-goal-column)
  2047.   (evi-save-command-keys))
  2048.  
  2049. (defun evi-shift-right (&optional count)
  2050.   "Shift right operator."
  2051.   (interactive (evi-count-arg))
  2052.   (evi-operator-command (or count 1) 'whole-lines '(evi-shift-internal 1)))
  2053.  
  2054. (defun evi-shift-left (&optional count)
  2055.   "Shift left operator."
  2056.   (interactive (evi-count-arg))
  2057.   (evi-operator-command (or count 1) 'whole-lines '(evi-shift-internal -1)))
  2058.  
  2059. (defun evi-shift-internal (direction)
  2060.   (if (= evi-mark (point))
  2061.     (message "Nothing shifted")
  2062.     (indent-rigidly evi-mark (point) (* evi-shift-width direction)))
  2063.   (goto-char evi-mark)
  2064.   (skip-chars-forward " \t"))
  2065.  
  2066. (defun evi-indent (&optional count)
  2067.   "Indent region."
  2068.   (interactive (evi-count-arg))
  2069.   (evi-operator-command (or count 1) 'whole-lines '(evi-indent-internal)))
  2070.  
  2071. (defun evi-indent-internal ()
  2072.   (if (= evi-mark (point))
  2073.     (message "Nothing indented")
  2074.     (indent-region evi-mark (point) nil))
  2075.   (goto-char evi-mark)
  2076.   (skip-chars-forward " \t"))
  2077.  
  2078. (defun evi-shell-filter (&optional count)
  2079.   "Filter region thru shell command."
  2080.   (interactive (evi-count-arg))
  2081.   (save-excursion
  2082.     (evi-operator-command (or count 1) 'whole-lines
  2083.               '(evi-filter-internal input-string) t)))
  2084.  
  2085. (defun evi-filter-internal (shell-command)
  2086.   (if (string= shell-command "!")
  2087.       (setq shell-command
  2088.     (or evi-last-shell-command
  2089.         (evi-error "No previous shell command to substitute for !")))
  2090.     (setq evi-last-shell-command shell-command))
  2091.   (shell-command-on-region evi-mark (point) shell-command t))
  2092.  
  2093. (defun evi-send-to-process (&optional count)
  2094.   "Send region to emacs process buffer."
  2095.   (interactive (evi-count-arg))
  2096.   (save-excursion
  2097.     (evi-operator-command (or count 1) 'to-next
  2098.               '(evi-to-process-internal)))
  2099.   (switch-to-buffer-other-window evi-process-buffer)
  2100.   (goto-char (process-mark (get-buffer-process evi-process-buffer)))
  2101.   (evi-insert))
  2102.  
  2103. (defun evi-to-process-internal ()
  2104.   (send-region
  2105.     (setq evi-process-buffer (read-buffer "* : " evi-process-buffer t))
  2106.     evi-mark (point)))
  2107.  
  2108. (defun evi-loop-over-lines-in-region (&optional count)
  2109.   "Execute a sequence of operations on every line in a region."
  2110.   (interactive (evi-count-arg))
  2111.   (evi-operator-command (or count 1) 'whole-lines
  2112.             '(evi-loop-lines-internal input-string) t))
  2113.  
  2114. (defun evi-loop-lines-internal (macro)
  2115.   (let ((evi-last-command-keys nil)
  2116.     (ending-mark (set-marker (make-marker) (point-marker)))
  2117.     (evi-prefix-count nil))
  2118.     (goto-char evi-mark)
  2119.     (beginning-of-line)
  2120.     (while (< (point) (marker-position ending-mark))
  2121.       (evi-execute-macro macro)
  2122.       (end-of-line)
  2123.       (forward-char))
  2124.     (set-marker ending-mark nil))
  2125.   (evi-fixup-cursor 'vertical))
  2126.  
  2127. (defun evi-operator-command (count context operation &optional more-input)
  2128.   (let ((evi-context context)
  2129.     (evi-prefix-count-multiplier count)
  2130.     (evi-default-keymap-list
  2131.       (list (evi-make-local-keymap
  2132.           '(((char-to-string last-command-char) evi-whole-lines)))
  2133.         evi-map-map evi-motion-map)))
  2134.     (evi-get-command))
  2135.   (let ((input-string (if (eq more-input t)
  2136.             (evi-read-string (concat evi-command-keys " : ")))))
  2137.     (eval operation))
  2138.   (evi-reset-goal-column)
  2139.   (evi-save-command-keys))
  2140.  
  2141. (defun evi-join-lines (&optional count)
  2142.   "Join together COUNT + 1 lines, supplying appropriate whitespace."
  2143.   (interactive (evi-count-arg))
  2144.   (let ((starting-point (point))
  2145.     (ending-point nil))
  2146.     (evi-iterate (max (1- (or count 2)) 1)
  2147.       (end-of-line)
  2148.       (if (evi-eobp)
  2149.       (progn (or ending-point
  2150.              (setq ending-point starting-point))
  2151.          (evi-break))
  2152.     (forward-char)
  2153.     (delete-region (1- (point))
  2154.                (progn (skip-chars-forward " \t") (point)))
  2155.     (or ending-point
  2156.         (setq ending-point (point)))
  2157.     (if (and (/= (preceding-char) ? )
  2158.          (/= (preceding-char) ?\t)
  2159.          (/= (following-char) ?\)))
  2160.         (insert-char ?  (if (= (preceding-char) ?.) 2 1)))))
  2161.     (goto-char ending-point))
  2162.   (evi-reset-goal-column)
  2163.   (evi-save-command-keys))
  2164.  
  2165. ;; Motion command
  2166.  
  2167. (defun evi-exchange-point-and-mark ()
  2168.   (let ((temp evi-mark))
  2169.     (setq evi-mark (point))
  2170.     (goto-char temp)))
  2171.  
  2172. (defun evi-expand-region-to-lines (context)
  2173.   (evi-exchange-point-and-mark)
  2174.   (beginning-of-line)
  2175.   (evi-exchange-point-and-mark)
  2176.   (end-of-line)
  2177.   (if (not (or (eobp) (eq context 'to-end))) (forward-char))
  2178.   (setq evi-region-shape 'lines))
  2179.  
  2180. ; 'normalizing' a horizontal region means expanding the region to whole lines
  2181. ; when 1) the beginning of the region is on the first non-white character
  2182. ; of a line, and 2) the ending of the region is on the end of the line
  2183.  
  2184. (defun evi-normalize-region ()
  2185.   (and (eolp)
  2186.        (save-excursion
  2187.      (beginning-of-line)
  2188.      (and (> (point) evi-mark)
  2189.           (progn (goto-char evi-mark)
  2190.              (skip-chars-backward " \t")
  2191.              (bolp))))
  2192.        (progn (evi-exchange-point-and-mark)
  2193.           (beginning-of-line)
  2194.           (evi-exchange-point-and-mark)
  2195.           (if (not (eobp))
  2196.         (forward-char))
  2197.           (setq evi-region-shape 'lines))))
  2198.  
  2199. (defun evi-fixup-cursor (direction)
  2200.   (or evi-internal-command
  2201.     (if (eq direction 'horizontal)
  2202.       (progn (if (and (eobp) (not (bobp)))
  2203.            (backward-char))
  2204.          (if (and (eolp) (not (bolp)))
  2205.            (backward-char)))
  2206.       (if (and (eobp) (not (bobp)))
  2207.     (progn (backward-char) (beginning-of-line))
  2208.     (if (and (eolp) (not (bolp))) (backward-char))))))
  2209.  
  2210. (defun evi-motion-command (move-function direction count context &optional arg)
  2211.   (if context
  2212.       (setq evi-mark (point))
  2213.     ; else, maintain the goal column.  kinda gross this being here, but...
  2214.     (if (or (eq move-function 'do-evi-next-line)
  2215.         (eq move-function 'do-evi-previous-line))
  2216.     (evi-set-goal-column)
  2217.       (evi-reset-goal-column)))
  2218.   (if arg
  2219.       (funcall move-function arg count context)
  2220.     (funcall move-function count context))
  2221.   (if context
  2222.       (progn
  2223.     (if (< (point) evi-mark) (evi-exchange-point-and-mark))
  2224.     (if (or (eq direction 'vertical) (eq context 'whole-lines))
  2225.         (evi-expand-region-to-lines context)
  2226.       (progn (setq evi-region-shape 'chars)
  2227.          (if (eq context 'to-next)
  2228.              (evi-normalize-region)))))
  2229.     ; fixup the location of the cursor, if necessary
  2230.     (evi-fixup-cursor direction)))
  2231.  
  2232. ;; Simple motion commands
  2233.  
  2234. (evi-defmotion horizontal evi-forward-char (&optional count context)
  2235.   "Move right COUNT characters on the current line."
  2236.   (forward-char (let ((here (point)))
  2237.           (end-of-line)
  2238.           (prog1 (min (or count 1) (- (point) here))
  2239.               (goto-char here))))
  2240.   (and (eolp) (not context) (not evi-internal-command)
  2241.        (evi-error "End of line")))
  2242.  
  2243. (evi-defmotion horizontal evi-backward-char (&optional count context)
  2244.   "Move left COUNT characters on the current line."
  2245.   (backward-char (let ((here (point)))
  2246.            (beginning-of-line)
  2247.            (prog1 (min (1- (or count 1)) (- here (point)))
  2248.                (goto-char here))))
  2249.   (if (bolp) (evi-error "Beginning of line") (backward-char)))
  2250.  
  2251. (evi-defmotion vertical evi-next-line (&optional count context)
  2252.   "Go to ARGth next line."
  2253.   (evi-next-line-internal (or count 1))
  2254.   (if (null context)
  2255.     (progn (evi-adjust-scroll-up)
  2256.        (move-to-column evi-goal-column))))
  2257.  
  2258. (evi-defmotion vertical evi-beginning-of-next-line (&optional count context)
  2259.   "Go to beginning of ARGth next line."
  2260.   (evi-next-line-internal (or count 1))
  2261.   (if (null context) (evi-adjust-scroll-up))
  2262.   (skip-chars-forward " \t"))
  2263.  
  2264. ;; ZZ maybe can use goal column in fixup-cursor to remove some of this here??
  2265. (defun evi-next-line-internal (count)
  2266.   (let* ((starting-point (point))
  2267.      (offset (forward-line count)))
  2268.     (or (not (eobp)) (= count 0)
  2269.     (progn (goto-char starting-point)
  2270.            (evi-error
  2271.          (if (= count 1)
  2272.              "Last line in buffer"
  2273.            "Not that many lines left in buffer"))))))
  2274.  
  2275. (defun evi-adjust-scroll-up ()
  2276.   (let ((window-line (count-lines (window-start) (1+ (point))))
  2277.     (window-height (1- (window-height))))
  2278.     (and (> window-line window-height)
  2279.      (< window-line (+ window-height (/ window-height 3)))
  2280.      (recenter (1- window-height)))))
  2281.  
  2282. (evi-defmotion vertical evi-previous-line (&optional count context)
  2283.   "Go to ARGth previous line."
  2284.   (evi-previous-line-internal (or count 1))
  2285.   (if (null context)
  2286.     (progn (evi-adjust-scroll-down)
  2287.        (move-to-column evi-goal-column))))
  2288.  
  2289. (evi-defmotion vertical evi-beginning-of-previous-line (&optional count context)
  2290.   "Go to beginning of ARGth previous line."
  2291.   (evi-previous-line-internal (or count 1))
  2292.   (if (null context) (evi-adjust-scroll-down))
  2293.   (back-to-indentation))
  2294.  
  2295. (defun evi-previous-line-internal (count)
  2296.   (let* ((starting-point (point))
  2297.      (offset (forward-line (- count))))
  2298.     (if (/= offset 0)
  2299.     (progn (goto-char starting-point)
  2300.            (evi-error
  2301.          (if (= count 1)
  2302.              "First line in buffer"
  2303.            "Not that many lines left in buffer"))))))
  2304.  
  2305. (defun evi-adjust-scroll-down ()
  2306.   (if (< (point) (window-start))
  2307.     (let ((window-line (count-lines (1+ (point)) (window-start)))
  2308.       (window-height (1- (window-height))))
  2309.       (and (< window-line (/ window-height 3))
  2310.        (recenter 0)))))
  2311.  
  2312. (evi-defmotion vertical evi-goto-line (&optional count context)
  2313.   "Go to line number LINE, or to end of file if no count specified."
  2314.   ; ZZ once again... if we know the move won't be far (like on same screen)
  2315.   ; perhaps shouldn't push context...
  2316.   (evi-push-context)
  2317.   (ex-goto-line count))
  2318.  
  2319. (evi-defmotion vertical evi-goto-top-of-window (&optional offset context)
  2320.   "Go to the top line of the window.  With an arg, OFFSET, goes to the
  2321. OFFSET'th line of the window."
  2322.   (move-to-window-line (1- (or offset 1)))
  2323.   (or context
  2324.       (skip-chars-forward " \t")))
  2325.  
  2326. (evi-defmotion vertical evi-goto-middle-of-window (&optional offset context)
  2327.   "Go to the middle line of the window."
  2328.   (move-to-window-line (/ (window-height) 2))
  2329.   (or context
  2330.       (skip-chars-forward " \t")))
  2331.  
  2332. (evi-defmotion vertical evi-goto-bottom-of-window (&optional offset context)
  2333.   "Go to the bottom line of the window.  With an arg, OFFSET, goes to the
  2334. OFFSET'th line from the bottom of the window."
  2335.   (move-to-window-line (- (1- (window-height)) (or offset 1)))
  2336.   (or context
  2337.       (skip-chars-forward " \t")))
  2338.  
  2339. (evi-defmotion horizontal evi-goto-column (&optional column context)
  2340.   "Go to column COLUMN, or as close to that column as possible."
  2341.   (move-to-column (1- (or column 1))))
  2342.  
  2343. (evi-defmotion vertical evi-whole-lines (&optional count context)
  2344.   "Go ARG - 1 lines forward."
  2345.   (evi-next-line-internal (1- (or count 1))))
  2346.  
  2347. (evi-defmotion horizontal evi-beginning-of-line (&optional count context)
  2348.   "Go to beginning of line."
  2349.   (beginning-of-line))
  2350.  
  2351. ; it's not at all clear why this doesn't take a count...
  2352. ; maybe it should...
  2353. (evi-defmotion horizontal evi-goto-indentation (&optional count context)
  2354.   "Go to beginning of indented text on current line."
  2355.   (beginning-of-line)
  2356.   (back-to-indentation))
  2357.  
  2358. (evi-defmotion horizontal evi-end-of-line (&optional count context)
  2359.   "Go to end of line."
  2360.   (evi-next-line-internal (1- (or count 1)))
  2361.   (end-of-line)
  2362.   ;; any sufficiently large number here will do
  2363.   (setq evi-goal-column 1000000
  2364.     evi-reset-goal-column nil))
  2365.  
  2366. ;; Word, sentence, paragraph and section motion commands
  2367.  
  2368. (defun evi-eobp ()
  2369.   (< (- (point-max) (point)) 3))
  2370.  
  2371. (evi-defmotion horizontal evi-forward-word (&optional count context)
  2372.   "Move to the beginning of the COUNTth next word."
  2373.   (evi-forward-word-internal evi-word (or count 1) context))
  2374.  
  2375. (evi-defmotion horizontal evi-forward-Word (&optional count context)
  2376.   "Move to the beginning of the COUNTth next white-space delimited word."
  2377.   (evi-forward-word-internal evi-Word (or count 1) context))
  2378.  
  2379. (defun evi-forward-word-internal (pattern count context)
  2380.   (and (not context) (evi-eobp)
  2381.        (evi-error "End of buffer"))
  2382.   (if context
  2383.     (setq count (1- count)))
  2384.   (if (looking-at pattern)
  2385.     (setq count (1+ count)))
  2386.   (if (and (re-search-forward pattern nil 'limit count)
  2387.        (or (not (eq context 'to-next))
  2388.            (re-search-forward pattern
  2389.          (save-excursion (end-of-line) (point)) 'limit)))
  2390.     (if (eq context 'to-end)
  2391.       (if (or (> count 0) (looking-at pattern))
  2392.     (goto-char (match-end 0))
  2393.     (forward-char))
  2394.       (goto-char (match-beginning 0)))
  2395.     (if (eobp)
  2396.       (backward-char))))
  2397.  
  2398. (evi-defmotion horizontal evi-end-of-word (&optional count context)
  2399.   "Move to the end of the COUNTth next word."
  2400.   (evi-end-of-word-internal evi-word (or count 1) context))
  2401.  
  2402. (evi-defmotion horizontal evi-end-of-Word (&optional count context)
  2403.   "Move to the end of the COUNTth next whitespace delimited word."
  2404.   (evi-end-of-word-internal evi-Word (or count 1) context))
  2405.  
  2406. (defun evi-end-of-word-internal (pattern count context)
  2407.   (and (not context) (evi-eobp)
  2408.        (evi-error "End of buffer"))
  2409.   (or context
  2410.       (forward-char))
  2411.   (if (re-search-forward pattern nil 'limit count)
  2412.     (goto-char (- (match-end 0) (if context 0 1)))
  2413.     (if (eobp)
  2414.       (backward-char))))
  2415.  
  2416. (evi-defmotion horizontal evi-backward-word (&optional count context)
  2417.   "Move to the beginning of the COUNTth previous word."
  2418.   (evi-backward-word-internal evi-word (or count 1)))
  2419.  
  2420. (evi-defmotion horizontal evi-backward-Word (&optional count context)
  2421.   "Move to the beginning of the COUNTth previous whitespace delimited word."
  2422.   (evi-backward-word-internal evi-Word (or count 1)))
  2423.  
  2424. (defun evi-backward-word-internal (pattern count)
  2425.   (if (bobp)
  2426.     (evi-error "Beginning of buffer"))
  2427.   (evi-iterate count
  2428.     (if (re-search-backward pattern nil 'limit)
  2429.       (progn
  2430.     (looking-at pattern)
  2431.     (let ((end (match-end 0))
  2432.           (at-beginning nil))
  2433.       (while (and (looking-at pattern) (= (match-end 0) end)
  2434.               (not (setq at-beginning (bobp))))
  2435.         (backward-char))
  2436.       (if (not at-beginning)
  2437.         (forward-char))))
  2438.       (evi-break))))
  2439.  
  2440. (defconst evi-sentence-beginning "\\([.?!][]\"')]*\\([\t\n]\\| [ \t\n]\\)\\|^[ \t]*\n\\|\\`\\)[ \t\n]*[^ \t\n]")
  2441.  
  2442. (defconst evi-sentence-ending "\\([.?!][]\"')]*\\([\t\n]\\| [ \t\n]\\)\\|^[ \t]*$\\)")
  2443.  
  2444. (defconst evi-paragraph-beginning "\\(^[ \t]*\n\\|\\`\\)[ \t\n]*[^ \t\n]")
  2445.  
  2446. (defconst evi-paragraph-ending "^[ \t]*$")
  2447.  
  2448. (defconst evi-section-beginning "^\\({\\|\\.\\(NH\\|SH\\|H\\|HU\\|nh\\|sh\\)[ \t\n]\\)")
  2449.  
  2450. (defconst evi-section-ending "[ \t\n]*\n\\(}\\|\\.\\(NH\\|SH\\|H\\|HU\\|nh\\|sh\\)[ \t\n]\\)")
  2451.  
  2452. (defun evi-not-at (pattern &optional limit)
  2453.   (let ((start (point)))
  2454.     (if (re-search-backward pattern limit 'limit)
  2455.       (prog1
  2456.     (/= (match-end 0) start)
  2457.     (goto-char start))
  2458.       t)))
  2459.  
  2460. (evi-defmotion horizontal evi-forward-sentence (&optional count context)
  2461.   "Move to the beginning of the COUNT'th next sentence."
  2462.   (and (not context) (evi-eobp)
  2463.        (evi-error "End of buffer"))
  2464.   (forward-char)
  2465.   (and (eq context 'to-next) (evi-not-at evi-sentence-beginning)
  2466.        (setq context 'to-end))
  2467.   (if (re-search-forward evi-sentence-beginning nil 'limit
  2468.              (- (or count 1) (if context 1 0)))
  2469.     (if context
  2470.       (if (eq context 'to-end)
  2471.     (if (re-search-forward evi-sentence-ending nil 'limit)
  2472.       (skip-chars-backward " \t\n"))
  2473.     (if (re-search-forward evi-sentence-beginning
  2474.           (save-excursion
  2475.         (re-search-forward evi-paragraph-ending nil 'limit)
  2476.         (1- (match-beginning 0)))
  2477.           'limit)
  2478.       (backward-char)))
  2479.       (backward-char))))
  2480.  
  2481. (evi-defmotion horizontal evi-backward-sentence (&optional count context)
  2482.   "Move to the beginning of the COUNT'th previous sentence."
  2483.   (if (bobp)
  2484.     (evi-error "Beginning of buffer"))
  2485.   (skip-chars-backward " \t\n")
  2486.   (if (re-search-backward evi-sentence-beginning nil 'limit (or count 1))
  2487.     (goto-char (1- (match-end 0)))))
  2488.  
  2489. (evi-defmotion horizontal evi-forward-paragraph (&optional count context)
  2490.   "Move to the beginning of the COUNT'th next paragraph."
  2491.   (and (not context) (evi-eobp)
  2492.        (evi-error "End of buffer"))
  2493.   (forward-char)
  2494.   (and (eq context 'to-next) (evi-not-at evi-paragraph-beginning)
  2495.        (setq context 'to-end))
  2496.   (if (re-search-forward evi-paragraph-beginning nil 'limit
  2497.              (- (or count 1) (if (eq context 'to-end) 1 0)))
  2498.     (if (eq context 'to-end)
  2499.     (if (re-search-forward evi-paragraph-ending nil 'limit)
  2500.       (goto-char (1- (match-beginning 0))))
  2501.       (if context
  2502.     (beginning-of-line))
  2503.       (backward-char))))
  2504.  
  2505. (evi-defmotion horizontal evi-backward-paragraph (&optional count context)
  2506.   "Move to the beginning of the COUNT'th previous paragraph."
  2507.   (if (bobp)
  2508.     (evi-error "Beginning of buffer"))
  2509.   (if (re-search-backward evi-paragraph-beginning nil 'limit (or count 1))
  2510.     (goto-char (1- (match-end 0)))))
  2511.  
  2512. (evi-defmotion horizontal evi-forward-section (&optional count context)
  2513.   "Move to the beginning of the COUNT'th next section."
  2514.   (and (not context) (evi-eobp)
  2515.        (evi-error "End of buffer"))
  2516.   (or context
  2517.       (evi-push-context (point)))
  2518.   (let ((start (point)))
  2519.     (skip-chars-forward "^ \t\n")
  2520.     (or (eobp)
  2521.     (forward-char))
  2522.     (and (eq context 'to-next) (evi-not-at evi-section-beginning start)
  2523.      (setq context 'to-end)))
  2524.   (if (re-search-forward evi-section-beginning nil 'limit
  2525.              (- (or count 1) (if (eq context 'to-end) 1 0)))
  2526.     (if (eq context 'to-end)
  2527.     (if (re-search-forward evi-section-ending nil 'limit)
  2528.       (or (eq (preceding-char) ?})
  2529.           (goto-char (match-beginning 0))))
  2530.       (goto-char (match-beginning 0))
  2531.       (if context
  2532.     (backward-char)))))
  2533.  
  2534. (evi-defmotion horizontal evi-backward-section (&optional count context)
  2535.   "Move to the beginning of the COUNT'th previous section."
  2536.   (if (bobp)
  2537.     (evi-error "Beginning of buffer"))
  2538.   (or context
  2539.       (evi-push-context (point)))
  2540.   (re-search-backward evi-section-beginning nil 'limit (or count 1)))
  2541.  
  2542. (defun evi-region-arbitrary ()
  2543.   "Define region bounded by mark and point (containing point)."
  2544.   (interactive)
  2545.   (if (< (point) evi-mark) (evi-exchange-point-and-mark))
  2546.   (forward-char)
  2547.   (setq evi-region-shape 'chars))
  2548.  
  2549. (defun evi-region-rectangle ()
  2550.   "Define region as rectangle bounded by mark and point (containing point)."
  2551.   (interactive)
  2552.   (if (< (point) evi-mark) (evi-exchange-point-and-mark))
  2553.   (setq evi-region-shape 'rectangle))
  2554.  
  2555. (defun evi-region-rows (context)
  2556.   "Define region as rows bounded by mark and point (containing point)."
  2557.   (interactive (evi-context-arg))
  2558.   (if (< (point) evi-mark) (evi-exchange-point-and-mark))
  2559.   (evi-expand-region-to-lines evi-context))
  2560.  
  2561. ;ZZ - very naive
  2562. (defun evi-region-columns ()
  2563.   "Define region as columns bounded by mark and point (containing point)."
  2564.   (interactive)
  2565.   (if (< (point) evi-mark) (evi-exchange-point-and-mark))
  2566.   (let ((start-col (save-excursion (goto-char evi-mark) (current-column)))
  2567.     (end-col (current-column)))
  2568.     (setq evi-mark start-col)
  2569.     (goto-char (point-max))
  2570.     (if (eolp)
  2571.     (backward-char))
  2572.     (beginning-of-line)
  2573.     (goto-char (+ (point) end-col)))
  2574.   (setq evi-region-shape 'rectangle))
  2575.  
  2576. ;; Searching
  2577.  
  2578. (evi-defmotion horizontal evi-search-forward
  2579.   (&string "/" string &optional count context)
  2580.   "Search forward for the ARGth occurence of a pattern.  A null string will
  2581. repeat the previous search."
  2582.   (evi-do-vi-search t string (or count 1)))
  2583.  
  2584. (evi-defmotion horizontal evi-search-backward
  2585.   (&string "?" string &optional count context)
  2586.   "Search backward for the ARGth occurence of a pattern.  A null string will
  2587. repeat the previous search."
  2588.   (evi-do-vi-search nil string (or count 1)))
  2589.  
  2590. (defun evi-do-vi-search (search-forward search-spec count)
  2591.   (let ((ex-user-buffer (current-buffer)))
  2592.     (set-buffer ex-work-space)
  2593.     (erase-buffer)
  2594.     (insert (if search-forward ?/ ??) search-spec "\n")
  2595.     (goto-char (point-min))
  2596.     (let ((string (ex-scan-regular-expression))
  2597.       (offset (ex-scan-line-offset)))
  2598.       (set-buffer ex-user-buffer)
  2599.       (or (string= string "")
  2600.       (setq evi-search-pattern string))
  2601.       (if evi-search-pattern
  2602.       (evi-do-search (setq evi-search-forward search-forward)
  2603.              evi-search-pattern count)
  2604.     (evi-error "No previous search pattern"))
  2605.       (if (> offset 0)
  2606.       (evi-next-line-internal offset)
  2607.     (if (< offset 0)
  2608.         (evi-previous-line-internal (- offset)))))))
  2609.  
  2610. (evi-defmotion horizontal evi-search-next (&optional count context)
  2611.   "Search for the next ARGth occurence of the previous search pattern."
  2612.   (if evi-search-pattern
  2613.     (evi-do-search evi-search-forward evi-search-pattern (or count 1))
  2614.     (evi-error "No previous search pattern")))
  2615.  
  2616. (evi-defmotion horizontal evi-search-next-reverse (&optional count context)
  2617.   "Search for the next ARGth occurence of the previous search pattern
  2618. but look in the opposite direction."
  2619.   (let ((evi-search-forward (not evi-search-forward)))
  2620.     (do-evi-search-next count context)))
  2621.  
  2622. (defun evi-do-search (search-forward search-string count)
  2623.   (let ((case-fold-search evi-ignore-case)
  2624.     (starting-point (point)))
  2625.     (if (if search-forward
  2626.       (evi-search-forward-count search-string count)
  2627.       (evi-search-backward-count search-string count))
  2628.       (progn
  2629.     ; ZZ if we know the search didn't take us far, perhaps we shouldn't
  2630.     ; push a context...
  2631.     (evi-push-context starting-point)
  2632.         (goto-char (match-beginning 0)))
  2633.       (progn
  2634.     (goto-char starting-point)
  2635.     (evi-error
  2636.       (concat
  2637.         (if (> count 1) "Nth occurrence not found" "Pattern not found")
  2638.         (if evi-search-wraparound ""
  2639.           (if search-forward
  2640.           " before end of file"
  2641.           " before beginning of file"))))))))
  2642.  
  2643. ; ZZ use evi-iterate
  2644. (defun evi-search-forward-count (string count)
  2645.   (if (> count 0)
  2646.     (progn (forward-char)
  2647.        (if (re-search-forward string nil t)
  2648.          (evi-search-forward-count string (1- count))
  2649.          (if evi-search-wraparound
  2650.            (progn (goto-char (point-min))
  2651.               (if (re-search-forward string nil t)
  2652.             (evi-search-forward-count string (1- count)))))))
  2653.     t))
  2654.  
  2655. (defun evi-search-backward-count (string count)
  2656.   (if (> count 0)
  2657.     (if (re-search-backward string nil t)
  2658.       (evi-search-backward-count string (1- count))
  2659.       (if evi-search-wraparound
  2660.     (progn (goto-char (point-max))
  2661.            (if (re-search-backward string nil t)
  2662.          (evi-search-backward-count string (1- count))))))
  2663.     t))
  2664.  
  2665. (evi-defmotion horizontal evi-find-character (&char char &optional count context)
  2666.   "Search for CHAR on the current line.  With COUNT find the COUNT'th occurance."
  2667.   (setq evi-find-character char
  2668.     evi-find-forward t
  2669.     evi-find-up-to nil)
  2670.   (evi-find-character-internal (or count 1) context))
  2671.  
  2672. (evi-defmotion horizontal evi-find-char-backwards
  2673.   (&char char &optional count context)
  2674.   "Search backwards for CHAR on the current line.  With COUNT find the
  2675. COUNT'th occurance."
  2676.   (setq evi-find-character char
  2677.     evi-find-forward nil
  2678.     evi-find-up-to nil)
  2679.   (evi-find-character-backwards-internal (or count 1) context))
  2680.  
  2681. (evi-defmotion horizontal evi-find-character-before
  2682.   (&char char &optional count context)
  2683.   "Search for CHAR on the current line and leave the cursor on the character
  2684. before it.  With COUNT find the COUNT'th occurance."
  2685.   (setq evi-find-character char
  2686.     evi-find-forward t
  2687.     evi-find-up-to t)
  2688.   (evi-find-character-internal (or count 1) context))
  2689.  
  2690. (evi-defmotion horizontal evi-find-char-backwards-after
  2691.   (&char char &optional count context)
  2692.   "Search backwards for CHAR on the current line and leave the cursor on
  2693. the character after it.  With COUNT find the COUNT'th occurance."
  2694.   (setq evi-find-character char
  2695.     evi-find-forward nil
  2696.     evi-find-up-to t)
  2697.   (evi-find-character-backwards-internal (or count 1) context))
  2698.  
  2699. (evi-defmotion horizontal evi-find-next-character (&optional count context)
  2700.   "Search for the next COUNT'th occurence of the previous search character."
  2701.   (if evi-find-character
  2702.     (if evi-find-forward
  2703.       (evi-find-character-internal (or count 1) context)
  2704.       (evi-find-character-backwards-internal (or count 1) context))
  2705.     (evi-error "No previous search character")))
  2706.  
  2707. (evi-defmotion horizontal evi-find-next-character-reverse (&optional count context)
  2708.   "Search for the next COUNT'th occurence of the previous search character
  2709. in the opposite direction."
  2710.   (let ((evi-find-forward (not evi-find-forward)))
  2711.     (do-evi-find-next-character count context)))
  2712.  
  2713. (defun evi-find-character-internal (count context)
  2714.   (forward-char)
  2715.   (let ((case-fold-search nil))
  2716.     (if (search-forward (char-to-string evi-find-character)
  2717.             (save-excursion (end-of-line) (point)) t count)
  2718.       (if evi-find-up-to
  2719.     (backward-char))
  2720.       (progn (backward-char)
  2721.          (evi-error "No more occurences on this line"))))
  2722.   (or context
  2723.       (backward-char)))
  2724.  
  2725. (defun evi-find-character-backwards-internal (count context)
  2726.   (let ((case-fold-search nil))
  2727.     (or (search-backward (char-to-string evi-find-character)
  2728.              (save-excursion (beginning-of-line) (point)) t count)
  2729.     (evi-error "No more occurences on this line")))
  2730.   (if evi-find-up-to
  2731.     (forward-char)))
  2732.  
  2733. (evi-defmotion horizontal evi-paren-match (&optional count context)
  2734.   "Move cursor to matching parenthesis, brace or bracket."
  2735.   (let ((end-point (save-excursion (end-of-line) (point))))
  2736.     (if (re-search-forward "[][(){}]" end-point t)
  2737.       (progn (backward-char)
  2738.          (if (looking-at "[({[]")
  2739.            (progn (forward-sexp 1)
  2740.               (or context (backward-char)))
  2741.            (progn (forward-char)
  2742.               (if context (setq evi-mark (1+ evi-mark)))
  2743.               (backward-sexp 1))))
  2744.       (evi-error "Nothing on rest of line to balance"))))
  2745.  
  2746. ;; Repeating
  2747.  
  2748. (defun evi-save-command-keys ()
  2749.   (setq evi-last-command-keys evi-command-keys
  2750.     evi-hidden-repeat-count 0))
  2751.  
  2752. (defun evi-repeat ()
  2753.   "Repeat last modifying command."
  2754.   (interactive)
  2755.   (let ((command-to-repeat evi-last-command-keys)
  2756.     (evi-repeat-count (1+ evi-hidden-repeat-count)))
  2757.     (evi-execute-macro evi-last-command-keys)
  2758.     (setq evi-last-command-keys command-to-repeat
  2759.       evi-hidden-repeat-count evi-repeat-count)))
  2760.  
  2761. (defun evi-prompt-repeat ()
  2762.   "Print last modifying command."
  2763.   (interactive)
  2764.   (let ((command (evi-read-string "Repeat: " evi-last-command-keys)))
  2765.     (evi-execute-macro command)
  2766.     (setq evi-last-command-keys command)))
  2767.  
  2768. ;; Prefix counts
  2769.  
  2770. (defun evi-read-number (prefix-value)
  2771.   (let ((char (evi-read-command-char)))
  2772.     (if (and (>= char ?0) (<= char ?9))
  2773.       (evi-read-number (+ (* prefix-value 10) (- char ?0)))
  2774.       (progn (evi-unread-command-char char)
  2775.          prefix-value))))
  2776.  
  2777. (defun evi-prefix-digit ()
  2778.   "Prefix count."
  2779.   (interactive)
  2780.   (let ((evi-prefix-count (* evi-prefix-count-multiplier
  2781.                  (evi-read-number (- last-command-char ?0)))))
  2782.     (evi-get-command)))
  2783.  
  2784. ;; Registers
  2785.  
  2786. (defun evi-prefix-register ()
  2787.   "Prefix register."
  2788.   (interactive)
  2789.   (let* ((char (evi-read-command-char))
  2790.      (evi-register-spec (cons (evi-register-number char)
  2791.                   (not (and (>= char ?a) (<= char ?z))))))
  2792.     (evi-get-command)))
  2793.  
  2794. (defun evi-register-number (register-name)
  2795.   (cond ((and (>= register-name ?a) (<= register-name ?z))
  2796.       (+ (- register-name ?a) 10))
  2797.     ((and (>= register-name ?A) (<= register-name ?Z))
  2798.       (+ (- register-name ?A) 10))
  2799.     ((and (>= register-name ?1) (<= register-name ?9))
  2800.      (% (+ evi-digit-register (- register-name ?0) evi-repeat-count) 9))
  2801.     ((eq register-name ?^)
  2802.       evi-register-unnamed)
  2803.     ((eq register-name ?@)
  2804.       (or evi-last-macro-register
  2805.           (evi-error "No previous macro register specified")))
  2806.     (t (evi-error "Invalid register name"))))
  2807.  
  2808. (defun evi-register-name (register-number)
  2809.   (if (> register-number 9)
  2810.     (+ register-number (- ?a 10))
  2811.     (+ register-number ?1)))
  2812.  
  2813. (defun evi-copy-region-to-registers (number-register-also)
  2814.   (let ((region (if (eq evi-region-shape 'rectangle)
  2815.             (extract-rectangle evi-mark (1+ (point)))
  2816.           (buffer-substring evi-mark (point)))))
  2817.     (evi-copy-region-to-register region evi-register-spec)
  2818.     (if number-register-also
  2819.       (progn (aset evi-registers
  2820.            evi-digit-register (cons region evi-region-shape))
  2821.          (setq evi-digit-register (if (= evi-digit-register 0)
  2822.                       8
  2823.                     (1- evi-digit-register)))))))
  2824.  
  2825. (defun evi-copy-region-to-register (region register-spec)
  2826.   (let ((register-number (car register-spec)))
  2827.     (if (not (eq register-number evi-register-unnamed))
  2828.     (aset evi-registers
  2829.           evi-register-unnamed (cons region evi-region-shape)))
  2830.     (if register-spec
  2831.     (aset evi-registers register-number
  2832.           (if (and (cdr register-spec)
  2833.                (not (eq evi-region-shape 'rectangle)))
  2834.           (let ((register (aref evi-registers register-number)))
  2835.             (cons (concat (car register) region) (cdr register)))
  2836.         (cons region evi-region-shape))))))
  2837.  
  2838. (defun evi-register-string (string &optional count)
  2839.   (interactive (evi-string-arg "\" "))
  2840.   (setq evi-region-shape 'chars)
  2841.   (evi-copy-region-to-register string
  2842.     (or evi-register-spec (cons evi-register-unnamed nil))))
  2843.  
  2844. (defun evi-register-char (char &optional count)
  2845.   (interactive (evi-character-arg))
  2846.   (evi-register-string (char-to-string char)))
  2847.  
  2848. (defun evi-buffer-name ()
  2849.   (interactive)
  2850.   (evi-register-string (buffer-name)))
  2851.  
  2852. ;; Undoing
  2853.  
  2854. (defun evi-undo ()
  2855.   "Undo previous change."
  2856.   (interactive)
  2857.   ; ZZ - is this the only place we're concerned with unnecessary output
  2858.   ; during a macro?
  2859.   (or evi-current-macro
  2860.       (message "undo!"))
  2861.   (evi-undo-start)
  2862.   (evi-undo-one-change)
  2863.   (evi-fixup-cursor 'vertical))
  2864.  
  2865. (if (boundp 'buffer-undo-list)
  2866.     (defun evi-undo-line ()
  2867.       "Undo all changes to this line."
  2868.       (interactive)
  2869.       (evi-undo-start)
  2870.       (evi-undo-one-line)
  2871.       (evi-fixup-cursor 'vertical)))
  2872.  
  2873. (defun evi-undo-start ()
  2874.   (undo-start)
  2875.   (if (boundp 'buffer-undo-list)
  2876.       ; if the first record is a boundary, skip it
  2877.       (while (and pending-undo-list (null (car pending-undo-list)))
  2878.     (setq pending-undo-list (cdr pending-undo-list)))
  2879.     (undo-more 1)))
  2880.  
  2881. (defun evi-undo-more ()
  2882.   "Continue undoing previous changes."
  2883.   (interactive)
  2884.   (if (boundp 'buffer-undo-list)
  2885.       (if (boundp 'pending-undo-list)
  2886.       (progn (message "undo more!")
  2887.          (evi-undo-one-change))
  2888.     (evi-error "No previous undo to continue"))
  2889.     (message "undo more!")
  2890.     (evi-undo-one-change))
  2891.   (evi-fixup-cursor 'vertical))
  2892.  
  2893. (defun evi-undo-one-change ()
  2894.   (let ((modified (buffer-modified-p)))
  2895.     (undo-more 1)
  2896.     (and modified (not (buffer-modified-p))
  2897.      (delete-auto-save-file-if-necessary)))
  2898.   (evi-reset-goal-column))
  2899.  
  2900. (defvar evi-last-undo-line-mark nil)
  2901.  
  2902. (if (boundp 'buffer-undo-list)
  2903.     ; undo records are:
  2904.     ;   (t . ...) which marks a file save
  2905.     ;   ("string" . pos) which undoes a delete
  2906.     ;   (pos . pos) which undoes an insert
  2907.     (defun evi-undo-one-line ()
  2908.       (if (eq evi-last-undo-line-mark (cdr buffer-undo-list))
  2909.     (evi-error "No undo for this line"))
  2910.       (let* ((begin (save-excursion (beginning-of-line) (point)))
  2911.          (end (save-excursion (end-of-line) (point)))
  2912.          (undo-new nil)
  2913.          (something-to-do nil))
  2914.     (evi-enumerate-condition undo-record pending-undo-list
  2915.       (cond ((eq (car undo-record) t)
  2916.           (setq undo-new (nconc undo-new list))
  2917.           nil)
  2918.         ((stringp (car undo-record))
  2919.           (if (and (>= (cdr undo-record) begin)
  2920.                (<= (cdr undo-record) end))
  2921.             (progn (setq end (+ end (length (car undo-record))))
  2922.                (setq undo-new
  2923.                  (nconc undo-new (list undo-record)))
  2924.                (setq something-to-do t)
  2925.                t)
  2926.             (progn (setq undo-new (nconc undo-new (list nil) list))
  2927.                nil)))
  2928.         ((integerp (car undo-record))
  2929.           (let* ((first (car undo-record))
  2930.              (second (cdr undo-record))
  2931.              (begin2 (if (< first begin) begin first))
  2932.              (end2 (if (> second end) end second))
  2933.              (diff (- end2 begin2)))
  2934.             (if (and (<= first end) (>= second begin) (/= begin2 end2))
  2935.               (progn
  2936.             (setq undo-new
  2937.                   (nconc undo-new (list (cons begin2 end2))))
  2938.             (setq something-to-do t)
  2939.             (if (or (< first begin) (> second end))
  2940.               (progn
  2941.                 (nconc undo-new (list nil))
  2942.                 (if (< first begin)
  2943.                   (nconc undo-new (list (cons first begin))))
  2944.                 (if (> second end)
  2945.                   (nconc undo-new
  2946.                 (list (cons (- end diff) (- second diff)))))
  2947.                 (nconc undo-new (cdr list))
  2948.                 nil)
  2949.               (progn (setq end (- end diff))
  2950.                  t)))
  2951.               (progn
  2952.                  (setq undo-new (nconc undo-new (list nil) list))
  2953.                  nil))))
  2954.         ((eq undo-record nil)
  2955.           t)))
  2956.     (if something-to-do
  2957.       (let ((modified (buffer-modified-p)))
  2958.         (setq pending-undo-list undo-new)
  2959.         (undo-more 1)
  2960.         (message "Undo!")
  2961.         (setq evi-last-undo-line-mark buffer-undo-list)
  2962.         (beginning-of-line)
  2963.         (and modified (not (buffer-modified-p))
  2964.          (delete-auto-save-file-if-necessary)))
  2965.       (evi-error "No undo for this line")))
  2966.       (evi-reset-goal-column)))
  2967.  
  2968. ;; Marks
  2969.  
  2970. (defun evi-set-mark (char &optional count)
  2971.   "Mark location."
  2972.   (interactive (evi-character-arg))
  2973.   (cond ((and (>= char ?a) (<= char ?z))
  2974.       (aset evi-registers (+ (- char ?a) 36) (point-marker)))
  2975.     ((eq char ?.)
  2976.       (setq evi-mark (point)))))
  2977.  
  2978. (evi-defmotion horizontal evi-goto-mark-horizontal (&optional count context)
  2979.   "Goto a mark."
  2980.   (evi-goto-mark-internal (evi-read-command-char) context))
  2981.  
  2982. (evi-defmotion vertical evi-goto-mark-vertical (&optional count context)
  2983.   "Goto a mark.  If an operand, define a whole lines region."
  2984.   (evi-goto-mark-internal (evi-read-command-char) context)
  2985.   (or context
  2986.     (back-to-indentation)))
  2987.  
  2988. (defun evi-goto-mark-internal (char &optional context)
  2989.   (cond ((and (>= char ?a) (<= char ?z))
  2990.       (let ((marker (aref evi-registers (+ (- char ?a) 36))))
  2991.         (if (not (eq (current-buffer) (marker-buffer marker)))
  2992.           (progn (switch-to-buffer (marker-buffer marker))
  2993.              ; unpleasant, but best we can do... (?)
  2994.              (if context (setq evi-mark (point)))))
  2995.         (evi-push-context)
  2996.         (goto-char marker)))
  2997.     ((or (eq char ?`) (eq char ?'))
  2998.       (goto-char (evi-exchange-context)))
  2999.     ((eq char ?.)
  3000.       (goto-char (evi-pop-context)))
  3001.     ((eq char ?,)
  3002.       (goto-char (evi-unpop-context)))))
  3003.  
  3004. (defun evi-push-context (&optional offset)
  3005.   (let ((marker (if offset (set-marker (make-marker) offset) (point-marker))))
  3006.     (aset evi-context-ring evi-context-ring-cursor marker)
  3007.     (setq evi-context-ring-cursor
  3008.       (if (= evi-context-ring-cursor 9) 0 (1+ evi-context-ring-cursor)))))
  3009.  
  3010. (defun evi-pop-context ()
  3011.   (setq evi-context-ring-cursor
  3012.     (if (= evi-context-ring-cursor 0) 9 (1- evi-context-ring-cursor)))
  3013.   (aref evi-context-ring evi-context-ring-cursor))
  3014.  
  3015. (defun evi-unpop-context ()
  3016.   (setq evi-context-ring-cursor
  3017.     (if (= evi-context-ring-cursor 9) 0 (1+ evi-context-ring-cursor)))
  3018.   (aref evi-context-ring evi-context-ring-cursor))
  3019.  
  3020. (defun evi-exchange-context ()
  3021.   (let ((cursor
  3022.      (if (= evi-context-ring-cursor 0) 9 (1- evi-context-ring-cursor))))
  3023.     (prog1 (aref evi-context-ring cursor)
  3024.        (aset evi-context-ring cursor (point-marker)))))
  3025.  
  3026. ;; Misc
  3027.  
  3028. (defun evi-redraw ()
  3029.   "Redraw the display."
  3030.   (interactive)
  3031.   (cond ((eq evi-emacs-version 'emacs18)
  3032.       (redraw-display))
  3033.     ((eq evi-emacs-version 'emacs19)
  3034.       (redraw-frame (selected-frame)))
  3035.     ((eq evi-emacs-version 'lucid19)
  3036.       (redraw-screen (selected-screen)))))
  3037.  
  3038. (defun evi-file-info ()
  3039.   "Give information on the file associated with the current buffer."
  3040.   (interactive)
  3041.   (let* ((line-number (count-lines 1 (min (1+ (point)) (point-max))))
  3042.      (total-lines (1- (+ line-number (count-lines (point) (point-max)))))
  3043.      (file-name (buffer-file-name)))
  3044.     (message "\"%s\"%s%s line %d of %d, column %d --%d%%--"
  3045.          (if file-name
  3046.            (if evi-global-directory
  3047.          (evi-abbreviate-file-name file-name (evi-current-directory))
  3048.          file-name)
  3049.            "")
  3050.          (if evi-buffer-read-only
  3051.            " [Read only]" "")
  3052.          (if (buffer-modified-p) " [Modified]" "")
  3053.          line-number
  3054.          total-lines
  3055.          (1+ (current-column))
  3056.          (/ (* line-number 100) total-lines))))
  3057.  
  3058. (defun evi-abbreviate-file-name (file-name directory &optional abbrev)
  3059.   (let* ((length (length directory))
  3060.      (ends-in-slash (= (aref directory (1- length)) ?/)))
  3061.     (if (and (> length 0)
  3062.          (>= (length file-name) length)
  3063.          (string= (substring file-name 0 length) directory))
  3064.       (concat (or abbrev "")
  3065.           (substring file-name
  3066.              (+ length (if (or abbrev ends-in-slash) 0 1))))
  3067.       file-name)))
  3068.  
  3069. (defun evi-tag ()
  3070.   "Go to the tag which is the next word in the buffer."
  3071.   (interactive)
  3072.   (evi-motion-command 'do-evi-forward-word 'horizontal 1 'to-end)
  3073.   (ex-tag (buffer-substring evi-mark (point))))
  3074.  
  3075. (defun evi-make-char-table ()
  3076.   (let ((table (make-vector 256 0))
  3077.     (i ?:))
  3078.     (while (<= ?0 (setq i (1- i)))
  3079.       (aset table i 1))
  3080.     (setq i ?\[)
  3081.     (while (<= ?A (setq i (1- i)))
  3082.       (aset table i 2))
  3083.     (setq i ?\{)
  3084.     (while (<= ?a (setq i (1- i)))
  3085.       (aset table i 2))
  3086.     (setq i ? )
  3087.     (while (<= 0 (setq i (1- i)))
  3088.       (aset table i 4))
  3089.     table))
  3090.  
  3091. (defvar evi-char-table (evi-make-char-table))
  3092.  
  3093. (defun evi-is-num (c)
  3094.   (= (logand (aref evi-char-table c) 1) 1))
  3095.  
  3096. (defun evi-is-alpha (c)
  3097.   (= (logand (aref evi-char-table c) 2) 2))
  3098.  
  3099. (defun evi-is-alphanum (c)
  3100.   (/= (logand (aref evi-char-table c) 3) 0))
  3101.  
  3102. (defun evi-is-nonalphanum (c)
  3103.   (= (logand (aref evi-char-table c) 3) 0))
  3104.  
  3105. (defun evi-is-control-char (c)
  3106.   (= (logand (aref evi-char-table c) 4) 4))
  3107.  
  3108. (defun evi-is-printable (c)
  3109.   (and (not (evi-is-control-char c))
  3110.        (< c ?\C-?)))
  3111.  
  3112. ;; Display of lists
  3113.  
  3114. (defun evi-display-and-prompt (command args)
  3115.   (let ((window (selected-window))
  3116.     (wconf (current-window-configuration)))
  3117.     ;; this is for lucid19
  3118.     (if (eq window (minibuffer-window))
  3119.     (select-window (previous-window)))
  3120.     (if (apply command args)
  3121.     (progn
  3122.       (select-window (minibuffer-window))
  3123.       (message
  3124.         "Hit SPACE or RET to continue, anything else to keep window")
  3125.       (let ((c (evi-read-char)))
  3126.         (if (or (= c ?\n) (= c ?\r) (= c ? ))
  3127.         (set-window-configuration wconf)
  3128.           (select-window window)))))))
  3129.  
  3130. (defun evi-display-list-and-prompt (buffer list &optional initial max-len)
  3131.   (evi-display-and-prompt
  3132.    'evi-display-list (list buffer list initial max-len)))
  3133.  
  3134. (defun evi-display-list (buffer list &optional initial max-len)
  3135.   (save-excursion
  3136.     (set-buffer (get-buffer-create buffer))
  3137.     (erase-buffer)
  3138.     (evi)
  3139.     (if initial
  3140.     (insert initial))
  3141.     (if (eq max-len 'half)
  3142.     (setq max-len (- (/ (window-width) 2) 2)))
  3143.     (if list
  3144.     (evi-insert-list-pretty list (or max-len (- (window-width) 2))))
  3145.     (goto-char (point-min))
  3146.     (display-buffer buffer t))
  3147.   ;; indicates to evi-display-and-prompt that something was displayed
  3148.   t)
  3149.  
  3150. (defun evi-insert-list-pretty (list max-len)
  3151.   (let* ((len (length list))
  3152.      (max-width (min (evi-max-len list) max-len))
  3153.      (col-width (+ max-width 2))
  3154.      (width (window-width))
  3155.      (cols (/ width col-width))
  3156.      (rows (/ (+ len (1- cols)) cols))
  3157.      (counters nil)
  3158.      (indent))
  3159.     (if (< len cols)
  3160.     (setq col-width (/ width len)
  3161.           max-width (- col-width 2)
  3162.           cols len
  3163.           rows 1))
  3164.     (evi-iterate cols
  3165.       (setq counters (cons (nthcdr (* (1- count) rows) list) counters)))
  3166.     (evi-iterate rows
  3167.       (setq indent 0)
  3168.       (evi-iterate-list item counters
  3169.     (let ((s (car (nthcdr (- rows count) item))))
  3170.       (if s
  3171.           (progn
  3172.         (indent-to indent)
  3173.         (insert (if (> (length s) max-width)
  3174.                 (concat (substring s 0 (- max-width 2)) "...")
  3175.               s))
  3176.         (setq indent (+ indent col-width))))))
  3177.       (insert ?\n))))
  3178.  
  3179. (defun evi-max-len (list)
  3180.   (let ((lengths (mapcar 'length list)))
  3181.     (apply 'max lengths)))
  3182.  
  3183. (defun evi-pretty-char (c)
  3184.   (cond ((evi-is-printable c)
  3185.       (char-to-string c))
  3186.     ((evi-is-control-char c)
  3187.       (if ex-input-escapes
  3188.           (cond ((= c ?\n) "\\n")
  3189.             ((= c ?\r) "\\r")
  3190.             ((= c ?\t) "\\t")
  3191.             ((= c ?\e) "\\e")
  3192.             (t (concat "\\C-"
  3193.                    (char-to-string (+ c (if (< c ?\e) ?` ?@))))))
  3194.         (concat "^" (char-to-string (+ c ?@)))))
  3195.     ((= c ?\C-?)
  3196.       (if ex-input-escapes "\\C-?" "^?"))
  3197.     (t
  3198.       (format "\\%03o" c))))
  3199.  
  3200. (defun evi-pretty-string (s)
  3201.   (mapconcat 'evi-pretty-char s ""))
  3202.  
  3203. ; works for maps as well as abbrev lists
  3204. (defun evi-pretty-binding (b)
  3205.   (concat (evi-pretty-string (car b)) " = "
  3206.       (evi-pretty-string (if (consp (cdr b))
  3207.                  (cdr (cdr b))
  3208.                    (cdr b)))))
  3209.  
  3210. ;; Ex
  3211.  
  3212. (defun evi-ex-command ()
  3213.   "Execute an ex command."
  3214.   (interactive)
  3215.   (evi-do-ex-command-string (ex-read-command))
  3216.   (evi-fixup-cursor 'vertical))
  3217.  
  3218. ; ZZ this should be cleaned up
  3219. (defvar ex-user-buffer nil)
  3220.  
  3221. (defun ex-read-command ()
  3222.   (let ((command nil)
  3223.     (ex-user-buffer (current-buffer)))
  3224.     (while (null command)
  3225.       (setq command (evi-read-string ":" nil evi-ex-map evi-ex-input-map)))
  3226.     command))
  3227.  
  3228. (defun ex-do-completion (name start c-name c-list-fun)
  3229.   (if c-name
  3230.       (if (stringp c-name)
  3231.       (if (string= name c-name)
  3232.           (evi-display-completions (funcall c-list-fun c-name))
  3233.         (progn (delete-region start (point))
  3234.            (insert c-name))))
  3235.     (progn (beep) (save-excursion (insert " [no match]"))
  3236.        (sit-for 2)
  3237.        (delete-region (point) (+ (point) 11)))))
  3238.  
  3239. (defun evi-display-completions (list)
  3240.   (evi-display-list " *Completions*" list "Possible completions are:\n"))
  3241.  
  3242. (defun ex-scan-command-point ()
  3243.   (ex-scan-addresses)
  3244.   (let* ((start-of-com (point))
  3245.      (command (ex-scan-command-name))
  3246.      (type (if command
  3247.            (ex-scan-parameter-list (cdr (car (cdr command))) t))))
  3248.     (cons type (cons start-of-com (point)))))
  3249.  
  3250. (defun ex-complete ()
  3251.   (interactive)
  3252.   (let* ((cmd-point (save-excursion (beginning-of-line)
  3253.                     (forward-char)    ; position after `:'
  3254.                     (ex-scan-command-point)))
  3255.      (type (if (and (= (point) (cdr (cdr cmd-point)))
  3256.             (/= (preceding-char) ? ))
  3257.            'command
  3258.          (car cmd-point)))
  3259.      (start-of-word
  3260.        (if (eq type 'command)
  3261.            (nth 1 cmd-point)
  3262.          (max (cdr (cdr cmd-point))
  3263.           (save-excursion (skip-chars-backward "^ \t") (point)))))
  3264.      (word (buffer-substring start-of-word (point))))
  3265.     (cond ((or (eq type 'file) (eq type 'files))
  3266.         ; ZZ perform substitution?
  3267.         (let* ((name (file-name-nondirectory word))
  3268.            (odir (file-name-directory word))
  3269.            (dir (let ((cur-buffer (current-buffer)))
  3270.               (set-buffer ex-user-buffer)
  3271.               (prog1
  3272.                 (if odir
  3273.                 (expand-file-name odir (evi-current-directory))
  3274.                   (evi-current-directory))
  3275.                 (set-buffer cur-buffer)))))
  3276.           (ex-do-completion name (+ start-of-word (length odir))
  3277.         (file-name-completion name dir)
  3278.         (function (lambda (c-name)
  3279.                 (file-name-all-completions c-name dir))))))
  3280.       ((eq type 'buffer)
  3281.         (let ((buf-list
  3282.            (mapcar 'list
  3283.              (evi-filter (function
  3284.                    (lambda (name) (/= (aref name 0) ? )))
  3285.                  (mapcar 'buffer-name (buffer-list))))))
  3286.           (ex-do-completion word start-of-word
  3287.             (try-completion word buf-list)
  3288.         (function (lambda (c-name)
  3289.                 (all-completions c-name buf-list))))))
  3290.       ((eq type 'settings)
  3291.         (if (> (save-excursion (goto-char start-of-word)
  3292.                    (skip-chars-forward "^=\n")
  3293.                    (point))
  3294.            (point))
  3295.         (beep)
  3296.           (let ((settings-list (mapcar 'car evi-option-list)))
  3297.         (ex-do-completion word start-of-word
  3298.           (try-completion word settings-list)
  3299.           (function (lambda (c-name)
  3300.                   (all-completions c-name settings-list)))))))
  3301.       ((or (eq type 'command) (eq type 'map) (eq type 'abbrev))
  3302.         (let ((cmd-list
  3303.            (if (eq type 'command)
  3304.                (mapcar 'car ex-commands)
  3305.              (if (eq type 'map)
  3306.              (evi-keymap-bindings evi-map-map)
  3307.                evi-abbrev-list))))
  3308.           (ex-do-completion word start-of-word
  3309.         (try-completion word cmd-list)
  3310.         (function (lambda (c-name)
  3311.                 (all-completions c-name cmd-list))))))
  3312.       (t (beep)))))
  3313.  
  3314. (defun evi-filter (pred list)
  3315.   (let* ((head (cons nil nil))
  3316.      (end head))
  3317.     (while list
  3318.       (if (funcall pred (car list))
  3319.       (setq end (setcdr end (cons (car list) nil))))
  3320.       (setq list (cdr list)))
  3321.     (cdr head)))
  3322.  
  3323. (defun evi-do-ex-command-file (filename)
  3324.   (if (file-readable-p filename)
  3325.     (let ((ex-user-buffer (current-buffer))
  3326.       (def-dir default-directory)
  3327.       (evi-interactive nil))
  3328.       (set-buffer ex-work-space)
  3329.       (erase-buffer)
  3330.       (let ((default-directory def-dir))
  3331.       (insert-file-contents filename))
  3332.       (goto-char (point-min))
  3333.       (evi-do-ex-command)
  3334.       (set-buffer ex-user-buffer))))
  3335.  
  3336. (defun evi-do-ex-command-string (command-string)
  3337.   (let ((ex-user-buffer (current-buffer)))
  3338.     (set-buffer ex-work-space)
  3339.     (erase-buffer)
  3340.     (insert command-string "\n")
  3341.     (goto-char (point-min))
  3342.     (evi-do-ex-command)
  3343.     (set-buffer ex-user-buffer)))
  3344.  
  3345. ;; Note - it is expected that the function that calls this one has set
  3346. ;; ex-user-buffer, and switched to buffer ex-work-space
  3347. (defun evi-do-ex-command ()
  3348.   (while (not (eobp))
  3349.     (let ((command (ex-scan-command)))
  3350.       (set-buffer ex-user-buffer)
  3351.       (if evi-global-directory
  3352.       (let ((default-directory (evi-current-directory)))
  3353.         (eval command))
  3354.     (eval command))
  3355.       (set-buffer ex-work-space)
  3356.       (forward-char))))
  3357.  
  3358. (defun ex-scan-command ()
  3359.   (if (= (following-char) ?:)
  3360.       (forward-char))
  3361.   (if (= (following-char) ?") ;")
  3362.       (end-of-line))
  3363.   (let* ((addresses (ex-scan-addresses))
  3364.      (command-struct (ex-scan-command-name))
  3365.      (number-of-addresses (car (car (cdr command-struct))))
  3366.      (command-name (car (car command-struct)))
  3367.      (command-prototype (cdr (car (cdr command-struct))))
  3368.      (command-function (cdr (cdr command-struct))))
  3369.     (if (null command-struct)
  3370.       (evi-error "Unknown ex command"))
  3371.     (if (> (ex-count-addresses addresses) number-of-addresses)
  3372.       (evi-error "The %s command only needs %d addresses"
  3373.                 command-name number-of-addresses))
  3374.     (let ((parameter-list (ex-scan-parameter-list command-prototype nil)))
  3375.       (skip-chars-forward " \t")
  3376.       (or (looking-at "[|\n]") (eobp)
  3377.       (evi-error "garbage after end of command: `%s'"
  3378.              (buffer-substring (point)
  3379.                        (progn (skip-chars-forward "^|\n")
  3380.                           (skip-chars-backward " \t")
  3381.                           (point)))))
  3382.       (cons command-function
  3383.         (cond ((eq number-of-addresses 1)
  3384.             (cons (list 'quote (car addresses)) parameter-list))
  3385.           ((eq number-of-addresses 2)
  3386.             (cons (list 'quote addresses) parameter-list))
  3387.           (t
  3388.             parameter-list))))))
  3389.  
  3390. (defun ex-scan-parameter-list (prototype-list completing)
  3391.   (if prototype-list
  3392.     (let ((prototype (cdr (car prototype-list)))
  3393.       (skip-white (eq (car (car prototype-list)) t)))
  3394.       (if (and completing
  3395.            (symbolp prototype)
  3396.            (not (eq prototype 'offset)))
  3397.       prototype
  3398.     (if skip-white
  3399.         (skip-chars-forward " \t")
  3400.       (if (eq (car (car prototype-list)) 'backup)
  3401.           (backward-char)))
  3402.     (let* ((param (ex-scan-parameter prototype))
  3403.            (recurs
  3404.          (ex-scan-parameter-list (cdr prototype-list) completing)))
  3405.       (if completing
  3406.           recurs
  3407.         (cons param recurs)))))))
  3408.  
  3409. (defun ex-scan-parameter (prototype)
  3410.   (cond ((null prototype)
  3411.       nil)
  3412.     ((stringp prototype)
  3413.       (ex-scan-string prototype))
  3414.     ((eq prototype 'address)
  3415.       (list 'quote (ex-scan-address)))
  3416.     ((eq prototype 'register)
  3417.       (list 'quote (ex-scan-register)))
  3418.     ((eq prototype 'file)
  3419.       (ex-scan-quoted "%#*?$" " \t|\n"))
  3420.     ((eq prototype 'buffer)
  3421.       (ex-scan-quoted nil "|\n"))
  3422.     ((eq prototype 'words)
  3423.       (ex-scan-quoted nil "|\n"))
  3424.     ((eq prototype 'rest-of-line)
  3425.       (ex-scan-quoted nil "\n"))
  3426.     ((or (eq prototype 'word)
  3427.          (eq prototype 'map)
  3428.          (eq prototype 'abbrev))
  3429.       (ex-scan-quoted nil " \t|\n"))
  3430.     ((eq prototype 'regular-expression)
  3431.       (ex-scan-regular-expression))
  3432.     ((eq prototype 'regular-expression2)
  3433.       (ex-scan-regular-expression t))
  3434.     ((eq prototype 'command)
  3435.       (list 'quote (ex-scan-command)))
  3436.     ((eq prototype 'settings)
  3437.       (list 'quote (ex-scan-settings)))
  3438.     ((eq prototype 'files)
  3439.       (ex-scan-files))
  3440.     ((eq prototype 'shell-command)
  3441.       (ex-scan-quoted "%#" "\n"))
  3442.     ((eq prototype 'offset)
  3443.       (ex-scan-edit-offset))
  3444.     ((eq prototype 'mark)
  3445.       (ex-scan-mark))
  3446.     ((listp prototype)
  3447.       (if (eq (car prototype) 'if)
  3448.           (if (ex-scan-parameter (car (cdr prototype)))
  3449.           (ex-scan-parameter (car (cdr (cdr prototype)))))))))
  3450.  
  3451. (defun ex-scan-addresses ()
  3452.   (skip-chars-forward " \t")
  3453.   (if (= (following-char) ?%)
  3454.       (progn (forward-char)
  3455.          (cons (cons (cons 'number 1) 0) (cons (cons 'dollar nil) 0)))
  3456.     (if (looking-at "[-+0-9.$'/?]")
  3457.       (cons
  3458.     (ex-scan-address)
  3459.     (progn (skip-chars-forward " \t")
  3460.            (if (= (following-char) ?,)
  3461.          (progn (forward-char)
  3462.             (skip-chars-forward " \t")
  3463.             (ex-scan-address))
  3464.          (cons (cons nil nil) 0))))
  3465.       (cons (cons (cons nil nil) 0) (cons (cons nil nil) 0)))))
  3466.  
  3467. (defun ex-scan-address ()
  3468.   (cons (ex-scan-linespec) (ex-scan-line-offset)))
  3469.  
  3470. (defun ex-scan-linespec ()
  3471.   (let ((char (following-char)))
  3472.     (cond
  3473.       ((and (>= char ?0) (<= char ?9))
  3474.     (let ((start (point)))
  3475.       (skip-chars-forward "0-9")
  3476.       (cons 'number (string-to-int (buffer-substring start (point))))))
  3477.       ((eq char ?.)
  3478.     (forward-char)
  3479.     (cons 'dot nil))
  3480.       ((eq char ?$)
  3481.     (forward-char)
  3482.     (cons 'dollar nil))
  3483.       ((eq char ?')
  3484.     (forward-char 2)
  3485.     (cons 'mark (preceding-char)))
  3486.       ((eq char ?/)
  3487.     (cons 're-forward (ex-scan-regular-expression)))
  3488.       ((eq char ??)
  3489.     (cons 're-backward (ex-scan-regular-expression))))))
  3490.  
  3491. ;; if evi-search-magic is nil, also rework the pattern so that . [ and *
  3492. ;; become literal, and \. \[ and \* are `magic' (i.e. behave as . [ and *
  3493. ;; in a regular expression)
  3494.  
  3495. (defun ex-scan-regular-expression (&optional esc-ampersand)
  3496.   (if (looking-at "[|\n]")
  3497.       nil
  3498.     (forward-char)
  3499.     (let* ((start (point))
  3500.        (stop-chars (concat (if esc-ampersand "&")
  3501.                    (if (not evi-search-magic) ".[*")))
  3502.        (skip-chars (concat "^\n\\\\\C-v" stop-chars
  3503.                    (char-to-string (preceding-char))))
  3504.        (stop-pat (concat "[\\\\\C-v" stop-chars "]")))
  3505.       (skip-chars-forward skip-chars)
  3506.       (while (looking-at stop-pat)
  3507.     (if (or (= (following-char) ?\\) (= (following-char) ?\C-v))
  3508.         (progn (forward-char)
  3509.            (and (/= (length stop-chars) 0)
  3510.             (looking-at (concat "[" stop-chars "]"))
  3511.             (delete-region (1- (point)) (point)))
  3512.            (forward-char))
  3513.       (insert "\\")
  3514.       (forward-char))
  3515.     (skip-chars-forward skip-chars))
  3516.       (prog1
  3517.       (buffer-substring start (point))
  3518.     (if (not (eolp))
  3519.         (forward-char))))))
  3520.  
  3521. (defun ex-scan-line-offset ()
  3522.   (if (looking-at "[0-9+-]")
  3523.       (let ((start (point)))
  3524.     (forward-char)
  3525.     (skip-chars-forward "0-9")
  3526.     ; if they only put a +/- without an offset, default to +/-1
  3527.     (if (and (= (- (point) start) 1) (< (preceding-char) ?0))
  3528.         (if (= (preceding-char) ?+) 1 -1)
  3529.       (string-to-int (buffer-substring start (point)))))
  3530.     0))
  3531.  
  3532. (defun ex-scan-edit-offset ()
  3533.   (if (/= (following-char) ?+)
  3534.       nil
  3535.     (forward-char)
  3536.     (if (evi-is-num (following-char))
  3537.     (ex-scan-line-offset)
  3538.       -1)))
  3539.  
  3540. ;; ZZ maybe recognize here that 0 is invalid?
  3541. (defun ex-define-region (addresses whole-lines default-whole-file)
  3542.   (let ((start (car addresses))
  3543.     (end (cdr addresses)))
  3544.     (if (and (null (car (car start))) default-whole-file)
  3545.       (progn (setq evi-mark (point-min))
  3546.          (goto-char (point-max)))
  3547.       (progn (let ((starting-point (point)))
  3548.            (ex-goto-address start)
  3549.            (setq evi-mark (point))
  3550.            (ex-goto-address end starting-point))
  3551.          (if whole-lines
  3552.            (evi-expand-region-to-lines 'ex))))))
  3553.  
  3554. (defun ex-goto-line (line)
  3555.   (if line
  3556.       (let ((starting-point (point)))
  3557.     (goto-char (point-min))
  3558.     (if (or (> (forward-line (1- line)) 0) (eobp))
  3559.         (progn (goto-char starting-point)
  3560.            (evi-error "Past end of buffer"))))
  3561.     (progn (goto-char (point-max))
  3562.        (if (= (preceding-char) ?\n)
  3563.            (forward-line -1)
  3564.          (beginning-of-line)))))
  3565.  
  3566. (defun ex-goto-address (address &optional starting-point)
  3567.   (let ((token (car (car address)))
  3568.     (value (cdr (car address))))
  3569.     (cond ((eq token 'number)
  3570.         (ex-goto-line value))
  3571.       ((eq token 'dot)
  3572.         (if starting-point (goto-char starting-point)))
  3573.       ((eq token 'dollar)
  3574.         (ex-goto-line nil))
  3575.       ((eq token 'mark)
  3576.         (evi-goto-mark-internal value))
  3577.       ((eq token 're-forward)
  3578.         (if (= (length value) 0)
  3579.           (if ex-previous-re
  3580.         (setq value ex-previous-re)
  3581.         (evi-error "No previous regular expression"))
  3582.           (setq ex-previous-re value))
  3583.         (if starting-point (goto-char starting-point))
  3584.         (end-of-line)
  3585.         (let ((message (catch 'abort
  3586.                  (evi-do-search t value 1)
  3587.                  nil)))
  3588.           (if message
  3589.         (progn (forward-line -1)
  3590.                (evi-error message)))))
  3591.       ((eq token 're-backward)
  3592.         (if starting-point (goto-char starting-point))
  3593.         (evi-do-search nil value 1))))
  3594.   (forward-line (cdr address)))
  3595.  
  3596. (defun ex-goto-line-after-address (address)
  3597.   (if (null (car (car address)))
  3598.     (forward-line)
  3599.     (if (and (eq (car (car address)) 'number)
  3600.          (= (cdr (car address)) 0))
  3601.       (goto-char (point-min))
  3602.       (progn (ex-goto-address address)
  3603.          (forward-line)))))
  3604.  
  3605. (defun ex-count-addresses (addresses)
  3606.   (if (eq (car (car (car addresses))) nil)
  3607.     0
  3608.     (if (eq (car (car (cdr addresses))) nil)
  3609.       1
  3610.       2)))
  3611.  
  3612. (defun ex-scan-command-name ()
  3613.   (skip-chars-forward " \t")
  3614.   (let ((start (point)))
  3615.     (if (looking-at "[a-zA-Z!<=>&@]")
  3616.       (progn (forward-char)
  3617.          (let ((char (preceding-char)))
  3618.            (if (or (and (>= char ?a) (<= char ?z))
  3619.                (and (>= char ?A) (<= char ?Z)))
  3620.          (skip-chars-forward "a-zA-Z")))))
  3621.     (ex-lookup-command ex-commands (buffer-substring start (point)))))
  3622.  
  3623. (defun ex-lookup-command (command-list command)
  3624.   (evi-find cmd-struct command-list
  3625.     (if (ex-command-eq command (car cmd-struct))
  3626.       cmd-struct)))
  3627.  
  3628. (defun ex-command-eq (command command-cell)
  3629.   (let ((full-command (car command-cell)))
  3630.     (or (string= command full-command)
  3631.     (let ((command-length (length command)))
  3632.       (and (>= command-length (cdr command-cell))
  3633.            (< command-length (length full-command))
  3634.            (string= command
  3635.             (substring (car command-cell) 0 (length command))))))))
  3636.  
  3637. (defun ex-scan-register ()
  3638.   (if (evi-is-alpha (following-char))
  3639.       (let ((char (following-char)))
  3640.     (forward-char)
  3641.     (cons (evi-register-number char)
  3642.           (not (and (>= char ?a) (<= char ?z)))))
  3643.     (cons evi-register-unnamed nil)))
  3644.  
  3645. (defun ex-scan-mark ()
  3646.   (if (evi-is-alpha (following-char))
  3647.       (let ((char (following-char)))
  3648.     (forward-char)
  3649.     (+ (- char (if (and (>= char ?a) (<= char ?z)) ?a ?A)) 36))
  3650.     (evi-error "marker name required for mark command")))
  3651.  
  3652. (defun ex-scan-files ()
  3653.   (let ((file)
  3654.     (flist nil))
  3655.     (while (> (length (setq file (ex-scan-quoted "%#*?$" " \t|\n"))) 0)
  3656.       (setq flist (cons file flist))
  3657.       (skip-chars-forward " \t"))
  3658.     (cons 'quote (cons (nreverse flist) nil))))
  3659.  
  3660. (defun ex-scan-quoted (stop-chars delim-chars)
  3661.   (let ((start (point))
  3662.     (skip-chars (concat "^\\\\\C-v" stop-chars delim-chars))
  3663.     (stop-pat (concat "[\\\\\C-v" stop-chars "]"))
  3664.     (expand-glob nil))
  3665.     (skip-chars-forward skip-chars)
  3666.     (while (looking-at stop-pat)
  3667.       (let ((char (following-char)))
  3668.     (cond ((= char ?\C-v)
  3669.         (delete-region (point) (1+ (point)))
  3670.         (forward-char))
  3671.           ((= char ?\\)
  3672.             (if ex-input-escapes
  3673.             (progn
  3674.               (delete-region (point) (1+ (point)))
  3675.               (let ((char (following-char)))
  3676.             (cond ((= char ?e)
  3677.                 (delete-region (point) (1+ (point)))
  3678.                 (insert ?\e))
  3679.                   ((= char ?n)
  3680.                 (delete-region (point) (1+ (point)))
  3681.                 (insert ?\n))
  3682.                   ((= char ?r)
  3683.                 (delete-region (point) (1+ (point)))
  3684.                 (insert ?\r))
  3685.                   ((= char ?t)
  3686.                 (delete-region (point) (1+ (point)))
  3687.                 (insert ?\t))
  3688.                   ((and (= char ?C)
  3689.                     (= (char-after (1+ (point))) ?-))
  3690.                 (let ((char (char-after (+ (point) 2))))
  3691.                   (insert (- char (if (< char ?a) ?@ ?`)))
  3692.                   (delete-region (point) (+ (point) 3))))
  3693.                   (t (forward-char 1)))))
  3694.           (forward-char)))
  3695.           ((= char ?%)
  3696.         (let ((file-name (buffer-file-name ex-user-buffer)))
  3697.           (if file-name
  3698.             (progn
  3699.               (delete-region (point) (1+ (point)))
  3700.               (insert file-name))
  3701.             (evi-error
  3702.               "Buffer has no filename to substitute for %%%%"))))
  3703.           ((= char ?#)
  3704.         (let* ((buffer (evi-next-file-buffer nil))
  3705.                (file-name (and buffer (buffer-file-name buffer))))
  3706.           (if file-name
  3707.             (progn
  3708.               (delete-region (point) (1+ (point)))
  3709.               (insert file-name))
  3710.             (evi-error
  3711.               "No alternate filename to substitute for #"))))
  3712.           (t
  3713.         (setq expand-glob t)
  3714.         (forward-char))))
  3715.       (skip-chars-forward skip-chars))
  3716.     (if expand-glob
  3717.       (progn (shell-command-on-region start (point)
  3718.            (concat "echo " (buffer-substring start (point))) t)
  3719.          (goto-char start)
  3720.          (skip-chars-forward (concat "^" delim-chars))))
  3721.     (if (/= start (point))
  3722.     (buffer-substring start (point)))))
  3723.  
  3724. (defun ex-scan-string (string)
  3725.   (let ((string-length (length string)))
  3726.     (if (<= string-length
  3727.         (- (save-excursion (skip-chars-forward "^|\n") (point))
  3728.            (point)))
  3729.       (let ((buffer-string
  3730.           (buffer-substring (point) (+ (point) string-length))))
  3731.     (if (string= string buffer-string)
  3732.       (progn (forward-char string-length)
  3733.          t))))))
  3734.  
  3735. (defun ex-not-implemented (&optional arg)
  3736.   (message "Command not implemented"))
  3737.  
  3738. (defun ex-abbrev (abbrev definition)
  3739.   (if abbrev
  3740.       (let ((elem (assoc abbrev evi-abbrev-list)))
  3741.     (if elem
  3742.         (if definition
  3743.         (setcdr elem (cons (length abbrev) definition))
  3744.           (message "%s" (evi-pretty-string (cdr (cdr elem)))))
  3745.       (if definition
  3746.           (setq evi-abbrev-list
  3747.             (cons
  3748.              (cons abbrev
  3749.                (cons (length abbrev) definition)) evi-abbrev-list))
  3750.         (evi-error "No abbrev for `%s'" abbrev))))
  3751.     (evi-display-list-and-prompt
  3752.       " *Abbrevs*" (mapcar 'evi-pretty-binding evi-abbrev-list))))
  3753.  
  3754. (defun ex-expand-abbrev ()
  3755.   (let ((abbrev evi-abbrev-list)
  3756.     (case-fold-search nil))
  3757.     (while abbrev
  3758.       (if (search-backward (car (car abbrev))
  3759.                (- (point) (nth 1 (car abbrev))) t)
  3760.       (if (evi-is-nonalphanum (preceding-char))
  3761.           (progn
  3762.         (delete-region (point) (+ (point) (nth 1 (car abbrev))))
  3763.         (insert (cdr (cdr (car abbrev)))))
  3764.         (goto-char (+ (point) (nth 1 (car abbrev))))))
  3765.       (setq abbrev (cdr abbrev)))))
  3766.  
  3767. (defun evi-self-insert ()
  3768.   (interactive)
  3769.   (if (evi-is-nonalphanum last-command-char)
  3770.       (ex-expand-abbrev))
  3771.   (self-insert-command 1))
  3772.  
  3773. (defun ex-change-buffer (exclam buffer-name)
  3774.   (ex-change-buffer-internal exclam buffer-name nil))
  3775.  
  3776. (defun ex-change-buffer-other-window (exclam buffer-name)
  3777.   (ex-change-buffer-internal exclam buffer-name t))
  3778.  
  3779. (defun ex-change-buffer-internal (exclam buffer-name other-window)
  3780.   (or buffer-name
  3781.       (setq buffer-name (buffer-name (other-buffer (current-buffer)))))
  3782.   (let ((found (ex-verify-buffer buffer-name)))
  3783.     (if (or exclam found)
  3784.       (if other-window
  3785.     (switch-to-buffer-other-window buffer-name)
  3786.     (switch-to-buffer buffer-name))
  3787.       (message "Buffer \"%s\" does not exist" buffer-name))
  3788.     (evi)))
  3789.     ; (and exclam (not found)
  3790.  
  3791. (defun ex-verify-buffer (buffer-name)
  3792.   (evi-find buf (buffer-list) (string= (buffer-name buf) buffer-name)))
  3793.  
  3794. (defun evi-expand-file-name (file-name)
  3795.   (let* ((expanded-name (expand-file-name file-name))
  3796.      (len (length expanded-name)))
  3797.     (if (= (aref expanded-name (1- len)) ?/)
  3798.     expanded-name
  3799.       (concat expanded-name "/"))))
  3800.  
  3801. (defun evi-current-directory ()
  3802.   (if evi-global-directory
  3803.       (car evi-directory-stack)
  3804.     default-directory))
  3805.  
  3806. (defun ex-change-directory (directory-name)
  3807.   (let ((expnd-dir-name (evi-expand-file-name (or directory-name "~"))))
  3808.     (if evi-global-directory
  3809.     (setcar evi-directory-stack expnd-dir-name)
  3810.       (setq default-directory expnd-dir-name))))
  3811.  
  3812. (defun ex-push-directory (directory-name)
  3813.   (if directory-name
  3814.       (setq evi-directory-stack
  3815.         (cons (evi-expand-file-name directory-name) evi-directory-stack))
  3816.     (if (null (cdr evi-directory-stack))
  3817.     (evi-error "Only one directory")
  3818.       (setq evi-directory-stack
  3819.         (cons (nth 1 evi-directory-stack)
  3820.           (cons (car evi-directory-stack)
  3821.             (cdr (cdr evi-directory-stack))))))))
  3822.  
  3823. (defun ex-pop-directory ()
  3824.   (if (null (cdr evi-directory-stack))
  3825.     (evi-error "Only one directory left")
  3826.     (setq evi-directory-stack (cdr evi-directory-stack))))
  3827.  
  3828. (defun ex-directory-stack ()
  3829.   (let ((home (getenv "HOME")))
  3830.     (message
  3831.       (mapconcat (function
  3832.            (lambda (f)
  3833.              (let* ((dir (evi-abbreviate-file-name f home "~"))
  3834.                 (end (1- (length dir))))
  3835.                (if (= (aref dir end) ?/)
  3836.              (substring dir 0 end)
  3837.              dir))))
  3838.          evi-directory-stack " "))))
  3839.  
  3840. (defun ex-copy (from-addresses to-address)
  3841.   (ex-define-region from-addresses t nil)
  3842.   (let ((text (buffer-substring evi-mark (point))))
  3843.     (ex-goto-line-after-address to-address)
  3844.     (insert text)))
  3845.  
  3846. (defun ex-delete (addresses register-struct)
  3847.   (let ((evi-register-spec register-struct))
  3848.     (ex-define-region addresses t nil)
  3849.     (evi-copy-region-to-registers t)
  3850.     ; to make undo's come out right
  3851.     (if (< evi-mark (point))
  3852.       (evi-exchange-point-and-mark))
  3853.     (delete-region (point) evi-mark)))
  3854.  
  3855. (defun ex-edit (exclam offset file-name)
  3856.   (ex-edit-internal exclam offset file-name nil))
  3857.  
  3858. (defun ex-edit-other-window (exclam offset file-name)
  3859.   (ex-edit-internal exclam offset file-name t))
  3860.  
  3861. (defun ex-edit-internal (exclam offset file-name other-window)
  3862.   (if (null file-name)
  3863.       (if (and (not exclam) (not other-window) (buffer-modified-p))
  3864.       (message "Buffer modified since last save (use :edit! to override)")
  3865.     (if other-window
  3866.         (split-window-vertically)
  3867.       (if (null (buffer-file-name))
  3868.           (message "Buffer has no file associated with it")
  3869.         (revert-buffer nil t)
  3870.         (evi))))
  3871.     (if other-window
  3872.     (find-file-other-window file-name)
  3873.       (find-file file-name))
  3874.     (evi))
  3875.   (if offset
  3876.       (ex-goto-line (if (= offset -1) nil offset))))
  3877.  
  3878. (defun ex-elisp-execute (lisp-expression)
  3879.   (eval (car (read-from-string lisp-expression))))
  3880.  
  3881. (defun ex-file (file-name)
  3882.   (if file-name
  3883.       (set-visited-file-name file-name)
  3884.     (evi-file-info)))
  3885.  
  3886. (defun ex-global (addresses notmatch pattern command)
  3887.   (let ((case-fold-search evi-ignore-case)
  3888.     (next-line-mark (make-marker))
  3889.     (end-line-mark (make-marker))
  3890.     (start)
  3891.     (none-found t)
  3892.     (end-pos (point))
  3893.     (large-region))
  3894.     (if (= (length pattern) 0)
  3895.     (if ex-previous-re
  3896.         (setq pattern ex-previous-re)
  3897.       (evi-error "No previous regular expression"))
  3898.       (setq ex-previous-re pattern))
  3899.     (ex-define-region addresses t t)
  3900.     (evi-exchange-point-and-mark)
  3901.     (setq large-region (> (- evi-mark (point)) 5000))
  3902.     (if large-region
  3903.       (message "running global command... "))
  3904.     (set-marker end-line-mark evi-mark)
  3905.     (while (< (point) end-line-mark)
  3906.       (setq start (point))
  3907.       (forward-line)
  3908.       (set-marker next-line-mark (point))
  3909.       (goto-char start)
  3910.       (or (eq (re-search-forward pattern next-line-mark t) notmatch)
  3911.       (progn
  3912.         (goto-char start)
  3913.         (setq none-found nil
  3914.           end-pos (point))
  3915.         (eval command)))
  3916.       (goto-char next-line-mark))
  3917.     (if large-region
  3918.       (message "running global command... complete."))
  3919.     (set-marker next-line-mark nil)
  3920.     (set-marker end-line-mark nil)
  3921.     (goto-char end-pos)
  3922.     (if none-found
  3923.     (evi-error "No occurance of pattern found"))))
  3924.  
  3925. (defun ex-vglobal (addresses pattern command)
  3926.   (ex-global addresses t pattern command))
  3927.  
  3928. (defun ex-recurse (fun)
  3929.   (let ((ex-user-buffer (current-buffer)))
  3930.     (set-buffer ex-work-space)
  3931.     (let ((work-string (buffer-string))
  3932.       (work-point (point)))
  3933.       (set-buffer ex-user-buffer)
  3934.       (eval fun)
  3935.       (setq ex-user-buffer (current-buffer))
  3936.       (set-buffer ex-work-space)
  3937.       (erase-buffer)
  3938.       (insert work-string)
  3939.       (goto-char work-point)
  3940.       (set-buffer ex-user-buffer))))
  3941.  
  3942. (defun ex-initialize ()
  3943.   (ex-recurse '(evi-customize)))
  3944.  
  3945. (defun ex-kill-buffer (exclam buffer-name)
  3946.   (ex-kill-buffer-internal exclam buffer-name nil))
  3947.  
  3948. (defun ex-kill-buffer-delete-windows (exclam buffer-name)
  3949.   (ex-kill-buffer-internal exclam buffer-name t))
  3950.  
  3951. (defun ex-kill-buffer-internal (exclam buffer windows-too)
  3952.   (setq buffer (get-buffer (or buffer (current-buffer))))
  3953.   (and (not exclam) (buffer-file-name buffer) (buffer-modified-p buffer)
  3954.        (evi-error
  3955.      "No write since last change (use :kill! to override)"))
  3956.   (set-buffer buffer)
  3957.   (set-buffer-modified-p nil)
  3958.   (delete-auto-save-file-if-necessary)
  3959.   (if windows-too
  3960.       (condition-case nil
  3961.       (delete-windows-on buffer)
  3962.     ;; ignore error about trying to delete only window on only screen
  3963.     (error nil)))
  3964.   (kill-buffer buffer)
  3965.   (setq ex-user-buffer (current-buffer)))
  3966.  
  3967. (defun ex-map (exclam key definition)
  3968.   (let ((map (if exclam evi-input-map-map evi-map-map)))
  3969.     (if key
  3970.     (if definition
  3971.         (if exclam
  3972.         (evi-define-key '(input-map) key definition)
  3973.           (evi-define-key '(map) key definition))
  3974.       (let ((mapping (lookup-key map key)))
  3975.         (if (stringp mapping)
  3976.         (message "%s" (evi-pretty-string mapping))
  3977.           (evi-error "No map for `%s'" key))))
  3978.       (evi-display-list-and-prompt
  3979.     " *Mappings*" (mapcar 'evi-pretty-binding
  3980.                   (evi-keymap-bindings map))))))
  3981.  
  3982. (defun ex-mark (address marker)
  3983.   (save-excursion
  3984.     (ex-goto-address address (point))
  3985.     (aset evi-registers marker (point-marker))))
  3986.  
  3987. (defun ex-move (from-addresses to-address)
  3988.   (ex-define-region from-addresses t nil)
  3989.   (let ((text (buffer-substring evi-mark (point)))
  3990.     (to-mark (copy-marker (save-excursion
  3991.                 (ex-goto-line-after-address to-address)
  3992.                 (point)))))
  3993.     ; to make undo's come out right
  3994.     (if (< evi-mark (point))
  3995.       (evi-exchange-point-and-mark))
  3996.     (delete-region (point) evi-mark)
  3997.     (goto-char to-mark)
  3998.     (insert text)
  3999.     (set-marker to-mark nil)))
  4000.  
  4001. (defun ex-preserve ()
  4002.   (do-auto-save))
  4003.  
  4004. (defun ex-print (addresses)
  4005.   (let ((position (save-excursion
  4006.             (ex-define-region addresses t nil) (point))))
  4007.     (switch-to-buffer-other-window (current-buffer))
  4008.     (goto-char position)
  4009.     (select-window (previous-window))))
  4010.  
  4011. (defun ex-next (exclam files)
  4012.   (ex-next-internal exclam files nil))
  4013.  
  4014. (defun ex-next-other-window (exclam files)
  4015.   (ex-next-internal exclam files t))
  4016.  
  4017. (defun ex-next-internal (exclam files other-window)
  4018.   (if files
  4019.       (let ((next-buffers
  4020.           (mapcar 'find-file-noselect files)))
  4021.     (if next-buffers
  4022.         (progn
  4023.           (if other-window
  4024.           (switch-to-buffer-other-window (car next-buffers))
  4025.         (switch-to-buffer (car next-buffers)))
  4026.           (evi))))
  4027.     (let ((next-buffer (evi-next-file-buffer t)))
  4028.       (if next-buffer
  4029.       (progn (bury-buffer (current-buffer))
  4030.          (if other-window
  4031.              (switch-to-buffer-other-window next-buffer)
  4032.            (switch-to-buffer next-buffer))
  4033.          (evi))
  4034.     (message "All files are displayed")))))
  4035.  
  4036. (defun evi-next-file-buffer (not-in-window)
  4037.   (let ((rest-of-list
  4038.       (evi-enumerate-condition buffer (cdr (buffer-list))
  4039.         (or (and not-in-window (get-buffer-window buffer))
  4040.         (null (buffer-file-name buffer))))))
  4041.     (if rest-of-list
  4042.       (car rest-of-list))))
  4043.  
  4044. (defun ex-put (address register-struct)
  4045.   (ex-goto-line-after-address address)
  4046.   (let ((register (aref evi-registers (car register-struct))))
  4047.     (if register
  4048.       (save-excursion
  4049.     (if (eq (evi-register-shape register) 'rectangle)
  4050.         (progn (newline (length (evi-register-text register)))
  4051.            (backward-char (length (evi-register-text register)))))
  4052.     (if (eq (evi-register-shape register) 'rectangle)
  4053.         (insert-rectangle (evi-register-text register))
  4054.       (insert (evi-register-text register)))
  4055.     (if (eq (evi-register-shape register) 'chars)
  4056.         (insert ?\n)))
  4057.       (if evi-register-spec
  4058.     (message "Nothing in register %c"
  4059.          (evi-register-name (car evi-register-spec)))
  4060.     (message "No text to put")))))
  4061.  
  4062. ;; ZZ should move to a misc section - actually this shouldn't be here: surely
  4063. ;; this is defined somewhere else?
  4064.  
  4065. (defun evi-list-apply (func l)
  4066.   (if l
  4067.     (progn (apply func (car l) nil)
  4068.        (evi-list-apply func (cdr l)))))
  4069.  
  4070. (cond ((eq evi-emacs-version 'emacs19)
  4071.         (defun ex-quit (discard)
  4072.       (if (= (length (frame-list)) 1)
  4073.           (ex-really-quit discard)
  4074.         (delete-frame))))
  4075.       ((eq evi-emacs-version 'lucid19)
  4076.         (defun ex-quit (discard)
  4077.       (if (= (length (screen-list)) 1)
  4078.           (ex-really-quit discard)
  4079.         (delete-screen))))
  4080.       (t
  4081.         (defun ex-quit (discard)
  4082.       (ex-really-quit discard))))
  4083.  
  4084. (defun ex-really-quit (discard)
  4085.   (if discard
  4086.       (progn
  4087.     (evi-list-apply
  4088.      (function (lambda (buf)
  4089.              (if (buffer-file-name buf)
  4090.              (progn (set-buffer buf)
  4091.                 (delete-auto-save-file-if-necessary)))))
  4092.      (buffer-list)))
  4093.     (let ((modified-buffers
  4094.          (evi-filter
  4095.            (function (lambda (buf)
  4096.                (let ((c (aref (buffer-name buf) 0)))
  4097.                  (and (buffer-modified-p buf)
  4098.                   (/= c ? ) (/= c ?*)))))
  4099.            (buffer-list))))
  4100.       (if modified-buffers
  4101.       (if (or (cdr modified-buffers)
  4102.           (not (eq (car modified-buffers) (current-buffer))))
  4103.           (evi-error "Modified buffers exist (use :quit! to override, :Wq to save buffers and quit)")
  4104.         (evi-error "No write since last change (use :quit! to override)")))))
  4105.   (kill-emacs))
  4106.  
  4107. (defun ex-read (address shell-command arg)
  4108.   (ex-goto-line-after-address address)
  4109.   (if shell-command
  4110.       (call-process shell-file-name nil t nil "-c" shell-command)
  4111.     (evi-insert-file arg)))
  4112.  
  4113. ; there's a bug in insert-file-contents that doesn't record an undo save
  4114. ; boundary when it's appropriate (ZZ)
  4115. (defun evi-insert-file (filename)
  4116.   (if (boundp 'buffer-undo-list)
  4117.       (progn
  4118.     ;; the insert will record a save record if appropriate
  4119.     (insert ?@)
  4120.     (delete-region (1- (point)) (point))
  4121.     ;; now just erase the existence of the insert and delete
  4122.     (setq buffer-undo-list (cdr (cdr buffer-undo-list)))))
  4123.   (insert-file-contents filename))
  4124.  
  4125. (defun ex-recover (exclam file-name)
  4126.   (or file-name
  4127.       (if (setq file-name (buffer-file-name))
  4128.       (and (not exclam) (buffer-modified-p)
  4129.            (evi-error
  4130.         "No write since last change (use :recover! to override)"))
  4131.     (evi-error "Buffer has no file associated with it")))
  4132.   (recover-file file-name)
  4133.   (auto-save-mode 1)
  4134.   (message "Auto save mode on")
  4135.   (evi))
  4136.  
  4137. (defun ex-set (settings)
  4138.   (if settings
  4139.       (ex-set-internal settings)
  4140.     (message (mapconcat 'evi-get-option evi-set-options " "))))
  4141.  
  4142. (defun ex-set-internal (settings)
  4143.   (if settings
  4144.     (let* ((setting (car settings))
  4145.        (name (car setting))
  4146.        (value (cdr setting)))
  4147.       (if (string= name "all")
  4148.       (evi-display-list-and-prompt
  4149.         " *Settings*"
  4150.         (mapcar (function (lambda (x) (evi-get-option (car (car x)))))
  4151.             (evi-filter (function (lambda (x) (cdr (cdr x))))
  4152.                 evi-option-list))
  4153.         nil 'half)
  4154.     (if (integerp value)
  4155.         (progn (princ (evi-get-option name))
  4156.            (princ " "))
  4157.       (evi-set-option name value)))
  4158.       (ex-set-internal (cdr settings)))))
  4159.  
  4160. (defun ex-scan-settings ()
  4161.   (skip-chars-forward " \t")
  4162.   (let ((settings nil))
  4163.     (while (looking-at "[A-Za-z-]")
  4164.       (let ((option (let ((start (point)))
  4165.               (skip-chars-forward "A-Za-z-")
  4166.               (buffer-substring start (point)))))
  4167.     (cond ((looking-at "=")
  4168.         (progn (forward-char 1)
  4169.                (setq settings
  4170.              (cons (cons option (ex-scan-quoted nil " \t|\n"))
  4171.                    settings))))
  4172.           ((looking-at "?")
  4173.         (progn (forward-char 1)
  4174.                (setq settings
  4175.              (cons (cons option ??) settings))))
  4176.           (t
  4177.         (setq settings (cons (cons option t) settings)))))
  4178.       (skip-chars-forward " \t"))
  4179.     (if (looking-at "[^|\n]")
  4180.       (evi-error "Invalid setting%s"
  4181.          (if settings (format " after `%s'" (car (car settings))) "")))
  4182.     settings))
  4183.  
  4184. (defun evi-get-option (option)
  4185.   (let* ((option-struct
  4186.        (or (evi-search-option-list evi-option-list option)
  4187.            (if (and (> (length option) 2)
  4188.             (= (aref option 0) ?n) (= (aref option 1) ?o))
  4189.            (evi-search-option-list evi-option-list
  4190.                        (substring option 2)))))
  4191.      (type (nth 1 option-struct)))
  4192.     (if (eq type nil)
  4193.       (evi-error "Invalid option `%s'" option)
  4194.       (let* ((long-name (car option-struct))
  4195.          (value (condition-case code
  4196.             (eval (cdr (cdr option-struct)))
  4197.               (error nil))))
  4198.     (cond
  4199.       ((eq (cdr (cdr option-struct)) nil)
  4200.         (if (or evi-interactive evi-report-unsupported-options)
  4201.         (evi-error "Option `%s' not implemented" long-name)
  4202.           (concat long-name "=<ignored>")))
  4203.       ((eq type 'bool)
  4204.         (if (eq value t) long-name (concat "no" long-name)))
  4205.       ((eq type 'number)
  4206.         (concat long-name "=" (if value (int-to-string value) "<undef>")))
  4207.       ((eq type 'string)
  4208.         (concat long-name "="
  4209.             (if value (evi-pretty-string value) "<undef>")))
  4210.       ((eq type 'char)
  4211.         (concat long-name "="
  4212.             (if value (evi-pretty-char value) "<undef>")))
  4213.       (t
  4214.         (evi-error "Internal Error: Invalid type `%s'"
  4215.                (prin1-to-string type))))))))
  4216.  
  4217. (defun evi-set-option (option value)
  4218.   (let* ((option-struct
  4219.        (or (evi-search-option-list evi-option-list option)
  4220.            (if (and (> (length option) 2)
  4221.             (= (aref option 0) ?n) (= (aref option 1) ?o))
  4222.            (prog1
  4223.                (evi-search-option-list evi-option-list
  4224.                            (substring option 2))
  4225.              (setq value nil)))))
  4226.      (type (nth 1 option-struct)))
  4227.     (cond
  4228.       ((eq type nil)
  4229.         (evi-warning "Invalid option `%s'" option))
  4230.       ((eq (cdr (cdr option-struct)) nil)
  4231.     (if (or evi-interactive evi-report-unsupported-options)
  4232.         (evi-warning "Option `%s' not implemented" (car option-struct))))
  4233.       ((eq type 'bool)
  4234.         (if (stringp value)
  4235.         (progn
  4236.           (evi-warning "Only %s or no%s allowed" option option)
  4237.           (setq option-struct nil))))
  4238.       ((eq type 'number)
  4239.         (if (stringp value)
  4240.         (setq value (string-to-int value))
  4241.       (evi-warning "Use %s=<number> to set, or %s? to query" option option)
  4242.       (setq option-struct nil)))
  4243.       ((eq type 'string)
  4244.         (or (stringp value)
  4245.         (progn
  4246.           (evi-warning
  4247.         "Use %s=<string> to set, or %s? to query" option option)
  4248.           (set option-struct nil))))
  4249.       ((eq type 'char)
  4250.         (if (stringp value)
  4251.         (if (= (length value) 1)
  4252.         (setq value (aref value 0))
  4253.           (evi-warning 
  4254.         "Only single character can be assigned to `%s'" option)
  4255.           (setq option-struct nil))
  4256.       (evi-warning
  4257.         "Use %s=<character> to set, or %s? to query" option option)
  4258.       (setq option-struct nil)))
  4259.       (t
  4260.     (evi-error "Internal Error: Invalid type `%s'"
  4261.            (prin1-to-string type))))
  4262.     (if (cdr (cdr option-struct))
  4263.     (progn (set (cdr (cdr option-struct)) value)
  4264.            (or (evi-find opt evi-set-options (equal opt option))
  4265.            (if evi-set-options
  4266.                (nconc evi-set-options (list option))
  4267.              (setq evi-set-options (list option))))))
  4268.     (if (fboundp (cdr (cdr option-struct)))
  4269.     (funcall (cdr (cdr option-struct)) value))))
  4270.  
  4271. (defun evi-search-option-list (option-list option)
  4272.   (evi-find option-struct option-list
  4273.         (let ((option-strings (car option-struct)))
  4274.           (if (evi-string-list-match option-strings option)
  4275.           (cons (car option-strings) (cdr option-struct))))))
  4276.  
  4277. (defun evi-string-list-match (string-list string)
  4278.   (if string-list
  4279.     (if (string= string (car string-list))
  4280.     t
  4281.     (evi-string-list-match (cdr string-list) string))))
  4282.  
  4283. (defvar evi-shell-mode-hook nil)
  4284.  
  4285. (defun evi-shell-mode-setup ()
  4286.   (run-hooks 'evi-shell-mode-hook)
  4287.   (or evi-insert-mode-local-bindings
  4288.       (set (make-local-variable 'evi-insert-mode-local-bindings) t))
  4289.   (evi)
  4290.   (setq evi-buffer-local-vi-map evi-shell-map))
  4291.  
  4292. (defun ex-shell ()
  4293.   (let ((evi-shell-mode-hook
  4294.      (if (boundp 'shell-mode-hook) shell-mode-hook nil))
  4295.     (shell-mode-hook 'evi-shell-mode-setup))
  4296.     (shell)
  4297.     (evi-insert)))
  4298.  
  4299. (defun ex-gdb (program-name)
  4300.   (let ((evi-shell-mode-hook
  4301.      (if (boundp 'gdb-mode-hook) gdb-mode-hook nil))
  4302.     (gdb-mode-hook 'evi-shell-mode-setup))
  4303.     (gdb program-name)
  4304.     (evi-insert)))
  4305.  
  4306. (defun ex-source-file (file-name)
  4307.   (if (file-exists-p file-name)
  4308.       (if (file-readable-p file-name)
  4309.       (ex-recurse (list 'evi-do-ex-command-file file-name))
  4310.     (evi-warning "Unable to read file `%s'" file-name))
  4311.     (evi-warning "No such file or directory: %s" file-name)))
  4312.  
  4313. (defun ex-substitute (addresses pattern replacement global query)
  4314.   (let ((case-fold-search evi-ignore-case)
  4315.     (end-line-mark (make-marker))
  4316.     (none-found t)
  4317.     (end-pos (point))
  4318.     (large-region))
  4319.     (ex-define-region addresses t nil)
  4320.     (if pattern
  4321.     (if (= (length pattern) 0)
  4322.         (if ex-previous-re
  4323.         (setq pattern ex-previous-re)
  4324.           (evi-error "No previous regular expression"))
  4325.       (setq ex-previous-re pattern))
  4326.       (if ex-previous-replacement
  4327.       (setq pattern ex-previous-re
  4328.         replacement ex-previous-replacement)
  4329.     (evi-error "No previous substitution")))
  4330.     (or replacement
  4331.     (setq replacement ""))
  4332.     (setq ex-previous-replacement replacement)
  4333.     ; there are problems with global subst'ing just the beginning or end of a
  4334.     ; line, but in those cases you can only match one per line anyway, so
  4335.     ; demote to a non-global search
  4336.     (if (or (= (aref pattern 0) ?^)
  4337.         (= (aref pattern 0) ?$))
  4338.     (setq global nil))
  4339.     (evi-exchange-point-and-mark)
  4340.     (setq large-region (> (- evi-mark (point)) 5000))
  4341.     (if large-region
  4342.       (message "running substitute command... "))
  4343.     (set-marker end-line-mark evi-mark)
  4344.     (while (and (< (point) end-line-mark)
  4345.         (re-search-forward pattern end-line-mark t))
  4346.       (goto-char (match-beginning 0))
  4347.       (setq none-found nil
  4348.         end-pos (point))
  4349.       (ex-replace-match query replacement)
  4350.       (or global
  4351.       (forward-line)))
  4352.     (if large-region
  4353.       (message "running substitute command... complete."))
  4354.     (set-marker end-line-mark nil)
  4355.     (goto-char end-pos)
  4356.     (if none-found
  4357.     (evi-error "No occurance of pattern `%s' found" pattern))))
  4358.  
  4359. (defun ex-substitute-again (addresses)
  4360.   (ex-substitute addresses "" "" nil nil))
  4361.  
  4362. (defun evi-hilight-region (start end)
  4363.   (let ((here (point))
  4364.     (flag nil)
  4365.     (going t))
  4366.     (goto-char start)
  4367.     (while going
  4368.       (if (not (sit-for 1))
  4369.       (setq going nil)
  4370.     (goto-char (if flag start end))
  4371.     (setq flag (not flag))))
  4372.     (goto-char here)))
  4373.  
  4374. (defun ex-replace-match (query replacement)
  4375.   (if (or (not query)
  4376.       (let ((beginning (match-beginning 0))
  4377.         (end (match-end 0))
  4378.         (answer nil))
  4379.         (while (not answer)
  4380.           (message "replace? (y or n)")
  4381.           (evi-hilight-region beginning (1- end))
  4382.           (setq answer (evi-read-char))
  4383.           ;; ZZ - a bit hardcoded
  4384.           (if (= answer ?\C-c)
  4385.           (keyboard-quit))
  4386.           (if (and (/= answer ?y) (/= answer ?n)
  4387.                (/= answer ?Y) (/= answer ?N))
  4388.           (progn (beep)
  4389.              (setq answer nil))))
  4390.         (or (= answer ?y) (= answer ?Y))))
  4391.       ; need to worry about `magic' here?
  4392.       (replace-match replacement t nil)
  4393.     (goto-char (match-end 0))))
  4394.  
  4395.  
  4396. (defun ex-tag (tag)
  4397.   (if tag
  4398.       (setq ex-tag tag)
  4399.     (or ex-tag
  4400.     (evi-error "No previous tag specified")))
  4401.   (find-tag ex-tag)
  4402.   (evi))
  4403.  
  4404. (defun ex-unabbrev (abbrev)
  4405.   (let ((alist evi-abbrev-list)
  4406.     (alist2 nil))
  4407.     (while alist
  4408.       (if (string= abbrev (car (car alist)))
  4409.       (progn
  4410.         (if alist2
  4411.         (setcdr alist2 (cdr alist))
  4412.           (setq evi-abbrev-list (cdr alist)))
  4413.         (setq alist nil))
  4414.     (setq alist2 alist alist (cdr alist))))))
  4415.  
  4416. (defun ex-unmap (exclam key)
  4417.   (if exclam
  4418.     (evi-define-key '(input-map) key nil)
  4419.     (evi-define-key '(map) key nil)))
  4420.  
  4421. (defun ex-evi-version ()
  4422.   (message evi-version))
  4423.  
  4424. (defun ex-write (addresses exclam append file-arg)
  4425.   (let ((file-name (or file-arg (buffer-file-name))))
  4426.     (if (or exclam file-arg (not evi-buffer-read-only))
  4427.     (save-excursion
  4428.       (ex-define-region addresses t t)
  4429.       (if (and (null file-arg)
  4430.            (= evi-mark (point-min)) (= (point) (point-max)))
  4431.           (progn
  4432.         ; force a write, even if not modified
  4433.         (set-buffer-modified-p t)
  4434.         (basic-save-buffer))
  4435.         (write-region evi-mark (point) file-name append)))
  4436.       (evi-error "File read-only (use :write! to attempt override)"))))
  4437.  
  4438. (defun ex-write-all-buffers (quietly)
  4439.   (save-some-buffers quietly))
  4440.  
  4441. (defun ex-write-kill ()
  4442.   (set-buffer-modified-p t)
  4443.   (basic-save-buffer)
  4444.   (ex-kill-buffer nil nil))
  4445.  
  4446. (defun ex-write-quit (discard)
  4447.   (set-buffer-modified-p t)
  4448.   (basic-save-buffer)
  4449.   (ex-quit discard))
  4450.  
  4451. (defun ex-write-all-and-quit (quietly)
  4452.   (save-some-buffers quietly t)
  4453.   (ex-quit t))
  4454.  
  4455. (defun ex-yank (addresses register-struct)
  4456.   (let ((evi-register-spec register-struct))
  4457.     (save-excursion
  4458.       (ex-define-region addresses t nil)
  4459.       (evi-copy-region-to-registers nil))))
  4460.  
  4461. (defun ex-shell-command (addresses background shell-command)
  4462.   (if (string= shell-command "!")
  4463.       (setq shell-command
  4464.     (or evi-last-shell-command
  4465.         (evi-error "No previous shell command to substitute for !")))
  4466.     (setq evi-last-shell-command shell-command))
  4467.   (if background
  4468.       (progn
  4469.     (switch-to-buffer-other-window
  4470.       (get-buffer-create "*Shell Command Output*"))
  4471.     (evi)
  4472.     (erase-buffer)
  4473.     (start-process (concat "\"" shell-command "\"")
  4474.                "*Shell Command Output*" "sh" "-c" shell-command)
  4475.     (select-window (previous-window)))
  4476.     (if (null (car (car (car addresses))))
  4477.     (progn
  4478.       (save-excursion
  4479.         (set-buffer (get-buffer-create "*Shell Command Output*"))
  4480.         (evi))
  4481.       (evi-display-and-prompt
  4482.         (function
  4483.           (lambda (cmd)
  4484.         (shell-command cmd)
  4485.         (if (eq evi-emacs-version 'emacs19)
  4486.             (and (get-buffer "*Shell Command Output*")
  4487.              (save-excursion
  4488.                (set-buffer "*Shell Command Output*")
  4489.                (> (count-lines (point-min) (point-max)) 1)))
  4490.           t)))
  4491.        (list shell-command)))
  4492.       (progn (ex-define-region addresses t nil)
  4493.          (shell-command-on-region evi-mark (point) shell-command t)))))
  4494.  
  4495. (defun ex-shift-right (addresses)
  4496.   (ex-define-region addresses t nil)
  4497.   (indent-rigidly evi-mark (point) evi-shift-width)
  4498.   (forward-line -1)
  4499.   (skip-chars-forward " \t"))
  4500.  
  4501. (defun ex-shift-left (addresses)
  4502.   (ex-define-region addresses t nil)
  4503.   (indent-rigidly evi-mark (point) (- evi-shift-width))
  4504.   (forward-line -1)
  4505.   (skip-chars-forward " \t"))
  4506.  
  4507. (defun ex-null (addresses)
  4508.   (ex-define-region addresses t nil)
  4509.   (forward-line -1))
  4510.  
  4511. (defvar evi-evi-list "evi-list@brandx.rain.com"
  4512.   "Address of site maintaining mailing list for Evi.")
  4513.  
  4514. (defvar evi-bug-address "jlewis@cse.ogi.edu"
  4515.   "Address of who maintains evi.")
  4516.  
  4517. (defun ex-mail (to)
  4518.   (mail nil to)
  4519.   (evi)
  4520.   (message "Type `:send' to send message.  Type `:kill' to abort.")
  4521.   (evi-insert))
  4522.  
  4523. (defun ex-mail-list (subject)
  4524.   (mail nil evi-evi-list subject)
  4525.   (evi)
  4526.   (goto-char (point-max))
  4527.   (insert "Using " evi-version " (" (emacs-version) ").\n\n")
  4528.   (message "Type `:send' to send message.  Type `:kill' to abort.")
  4529.   (evi-insert))
  4530.  
  4531. (defun ex-elisp-bind (input key definition)
  4532.   (funcall 'evi-define-key (if input '(insert replace ex) '(vi))
  4533.                key (car (read-from-string definition))))
  4534.  
  4535. (defun ex-report-bug (subject)
  4536.   (mail nil evi-bug-address subject)
  4537.   (evi)
  4538.   (goto-char (point-max))
  4539.   (insert "In " evi-version " (" (emacs-version) ")\n\n")
  4540.   (message "Type `:send' to send bug report.  Type `:kill' to abort.")
  4541.   (evi-insert))
  4542.  
  4543. (defun ex-send-mail (exclam)
  4544.   (mail-send)
  4545.   (if exclam
  4546.       (ex-kill-buffer t nil)))
  4547.  
  4548. (provide 'evi)
  4549.