Mercurial > emacs
annotate lisp/textmodes/flyspell.el @ 22723:04b653d7f842
(code_convert_string): Count characters again if we
encounter some invalid code while decoding.
author | Kenichi Handa <handa@m17n.org> |
---|---|
date | Thu, 09 Jul 1998 04:33:00 +0000 |
parents | 3b7f1e026beb |
children | 1104a715c324 |
rev | line source |
---|---|
22611 | 1 ;;; flyspell.el --- On-the-fly spell checker |
2 | |
3 ;; Copyright (C) 1998 Free Software Foundation, Inc. | |
4 | |
5 ;; Author: Manuel Serrano <Manuel.Serrano@unice.fr> | |
22612
6def3da74c7c
Delete defcustom definition.
Richard M. Stallman <rms@gnu.org>
parents:
22611
diff
changeset
|
6 ;; Keywords: convenience |
22611 | 7 |
8 ;;; This file is part of GNU Emacs. | |
9 | |
10 ;; GNU Emacs is free software; you can redistribute it and/or modify | |
11 ;; it under the terms of the GNU General Public License as published by | |
12 ;; the Free Software Foundation; either version 2, or (at your option) | |
13 ;; any later version. | |
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 | |
21 ;; along with GNU Emacs; see the file COPYING. If not, write to the | |
22 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
23 ;; Boston, MA 02111-1307, USA. | |
24 | |
25 ;;; commentary: | |
26 ;; | |
27 ;; Flyspell is a minor Emacs mode performing on-the-fly spelling | |
22612
6def3da74c7c
Delete defcustom definition.
Richard M. Stallman <rms@gnu.org>
parents:
22611
diff
changeset
|
28 ;; checking. |
22611 | 29 ;; |
30 ;; To enter the flyspell minor mode, Meta-x flyspell-mode. | |
31 ;; | |
32 ;; Note: consider setting the variable ispell-parser to 'tex to | |
33 ;; avoid TeX command checking (use `(setq ispell-parser 'tex)') | |
34 ;; _before_ entering flyspell. | |
35 ;; | |
36 ;; Some user variables control the behavior of flyspell. They are | |
37 ;; those defined under the `User variables' comment. | |
38 ;; | |
22612
6def3da74c7c
Delete defcustom definition.
Richard M. Stallman <rms@gnu.org>
parents:
22611
diff
changeset
|
39 ;; Note: as suggested by Yaron M. Minsky, if you use flyspell when |
22611 | 40 ;; sending mails, you should add the following: |
41 ;; (add-hook 'mail-send-hook 'flyspell-mode-off) | |
42 | |
43 ;;; Code: | |
44 (require 'font-lock) | |
45 (require 'ispell) | |
46 | |
47 (defgroup flyspell nil | |
48 "Spellchecking on the fly." | |
49 :tag "FlySpell" | |
50 :prefix "flyspell-" | |
22648
3b7f1e026beb
*** empty log message ***
Dan Nicolaescu <done@ece.arizona.edu>
parents:
22612
diff
changeset
|
51 :group 'processes |
3b7f1e026beb
*** empty log message ***
Dan Nicolaescu <done@ece.arizona.edu>
parents:
22612
diff
changeset
|
52 :version "20.3") |
22611 | 53 |
54 ;*---------------------------------------------------------------------*/ | |
55 ;* User variables ... */ | |
56 ;*---------------------------------------------------------------------*/ | |
57 (defcustom flyspell-highlight-flag t | |
58 "*Non-nil means use highlight, nil means use mini-buffer messages." | |
59 :group 'flyspell | |
60 :type 'boolean) | |
61 | |
62 (defcustom flyspell-doublon-as-error-flag t | |
63 "*Non-nil means consider doublon as misspelling." | |
64 :group 'flyspell | |
65 :type 'boolean) | |
66 | |
67 (defcustom flyspell-sort-corrections t | |
68 "*Non-nil means, sort the corrections alphabetically before popping them." | |
69 :group 'flyspell | |
70 :type 'boolean) | |
71 | |
72 (defcustom flyspell-incorrect-color "OrangeRed" | |
73 "*The color used for highlighting incorrect words." | |
74 :group 'flyspell | |
75 :type 'string) | |
76 | |
77 (defcustom flyspell-duplicate-color "Gold3" | |
78 "*The color used for highlighting incorrect words but appearing at least twice." | |
79 :group 'flyspell | |
80 :type 'string) | |
81 | |
82 (defcustom flyspell-underline-p t | |
83 "*Non-nil means, incorrect words are underlined." | |
84 :group 'flyspell | |
85 :type 'boolean) | |
86 | |
87 (defcustom flyspell-auto-correct-binding | |
88 "\M-\t" | |
89 "*Non-nil means that its value (a binding) will bound to the flyspell | |
90 auto-correct." | |
91 :group 'flyspell | |
22612
6def3da74c7c
Delete defcustom definition.
Richard M. Stallman <rms@gnu.org>
parents:
22611
diff
changeset
|
92 :type '(choice (const nil) string)) |
22611 | 93 |
94 (defcustom flyspell-command-hook t | |
95 "*Non-nil means that `post-command-hook' is used to check | |
96 already typed words." | |
97 :group 'flyspell | |
98 :type 'boolean) | |
99 | |
100 (defcustom flyspell-duplicate-distance -1 | |
101 "*The distance from duplication. | |
102 -1 means no limit. | |
103 0 means no window." | |
104 :group 'flyspell | |
105 :type 'number) | |
106 | |
107 (defcustom flyspell-delay 3 | |
108 "*The number of second before checking words on post-command-hook if | |
109 the current command is a delay command." | |
110 :group 'flyspell | |
111 :type 'number) | |
112 | |
113 (defcustom flyspell-persistent-highlight t | |
114 "*T means that hilighted words are not removed until the word are corrected." | |
115 :group 'flyspell | |
116 :type 'boolean) | |
117 | |
118 (defcustom flyspell-highlight-properties t | |
119 "*T means highlight incorrect words even if a property exists for this word." | |
120 :group 'flyspell | |
121 :type 'boolean) | |
122 | |
123 (defcustom flyspell-default-delayed-commands | |
124 '(self-insert-command | |
125 delete-backward-char | |
126 delete-char) | |
127 "The list of always delayed command (that is flyspell is not activated | |
128 after any of these commands." | |
129 :group 'flyspell | |
130 :type '(repeat (symbol))) | |
131 | |
132 (defcustom flyspell-delayed-commands | |
133 nil | |
134 "*If non nil, this variable must hold a list a symbol. Each symbol is | |
135 the name of an delayed command (that is a command that does not activate | |
136 flyspell checking." | |
137 :group 'flyspell | |
138 :type '(repeat (symbol))) | |
139 | |
140 (defcustom flyspell-issue-welcome-flag t | |
141 "*Non-nil means that flyspell issues a welcome message when started." | |
142 :group 'flyspell | |
143 :type 'boolean) | |
144 | |
145 (defcustom flyspell-consider-dash-as-word-delimiter-flag nil | |
146 "*Non-nil means that the `-' char is considered as a word delimiter." | |
147 :group 'flyspell | |
148 :type 'boolean) | |
149 | |
150 (defcustom flyspell-incorrect-hook nil | |
151 "*Non-nil means a list of hooks to be executed when incorrect | |
152 words are encountered. Each hook is a function of two arguments that are | |
153 location of the beginning and the end of the incorrect region." | |
154 :group 'flyspell) | |
155 | |
156 (defcustom flyspell-multi-language-p t | |
157 "*Non-nil means that flyspell could be use with several buffers checking | |
158 several languages. Non-nil means that a new ispell process will be spawned | |
159 per buffer. If nil, only one unique ispell process will be running." | |
160 :group 'flyspell | |
161 :type 'boolean) | |
162 | |
163 ;*---------------------------------------------------------------------*/ | |
164 ;* Mode specific options */ | |
165 ;* ------------------------------------------------------------- */ | |
166 ;* Mode specific options enable users to disable flyspell on */ | |
167 ;* certain word depending of the emacs mode. For instance, when */ | |
168 ;* using flyspell with mail-mode add the following expression */ | |
169 ;* in your .emacs file: */ | |
170 ;* (add-hook 'mail-mode */ | |
171 ;* '(lambda () (setq flyspell-generic-check-word-p */ | |
172 ;* 'mail-mode-flyspell-verify))) */ | |
173 ;*---------------------------------------------------------------------*/ | |
174 (defvar flyspell-generic-check-word-p nil | |
175 "Function providing per-mode customization over which words are flyspelled. | |
176 Returns t to continue checking, nil otherwise.") | |
177 (make-variable-buffer-local 'flyspell-generic-check-word-p) | |
178 | |
179 (defun mail-mode-flyspell-verify () | |
180 "Return t if we want flyspell to check the word under point." | |
181 (save-excursion | |
22612
6def3da74c7c
Delete defcustom definition.
Richard M. Stallman <rms@gnu.org>
parents:
22611
diff
changeset
|
182 (or (progn |
6def3da74c7c
Delete defcustom definition.
Richard M. Stallman <rms@gnu.org>
parents:
22611
diff
changeset
|
183 (beginning-of-line) |
6def3da74c7c
Delete defcustom definition.
Richard M. Stallman <rms@gnu.org>
parents:
22611
diff
changeset
|
184 (looking-at "Subject:")) |
6def3da74c7c
Delete defcustom definition.
Richard M. Stallman <rms@gnu.org>
parents:
22611
diff
changeset
|
185 (not (or (re-search-forward mail-header-separator nil t) |
6def3da74c7c
Delete defcustom definition.
Richard M. Stallman <rms@gnu.org>
parents:
22611
diff
changeset
|
186 (re-search-backward message-signature-separator nil t) |
6def3da74c7c
Delete defcustom definition.
Richard M. Stallman <rms@gnu.org>
parents:
22611
diff
changeset
|
187 (progn |
6def3da74c7c
Delete defcustom definition.
Richard M. Stallman <rms@gnu.org>
parents:
22611
diff
changeset
|
188 (beginning-of-line) |
6def3da74c7c
Delete defcustom definition.
Richard M. Stallman <rms@gnu.org>
parents:
22611
diff
changeset
|
189 (looking-at "[>}|]"))))))) |
22611 | 190 |
191 (defun texinfo-mode-flyspell-verify () | |
192 "Return t if we want flyspell to check the word under point." | |
193 (save-excursion | |
194 (forward-word -1) | |
195 (not (looking-at "@")))) | |
196 | |
197 ;*---------------------------------------------------------------------*/ | |
198 ;* Overlay compatibility */ | |
199 ;*---------------------------------------------------------------------*/ | |
200 (autoload 'make-overlay "overlay" "" t) | |
201 (autoload 'move-overlay "overlay" "" t) | |
202 (autoload 'overlayp "overlay" "" t) | |
203 (autoload 'overlay-properties "overlay" "" t) | |
204 (autoload 'overlays-in "overlay" "" t) | |
205 (autoload 'delete-overlay "overlay" "" t) | |
206 (autoload 'overlays-at "overlay" "" t) | |
207 (autoload 'overlay-put "overlay" "" t) | |
208 (autoload 'overlay-get "overlay" "" t) | |
209 | |
210 (defun flyspell-font-lock-make-face (l) | |
211 "Because emacs and xemacs does not behave the same I uses my owe | |
212 font-lock-make-face function. This function is similar to the gnu-emacs | |
213 font-lock-make-face function." | |
214 (let ((fname (car l)) | |
215 (color (car (cdr l))) | |
216 (italic (car (cdr (cdr l)))) | |
217 (bold (car (cdr (cdr (cdr l))))) | |
218 (underline (car (cdr (cdr (cdr (cdr l))))))) | |
219 (let ((face (copy-face 'default fname))) | |
220 (if color | |
221 (set-face-foreground face color)) | |
222 (if (and italic bold) | |
223 (condition-case nil | |
224 (make-face-bold-italic face) | |
225 (error nil)) | |
226 (progn | |
227 (if italic | |
228 (condition-case nil | |
229 (make-face-italic face) | |
230 (error nil))) | |
231 (if bold | |
232 (condition-case nil | |
233 (make-face-bold face) | |
234 (error nil))))) | |
235 (if underline | |
236 (condition-case nil | |
237 (set-face-underline-p face t) | |
238 (error nil))) | |
239 (if (not (x-display-color-p)) | |
240 (condition-case nil | |
241 (make-face-bold face) | |
242 (error nil))) | |
243 face))) | |
244 | |
245 ;*---------------------------------------------------------------------*/ | |
246 ;* Which emacs are we currently running */ | |
247 ;*---------------------------------------------------------------------*/ | |
248 (defvar flyspell-emacs | |
249 (cond | |
250 ((string-match "XEmacs" emacs-version) | |
251 'xemacs) | |
252 (t | |
253 'emacs)) | |
254 "The Emacs we are currently running.") | |
255 | |
256 ;*---------------------------------------------------------------------*/ | |
257 ;* cl compatibility */ | |
258 ;*---------------------------------------------------------------------*/ | |
259 (defmacro push (x place) | |
260 "(push X PLACE): insert X at the head of the list stored in PLACE. | |
261 Analogous to (setf PLACE (cons X PLACE)), though more careful about | |
262 evaluating each argument only once and in the right order. PLACE has | |
263 to be a symbol." | |
264 (list 'setq place (list 'cons x place))) | |
265 | |
266 ;*---------------------------------------------------------------------*/ | |
267 ;* The minor mode declaration. */ | |
268 ;*---------------------------------------------------------------------*/ | |
269 (defvar flyspell-mode nil) | |
270 (make-variable-buffer-local 'flyspell-mode) | |
271 | |
272 (defvar flyspell-mode-map (make-sparse-keymap)) | |
273 (defvar flyspell-mouse-map (make-sparse-keymap)) | |
274 | |
275 (or (assoc 'flyspell-mode minor-mode-alist) | |
276 (push '(flyspell-mode " Fly") minor-mode-alist)) | |
277 | |
278 (or (assoc 'flyspell-mode minor-mode-map-alist) | |
279 (push (cons 'flyspell-mode flyspell-mode-map) minor-mode-map-alist)) | |
280 | |
281 (if flyspell-auto-correct-binding | |
282 (define-key flyspell-mode-map flyspell-auto-correct-binding | |
283 (function flyspell-auto-correct-word))) | |
284 ;; mouse bindings | |
22612
6def3da74c7c
Delete defcustom definition.
Richard M. Stallman <rms@gnu.org>
parents:
22611
diff
changeset
|
285 (cond |
6def3da74c7c
Delete defcustom definition.
Richard M. Stallman <rms@gnu.org>
parents:
22611
diff
changeset
|
286 ((eq flyspell-emacs 'xemacs) |
6def3da74c7c
Delete defcustom definition.
Richard M. Stallman <rms@gnu.org>
parents:
22611
diff
changeset
|
287 (define-key flyspell-mouse-map [(button2)] |
6def3da74c7c
Delete defcustom definition.
Richard M. Stallman <rms@gnu.org>
parents:
22611
diff
changeset
|
288 (function flyspell-correct-word/mouse-keymap))) |
6def3da74c7c
Delete defcustom definition.
Richard M. Stallman <rms@gnu.org>
parents:
22611
diff
changeset
|
289 (t |
22611 | 290 (define-key flyspell-mode-map [(mouse-2)] |
22612
6def3da74c7c
Delete defcustom definition.
Richard M. Stallman <rms@gnu.org>
parents:
22611
diff
changeset
|
291 (function flyspell-correct-word/local-keymap)))) |
22611 | 292 |
293 ;; the name of the overlay property that defines the keymap | |
294 (defvar flyspell-overlay-keymap-property-name | |
295 (if (string-match "19.*XEmacs" emacs-version) | |
296 'keymap | |
297 'local-map)) | |
298 | |
299 ;*---------------------------------------------------------------------*/ | |
300 ;* Highlighting */ | |
301 ;*---------------------------------------------------------------------*/ | |
302 (flyspell-font-lock-make-face (list 'flyspell-incorrect-face | |
303 flyspell-incorrect-color | |
304 nil | |
305 t | |
306 flyspell-underline-p)) | |
307 (flyspell-font-lock-make-face (list 'flyspell-duplicate-face | |
308 flyspell-duplicate-color | |
309 nil | |
310 t | |
311 flyspell-underline-p)) | |
312 | |
313 (defvar flyspell-overlay nil) | |
314 | |
315 ;*---------------------------------------------------------------------*/ | |
316 ;* flyspell-mode ... */ | |
317 ;*---------------------------------------------------------------------*/ | |
318 ;;;###autoload | |
319 (defun flyspell-mode (&optional arg) | |
320 "Minor mode performing on-the-fly spelling checking. | |
321 Ispell is automatically spawned on background for each entered words. | |
322 The default flyspells behavior is to highlight incorrect words. | |
323 With prefix ARG, turn Flyspell minor mode on iff ARG is positive. | |
324 | |
325 Bindings: | |
326 \\[ispell-word]: correct words (using Ispell). | |
327 \\[flyspell-auto-correct-word]: automatically correct word. | |
328 \\[flyspell-correct-word] (or mouse-2): popup correct words. | |
329 | |
330 Hooks: | |
331 flyspell-mode-hook is runner after flyspell is entered. | |
332 | |
333 Remark: | |
334 `flyspell-mode' uses `ispell-mode'. Thus all Ispell options are | |
335 valid. For instance, a personal dictionary can be used by | |
336 invoking `ispell-change-dictionary'. | |
337 | |
338 Consider using the `ispell-parser' to check your text. For instance | |
339 consider adding: | |
340 (add-hook 'tex-mode-hook (function (lambda () (setq ispell-parser 'tex)))) | |
341 in your .emacs file. | |
342 | |
343 flyspell-region checks all words inside a region. | |
344 | |
345 flyspell-buffer checks the whole buffer." | |
346 (interactive "P") | |
347 ;; we set the mode on or off | |
348 (setq flyspell-mode (not (or (and (null arg) flyspell-mode) | |
349 (<= (prefix-numeric-value arg) 0)))) | |
350 (if flyspell-mode | |
351 (flyspell-mode-on) | |
352 (flyspell-mode-off)) | |
353 ;; we force the modeline re-printing | |
354 (set-buffer-modified-p (buffer-modified-p))) | |
355 | |
356 ;*---------------------------------------------------------------------*/ | |
357 ;* flyspell-mode-on ... */ | |
358 ;*---------------------------------------------------------------------*/ | |
359 (defun flyspell-mode-on () | |
360 "Turn flyspell mode on. Do not use, use `flyspell-mode' instead." | |
361 (message "flyspell on: %S" (current-buffer)) | |
362 (setq ispell-highlight-face 'flyspell-incorrect-face) | |
363 ;; ispell initialization | |
364 (if flyspell-multi-language-p | |
365 (progn | |
366 (make-variable-buffer-local 'ispell-dictionary) | |
367 (make-variable-buffer-local 'ispell-process) | |
368 (make-variable-buffer-local 'ispell-filter) | |
369 (make-variable-buffer-local 'ispell-filter-continue) | |
370 (make-variable-buffer-local 'ispell-process-directory) | |
371 (make-variable-buffer-local 'ispell-parser))) | |
372 ;; we initialize delayed commands symbol | |
373 (flyspell-delay-commands) | |
374 ;; we bound flyspell action to post-command hook | |
375 (if flyspell-command-hook | |
376 (progn | |
377 (make-local-hook 'post-command-hook) | |
378 (add-hook 'post-command-hook | |
379 (function flyspell-post-command-hook) | |
380 t | |
381 t))) | |
382 ;; we bound flyspell action to pre-command hook | |
383 (if flyspell-command-hook | |
384 (progn | |
385 (make-local-hook 'pre-command-hook) | |
386 (add-hook 'pre-command-hook | |
387 (function flyspell-pre-command-hook) | |
388 t | |
389 t))) | |
390 ;; the welcome message | |
391 (if flyspell-issue-welcome-flag | |
392 (message | |
393 (if flyspell-auto-correct-binding | |
394 (format "Welcome to flyspell. Use %S or mouse-2 to correct words." | |
395 (key-description flyspell-auto-correct-binding)) | |
396 "Welcome to flyspell. Use mouse-2 to correct words."))) | |
397 ;; we have to kill the flyspell process when the buffer is deleted. | |
398 ;; (thanks to Jeff Miller and Roland Rosenfeld who sent me this | |
399 ;; improvement). | |
400 (add-hook 'kill-buffer-hook | |
401 '(lambda () | |
402 (if flyspell-mode | |
403 (flyspell-mode-off)))) | |
404 ;; we end with the flyspell hooks | |
405 (run-hooks 'flyspell-mode-hook)) | |
406 | |
407 ;*---------------------------------------------------------------------*/ | |
408 ;* flyspell-delay-commands ... */ | |
409 ;*---------------------------------------------------------------------*/ | |
410 (defun flyspell-delay-commands () | |
411 "Install the delayed command." | |
412 (mapcar 'flyspell-delay-command flyspell-default-delayed-commands) | |
413 (mapcar 'flyspell-delay-command flyspell-delayed-commands)) | |
414 | |
415 ;*---------------------------------------------------------------------*/ | |
416 ;* flyspell-delay-command ... */ | |
417 ;*---------------------------------------------------------------------*/ | |
418 (defun flyspell-delay-command (command) | |
419 "Set COMMAND to be delayed. | |
420 When flyspell `post-command-hook' is invoked because a delayed command | |
421 as been used the current word is not immediatly checked. | |
422 It will be checked only after flyspell-delay second." | |
423 (interactive "Scommand: ") | |
424 (put command 'flyspell-delayed t)) | |
425 | |
426 ;*---------------------------------------------------------------------*/ | |
427 ;* flyspell-ignore-commands ... */ | |
428 ;*---------------------------------------------------------------------*/ | |
429 (defun flyspell-ignore-commands () | |
430 "This is an obsolete function, use flyspell-delays command instead." | |
431 (flyspell-delay-commands)) | |
432 | |
433 ;*---------------------------------------------------------------------*/ | |
434 ;* flyspell-ignore-command ... */ | |
435 ;*---------------------------------------------------------------------*/ | |
436 (defun flyspell-ignore-command (command) | |
437 "This is an obsolete function, use flyspell-delay command instead. | |
438 COMMAND is the name of the command to be delayed." | |
439 (flyspell-delay-command command)) | |
440 | |
441 (make-obsolete 'flyspell-ignore-commands 'flyspell-delay-commands) | |
442 (make-obsolete 'flyspell-ignore-command 'flyspell-delay-command) | |
443 | |
444 ;*---------------------------------------------------------------------*/ | |
445 ;* flyspell-word-cache ... */ | |
446 ;*---------------------------------------------------------------------*/ | |
447 (defvar flyspell-word-cache-start nil) | |
448 (defvar flyspell-word-cache-end nil) | |
449 (defvar flyspell-word-cache-word nil) | |
450 (make-variable-buffer-local 'flyspell-word-cache-start) | |
451 (make-variable-buffer-local 'flyspell-word-cache-end) | |
452 (make-variable-buffer-local 'flyspell-word-cache-word) | |
453 | |
454 ;*---------------------------------------------------------------------*/ | |
455 ;* The flyspell pre-hook, store the current position. In the */ | |
456 ;* post command hook, we will check, if the word at this position */ | |
457 ;* has to be spell checked. */ | |
458 ;*---------------------------------------------------------------------*/ | |
459 (defvar flyspell-pre-buffer nil) | |
460 (defvar flyspell-pre-point nil) | |
461 | |
462 ;*---------------------------------------------------------------------*/ | |
463 ;* flyspell-pre-command-hook ... */ | |
464 ;*---------------------------------------------------------------------*/ | |
465 (defun flyspell-pre-command-hook () | |
466 "This function is internally used by Flyspell to get a cursor location | |
467 before a user command." | |
468 (interactive) | |
469 (setq flyspell-pre-buffer (current-buffer)) | |
470 (setq flyspell-pre-point (point))) | |
471 | |
472 ;*---------------------------------------------------------------------*/ | |
473 ;* flyspell-mode-off ... */ | |
474 ;*---------------------------------------------------------------------*/ | |
475 (defun flyspell-mode-off () | |
476 "Turn flyspell mode off. Do not use. Use `flyspell-mode' instead." | |
477 ;; the bye-bye message | |
478 (message "Quiting Flyspell...%S" (current-buffer)) | |
479 ;; we stop the running ispell | |
480 (ispell-kill-ispell t) | |
481 ;; we remove the hooks | |
482 (if flyspell-command-hook | |
483 (progn | |
484 (remove-hook 'post-command-hook | |
485 (function flyspell-post-command-hook) | |
486 t) | |
487 (remove-hook 'pre-command-hook | |
488 (function flyspell-pre-command-hook) | |
489 t))) | |
490 ;; we remove all the flyspell hilightings | |
491 (flyspell-delete-all-overlays) | |
492 ;; we have to erase pre cache variables | |
493 (setq flyspell-pre-buffer nil) | |
494 (setq flyspell-pre-point nil) | |
495 ;; we mark the mode as killed | |
496 (setq flyspell-mode nil)) | |
497 | |
498 ;*---------------------------------------------------------------------*/ | |
499 ;* flyspell-check-word-p ... */ | |
500 ;*---------------------------------------------------------------------*/ | |
501 (defun flyspell-check-word-p () | |
502 "This function returns t when the word at `point' has to be | |
503 checked. The answer depends of several criteria. Mostly we | |
504 check word delimiters." | |
505 (cond | |
506 ((<= (- (point-max) 1) (point-min)) | |
507 ;; the buffer is not filled enough | |
508 nil) | |
509 ((not (and (symbolp this-command) (get this-command 'flyspell-delayed))) | |
510 ;; the current command is not delayed, that | |
511 ;; is that we must check the word now | |
512 t) | |
513 ((and (> (point) (point-min)) | |
514 (save-excursion | |
515 (backward-char 1) | |
516 (and (looking-at (flyspell-get-not-casechars)) | |
517 (or flyspell-consider-dash-as-word-delimiter-flag | |
518 (not (looking-at "\\-")))))) | |
519 ;; yes because we have reached or typed a word delimiter | |
520 t) | |
521 ((not (integerp flyspell-delay)) | |
522 ;; yes because the user had settup a non delay configuration | |
523 t) | |
524 (t | |
525 (if (fboundp 'about-xemacs) | |
526 (sit-for flyspell-delay nil) | |
527 (sit-for flyspell-delay 0 nil))))) | |
528 | |
529 ;*---------------------------------------------------------------------*/ | |
530 ;* flyspell-check-pre-word-p ... */ | |
531 ;*---------------------------------------------------------------------*/ | |
532 (defun flyspell-check-pre-word-p () | |
533 "When to we have to check the word that was at point before | |
534 the current command?" | |
535 (cond | |
536 ((or (not (numberp flyspell-pre-point)) | |
537 (not (bufferp flyspell-pre-buffer)) | |
538 (not (buffer-live-p flyspell-pre-buffer))) | |
539 nil) | |
540 ((or (= flyspell-pre-point (- (point) 1)) | |
541 (= flyspell-pre-point (point)) | |
542 (= flyspell-pre-point (+ (point) 1))) | |
543 nil) | |
544 ((not (eq (current-buffer) flyspell-pre-buffer)) | |
545 t) | |
546 ((not (and (numberp flyspell-word-cache-start) | |
547 (numberp flyspell-word-cache-end))) | |
548 t) | |
549 (t | |
550 (or (< flyspell-pre-point flyspell-word-cache-start) | |
551 (> flyspell-pre-point flyspell-word-cache-end))))) | |
552 | |
553 ;*---------------------------------------------------------------------*/ | |
554 ;* flyspell-post-command-hook ... */ | |
555 ;*---------------------------------------------------------------------*/ | |
556 (defun flyspell-post-command-hook () | |
557 "The `post-command-hook' used by flyspell to check a word in-the-fly." | |
558 (interactive) | |
559 (if (flyspell-check-word-p) | |
560 (flyspell-word)) | |
561 (if (flyspell-check-pre-word-p) | |
562 (save-excursion | |
563 (set-buffer flyspell-pre-buffer) | |
564 (save-excursion | |
565 (goto-char flyspell-pre-point) | |
566 (flyspell-word))))) | |
567 | |
568 ;*---------------------------------------------------------------------*/ | |
569 ;* flyspell-word ... */ | |
570 ;*---------------------------------------------------------------------*/ | |
571 (defun flyspell-word (&optional following) | |
572 "Spell check a word." | |
573 (interactive (list current-prefix-arg)) | |
574 (if (interactive-p) | |
575 (setq following ispell-following-word)) | |
576 (save-excursion | |
577 (ispell-accept-buffer-local-defs) ; use the correct dictionary | |
578 (let ((cursor-location (point)) ; retain cursor location | |
579 (word (flyspell-get-word following)) | |
580 start end poss) | |
581 (if (or (eq word nil) | |
582 (and (fboundp flyspell-generic-check-word-p) | |
583 (not (funcall flyspell-generic-check-word-p)))) | |
584 t | |
585 (progn | |
586 ;; destructure return word info list. | |
587 (setq start (car (cdr word)) | |
588 end (car (cdr (cdr word))) | |
589 word (car word)) | |
590 ;; before checking in the directory, we check for doublons. | |
591 (cond | |
592 ((and flyspell-doublon-as-error-flag | |
593 (save-excursion | |
594 (goto-char start) | |
595 (word-search-backward word | |
596 (- start | |
597 (+ 1 (- end start))) | |
598 t))) | |
599 ;; yes, this is a doublon | |
600 (flyspell-highlight-incorrect-region start end)) | |
601 ((and (eq flyspell-word-cache-start start) | |
602 (eq flyspell-word-cache-end end) | |
603 (string-equal flyspell-word-cache-word word)) | |
604 ;; this word had been already checked, we skip | |
605 nil) | |
606 ((and (eq ispell-parser 'tex) | |
607 (flyspell-tex-command-p word)) | |
608 ;; this is a correct word (because a tex command) | |
609 (flyspell-unhighlight-at start) | |
610 (if (> end start) | |
611 (flyspell-unhighlight-at (- end 1))) | |
612 t) | |
613 (t | |
614 ;; we setup the cache | |
615 (setq flyspell-word-cache-start start) | |
616 (setq flyspell-word-cache-end end) | |
617 (setq flyspell-word-cache-word word) | |
618 ;; now check spelling of word. | |
619 (process-send-string ispell-process "%\n") | |
620 ;; put in verbose mode | |
621 (process-send-string ispell-process | |
622 (concat "^" word "\n")) | |
623 ;; wait until ispell has processed word | |
624 (while (progn | |
625 (accept-process-output ispell-process) | |
626 (not (string= "" (car ispell-filter))))) | |
627 ;; (process-send-string ispell-process "!\n") | |
628 ;; back to terse mode. | |
629 (setq ispell-filter (cdr ispell-filter)) | |
630 (if (listp ispell-filter) | |
631 (setq poss (ispell-parse-output (car ispell-filter)))) | |
632 (cond ((eq poss t) | |
633 ;; correct | |
634 (flyspell-unhighlight-at start) | |
635 (if (> end start) | |
636 (flyspell-unhighlight-at (- end 1))) | |
637 t) | |
638 ((and (stringp poss) flyspell-highlight-flag) | |
639 ;; correct | |
640 (flyspell-unhighlight-at start) | |
641 (if (> end start) | |
642 (flyspell-unhighlight-at (- end 1))) | |
643 t) | |
644 ((null poss) | |
645 (flyspell-unhighlight-at start) | |
646 (if (> end start) | |
647 (flyspell-unhighlight-at (- end 1))) | |
648 (message "Error in ispell process")) | |
649 ((or (and (< flyspell-duplicate-distance 0) | |
650 (or (save-excursion | |
651 (goto-char start) | |
652 (word-search-backward word | |
653 (point-min) | |
654 t)) | |
655 (save-excursion | |
656 (goto-char end) | |
657 (word-search-forward word | |
658 (point-max) | |
659 t)))) | |
660 (and (> flyspell-duplicate-distance 0) | |
661 (or (save-excursion | |
662 (goto-char start) | |
663 (word-search-backward | |
664 word | |
665 (- start | |
666 flyspell-duplicate-distance) | |
667 t)) | |
668 (save-excursion | |
669 (goto-char end) | |
670 (word-search-forward | |
671 word | |
672 (+ end | |
673 flyspell-duplicate-distance) | |
674 t))))) | |
675 (if flyspell-highlight-flag | |
676 (flyspell-highlight-duplicate-region start end) | |
677 (message (format "misspelling duplicate `%s'" | |
678 word)))) | |
679 (t | |
680 ;; incorrect highlight the location | |
681 (if flyspell-highlight-flag | |
682 (flyspell-highlight-incorrect-region start end) | |
683 (message (format "mispelling `%s'" word))))) | |
684 (goto-char cursor-location) ; return to original location | |
685 (if ispell-quit (setq ispell-quit nil))))))))) | |
686 | |
687 ;*---------------------------------------------------------------------*/ | |
688 ;* flyspell-tex-command-p ... */ | |
689 ;*---------------------------------------------------------------------*/ | |
690 (defun flyspell-tex-command-p (word) | |
691 "Is a word a TeX command?" | |
692 (eq (aref word 0) ?\\)) | |
693 | |
694 ;*---------------------------------------------------------------------*/ | |
695 ;* flyspell-casechars-cache ... */ | |
696 ;*---------------------------------------------------------------------*/ | |
697 (defvar flyspell-casechars-cache nil) | |
698 (defvar flyspell-ispell-casechars-cache nil) | |
699 (make-variable-buffer-local 'flyspell-casechars-cache) | |
700 (make-variable-buffer-local 'flyspell-ispell-casechars-cache) | |
701 | |
702 ;*---------------------------------------------------------------------*/ | |
703 ;* flyspell-get-casechars ... */ | |
704 ;*---------------------------------------------------------------------*/ | |
705 (defun flyspell-get-casechars () | |
706 "This function builds a string that is the regexp of word chars. | |
707 In order | |
708 to avoid one useless string construction, this function changes the last | |
709 char of the ispell-casechars string." | |
710 (let ((ispell-casechars (ispell-get-casechars))) | |
711 (cond | |
712 ((eq ispell-casechars flyspell-ispell-casechars-cache) | |
713 flyspell-casechars-cache) | |
714 ((not (eq ispell-parser 'tex)) | |
715 (setq flyspell-ispell-casechars-cache ispell-casechars) | |
716 (setq flyspell-casechars-cache | |
717 (concat (substring ispell-casechars | |
718 0 | |
719 (- (length ispell-casechars) 1)) | |
720 "{}]")) | |
721 flyspell-casechars-cache) | |
722 (t | |
723 (setq flyspell-ispell-casechars-cache ispell-casechars) | |
724 (setq flyspell-casechars-cache ispell-casechars) | |
725 flyspell-casechars-cache)))) | |
726 | |
727 ;*---------------------------------------------------------------------*/ | |
728 ;* flyspell-get-not-casechars-cache ... */ | |
729 ;*---------------------------------------------------------------------*/ | |
730 (defvar flyspell-not-casechars-cache nil) | |
731 (defvar flyspell-ispell-not-casechars-cache nil) | |
732 (make-variable-buffer-local 'flyspell-not-casechars-cache) | |
733 (make-variable-buffer-local 'flyspell-ispell-not-casechars-cache) | |
734 | |
735 ;*---------------------------------------------------------------------*/ | |
736 ;* flyspell-get-not-casechars ... */ | |
737 ;*---------------------------------------------------------------------*/ | |
738 (defun flyspell-get-not-casechars () | |
739 "This function builds a string that is the regexp of non-word chars." | |
740 (let ((ispell-not-casechars (ispell-get-not-casechars))) | |
741 (cond | |
742 ((eq ispell-not-casechars flyspell-ispell-not-casechars-cache) | |
743 flyspell-not-casechars-cache) | |
744 ((not (eq ispell-parser 'tex)) | |
745 (setq flyspell-ispell-not-casechars-cache ispell-not-casechars) | |
746 (setq flyspell-not-casechars-cache | |
747 (concat (substring ispell-not-casechars | |
748 0 | |
749 (- (length ispell-not-casechars) 1)) | |
750 "{}]")) | |
751 flyspell-not-casechars-cache) | |
752 (t | |
753 (setq flyspell-ispell-not-casechars-cache ispell-not-casechars) | |
754 (setq flyspell-not-casechars-cache ispell-not-casechars) | |
755 flyspell-not-casechars-cache)))) | |
756 | |
757 ;*---------------------------------------------------------------------*/ | |
758 ;* flyspell-get-word ... */ | |
759 ;*---------------------------------------------------------------------*/ | |
760 (defun flyspell-get-word (following) | |
761 "Return the word for spell-checking according to Ispell syntax. | |
762 If optional argument FOLLOWING is non-nil or if `ispell-following-word' | |
763 is non-nil when called interactively, then the following word | |
764 \(rather than preceding\) is checked when the cursor is not over a word. | |
765 Optional second argument contains otherchars that can be included in word | |
766 many times. | |
767 | |
768 Word syntax described by `ispell-dictionary-alist' (which see)." | |
769 (let* ((flyspell-casechars (flyspell-get-casechars)) | |
770 (flyspell-not-casechars (flyspell-get-not-casechars)) | |
771 (ispell-otherchars (ispell-get-otherchars)) | |
772 (ispell-many-otherchars-p (ispell-get-many-otherchars-p)) | |
773 (word-regexp (concat flyspell-casechars | |
774 "+\\(" | |
775 ispell-otherchars | |
776 "?" | |
777 flyspell-casechars | |
778 "+\\)" | |
779 (if ispell-many-otherchars-p | |
780 "*" "?"))) | |
781 (tex-prelude "[\\\\{]") | |
782 (tex-regexp (if (eq ispell-parser 'tex) | |
783 (concat tex-prelude "?" word-regexp "}?") | |
784 word-regexp)) | |
785 | |
786 did-it-once | |
787 start end word) | |
788 ;; find the word | |
789 (if (not (or (looking-at flyspell-casechars) | |
790 (and (eq ispell-parser 'tex) | |
791 (looking-at tex-prelude)))) | |
792 (if following | |
793 (re-search-forward flyspell-casechars (point-max) t) | |
794 (re-search-backward flyspell-casechars (point-min) t))) | |
795 ;; move to front of word | |
796 (re-search-backward flyspell-not-casechars (point-min) 'start) | |
797 (let ((pos nil)) | |
798 (while (and (looking-at ispell-otherchars) | |
799 (not (bobp)) | |
800 (or (not did-it-once) | |
801 ispell-many-otherchars-p) | |
802 (not (eq pos (point)))) | |
803 (setq pos (point)) | |
804 (setq did-it-once t) | |
805 (backward-char 1) | |
806 (if (looking-at flyspell-casechars) | |
807 (re-search-backward flyspell-not-casechars (point-min) 'move) | |
808 (backward-char -1)))) | |
809 ;; Now mark the word and save to string. | |
810 (if (eq (re-search-forward tex-regexp (point-max) t) nil) | |
811 nil | |
812 (progn | |
813 (setq start (match-beginning 0) | |
814 end (point) | |
815 word (buffer-substring start end)) | |
816 (list word start end))))) | |
817 | |
818 ;*---------------------------------------------------------------------*/ | |
819 ;* flyspell-region ... */ | |
820 ;*---------------------------------------------------------------------*/ | |
821 (defun flyspell-region (beg end) | |
822 "Flyspell text between BEG and END." | |
823 (interactive "r") | |
824 (save-excursion | |
825 (goto-char beg) | |
22612
6def3da74c7c
Delete defcustom definition.
Richard M. Stallman <rms@gnu.org>
parents:
22611
diff
changeset
|
826 (let ((count 0)) |
6def3da74c7c
Delete defcustom definition.
Richard M. Stallman <rms@gnu.org>
parents:
22611
diff
changeset
|
827 (while (< (point) end) |
6def3da74c7c
Delete defcustom definition.
Richard M. Stallman <rms@gnu.org>
parents:
22611
diff
changeset
|
828 (if (= count 100) |
6def3da74c7c
Delete defcustom definition.
Richard M. Stallman <rms@gnu.org>
parents:
22611
diff
changeset
|
829 (progn |
6def3da74c7c
Delete defcustom definition.
Richard M. Stallman <rms@gnu.org>
parents:
22611
diff
changeset
|
830 (message "Spell Checking...%d%%" |
6def3da74c7c
Delete defcustom definition.
Richard M. Stallman <rms@gnu.org>
parents:
22611
diff
changeset
|
831 (* 100 (/ (float (point)) (- end beg)))) |
6def3da74c7c
Delete defcustom definition.
Richard M. Stallman <rms@gnu.org>
parents:
22611
diff
changeset
|
832 (setq count 0)) |
6def3da74c7c
Delete defcustom definition.
Richard M. Stallman <rms@gnu.org>
parents:
22611
diff
changeset
|
833 (setq count (+ 1 count))) |
6def3da74c7c
Delete defcustom definition.
Richard M. Stallman <rms@gnu.org>
parents:
22611
diff
changeset
|
834 (flyspell-word) |
6def3da74c7c
Delete defcustom definition.
Richard M. Stallman <rms@gnu.org>
parents:
22611
diff
changeset
|
835 (let ((cur (point))) |
6def3da74c7c
Delete defcustom definition.
Richard M. Stallman <rms@gnu.org>
parents:
22611
diff
changeset
|
836 (forward-word 1) |
6def3da74c7c
Delete defcustom definition.
Richard M. Stallman <rms@gnu.org>
parents:
22611
diff
changeset
|
837 (if (and (< (point) end) (> (point) (+ cur 1))) |
6def3da74c7c
Delete defcustom definition.
Richard M. Stallman <rms@gnu.org>
parents:
22611
diff
changeset
|
838 (backward-char 1))))) |
22611 | 839 (backward-char 1) |
840 (message "Spell Checking...done") | |
841 (flyspell-word))) | |
842 | |
843 ;*---------------------------------------------------------------------*/ | |
844 ;* flyspell-buffer ... */ | |
845 ;*---------------------------------------------------------------------*/ | |
846 (defun flyspell-buffer () | |
847 "Flyspell whole buffer." | |
848 (interactive) | |
849 (flyspell-region (point-min) (point-max))) | |
850 | |
851 ;*---------------------------------------------------------------------*/ | |
852 ;* flyspell-overlay-p ... */ | |
853 ;*---------------------------------------------------------------------*/ | |
854 (defun flyspell-overlay-p (o) | |
855 "A predicate that return true iff O is an overlay used by flyspell." | |
856 (and (overlayp o) (overlay-get o 'flyspell-overlay))) | |
857 | |
858 ;*---------------------------------------------------------------------*/ | |
859 ;* flyspell-delete-all-overlays ... */ | |
860 ;* ------------------------------------------------------------- */ | |
861 ;* Remove all the overlays introduced by flyspell. */ | |
862 ;*---------------------------------------------------------------------*/ | |
863 (defun flyspell-delete-all-overlays () | |
864 "Delete all the overlays used by flyspell." | |
865 (let ((l (overlays-in (point-min) (point-max)))) | |
866 (while (consp l) | |
867 (progn | |
868 (if (flyspell-overlay-p (car l)) | |
869 (delete-overlay (car l))) | |
870 (setq l (cdr l)))))) | |
871 | |
872 ;*---------------------------------------------------------------------*/ | |
873 ;* flyspell-unhighlight-at ... */ | |
874 ;*---------------------------------------------------------------------*/ | |
875 (defun flyspell-unhighlight-at (pos) | |
876 "Remove the flyspell overlay that are located at POS." | |
877 (if flyspell-persistent-highlight | |
878 (let ((overlays (overlays-at pos))) | |
879 (while (consp overlays) | |
880 (if (flyspell-overlay-p (car overlays)) | |
881 (delete-overlay (car overlays))) | |
882 (setq overlays (cdr overlays)))) | |
883 (delete-overlay flyspell-overlay))) | |
884 | |
885 ;*---------------------------------------------------------------------*/ | |
886 ;* flyspell-properties-at-p ... */ | |
887 ;* ------------------------------------------------------------- */ | |
888 ;* Is there an highlight properties at position pos? */ | |
889 ;*---------------------------------------------------------------------*/ | |
890 (defun flyspell-properties-at-p (beg) | |
891 "Return the text property at position BEG." | |
892 (let ((prop (text-properties-at beg)) | |
893 (keep t)) | |
894 (while (and keep (consp prop)) | |
895 (if (and (eq (car prop) 'local-map) (consp (cdr prop))) | |
896 (setq prop (cdr (cdr prop))) | |
897 (setq keep nil))) | |
898 (consp prop))) | |
899 | |
900 ;*---------------------------------------------------------------------*/ | |
901 ;* make-flyspell-overlay ... */ | |
902 ;*---------------------------------------------------------------------*/ | |
903 (defun make-flyspell-overlay (beg end face mouse-face) | |
904 "Allocate a new flyspell overlay that will be used to hilight | |
905 an incorrect word." | |
906 (let ((flyspell-overlay (make-overlay beg end))) | |
907 (overlay-put flyspell-overlay 'face face) | |
908 (overlay-put flyspell-overlay 'mouse-face mouse-face) | |
909 (overlay-put flyspell-overlay 'flyspell-overlay t) | |
910 (if (eq flyspell-emacs 'xemacs) | |
911 (overlay-put flyspell-overlay | |
912 flyspell-overlay-keymap-property-name | |
913 flyspell-mouse-map)))) | |
914 | |
915 ;*---------------------------------------------------------------------*/ | |
916 ;* flyspell-highlight-incorrect-region ... */ | |
917 ;*---------------------------------------------------------------------*/ | |
918 (defun flyspell-highlight-incorrect-region (beg end) | |
919 "The setup of an overlay on a region (starting at BEG and ending at END) | |
920 that corresponds to an incorrect word." | |
921 (run-hook-with-args 'flyspell-incorrect-hook beg end) | |
922 (if (or (not (flyspell-properties-at-p beg)) flyspell-highlight-properties) | |
923 (progn | |
924 ;; we cleanup current overlay at the same position | |
925 (if (and (not flyspell-persistent-highlight) | |
926 (overlayp flyspell-overlay)) | |
927 (delete-overlay flyspell-overlay) | |
928 (let ((overlays (overlays-at beg))) | |
929 (while (consp overlays) | |
930 (if (flyspell-overlay-p (car overlays)) | |
931 (delete-overlay (car overlays))) | |
932 (setq overlays (cdr overlays))))) | |
933 ;; now we can use a new overlay | |
934 (setq flyspell-overlay | |
935 (make-flyspell-overlay beg end | |
936 'flyspell-incorrect-face 'highlight))))) | |
937 | |
938 ;*---------------------------------------------------------------------*/ | |
939 ;* flyspell-highlight-duplicate-region ... */ | |
940 ;*---------------------------------------------------------------------*/ | |
941 (defun flyspell-highlight-duplicate-region (beg end) | |
942 "The setup of an overlay on a region (starting at BEG and ending at END) | |
943 that corresponds to an duplicated word." | |
944 (if (or (not (flyspell-properties-at-p beg)) flyspell-highlight-properties) | |
945 (progn | |
946 ;; we cleanup current overlay at the same position | |
947 (if (and (not flyspell-persistent-highlight) | |
948 (overlayp flyspell-overlay)) | |
949 (delete-overlay flyspell-overlay) | |
950 (let ((overlays (overlays-at beg))) | |
951 (while (consp overlays) | |
952 (if (flyspell-overlay-p (car overlays)) | |
953 (delete-overlay (car overlays))) | |
954 (setq overlays (cdr overlays))))) | |
955 ;; now we can use a new overlay | |
956 (setq flyspell-overlay | |
957 (make-flyspell-overlay beg end | |
958 'flyspell-duplicate-face 'highlight))))) | |
959 | |
960 ;*---------------------------------------------------------------------*/ | |
961 ;* flyspell-auto-correct-cache ... */ | |
962 ;*---------------------------------------------------------------------*/ | |
963 (defvar flyspell-auto-correct-pos nil) | |
964 (defvar flyspell-auto-correct-region nil) | |
965 (defvar flyspell-auto-correct-ring nil) | |
966 | |
967 ;*---------------------------------------------------------------------*/ | |
968 ;* flyspell-auto-correct-word ... */ | |
969 ;*---------------------------------------------------------------------*/ | |
970 (defun flyspell-auto-correct-word (pos) | |
971 "Auto correct the word at position POS." | |
972 (interactive "d") | |
973 ;; use the correct dictionary | |
974 (ispell-accept-buffer-local-defs) | |
975 (if (eq flyspell-auto-correct-pos pos) | |
976 ;; we have already been using the function at the same location | |
977 (progn | |
978 (save-excursion | |
979 (let ((start (car flyspell-auto-correct-region)) | |
980 (len (cdr flyspell-auto-correct-region))) | |
981 (delete-region start (+ start len)) | |
982 (setq flyspell-auto-correct-ring (cdr flyspell-auto-correct-ring)) | |
983 (let* ((word (car flyspell-auto-correct-ring)) | |
984 (len (length word))) | |
985 (rplacd flyspell-auto-correct-region len) | |
986 (goto-char start) | |
987 (insert word)))) | |
988 (setq flyspell-auto-correct-pos (point))) | |
989 ;; retain cursor location | |
990 (let ((cursor-location pos) | |
991 (word (flyspell-get-word nil)) | |
992 start end poss) | |
993 ;; destructure return word info list. | |
994 (setq start (car (cdr word)) | |
995 end (car (cdr (cdr word))) | |
996 word (car word)) | |
997 ;; now check spelling of word. | |
998 (process-send-string ispell-process "%\n") ;put in verbose mode | |
999 (process-send-string ispell-process (concat "^" word "\n")) | |
1000 ;; wait until ispell has processed word | |
1001 (while (progn | |
1002 (accept-process-output ispell-process) | |
1003 (not (string= "" (car ispell-filter))))) | |
1004 (setq ispell-filter (cdr ispell-filter)) | |
1005 (if (listp ispell-filter) | |
1006 (setq poss (ispell-parse-output (car ispell-filter)))) | |
1007 (cond ((or (eq poss t) (stringp poss)) | |
1008 ;; don't correct word | |
1009 t) | |
1010 ((null poss) | |
1011 ;; ispell error | |
1012 (error "Ispell: error in Ispell process")) | |
1013 (t | |
1014 ;; the word is incorrect, we have to propose a replacement | |
1015 (let ((replacements (if flyspell-sort-corrections | |
1016 (sort (car (cdr (cdr poss))) 'string<) | |
1017 (car (cdr (cdr poss)))))) | |
1018 (if (consp replacements) | |
1019 (progn | |
1020 (let ((replace (car replacements))) | |
1021 (setq word replace) | |
1022 (setq cursor-location (+ (- (length word) (- end start)) | |
1023 cursor-location)) | |
1024 (if (not (equal word (car poss))) | |
1025 (progn | |
1026 ;; the save the current replacements | |
1027 (setq flyspell-auto-correct-pos cursor-location) | |
1028 (setq flyspell-auto-correct-region | |
1029 (cons start (length word))) | |
1030 (let ((l replacements)) | |
1031 (while (consp (cdr l)) | |
1032 (setq l (cdr l))) | |
1033 (rplacd l (cons (car poss) replacements))) | |
1034 (setq flyspell-auto-correct-ring | |
1035 (cdr replacements)) | |
1036 (delete-region start end) | |
1037 (insert word))))))))) | |
1038 ;; return to original location | |
1039 (goto-char cursor-location) | |
1040 (ispell-pdict-save t)))) | |
1041 | |
1042 ;*---------------------------------------------------------------------*/ | |
1043 ;* flyspell-correct-word ... */ | |
1044 ;*---------------------------------------------------------------------*/ | |
1045 (defun flyspell-correct-word (event) | |
1046 "Check spelling of word under or before the cursor. | |
1047 If the word is not found in dictionary, display possible corrections | |
1048 in a popup menu allowing you to choose one. | |
1049 | |
1050 Word syntax described by `ispell-dictionary-alist' (which see). | |
1051 | |
1052 This will check or reload the dictionary. Use \\[ispell-change-dictionary] | |
1053 or \\[ispell-region] to update the Ispell process." | |
1054 (interactive "e") | |
1055 (if (eq flyspell-emacs 'xemacs) | |
1056 (flyspell-correct-word/mouse-keymap event) | |
1057 (flyspell-correct-word/local-keymap event))) | |
1058 | |
1059 ;*---------------------------------------------------------------------*/ | |
1060 ;* flyspell-correct-word/local-keymap ... */ | |
1061 ;*---------------------------------------------------------------------*/ | |
1062 (defun flyspell-correct-word/local-keymap (event) | |
1063 "emacs 19.xx seems to be buggous. Overlay keymap does not seems | |
1064 to work correctly with local map. That is, if a key is not | |
1065 defined for the overlay keymap, the current local map, is not | |
1066 checked. The binding is resolved with the global map. The | |
1067 consequence is that we can not use overlay map with flyspell." | |
1068 (interactive "e") | |
1069 (save-window-excursion | |
1070 (let ((save (point))) | |
1071 (mouse-set-point event) | |
1072 ;; we look for a flyspell overlay here | |
1073 (let ((overlays (overlays-at (point))) | |
1074 (overlay nil)) | |
1075 (while (consp overlays) | |
1076 (if (flyspell-overlay-p (car overlays)) | |
1077 (progn | |
1078 (setq overlay (car overlays)) | |
1079 (setq overlays nil)) | |
1080 (setq overlays (cdr overlays)))) | |
1081 ;; we return to the correct location | |
1082 (goto-char save) | |
1083 ;; we check to see if button2 has been used overlay a | |
1084 ;; flyspell overlay | |
1085 (if overlay | |
1086 ;; yes, so we use the flyspell function | |
1087 (flyspell-correct-word/mouse-keymap event) | |
1088 ;; no so we have to use the non flyspell binding | |
1089 (let ((flyspell-mode nil)) | |
1090 (if (key-binding (this-command-keys)) | |
1091 (command-execute (key-binding (this-command-keys)))))))))) | |
1092 | |
1093 ;*---------------------------------------------------------------------*/ | |
1094 ;* flyspell-correct-word ... */ | |
1095 ;*---------------------------------------------------------------------*/ | |
1096 (defun flyspell-correct-word/mouse-keymap (event) | |
1097 "Popup a menu to present possible correction. The word checked is the | |
1098 word at the mouse position." | |
1099 (interactive "e") | |
1100 ;; use the correct dictionary | |
1101 (ispell-accept-buffer-local-defs) | |
1102 ;; retain cursor location (I don't know why but save-excursion here fails). | |
1103 (let ((save (point))) | |
1104 (mouse-set-point event) | |
1105 (let ((cursor-location (point)) | |
1106 (word (flyspell-get-word nil)) | |
1107 start end poss replace) | |
1108 ;; destructure return word info list. | |
1109 (setq start (car (cdr word)) | |
1110 end (car (cdr (cdr word))) | |
1111 word (car word)) | |
1112 ;; now check spelling of word. | |
1113 (process-send-string ispell-process "%\n") ;put in verbose mode | |
1114 (process-send-string ispell-process (concat "^" word "\n")) | |
1115 ;; wait until ispell has processed word | |
1116 (while (progn | |
1117 (accept-process-output ispell-process) | |
1118 (not (string= "" (car ispell-filter))))) | |
1119 (setq ispell-filter (cdr ispell-filter)) | |
1120 (if (listp ispell-filter) | |
1121 (setq poss (ispell-parse-output (car ispell-filter)))) | |
1122 (cond ((or (eq poss t) (stringp poss)) | |
1123 ;; don't correct word | |
1124 t) | |
1125 ((null poss) | |
1126 ;; ispell error | |
1127 (error "Ispell: error in Ispell process")) | |
1128 ((string-match "GNU" (emacs-version)) | |
1129 ;; the word is incorrect, we have to propose a replacement | |
1130 (setq replace (flyspell-gnuemacs-popup event poss word)) | |
1131 (cond ((eq replace 'ignore) | |
1132 nil) | |
1133 ((eq replace 'save) | |
1134 (process-send-string ispell-process (concat "*" word "\n")) | |
1135 (flyspell-unhighlight-at cursor-location) | |
1136 (setq ispell-pdict-modified-p '(t))) | |
1137 ((or (eq replace 'buffer) (eq replace 'session)) | |
1138 (process-send-string ispell-process (concat "@" word "\n")) | |
1139 (if (null ispell-pdict-modified-p) | |
1140 (setq ispell-pdict-modified-p | |
1141 (list ispell-pdict-modified-p))) | |
1142 (flyspell-unhighlight-at cursor-location) | |
1143 (if (eq replace 'buffer) | |
1144 (ispell-add-per-file-word-list word))) | |
1145 (replace | |
1146 (setq word (if (atom replace) replace (car replace)) | |
1147 cursor-location (+ (- (length word) (- end start)) | |
1148 cursor-location)) | |
1149 (if (not (equal word (car poss))) | |
1150 (progn | |
1151 (delete-region start end) | |
1152 (insert word)))))) | |
1153 ((string-match "XEmacs" (emacs-version)) | |
1154 (flyspell-xemacs-popup | |
1155 event poss word cursor-location start end))) | |
1156 (ispell-pdict-save t)) | |
1157 (if (< save (point-max)) | |
1158 (goto-char save) | |
1159 (goto-char (point-max))))) | |
1160 | |
1161 ;*---------------------------------------------------------------------*/ | |
1162 ;* flyspell-xemacs-correct ... */ | |
1163 ;*---------------------------------------------------------------------*/ | |
1164 (defun flyspell-xemacs-correct (replace poss word cursor-location start end) | |
1165 "The xemacs popup menu callback." | |
1166 (cond ((eq replace 'ignore) | |
1167 nil) | |
1168 ((eq replace 'save) | |
1169 (process-send-string ispell-process (concat "*" word "\n")) | |
1170 (flyspell-unhighlight-at cursor-location) | |
1171 (setq ispell-pdict-modified-p '(t))) | |
1172 ((or (eq replace 'buffer) (eq replace 'session)) | |
1173 (process-send-string ispell-process (concat "@" word "\n")) | |
1174 (flyspell-unhighlight-at cursor-location) | |
1175 (if (null ispell-pdict-modified-p) | |
1176 (setq ispell-pdict-modified-p | |
1177 (list ispell-pdict-modified-p))) | |
1178 (if (eq replace 'buffer) | |
1179 (ispell-add-per-file-word-list word))) | |
1180 (replace | |
1181 (setq word (if (atom replace) replace (car replace)) | |
1182 cursor-location (+ (- (length word) (- end start)) | |
1183 cursor-location)) | |
1184 (if (not (equal word (car poss))) | |
1185 (save-excursion | |
1186 (delete-region start end) | |
1187 (goto-char start) | |
1188 (insert word)))))) | |
1189 | |
1190 ;*---------------------------------------------------------------------*/ | |
1191 ;* flyspell-gnuemacs-popup */ | |
1192 ;*---------------------------------------------------------------------*/ | |
1193 (defun flyspell-gnuemacs-popup (event poss word) | |
1194 "The gnu-emacs popup menu." | |
1195 (if (not event) | |
1196 (let* ((mouse-pos (mouse-position)) | |
1197 (mouse-pos (if (nth 1 mouse-pos) | |
1198 mouse-pos | |
1199 (set-mouse-position (car mouse-pos) | |
1200 (/ (frame-width) 2) 2) | |
1201 (unfocus-frame) | |
1202 (mouse-position)))) | |
1203 (setq event (list (list (car (cdr mouse-pos)) | |
1204 (1+ (cdr (cdr mouse-pos)))) | |
1205 (car mouse-pos))))) | |
1206 (let* ((corrects (if flyspell-sort-corrections | |
1207 (sort (car (cdr (cdr poss))) 'string<) | |
1208 (car (cdr (cdr poss))))) | |
1209 (cor-menu (if (consp corrects) | |
1210 (mapcar (lambda (correct) | |
1211 (list correct correct)) | |
1212 corrects) | |
1213 '())) | |
1214 (affix (car (cdr (cdr (cdr poss))))) | |
1215 (base-menu (let ((save (if (consp affix) | |
1216 (list | |
1217 (list (concat "Save affix: " (car affix)) | |
1218 'save) | |
1219 '("Accept (session)" accept) | |
1220 '("Accept (buffer)" buffer)) | |
1221 '(("Save word" save) | |
1222 ("Accept (session)" session) | |
1223 ("Accept (buffer)" buffer))))) | |
1224 (if (consp cor-menu) | |
1225 (append cor-menu (cons "" save)) | |
1226 save))) | |
1227 (menu (cons "flyspell correction menu" base-menu))) | |
1228 (car (x-popup-menu event | |
1229 (list (format "%s [%s]" word (or ispell-local-dictionary | |
1230 ispell-dictionary)) | |
1231 menu))))) | |
1232 | |
1233 ;*---------------------------------------------------------------------*/ | |
1234 ;* flyspell-xemacs-popup */ | |
1235 ;*---------------------------------------------------------------------*/ | |
1236 (defun flyspell-xemacs-popup (event poss word cursor-location start end) | |
1237 "The xemacs popup menu." | |
1238 (let* ((corrects (if flyspell-sort-corrections | |
1239 (sort (car (cdr (cdr poss))) 'string<) | |
1240 (car (cdr (cdr poss))))) | |
1241 (cor-menu (if (consp corrects) | |
1242 (mapcar (lambda (correct) | |
1243 (vector correct | |
1244 (list 'flyspell-xemacs-correct | |
1245 correct | |
1246 (list 'quote poss) | |
1247 word | |
1248 cursor-location | |
1249 start | |
1250 end) | |
1251 t)) | |
1252 corrects) | |
1253 '())) | |
1254 (affix (car (cdr (cdr (cdr poss))))) | |
1255 (menu (let ((save (if (consp affix) | |
1256 (vector | |
1257 (concat "Save affix: " (car affix)) | |
1258 (list 'flyspell-xemacs-correct | |
1259 ''save | |
1260 (list 'quote poss) | |
1261 word | |
1262 cursor-location | |
1263 start | |
1264 end) | |
1265 t) | |
1266 (vector | |
1267 "Save word" | |
1268 (list 'flyspell-xemacs-correct | |
1269 ''save | |
1270 (list 'quote poss) | |
1271 word | |
1272 cursor-location | |
1273 start | |
1274 end) | |
1275 t))) | |
1276 (session (vector "Accept (session)" | |
1277 (list 'flyspell-xemacs-correct | |
1278 ''session | |
1279 (list 'quote poss) | |
1280 word | |
1281 cursor-location | |
1282 start | |
1283 end) | |
1284 t)) | |
1285 (buffer (vector "Accept (buffer)" | |
1286 (list 'flyspell-xemacs-correct | |
1287 ''buffer | |
1288 (list 'quote poss) | |
1289 word | |
1290 cursor-location | |
1291 start | |
1292 end) | |
1293 t))) | |
1294 (if (consp cor-menu) | |
1295 (append cor-menu (list "-" save session buffer)) | |
1296 (list save session buffer))))) | |
1297 (popup-menu (cons (format "%s [%s]" word (or ispell-local-dictionary | |
1298 ispell-dictionary)) | |
1299 menu)))) | |
1300 | |
1301 (provide 'flyspell) | |
1302 | |
1303 ;;; flyspell.el ends here |