Let vimpulse-setq-* accept multiple sym-val pairs.
[vimpulse:vimpulse.git] / vimpulse-dependencies.el
1 ;;; Code:
2
3 (defconst vimpulse-version "0.4+git"
4   "The current version of Vimpulse")
5
6 (defun vimpulse-version ()
7   (interactive)
8   (message "Vimpulse version is %s" vimpulse-version))
9
10 ;; Load Viper
11 (defvar viper-mode t)
12 (defvar viper-inhibit-startup-message t)
13 (defvar viper-expert-level 5)
14 (defvar viper-want-ctl-h-help t)
15 (require 'viper)
16
17 ;; Load undo-tree.el if available, with redo.el as fall-back
18 (unless (featurep 'undo-tree)
19   (condition-case nil
20       (require 'undo-tree)
21     (error (condition-case nil
22                (require 'redo)
23              (error nil)))))
24 (and (fboundp 'global-undo-tree-mode)
25      (global-undo-tree-mode 1))
26
27 ;;; Customization group for Vimpulse
28
29 (defgroup vimpulse nil
30   "Vim emulation within Emacs."
31   :group  'emulations
32   :link   '(custom-group-link "viper")
33   :prefix 'vimpulse-)
34
35 (defcustom vimpulse-experimental t
36   "Whether or not to use experimental features.
37 Turned on by default, so you will give feedback :P"
38   :group 'vimpulse
39   :type  'boolean)
40
41 (defcustom vimpulse-want-change-state nil
42   "Whether commands like \"cw\" invoke Replace state, vi-like.
43 The default is to delete the text and enter Insert state,
44 like in Vim."
45   :group 'vimpulse
46   :type  'boolean)
47
48 (defcustom vimpulse-want-C-u-like-Vim nil
49   "Whether C-u scrolls like in Vim, off by default."
50   :group 'vimpulse
51   :type  'boolean)
52
53 (defcustom vimpulse-enhanced-paren-matching t
54   "Enhanced matching of parentheses, on by default."
55   :group 'vimpulse
56   :type  'boolean)
57
58 (defcustom vimpulse-want-operator-pending-cursor t
59   "Whether the cursor changes in Operator-Pending mode, on by default."
60   :group 'vimpulse
61   :type  'boolean)
62
63 (defcustom vimpulse-visual-block-untabify nil
64   "Whether Block mode may change tabs to spaces for fine movement.
65 Off by default."
66   :type  'boolean
67   :group 'vimpulse-visual)
68
69 (defcustom vimpulse-incremental-search t
70   "Use isearch for / and ?, on by default.")
71
72 (defcustom vimpulse-flash-delay 2
73   "Number of seconds to flash search matches.")
74
75 (defvar vimpulse-flash-timer nil
76   "Timer for flashing search results.")
77
78 (defcustom vimpulse-want-vi-keys-in-apropos t
79   "Whether to use vi keys in Apropos mode, on by default."
80   :group 'vimpulse
81   :type  'boolean)
82
83 (defcustom vimpulse-want-vi-keys-in-buffmenu t
84   "Whether to use vi keys in Buffer menu, on by default."
85   :group 'vimpulse
86   :type  'boolean)
87
88 (defcustom vimpulse-want-vi-keys-in-dired t
89   "Whether to use vi keys in Dired mode, on by default."
90   :group 'vimpulse
91   :type  'boolean)
92
93 (defcustom vimpulse-want-vi-keys-in-Info t
94   "Whether to use vi keys in Info mode, on by default."
95   :group 'vimpulse
96   :type  'boolean)
97
98 (defcustom vimpulse-want-vi-keys-in-help t
99   "Whether to use vi keys in Help mode, on by default."
100   :group 'vimpulse
101   :type  'boolean)
102
103 (defcustom vimpulse-fold-level 0
104   "Default fold level."
105   :type  'boolean
106   :group 'vimpulse)
107
108 ;; The secrets discovered from untold diggings among
109 ;; the ruins of Customize code
110 (defun vimpulse-custom-value-p (symbol)
111   "Non-nil if SYMBOL has a customized value."
112   (or (get symbol 'customized-value)
113       (get symbol 'customized-face)
114       (get symbol 'saved-value)))
115
116 (defmacro vimpulse-setq-custom (sym val &rest body)
117   "Set the customized value of SYM to VAL."
118   `(progn
119      (prog1 (setq ,sym ,val)            ; return VAL
120        (when (get ',sym 'custom-autoload)
121          (custom-load-symbol ',sym))
122        (put ',sym 'customized-value (list (custom-quote ,val))))
123      ,@(when body
124          `((vimpulse-setq-custom ,@body)))))
125
126 (defmacro vimpulse-setq-custom-default (symbol value &rest body)
127   "Set the customized default value of SYMBOL to VALUE."
128   `(progn
129      (prog1 ,value                       ; return VALUE
130        (when (get ',symbol 'custom-autoload)
131          (custom-load-symbol ',symbol))
132        (put ',symbol 'standard-value (list (custom-quote ,value))))
133      ,@(when body
134          `((vimpulse-setq-custom-default ,@body)))))
135
136 (defmacro vimpulse-setq (sym val &rest body)
137   "Set SYM to VAL, defaults included, unless SYM is customized.
138 SYM is unquoted. Returns VAL."
139   `(progn
140      (cond
141       ;; Customized value: just set custom standard value
142       ((vimpulse-custom-value-p ',sym)
143        (vimpulse-setq-custom-default ,sym ,val))
144       ;; Customized variable: set custom and regular values
145       ((custom-variable-p ',sym)
146        (vimpulse-setq-custom-default ,sym ,val)
147        (vimpulse-setq-custom ,sym ,val)
148        (setq-default ,sym ,val)
149        (setq ,sym ,val))
150       ;; Regular variable; set default and local values
151       (t
152        (setq-default ,sym ,val)
153        (setq ,sym ,val)))
154      ,@(when body
155          `((vimpulse-setq ,@body)))))
156
157 ;;; Initialize variables
158
159 (defvar dabbrev--last-abbrev-location)
160 (defvar dabbrev--last-abbreviation)
161 (defvar dabbrev--last-direction)
162 (defvar dabbrev--last-expansion)
163 (defvar isearch-forward)
164 (defvar isearch-lazy-highlight-end)
165 (defvar isearch-lazy-highlight-last-string)
166 (defvar isearch-lazy-highlight-start)
167 (defvar isearch-lazy-highlight-wrapped)
168 (defvar isearch-regexp)
169 (defvar isearch-string)
170 (defvar killed-rectangle nil)
171 (defvar show-paren-delay)
172 (defvar undo-tree-visualizer-map)
173 (defvar woman-use-own-frame)
174 (defvar woman-use-topic-at-point)
175
176 (defvar ex-token-alist)
177 (defvar viper-mode-string)
178
179 (defvar vimpulse-viper-movement-cmds
180   '(viper-backward-Word viper-backward-char viper-backward-paragraph
181     viper-backward-sentence viper-backward-word
182     viper-beginning-of-line viper-command-argument
183     viper-digit-argument viper-end-of-Word viper-end-of-word
184     viper-exec-mapped-kbd-macro viper-find-char-backward
185     viper-find-char-forward viper-forward-Word viper-forward-char
186     viper-forward-paragraph viper-forward-sentence viper-forward-word
187     viper-goto-char-backward viper-goto-char-forward viper-goto-eol
188     viper-goto-line viper-line-to-bottom viper-line-to-middle
189     viper-line-to-top viper-next-line viper-previous-line
190     viper-scroll-down-one viper-scroll-down viper-scroll-up
191     viper-scroll-up-one viper-window-bottom viper-window-middle
192     viper-window-top vimpulse-end-of-previous-word
193     vimpulse-goto-first-line vimpulse-goto-definition
194     vimpulse-goto-line vimpulse-search-backward-for-symbol-at-point
195     vimpulse-search-forward-for-symbol-at-point vimpulse-jump-backward
196     vimpulse-jump-forward vimpulse-visual-toggle-normal
197     vimpulse-visual-toggle-line vimpulse-visual-toggle-block)
198   "List of Viper/Vimpulse movement commands.")
199
200 (defvar vimpulse-core-movement-cmds
201   '(viper-backward-char
202     viper-next-line
203     viper-previous-line
204     viper-forward-char
205     viper-intercept-ESC-key
206     viper-ex)
207   "List of Viper \"core\" movement commands.
208 These should be present in every mode, to avoid confusion.")
209
210 (viper-deflocalvar vimpulse-mark-list nil
211   "List of mark positions to jump to with `vimpulse-jump-forward'.
212  They are stored as markers, the current position first:
213
214      (car vimpulse-mark-list)  = current position (last popped)
215      (cdr vimpulse-mark-list)  = future positions (previously popped)
216      (cadr vimpulse-mark-list) = next position (to jump to)
217
218  In other words, a sort of \"reverse mark ring\": marks which are
219  popped off the mark ring, are collected here.")
220
221 (viper-deflocalvar vimpulse-replace-alist nil
222   "Alist of characters overwritten in Replace mode.
223  Used by `vimpulse-replace-backspace' to restore text.
224  The format is (POS . CHAR).")
225
226 (viper-deflocalvar vimpulse-exit-point nil
227   "Like `viper-insert-point', but when exiting Insert mode.")
228
229 (defvar vimpulse-last-command-event nil
230   "Value for overwriting `last-command-event'.
231 Used by `vimpulse-modal-pre-hook'.")
232
233 (defvar vimpulse-modal-alist nil
234   "Key bindings for which `vimpulse-modal-pre-hook' is active.
235 That is, `last-command-event' and `read-char' work differently
236 for these bindings. The format is (KEY-VECTOR . COMMAND).")
237
238 (defvar vimpulse-modal-map (make-sparse-keymap)
239   "Keymap of bindings overwritten by `vimpulse-map' et al.")
240
241 (defvar vimpulse-paren-overlay-open nil
242   "Overlay used to highlight the opening paren.")
243
244 (defvar vimpulse-paren-overlay-close nil
245   "Overlay used to highlight the closing paren.")
246
247 (defvar vimpulse-operator-basic-map)
248
249 (defvar vimpulse-operator-remap-map (make-sparse-keymap))
250
251 (defvar vimpulse-operator-remap-alist nil
252   "Association list of command remappings in Operator-Pending mode.")
253
254 (defvar vimpulse-this-operator nil
255   "Current operator.
256 In general, motions and operators are orthogonal, with some exceptions:
257 \"cw\" and \"dw\" work on slightly different ranges, for example.
258 Motions can check this variable if they need to know what
259 operator receives their range. See also `vimpulse-this-motion'.")
260
261 (defvar vimpulse-this-motion nil
262   "Current motion.
263 In general, motions and operators are orthogonal, with some exceptions:
264 \"cc\" may indent the current line while \"cw\" may not, for example.
265 Operators may check this variable if they need to know what
266 motion produced the current range. See also `vimpulse-this-operator'.")
267
268 (defvar vimpulse-this-count nil
269   "Current count (operator count times motion count).")
270
271 (defvar vimpulse-this-motion-type nil
272   "Current motion type.
273 May be `block', `line', `inclusive', `exclusive' or nil.")
274
275 (defvar vimpulse-last-motion-type nil
276   "Last repeated range type.
277 May be `block', `line', `inclusive', `exclusive' or nil.")
278
279 (defvar vimpulse-last-operator nil
280   "Last repeated operator.
281 Used by `vimpulse-operator-repeat'.")
282
283 (defvar vimpulse-last-motion nil
284   "Last repeated motion.
285 Used by `vimpulse-operator-repeat'.")
286
287 (defvar vimpulse-visual-basic-map)
288
289 (defvar vimpulse-visual-remap-alist nil
290   "Association list of command remappings in Visual mode.")
291
292 (put 'vimpulse-visual-basic-map
293      'remap-alist 'vimpulse-visual-remap-alist)
294
295 (viper-deflocalvar vimpulse-visual-mode nil
296   "Current Visual mode: may be nil, `normal', `line' or `block'.")
297
298 (viper-deflocalvar vimpulse-visual-global-vars nil
299   "List of variables which were global.")
300
301 (viper-deflocalvar vimpulse-visual-local-vars
302   '(cua-mode
303     mark-active
304     transient-mark-mode
305     zmacs-regions
306     vimpulse-visual-region-expanded)
307   "System variables which are reset for each Visual session.")
308
309 (viper-deflocalvar vimpulse-visual-vars-alist nil
310   "Alist of old variable values.")
311
312 (viper-deflocalvar vimpulse-visual-last nil
313   "Last active Visual mode.
314 May be `normal', `line', `block' or nil.")
315
316 (viper-deflocalvar vimpulse-visual-previous-state 'viper-state
317   "Previous state before enabling Visual mode.
318 This lets us revert to Emacs state in non-vi buffers.")
319
320 (viper-deflocalvar vimpulse-visual-region-expanded nil
321   "Whether region is expanded to the Visual selection.")
322
323 (viper-deflocalvar vimpulse-visual-point nil
324   "Last expanded `point' in Visual mode.")
325
326 (viper-deflocalvar vimpulse-visual-mark nil
327   "Last expanded `mark' in Visual mode.")
328
329 (viper-deflocalvar vimpulse-visual-overlay nil
330   "Overlay for Visual selection.
331 In XEmacs, this is an extent.")
332
333 (viper-deflocalvar vimpulse-visual-block-overlays nil
334   "Overlays for Visual Block selection.")
335
336 (viper-deflocalvar vimpulse-visual-whitespace-overlay nil
337   "Overlay encompassing text inserted into the buffer
338 to make Block selection at least one column wide.")
339
340 (viper-deflocalvar vimpulse-undo-needs-adjust nil
341   "If true, several commands in the undo-list should be connected.")
342
343 (defconst vimpulse-buffer-undo-list-mark 'vimpulse
344   "Everything up to this mark is united in the undo-list.")
345
346 (defvar vimpulse-visual-height nil
347   "Height of last Visual selection.")
348
349 (defvar vimpulse-visual-width nil
350   "Width of last Visual selection.")
351
352 (defvar vimpulse-visual-insert-coords nil
353   "List with (I-COM UL-POS COL NLINES), where
354 I-COM is the insert command (?i, ?a, ?I or ?A),
355 UL-POS is the position of the upper left corner of the region,
356 COL is the column of insertion, and
357 NLINES is the number of lines in the region.")
358
359 (defvar vimpulse-movement-cmds
360   '(backward-char backward-list backward-paragraph backward-sentence
361     backward-sexp backward-up-list backward-word beginning-of-buffer
362     beginning-of-defun beginning-of-line beginning-of-visual-line
363     cua-cancel digit-argument down-list end-of-buffer end-of-defun
364     end-of-line end-of-visual-line exchange-point-and-mark
365     forward-char forward-list forward-paragraph forward-sentence
366     forward-sexp forward-word keyboard-quit mouse-drag-region
367     mouse-save-then-kill mouse-set-point mouse-set-region
368     move-beginning-of-line move-end-of-line next-line previous-line
369     scroll-down scroll-up undo universal-argument up-list
370     vimpulse-end-of-previous-word vimpulse-goto-definition
371     vimpulse-goto-first-line vimpulse-goto-line
372     vimpulse-visual-block-rotate vimpulse-visual-exchange-corners
373     vimpulse-visual-reselect vimpulse-visual-restore
374     vimpulse-visual-toggle-block vimpulse-visual-toggle-line
375     vimpulse-visual-toggle-normal viper-backward-Word
376     viper-backward-char viper-backward-paragraph
377     viper-backward-sentence viper-backward-word
378     viper-beginning-of-line viper-digit-argument viper-end-of-Word
379     viper-end-of-word viper-exec-mapped-kbd-macro
380     viper-find-char-backward viper-find-char-forward
381     viper-forward-Word viper-forward-char viper-forward-paragraph
382     viper-forward-sentence viper-forward-word viper-goto-char-backward
383     viper-goto-char-forward viper-goto-eol viper-goto-line
384     viper-insert viper-intercept-ESC-key viper-line-to-bottom
385     viper-line-to-middle viper-line-to-top viper-next-line
386     viper-paren-match viper-previous-line viper-search-Next
387     viper-search-backward viper-search-forward viper-search-next
388     viper-window-bottom viper-window-middle viper-window-top)
389   "List of commands that move point.
390 If listed here, the region is not expanded to the
391 Visual selection before the command is executed.")
392
393 (defvar vimpulse-newline-cmds
394   '(cua-copy-region cua-cut-region cua-delete-region delete-region
395     exchange-point-and-mark execute-extended-command kill-region
396     kill-ring-save vimpulse-Put-and-indent vimpulse-put-and-indent
397     vimpulse-visual-exchange-corners viper-Put-back viper-put-back)
398   "Non-operator commands needing trailing newline in Visual Line mode.
399 In most cases, it's more useful not to include this newline in
400 the region acted on.")
401
402 (defvar vimpulse-search-prompt nil
403   "String to use for vi-like searching.")
404
405 ;;; Carefully set Viper/woman variables
406
407 (defun vimpulse-configure-variables ()
408   "Set various variables, unless customized."
409   ;; Can backspace past start of insert/line
410   (vimpulse-setq viper-ex-style-editing nil)
411   ;; Don't create new frame for manpages
412   (vimpulse-setq woman-use-own-frame nil)
413   ;; Don't prompt upon K key (manpage display)
414   (vimpulse-setq woman-use-topic-at-point t)
415   ;; No start-up message
416   (vimpulse-setq viper-inhibit-startup-message t)
417   ;; Viper expert level 5
418   (vimpulse-setq viper-expert-level 5)
419   ;; Make cursor color consistent
420   (vimpulse-setq viper-insert-state-cursor-color
421                  viper-vi-state-cursor-color)
422   ;; Cursor moves backwards when exiting Insert state
423   (vimpulse-setq viper-ESC-moves-cursor-back t)
424   ;; Not in Vim: C-h is indispensable in Emacs
425   (vimpulse-setq viper-want-ctl-h-help t)
426   ;; Refresh Viper settings
427   (viper-change-state-to-vi))
428
429 (if (and (boundp 'after-init-time) after-init-time)
430     (vimpulse-configure-variables)
431   (add-hook 'after-init-hook 'vimpulse-configure-variables))
432
433 (provide 'vimpulse-dependencies)