avoid recursive `require' when loading semantic
[bpt/emacs.git] / lisp / avoid.el
CommitLineData
be010748 1;;; avoid.el --- make mouse pointer stay out of the way of editing
bb5d4e1a 2
ba318903 3;; Copyright (C) 1993-1994, 2000-2014 Free Software Foundation, Inc.
bb5d4e1a 4
5762abec 5;; Author: Boris Goldowsky <boris@gnu.org>
bb5d4e1a 6;; Keywords: mouse
bb5d4e1a
RS
7
8;; This file is part of GNU Emacs.
9
eb3fa2cf 10;; GNU Emacs is free software: you can redistribute it and/or modify
bb5d4e1a 11;; it under the terms of the GNU General Public License as published by
eb3fa2cf
GM
12;; the Free Software Foundation, either version 3 of the License, or
13;; (at your option) any later version.
bb5d4e1a
RS
14
15;; GNU Emacs is distributed in the hope that it will be useful,
16;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18;; GNU General Public License for more details.
19
20;; You should have received a copy of the GNU General Public License
eb3fa2cf 21;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
bb5d4e1a
RS
22
23;;; Commentary:
bb5d4e1a 24
b578f267
EN
25;; For those who are annoyed by the mouse pointer obscuring text,
26;; this mode moves the mouse pointer - either just a little out of
187bd11c 27;; the way, or all the way to the corner of the frame.
b578f267 28;; To use, load or evaluate this file and type M-x mouse-avoidance-mode .
187bd11c 29;; To set up permanently, put the following in your .emacs:
b578f267 30;;
95d059bd 31;; (if (display-mouse-p) (mouse-avoidance-mode 'animate))
b578f267 32;;
8557ea06
RS
33;; Other legitimate alternatives include
34;; `banish', `exile', `jump', `cat-and-mouse', and `proteus'.
35;; They do somewhat different things.
b578f267
EN
36;; See the documentation for function `mouse-avoidance-mode' for
37;; details of the different modes.
38;;
39;; For added silliness, make the animatee animate...
40;; put something similar to the following into your .emacs:
41;;
95d059bd 42;; (if (eq window-system 'x)
b578f267 43;; (mouse-avoidance-set-pointer-shape
40f7e0e8
SM
44;; (nth (random 4)
45;; (list x-pointer-man x-pointer-spider
46;; x-pointer-gobbler x-pointer-gumby))))
b578f267
EN
47;;
48;; For completely random pointer shape, replace the setq above with:
49;; (setq x-pointer-shape (mouse-avoidance-random-shape))
187bd11c 50;;
b578f267
EN
51;; Bugs / Warnings / To-Do:
52;;
88b4ca18 53;; - Using this code does slow Emacs down. "banish" mode shouldn't
b578f267 54;; be too bad, and on my workstation even "animate" is reasonable.
b578f267
EN
55
56;; Credits:
187bd11c 57;; This code was helped by all those who contributed suggestions,
b578f267
EN
58;; fixes, and additions
59;; Joe Harrington (and his advisor), for the original inspiration.
60;; Ken Manheimer, for dreaming up the Protean mode.
61;; Richard Stallman, for the awful cat-and-mouse pun, among other things.
62;; Mike Williams, Denis Howe, Bill Benedetto, Chris Moore, Don Morris,
63;; Simon Marshall, and M.S. Ashton, for their feedback.
64
bb5d4e1a
RS
65;;; Code:
66
f58e0fd5 67(eval-when-compile (require 'cl-lib))
bb5d4e1a 68
00ed33e7
RS
69(defgroup avoid nil
70 "Make mouse pointer stay out of the way of editing."
71 :prefix "mouse-avoidance-"
72 :group 'mouse)
73
4bce8c17 74;;;###autoload
8557ea06 75(defcustom mouse-avoidance-mode nil
ad22b7f7 76 "Activate Mouse Avoidance mode.
8557ea06 77See function `mouse-avoidance-mode' for possible values.
970ce0d8
DL
78Setting this variable directly does not take effect;
79use either \\[customize] or the function `mouse-avoidance-mode'."
4d6769e1 80 :set (lambda (_symbol value)
8557ea06 81 ;; 'none below prevents toggling when value is nil.
187bd11c 82 (mouse-avoidance-mode (or value 'none)))
8557ea06 83 :initialize 'custom-initialize-default
187bd11c 84 :type '(choice (const :tag "none" nil) (const banish) (const jump)
ad22b7f7 85 (const animate) (const exile) (const proteus))
8557ea06 86 :group 'avoid
f9e9ac1d
DN
87 :require 'avoid
88 :version "20.3")
8557ea06 89
bb5d4e1a 90
00ed33e7 91(defcustom mouse-avoidance-nudge-dist 15
9201cc28 92 "Average distance that mouse will be moved when approached by cursor.
ad22b7f7 93Only applies in Mouse Avoidance mode `jump' and its derivatives.
00ed33e7
RS
94For best results make this larger than `mouse-avoidance-threshold'."
95 :type 'integer
96 :group 'avoid)
bb5d4e1a 97
00ed33e7 98(defcustom mouse-avoidance-nudge-var 10
9201cc28 99 "Variability of `mouse-avoidance-nudge-dist' (which see)."
00ed33e7
RS
100 :type 'integer
101 :group 'avoid)
bb5d4e1a 102
00ed33e7
RS
103(defcustom mouse-avoidance-animation-delay .01
104 "Delay between animation steps, in seconds."
105 :type 'number
106 :group 'avoid)
bb5d4e1a 107
00ed33e7 108(defcustom mouse-avoidance-threshold 5
9201cc28 109 "Mouse-pointer's flight distance.
bb5d4e1a 110If the cursor gets closer than this, the mouse pointer will move away.
ad22b7f7 111Only applies in Mouse Avoidance modes `animate' and `jump'."
00ed33e7
RS
112 :type 'integer
113 :group 'avoid)
bb5d4e1a 114
0f84437b
TV
115(defcustom mouse-avoidance-banish-position '((frame-or-window . frame)
116 (side . right)
117 (side-pos . 3)
118 (top-or-bottom . top)
119 (top-or-bottom-pos . 0))
120 "Position to which Mouse Avoidance mode `banish' moves the mouse.
121An alist where keywords mean:
122FRAME-OR-WINDOW: banish the mouse to corner of frame or window.
123SIDE: banish the mouse on right or left corner of frame or window.
124SIDE-POS: Distance from right or left edge of frame or window.
125TOP-OR-BOTTOM: banish the mouse to top or bottom of frame or window.
126TOP-OR-BOTTOM-POS: Distance from top or bottom edge of frame or window."
127 :group 'avoid
d1a1c7e6 128 :version "24.3"
2614b25f
JL
129 :type '(alist :key-type symbol :value-type (choice symbol integer))
130 :options '((frame-or-window symbol) (side symbol) (side-pos integer)
131 (top-or-bottom symbol) (top-or-bottom-pos integer)))
0f84437b 132
bdd20095
KH
133;; Internal variables
134(defvar mouse-avoidance-state nil)
bb5d4e1a
RS
135(defvar mouse-avoidance-pointer-shapes nil)
136(defvar mouse-avoidance-n-pointer-shapes 0)
5babefcf 137(defvar mouse-avoidance-old-pointer-shape nil)
38ceb48f 138(defvar mouse-avoidance-animating-pointer nil)
bb5d4e1a 139
85c92290
RS
140;; This timer is used to run something when Emacs is idle.
141(defvar mouse-avoidance-timer nil)
142
bb5d4e1a
RS
143;;; Functions:
144
1f31a9f1
BG
145(defsubst mouse-avoidance-set-pointer-shape (shape)
146 "Set the shape of the mouse pointer to SHAPE."
a9f73104
EZ
147 (when (boundp 'x-pointer-shape)
148 (setq x-pointer-shape shape)
149 (set-mouse-color nil)))
1f31a9f1 150
bdd20095 151(defun mouse-avoidance-point-position ()
3f32656c 152 "Return the position of point as (FRAME X . Y).
88b4ca18 153Analogous to `mouse-position'."
f167c27b
MR
154 (let* ((edges (window-inside-edges))
155 (posn-at-point (posn-at-point))
156 (x-y (and posn-at-point (posn-x-y posn-at-point))))
157 (when x-y
158 (cons (selected-frame)
159 (cons (+ (car edges)
160 (/ (car x-y) (frame-char-width)))
161 (+ (car (cdr edges))
162 (/ (cdr x-y) (frame-char-height))))))))
96ae4787
RS
163
164;(defun mouse-avoidance-point-position-test ()
165; (interactive)
187bd11c 166; (message (format "point=%s mouse=%s"
96ae4787
RS
167; (cdr (mouse-avoidance-point-position))
168; (cdr (mouse-position)))))
bdd20095
KH
169
170(defun mouse-avoidance-set-mouse-position (pos)
171 ;; Carefully set mouse position to given position (X . Y)
bdd20095
KH
172 ;; Returns t if it moved the mouse.
173 (let ((f (selected-frame)))
bdd20095
KH
174 (set-mouse-position f (car pos) (cdr pos))
175 t))
187bd11c 176
bdd20095 177(defun mouse-avoidance-too-close-p (mouse)
02790ce2
GM
178 "Return t if mouse pointer and point cursor are too close.
179MOUSE is the current mouse position as returned by `mouse-position'.
180Acceptable distance is defined by `mouse-avoidance-threshold'."
181 (let* ((frame (car mouse))
182 (mouse-y (cdr (cdr mouse)))
f167c27b
MR
183 (tool-bar-lines (frame-parameter nil 'tool-bar-lines))
184 point)
a9f73104
EZ
185 (or tool-bar-lines
186 (setq tool-bar-lines 0))
f167c27b
MR
187 (cond
188 ((and mouse-y (< mouse-y tool-bar-lines))
189 nil)
190 ((setq point (mouse-avoidance-point-position))
191 (let ((mouse-x (car (cdr mouse))))
02790ce2
GM
192 (and (eq frame (car point))
193 (not (null mouse-x))
194 (< (abs (- mouse-x (car (cdr point))))
195 mouse-avoidance-threshold)
196 (< (abs (- mouse-y (cdr (cdr point))))
f167c27b 197 mouse-avoidance-threshold)))))))
bb5d4e1a 198
bdd20095 199(defun mouse-avoidance-banish-destination ()
ad22b7f7 200 "The position to which Mouse Avoidance mode `banish' moves the mouse.
0f84437b
TV
201
202If you want the mouse banished to a different corner set
203`mouse-avoidance-banish-position' as you need."
204 (let* ((fra-or-win (assoc-default
205 'frame-or-window
206 mouse-avoidance-banish-position 'eq))
f58e0fd5
SM
207 (list-values (pcase fra-or-win
208 (`frame (list 0 0 (frame-width) (frame-height)))
209 (`window (window-edges))))
210 (alist (cl-loop for v in list-values
211 for k in '(left top right bottom)
212 collect (cons k v)))
0f84437b
TV
213 (side (assoc-default
214 'side
f58e0fd5 215 mouse-avoidance-banish-position #'eq))
0f84437b
TV
216 (side-dist (assoc-default
217 'side-pos
f58e0fd5 218 mouse-avoidance-banish-position #'eq))
0f84437b
TV
219 (top-or-bottom (assoc-default
220 'top-or-bottom
f58e0fd5 221 mouse-avoidance-banish-position #'eq))
0f84437b
TV
222 (top-or-bottom-dist (assoc-default
223 'top-or-bottom-pos
f58e0fd5
SM
224 mouse-avoidance-banish-position #'eq))
225 (side-fn (pcase side
226 (`left '+)
227 (`right '-)))
228 (top-or-bottom-fn (pcase top-or-bottom
229 (`top '+)
230 (`bottom '-))))
0f84437b
TV
231 (cons (funcall side-fn ; -/+
232 (assoc-default side alist 'eq) ; right or left
233 side-dist) ; distance from side
234 (funcall top-or-bottom-fn ; -/+
235 (assoc-default top-or-bottom alist 'eq) ; top/bottom
236 top-or-bottom-dist)))) ; distance from top/bottom
bdd20095 237
bb5d4e1a 238(defun mouse-avoidance-banish-mouse ()
0f84437b 239 "Put the mouse pointer to `mouse-avoidance-banish-position'."
bdd20095
KH
240 (mouse-avoidance-set-mouse-position (mouse-avoidance-banish-destination)))
241
242(defsubst mouse-avoidance-delta (cur delta dist var min max)
243 ;; Decide how far to move in either dimension.
244 ;; Args are the CURRENT location, the desired DELTA for
245 ;; warp-conservation, the DISTANCE we like to move, the VARIABILITY
246 ;; in distance allowed, and the MIN and MAX possible window positions.
a7acbbe4 247 ;; Returns something as close to DELTA as possible within the constraints.
bdd20095
KH
248 (let ((L1 (max (- min cur) (+ (- dist) (- var))))
249 (R1 (+ (- dist) var ))
250 (L2 (+ dist (- var)))
251 (R2 (min (- max cur) (+ dist var))))
252 (if (< R1 (- min cur)) (setq L1 nil R1 nil))
253 (if (> L2 (- max cur)) (setq L2 nil R2 nil))
254 (cond ((and L1 (< delta L1)) L1)
255 ((and R1 (< delta R1)) delta)
256 ((and R1 (< delta 0)) R1)
257 ((and L2 (< delta L2)) L2)
258 ((and R2 (< delta R2)) delta)
259 (R2)
260 ((or R1 L2))
261 (t 0))))
bb5d4e1a 262
187bd11c 263(defun mouse-avoidance-nudge-mouse ()
88b4ca18 264 ;; Push the mouse a little way away, possibly animating the move.
bdd20095
KH
265 ;; For these modes, state keeps track of the total offset that we've
266 ;; accumulated, and tries to keep it close to zero.
bb5d4e1a 267 (let* ((cur (mouse-position))
bdd20095 268 (cur-pos (cdr cur))
88b4ca18
SM
269 (pos (window-edges))
270 (wleft (pop pos))
271 (wtop (pop pos))
272 (wright (pop pos))
273 (wbot (pop pos))
187bd11c 274 (deltax (mouse-avoidance-delta
bdd20095
KH
275 (car cur-pos) (- (random mouse-avoidance-nudge-var)
276 (car mouse-avoidance-state))
277 mouse-avoidance-nudge-dist mouse-avoidance-nudge-var
88b4ca18 278 wleft (1- wright)))
187bd11c 279 (deltay (mouse-avoidance-delta
bdd20095
KH
280 (cdr cur-pos) (- (random mouse-avoidance-nudge-var)
281 (cdr mouse-avoidance-state))
282 mouse-avoidance-nudge-dist mouse-avoidance-nudge-var
88b4ca18 283 wtop (1- wbot))))
bdd20095
KH
284 (setq mouse-avoidance-state
285 (cons (+ (car mouse-avoidance-state) deltax)
286 (+ (cdr mouse-avoidance-state) deltay)))
187bd11c 287 (if (or (eq mouse-avoidance-mode 'animate)
bb5d4e1a 288 (eq mouse-avoidance-mode 'proteus))
38ceb48f
CY
289 (let ((i 0.0)
290 (incr (max .1 (/ 1.0 mouse-avoidance-nudge-dist))))
291 (setq mouse-avoidance-animating-pointer t)
bb5d4e1a 292 (while (<= i 1)
187bd11c 293 (mouse-avoidance-set-mouse-position
bdd20095
KH
294 (cons (+ (car cur-pos) (round (* i deltax)))
295 (+ (cdr cur-pos) (round (* i deltay)))))
38ceb48f 296 (setq i (+ i incr))
bb5d4e1a 297 (if (eq mouse-avoidance-mode 'proteus)
187bd11c 298 (mouse-avoidance-set-pointer-shape
1f31a9f1 299 (mouse-avoidance-random-shape)))
38ceb48f
CY
300 (sit-for mouse-avoidance-animation-delay))
301 (setq mouse-avoidance-animating-pointer nil))
3f32656c
RS
302 (mouse-avoidance-set-mouse-position (cons (+ (car (cdr cur)) deltax)
303 (+ (cdr (cdr cur)) deltay))))))
bb5d4e1a
RS
304
305(defun mouse-avoidance-random-shape ()
306 "Return a random cursor shape.
307This assumes that any variable whose name begins with x-pointer- and
308has an integer value is a valid cursor shape. You might want to
309redefine this function to suit your own tastes."
310 (if (null mouse-avoidance-pointer-shapes)
311 (progn
312 (setq mouse-avoidance-pointer-shapes
76d1e5a4 313 (mapcar (lambda (x) (symbol-value (intern x)))
bb5d4e1a 314 (all-completions "x-pointer-" obarray
187bd11c 315 (lambda (x)
bb5d4e1a
RS
316 (and (boundp x)
317 (integerp (symbol-value x)))))))
187bd11c 318 (setq mouse-avoidance-n-pointer-shapes
bb5d4e1a
RS
319 (length mouse-avoidance-pointer-shapes))))
320 (nth (random mouse-avoidance-n-pointer-shapes)
321 mouse-avoidance-pointer-shapes))
322
88b4ca18
SM
323(defun mouse-avoidance-ignore-p ()
324 (let ((mp (mouse-position)))
36ba6f07 325 (or (not (frame-pointer-visible-p)) ; The pointer is hidden
ec6ecaed 326 (not cursor-type) ; There's no cursor
36ba6f07 327 executing-kbd-macro ; don't check inside macro
88b4ca18
SM
328 (null (cadr mp)) ; don't move unless in an Emacs frame
329 (not (eq (car mp) (selected-frame)))
330 ;; Don't do anything if last event was a mouse event.
331 ;; FIXME: this code fails in the case where the mouse was moved
332 ;; since the last key-press but without generating any event.
333 (and (consp last-input-event)
334 (symbolp (car last-input-event))
335 (let ((modifiers (event-modifiers (car last-input-event))))
336 (or (memq (car last-input-event)
337 '(mouse-movement scroll-bar-movement
a2115113 338 select-window focus-out))
88b4ca18
SM
339 (memq 'click modifiers)
340 (memq 'double modifiers)
341 (memq 'triple modifiers)
342 (memq 'drag modifiers)
a2115113
JL
343 (memq 'down modifiers)
344 (memq 'meta modifiers)
345 (memq 'control modifiers)
346 (memq 'shift modifiers)
347 (memq 'hyper modifiers)
348 (memq 'super modifiers)
349 (memq 'alt modifiers)))))))
88b4ca18 350
38ceb48f 351(defun mouse-avoidance-banish ()
88b4ca18 352 (if (not (mouse-avoidance-ignore-p))
bdd20095
KH
353 (mouse-avoidance-banish-mouse)))
354
38ceb48f 355(defun mouse-avoidance-exile ()
bdd20095
KH
356 ;; For exile mode, the state is nil when the mouse is in its normal
357 ;; position, and set to the old mouse-position when the mouse is in exile.
88b4ca18 358 (if (not (mouse-avoidance-ignore-p))
bdd20095
KH
359 (let ((mp (mouse-position)))
360 (cond ((and (not mouse-avoidance-state)
361 (mouse-avoidance-too-close-p mp))
362 (setq mouse-avoidance-state mp)
363 (mouse-avoidance-banish-mouse))
364 ((and mouse-avoidance-state
365 (not (mouse-avoidance-too-close-p mouse-avoidance-state)))
366 (if (and (eq (car mp) (selected-frame))
367 (equal (cdr mp) (mouse-avoidance-banish-destination)))
368 (mouse-avoidance-set-mouse-position
369 ;; move back only if user has not moved mouse
370 (cdr mouse-avoidance-state)))
371 ;; but clear state anyway, to be ready for another move
372 (setq mouse-avoidance-state nil))))))
bb5d4e1a 373
38ceb48f 374(defun mouse-avoidance-fancy ()
bdd20095 375 ;; Used for the "fancy" modes, ie jump et al.
38ceb48f
CY
376 (if (and (not mouse-avoidance-animating-pointer)
377 (not (mouse-avoidance-ignore-p))
bdd20095 378 (mouse-avoidance-too-close-p (mouse-position)))
d9f132a8
RS
379 (let ((old-pos (mouse-position)))
380 (mouse-avoidance-nudge-mouse)
1f31a9f1
BG
381 (if (not (eq (selected-frame) (car old-pos)))
382 ;; This should never happen.
383 (apply 'set-mouse-position old-pos)))))
bb5d4e1a 384
1f31a9f1 385;;;###autoload
bb5d4e1a 386(defun mouse-avoidance-mode (&optional mode)
ad22b7f7 387 "Set Mouse Avoidance mode to MODE.
bdd20095 388MODE should be one of the symbols `banish', `exile', `jump', `animate',
d9f132a8
RS
389`cat-and-mouse', `proteus', or `none'.
390
187bd11c 391If MODE is nil, toggle mouse avoidance between `none' and `banish'
d9f132a8
RS
392modes. Positive numbers and symbols other than the above are treated
393as equivalent to `banish'; negative numbers and `-' are equivalent to `none'.
394
187bd11c 395Effects of the different modes:
3f32656c
RS
396 * banish: Move the mouse to the upper-right corner on any keypress.
397 * exile: Move the mouse to the corner only if the cursor gets too close,
bdd20095 398 and allow it to return once the cursor is out of the way.
3f32656c 399 * jump: If the cursor gets too close to the mouse, displace the mouse
bdd20095 400 a random distance & direction.
3f32656c
RS
401 * animate: As `jump', but shows steps along the way for illusion of motion.
402 * cat-and-mouse: Same as `animate'.
403 * proteus: As `animate', but changes the shape of the mouse pointer too.
d9f132a8 404
ad22b7f7 405\(See `mouse-avoidance-threshold' for definition of \"too close\",
d9f132a8
RS
406and `mouse-avoidance-nudge-dist' and `mouse-avoidance-nudge-var' for
407definition of \"random distance\".)"
bb5d4e1a
RS
408 (interactive
409 (list (intern (completing-read
410 "Select cursor avoidance technique (SPACE for list): "
bdd20095
KH
411 '(("banish") ("exile") ("jump") ("animate")
412 ("cat-and-mouse") ("proteus") ("none"))
bb5d4e1a
RS
413 nil t))))
414 (if (eq mode 'cat-and-mouse)
415 (setq mode 'animate))
85c92290
RS
416 (if mouse-avoidance-timer
417 (cancel-timer mouse-avoidance-timer))
418 (setq mouse-avoidance-timer nil)
5babefcf
RS
419
420 ;; Restore pointer shape if necessary
421 (if (eq mouse-avoidance-mode 'proteus)
422 (mouse-avoidance-set-pointer-shape mouse-avoidance-old-pointer-shape))
423
424 ;; Do additional setup depending on version of mode requested
bb5d4e1a
RS
425 (cond ((eq mode 'none)
426 (setq mouse-avoidance-mode nil))
427 ((or (eq mode 'jump)
428 (eq mode 'animate)
429 (eq mode 'proteus))
85c92290 430 (setq mouse-avoidance-timer
38ceb48f 431 (run-with-idle-timer 0.1 t 'mouse-avoidance-fancy))
bdd20095 432 (setq mouse-avoidance-mode mode
5babefcf 433 mouse-avoidance-state (cons 0 0)
a9f73104
EZ
434 mouse-avoidance-old-pointer-shape
435 (and (boundp 'x-pointer-shape) x-pointer-shape)))
bdd20095 436 ((eq mode 'exile)
85c92290 437 (setq mouse-avoidance-timer
38ceb48f 438 (run-with-idle-timer 0.1 t 'mouse-avoidance-exile))
bdd20095
KH
439 (setq mouse-avoidance-mode mode
440 mouse-avoidance-state nil))
187bd11c 441 ((or (eq mode 'banish)
bb5d4e1a
RS
442 (eq mode t)
443 (and (null mode) (null mouse-avoidance-mode))
444 (and mode (> (prefix-numeric-value mode) 0)))
85c92290 445 (setq mouse-avoidance-timer
38ceb48f 446 (run-with-idle-timer 0.1 t 'mouse-avoidance-banish))
bb5d4e1a 447 (setq mouse-avoidance-mode 'banish))
bdd20095
KH
448 (t (setq mouse-avoidance-mode nil)))
449 (force-mode-line-update))
bb5d4e1a 450
ed62ad33
KH
451;; Most people who use avoid mode leave it on all the time, so it's not
452;; very informative to announce it in the mode line.
453;;(or (assq 'mouse-avoidance-mode minor-mode-alist)
454;; (setq minor-mode-alist (cons '(mouse-avoidance-mode " Avoid")
455;; minor-mode-alist)))
bb5d4e1a 456
8557ea06 457;; Needed for custom.
187bd11c 458(if mouse-avoidance-mode
8557ea06
RS
459 (mouse-avoidance-mode mouse-avoidance-mode))
460
4b63a9ca
LI
461(provide 'avoid)
462
8557ea06 463;;; avoid.el ends here