-;;; flyspell.el --- On-the-fly spell checker
+;;; flyspell.el --- on-the-fly spell checker
-;; Copyright (C) 1998, 2000 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 2000, 2001 Free Software Foundation, Inc.
;; Author: Manuel Serrano <Manuel.Serrano@unice.fr>
;; Keywords: convenience
-;;; This file is part of GNU Emacs.
+;; This file is part of GNU Emacs.
;; GNU Emacs is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; Flyspell is a minor Emacs mode performing on-the-fly spelling
;; checking.
;;
-;; To enable Flyspell minor mode, type Meta-x flyspell-mode.
+;; To enable Flyspell minor mode, type M-x flyspell-mode.
;; This applies only to the current buffer.
;;
;; To enable Flyspell in text representing computer programs, type
-;; Meta-x flyspell-prog-mode.
-;; In that mode only text inside comments are checked.
+;; M-x flyspell-prog-mode.
+;; In that mode only text inside comments is checked.
;;
;; Note: consider setting the variable ispell-parser to `tex' to
;; avoid TeX command checking; use `(setq ispell-parser 'tex)'.
;* Group ... */
;*---------------------------------------------------------------------*/
(defgroup flyspell nil
- "Spellchecking on the fly."
+ "Spell checking on the fly."
:tag "FlySpell"
:prefix "flyspell-"
:group 'processes)
(defcustom flyspell-sort-corrections nil
"*Non-nil means, sort the corrections alphabetically before popping them."
:group 'flyspell
+ :version "21.1"
:type 'boolean)
(defcustom flyspell-duplicate-distance -1
-1 means no limit (search the whole buffer).
0 means do not search for duplicate unrecognized spellings."
:group 'flyspell
+ :version "21.1"
:type 'number)
(defcustom flyspell-delay 3
"The standard list of delayed commands for Flyspell.
See `flyspell-delayed-commands'."
:group 'flyspell
+ :version "21.1"
:type '(repeat (symbol)))
(defcustom flyspell-delayed-commands nil
"The standard list of deplacement commands for Flyspell.
See `flyspell-deplacement-commands'."
:group 'flyspell
+ :version "21.1"
:type '(repeat (symbol)))
(defcustom flyspell-deplacement-commands nil
After these commands, Flyspell checking is performed only if the previous
command was not the very same command."
:group 'flyspell
+ :version "21.1"
:type '(repeat (symbol)))
(defcustom flyspell-issue-welcome-flag t
(defcustom flyspell-incorrect-hook nil
"*List of functions to be called when incorrect words are encountered.
Each function is given three arguments: the beginning and the end
-of the incorrect region. The third is either the symbol 'doublon' or the list
-of possible corrections returned as returned by 'ispell-parse-output'.
+of the incorrect region. The third is either the symbol 'doublon' or the list
+of possible corrections as returned by 'ispell-parse-output'.
-If any of the functions return non-Nil, the word is not highligted as
+If any of the functions return non-Nil, the word is not highlighted as
incorrect."
:group 'flyspell
+ :version "21.1"
:type 'hook)
-(defcustom flyspell-default-dictionary "american"
+(defcustom flyspell-default-dictionary nil
"A string that is the name of the default dictionary.
-This is passed to the ispell-change-dictionary when flyspell is started.
-If the variables ispell-local-dictionary or ispell-dictionary are non nil
-when flyspell is started, the value of that variables is used instead
-of flyspell-default-dictionary to select the default dictionary."
+This is passed to the `ispell-change-dictionary' when flyspell is started.
+If the variable `ispell-local-dictionary' or `ispell-dictionary' is non-nil
+when flyspell is started, the value of that variable is used instead
+of `flyspell-default-dictionary' to select the default dictionary.
+Otherwise, if `flyspell-default-dictionary' is nil, it means to use
+Ispell's ultimate default dictionary."
:group 'flyspell
- :type 'string)
+ :version "21.1"
+ :type '(choice string (const :tag "Default" nil)))
(defcustom flyspell-tex-command-regexp
"\\(\\(begin\\|end\\)[ \t]*{\\|\\(cite[a-z*]*\\|label\\|ref\\|eqref\\|usepackage\\|documentclass\\)[ \t]*\\(\\[[^]]*\\]\\)?{[^{}]*\\)"
"A string that is the regular expression that matches TeX commands."
:group 'flyspell
+ :version "21.1"
:type 'string)
(defcustom flyspell-check-tex-math-command nil
- "*Non nils means check even inside TeX math environement. TeX math
-environement are discovered byt eh TEXMATHP that is implemented inside
-the eponyme emacs package. That package may be found at:
+ "*Non nil means check even inside TeX math environment.
+TeX math environments are discovered by the TEXMATHP that implemented
+inside the texmathp.el Emacs package. That package may be found at:
http://strw.leidenuniv.nl/~dominik/Tools"
:group 'flyspell
:type 'boolean)
'("francais" "deutsch8" "norsk")
"List of dictionary names that consider `-' as word delimiter."
:group 'flyspell
+ :version "21.1"
:type '(repeat (string)))
(defcustom flyspell-abbrev-p
t
"*If true, add correction to abbreviation table."
:group 'flyspell
+ :version "21.1"
:type 'boolean)
(defcustom flyspell-use-global-abbrev-table-p
nil
"*If true, prefer global abbrev table to local abbrev table."
:group 'flyspell
+ :version "21.1"
:type 'boolean)
;;;###autoload
:type 'string)
(defcustom flyspell-large-region 1000
- "*The threshold that determines if an region is small. The flyspell-region
-is invoked, if the region is small, the word are checked one after the
-other using regular flyspell check means. If the region is large, a new
-ispell process is spawned to get speed."
+ "*The threshold that determines if a region is small.
+The `flyspell-region' function is invoked if the region is small, the
+word are checked one after the other using regular flyspell check
+means. If the region is large, a new Ispell process is spawned to get
+speed."
:group 'flyspell
+ :version "21.1"
:type 'number)
;*---------------------------------------------------------------------*/
(put 'message-mode 'flyspell-mode-predicate 'mail-mode-flyspell-verify)
(defun mail-mode-flyspell-verify ()
"This function is used for `flyspell-generic-check-word-p' in Mail mode."
- (save-excursion
- (not (or (re-search-forward mail-header-separator nil t)
- (re-search-backward message-signature-separator nil t)
- (progn
- (beginning-of-line)
- (looking-at "[>}|]\\To:"))))))
+ (let ((in-headers (save-excursion
+ (re-search-forward mail-header-separator nil t)))
+ (in-signature (save-excursion
+ (re-search-backward message-signature-separator nil t))))
+ (cond (in-headers
+ (and (save-excursion (beginning-of-line)
+ (looking-at "^Subject:"))
+ (> (point) (match-end 0))))
+ (in-signature
+ nil)
+ (t
+ (save-excursion
+ (beginning-of-line)
+ (not (looking-at "[>}|]\\To:")))))))
;*--- texinfo mode ----------------------------------------------------*/
(put 'texinfo-mode 'flyspell-mode-predicate 'texinfo-mode-flyspell-verify)
;*---------------------------------------------------------------------*/
;* Programming mode */
;*---------------------------------------------------------------------*/
+(defvar flyspell-prog-text-faces
+ '(font-lock-string-face font-lock-comment-face font-lock-doc-face)
+ "Faces corresponding to text in programming-mode buffers.")
+
(defun flyspell-generic-progmode-verify ()
"Used for `flyspell-generic-check-word-p' in programming modes."
(let ((f (get-text-property (point) 'face)))
- (memq f '(font-lock-comment-face font-lock-string-face))))
+ (memq f flyspell-prog-text-faces)))
;;;###autoload
(defun flyspell-prog-mode ()
(let ((map (make-sparse-keymap)))
(cond
((eq flyspell-emacs 'xemacs)
- (define-key map [(button2)]
- #'flyspell-correct-word/mouse-keymap)
+ (define-key map [(button2)] #'flyspell-correct-word)
(define-key map "\M-\t" #'flyspell-auto-correct-word))
(flyspell-use-local-map
- (define-key map [(mouse-2)] #'flyspell-correct-word/mouse-keymap)
+ (define-key map [(mouse-2)] #'flyspell-correct-word)
(define-key map "\M-\t" #'flyspell-auto-correct-word)))
map))
(setq minor-mode-map-alist
(cons (cons 'flyspell-mode flyspell-mode-map)
minor-mode-map-alist)))
- (define-key flyspell-mode-map "\M-\t" 'flyspell-auto-correct-word)
- (define-key flyspell-mode-map [(mouse-2)]
- (function flyspell-correct-word/local-keymap)))
-
+ (define-key flyspell-mode-map "\M-\t" 'flyspell-auto-correct-word))
;; the name of the overlay property that defines the keymap
-(defvar flyspell-overlay-keymap-property-name
- (if (string-match "19.*XEmacs" emacs-version)
- 'keymap
- 'local-map))
+(defvar flyspell-overlay-keymap-property-name 'keymap)
;; dash character machinery
(defvar flyspell-consider-dash-as-word-delimiter-flag nil
;* Highlighting */
;*---------------------------------------------------------------------*/
(defface flyspell-incorrect-face
- '((((class color)) (:foreground "OrangeRed" :bold t :underline t))
- (t (:bold t)))
+ '((((class color)) (:foreground "OrangeRed" :weight bold :underline t))
+ (t (:weight bold)))
"Face used for marking a misspelled word in Flyspell."
:group 'flyspell)
(defface flyspell-duplicate-face
- '((((class color)) (:foreground "Gold3" :bold t :underline t))
- (t (:bold t)))
+ '((((class color)) (:foreground "Gold3" :weight bold :underline t))
+ (t (:weight bold)))
"Face used for marking a misspelled word that appears twice in the buffer.
See also `flyspell-duplicate-distance'."
:group 'flyspell)
\\[flyspell-correct-word] (or mouse-2): popup correct words.
Hooks:
-flyspell-mode-hook is run after flyspell is entered.
+This runs `flyspell-mode-hook' after flyspell is entered.
Remark:
`flyspell-mode' uses `ispell-mode'. Thus all Ispell options are
\(add-hook 'tex-mode-hook (function (lambda () (setq ispell-parser 'tex))))
in your .emacs file.
-flyspell-region checks all words inside a region.
-
-flyspell-buffer checks the whole buffer."
+\\[flyspell-region] checks all words inside a region.
+\\[flyspell-buffer] checks the whole buffer."
(interactive "P")
(let ((old-flyspell-mode flyspell-mode))
;; Mark the mode as on or off.
;*---------------------------------------------------------------------*/
;* Autoloading */
;*---------------------------------------------------------------------*/
-;;;###autoload
-(if (fboundp 'add-minor-mode)
- (add-minor-mode 'flyspell-mode
- 'flyspell-mode-line-string
- flyspell-mode-map
- nil
- 'flyspell-mode)
- (or (assoc 'flyspell-mode minor-mode-alist)
- (setq minor-mode-alist
- (cons '(flyspell-mode flyspell-mode-line-string)
- minor-mode-alist)))
-
- (or (assoc 'flyspell-mode minor-mode-map-alist)
- (setq minor-mode-map-alist
- (cons (cons 'flyspell-mode flyspell-mode-map)
- minor-mode-map-alist))))
-
+;;;###autoload
+(add-minor-mode 'flyspell-mode
+ 'flyspell-mode-line-string
+ flyspell-mode-map
+ nil
+ 'flyspell-mode)
;*---------------------------------------------------------------------*/
;* flyspell-buffers ... */
;; we put the `flyspel-deplacement' property on some commands
(flyspell-deplacement-commands)
;; we bound flyspell action to post-command hook
- (make-local-hook 'post-command-hook)
(add-hook 'post-command-hook (function flyspell-post-command-hook) t t)
;; we bound flyspell action to pre-command hook
- (make-local-hook 'pre-command-hook)
(add-hook 'pre-command-hook (function flyspell-pre-command-hook) t t)
;; we bound flyspell action to after-change hook
(make-local-variable 'after-change-functions)
(let ((mode-predicate (get major-mode 'flyspell-mode-predicate)))
(if mode-predicate
(setq flyspell-generic-check-word-p mode-predicate)))
- ;; work around the fact that the `local-map' text-property replaces the
- ;; buffer's local map rather than shadowing it.
- (set (make-local-variable 'flyspell-mouse-map)
- (let ((map (copy-keymap flyspell-mouse-map)))
- (set-keymap-parent map (current-local-map))
- map))
;; the welcome message
- (if flyspell-issue-welcome-flag
+ (if (and flyspell-issue-welcome-flag (interactive-p))
(let ((binding (where-is-internal 'flyspell-auto-correct-word
nil 'non-ascii)))
(message
(format "Welcome to flyspell. Use %s or Mouse-2 to correct words."
(key-description binding))
"Welcome to flyspell. Use Mouse-2 to correct words."))))
-
- ;; Use this so that we can still get major mode bindings at a
- ;; misspelled word (unless they're overridden by
- ;; `flyspell-mouse-map').
- (set (make-local-variable 'flyspell-local-mouse-map)
- (let ((map (copy-keymap flyspell-mouse-map)))
- (if (eq flyspell-emacs 'xemacs)
- (set-keymap-parents (list (current-local-map)))
- (set-keymap-parent map (current-local-map)))
- map))
;; we end with the flyspell hooks
(run-hooks 'flyspell-mode-hook))
(defun flyspell-delay-command (command)
"Set COMMAND to be delayed, for Flyspell.
When flyspell `post-command-hook' is invoked because a delayed command
-as been used the current word is not immediatly checked.
+as been used the current word is not immediately checked.
It will be checked only after `flyspell-delay' seconds."
(interactive "SDelay Flyspell after Command: ")
(put command 'flyspell-delayed t))
(insert (format " %S : %S\n" msg obj)))))
;*---------------------------------------------------------------------*/
-;* flyspell-debug-signal-pre-word-checked ... */
+;* flyspell-debug-signal-pre-word-checked ... */
;*---------------------------------------------------------------------*/
(defun flyspell-debug-signal-pre-word-checked ()
(setq debug-on-error t)
(goto-char (point-max)))))
;*---------------------------------------------------------------------*/
-;* flyspell-debug-signal-word-checked ... */
+;* flyspell-debug-signal-word-checked ... */
;*---------------------------------------------------------------------*/
(defun flyspell-debug-signal-word-checked ()
(setq debug-on-error t)
(goto-char (point-max)))))
;*---------------------------------------------------------------------*/
-;* flyspell-debug-signal-changed-checked ... */
+;* flyspell-debug-signal-changed-checked ... */
;*---------------------------------------------------------------------*/
(defun flyspell-debug-signal-changed-checked ()
(setq debug-on-error t)
(setq following ispell-following-word))
(save-excursion
;; use the correct dictionary
- (flyspell-accept-buffer-local-defs)
+ (flyspell-accept-buffer-local-defs)
(let* ((cursor-location (point))
(flyspell-word (flyspell-get-word following))
start end poss word)
(flyspell-highlight-incorrect-region start end poss)
(flyspell-notify-misspell start end word poss))))
;; return to original location
- (goto-char cursor-location)
+ (goto-char cursor-location)
(if ispell-quit (setq ispell-quit nil)))))))))
;*---------------------------------------------------------------------*/
If argument FOLLOWING is non-nil or if `ispell-following-word'
is non-nil when called interactively, then the following word
\(rather than preceding\) is checked when the cursor is not over a word.
-Optional second argument contains otherchars that can be included in word
+Optional second argument contains other chars that can be included in word
many times.
Word syntax described by `ispell-dictionary-alist' (which see)."
(progn
(setq start (match-beginning 0)
end (point)
- word (buffer-substring start end))
+ word (buffer-substring-no-properties start end))
(list word start end)))))
;*---------------------------------------------------------------------*/
;* flyspell-external-ispell-process ... */
;*---------------------------------------------------------------------*/
(defvar flyspell-external-ispell-process '()
- "The external Flyspell ispell process")
+ "The external Flyspell Ispell process.")
;*---------------------------------------------------------------------*/
;* flyspell-external-ispell-buffer ... */
(setq flyspell-large-region-end end)
(set-buffer buffer)
(erase-buffer)
- ;; this is done, we can start ckecking...
+ ;; this is done, we can start checking...
(message "Checking region...")
(set-buffer curbuf)
(let ((c (apply 'call-process-region beg
;* pointed out words are then searched in the region a checked with */
;* regular flyspell means. */
;*---------------------------------------------------------------------*/
+;;;###autoload
(defun flyspell-region (beg end)
"Flyspell text between BEG and END."
(interactive "r")
;*---------------------------------------------------------------------*/
;* flyspell-buffer ... */
;*---------------------------------------------------------------------*/
+;;;###autoload
(defun flyspell-buffer ()
"Flyspell whole buffer."
(interactive)
(setq ovs (cdr ovs))))
(not r)))
(setq pos (1+ pos)))
- ;; save the current location for next invokation
+ ;; save the current location for next invocation
(setq flyspell-old-pos-error pos)
(setq flyspell-old-buffer-error (current-buffer))
(goto-char pos)
(if flyspell-use-local-map
(overlay-put flyspell-overlay
flyspell-overlay-keymap-property-name
- flyspell-local-mouse-map))
+ flyspell-mouse-map))
flyspell-overlay))
;*---------------------------------------------------------------------*/
;* flyspell-check-previous-highlighted-word ... */
;*---------------------------------------------------------------------*/
(defun flyspell-check-previous-highlighted-word (&optional arg)
- "Correct the closer mispelled word.
+ "Correct the closer misspelled word.
This function scans a mis-spelled word before the cursor. If it finds one
it proposes replacement for that word. With prefix arg, count that many
misspelled words backwards."
(save-excursion
(goto-char pos)
(ispell-word))
- (error "No word to correct before point."))))
+ (error "No word to correct before point"))))
;*---------------------------------------------------------------------*/
;* flyspell-display-next-corrections ... */
old-max))))))))))
(setq flyspell-auto-correct-pos (point))
(ispell-pdict-save t)))))
-
+
;*---------------------------------------------------------------------*/
;* flyspell-correct-word ... */
;*---------------------------------------------------------------------*/
(defun flyspell-correct-word (event)
- "Check spelling of word under or before the cursor.
-If the word is not found in dictionary, display possible corrections
-in a popup menu allowing you to choose one.
-
-Word syntax described by `ispell-dictionary-alist' (which see).
-
-This will check or reload the dictionary. Use \\[ispell-change-dictionary]
-or \\[ispell-region] to update the Ispell process."
- (interactive "e")
- (if (eq flyspell-emacs 'xemacs)
- (flyspell-correct-word/mouse-keymap event)
- (flyspell-correct-word/local-keymap event)))
-
-;*---------------------------------------------------------------------*/
-;* flyspell-correct-word/local-keymap ... */
-;*---------------------------------------------------------------------*/
-(defun flyspell-correct-word/local-keymap (event)
- "emacs 19.xx seems to be buggous. Overlay keymap does not seems
-to work correctly with local map. That is, if a key is not
-defined for the overlay keymap, the current local map, is not
-checked. The binding is resolved with the global map. The
-consequence is that we can not use overlay map with flyspell."
- (interactive "e")
- (save-window-excursion
- (let ((save (point)))
- (mouse-set-point event)
- ;; we look for a flyspell overlay here
- (let ((overlays (overlays-at (point)))
- (overlay nil))
- (while (consp overlays)
- (if (flyspell-overlay-p (car overlays))
- (progn
- (setq overlay (car overlays))
- (setq overlays nil))
- (setq overlays (cdr overlays))))
- ;; we return to the correct location
- (goto-char save)
- ;; we check to see if button2 has been used overlay a
- ;; flyspell overlay
- (if overlay
- ;; yes, so we use the flyspell function
- (flyspell-correct-word/mouse-keymap event)
- ;; no so we have to use the non flyspell binding
- (let ((flyspell-mode nil))
- (if (key-binding (this-command-keys))
- (command-execute (key-binding (this-command-keys))))))))))
-
-;*---------------------------------------------------------------------*/
-;* flyspell-correct-word/mouse-keymap ... */
-;*---------------------------------------------------------------------*/
-(defun flyspell-correct-word/mouse-keymap (event)
"Pop up a menu of possible corrections for a misspelled word.
The word checked is the word at the mouse position."
(interactive "e")
;* flyspell-xemacs-popup ... */
;*---------------------------------------------------------------------*/
(defun flyspell-xemacs-popup (event poss word cursor-location start end save)
- "The xemacs popup menu."
+ "The XEmacs popup menu."
(let* ((corrects (if flyspell-sort-corrections
(sort (car (cdr (cdr poss))) 'string<)
(car (cdr (cdr poss)))))
menu))))
;*---------------------------------------------------------------------*/
-;* Some example functions for real autocrrecting */
+;* Some example functions for real autocorrecting */
;*---------------------------------------------------------------------*/
+
(defun flyspell-maybe-correct-transposition (beg end poss)
- "Apply 'transpose-chars' to all points in the region BEG to END and
-return t if any those result in a possible replacement suggested by ispell
-in POSS. Otherwise the change is undone.
+ "Check replacements for transposed characters.
+
+If the text between BEG and END is equal to a correction suggested by
+Ispell, after transposing two adjacent characters, correct the text,
+and return t.
+
+The third arg POSS is either the symbol 'doublon' or a list of
+possible corrections as returned by 'ispell-parse-output'.
This function is meant to be added to 'flyspell-incorrect-hook'."
- (when (consp poss)
- (catch 'done
+ (when (consp poss)
+ (let ((temp-buffer (get-buffer-create " *flyspell-temp*"))
+ found)
+ (save-excursion
+ (copy-to-buffer temp-buffer beg end)
+ (set-buffer temp-buffer)
+ (goto-char (1+ (point-min)))
+ (while (and (not (eobp)) (not found))
+ (transpose-chars 1)
+ (if (member (buffer-string) (nth 2 poss))
+ (setq found (point))
+ (transpose-chars -1)
+ (forward-char))))
+ (when found
(save-excursion
- (goto-char (1+ beg))
- (while (< (point) end)
- (transpose-chars 1)
- (when (member (buffer-substring beg end) (nth 2 poss))
- (throw 'done t))
- (transpose-chars -1)
- (forward-char))
- nil))))
+ (goto-char (+ beg found -1))
+ (transpose-chars -1)
+ t)))))
(defun flyspell-maybe-correct-doubling (beg end poss)
- "For each doubled charachter in the region BEG to END, remove one and
-return t if any those result in a possible replacement suggested by ispell
-in POSS. Otherwise the change is undone.
+ "Check replacements for doubled characters.
+
+If the text between BEG and END is equal to a correction suggested by
+Ispell, after removing a pair of doubled characters, correct the text,
+and return t.
+
+The third arg POSS is either the symbol 'doublon' or a list of
+possible corrections as returned by 'ispell-parse-output'.
This function is meant to be added to 'flyspell-incorrect-hook'."
- (when (consp poss)
- (catch 'done
+ (when (consp poss)
+ (let ((temp-buffer (get-buffer-create " *flyspell-temp*"))
+ found)
+ (save-excursion
+ (copy-to-buffer temp-buffer beg end)
+ (set-buffer temp-buffer)
+ (goto-char (1+ (point-min)))
+ (while (and (not (eobp)) (not found))
+ (when (char-equal (char-after) (char-before))
+ (delete-char 1)
+ (if (member (buffer-string) (nth 2 poss))
+ (setq found (point))
+ (insert-char (char-before) 1)))
+ (forward-char)))
+ (when found
(save-excursion
- (let ((last (char-after beg))
- this)
- (goto-char (1+ beg))
- (while (< (point) end)
- (setq this (char-after))
- (if (not (char-equal this last))
- (forward-char)
- (delete-char 1)
- (when (member (buffer-substring beg (1- end)) (nth 2 poss))
- (throw 'done t))
- ;; undo
- (insert-char this 1))
- (setq last this))
- nil)))))
+ (goto-char (+ beg found -1))
+ (delete-char 1)
+ t)))))
;*---------------------------------------------------------------------*/
;* flyspell-already-abbrevp ... */
(set (abbrev-symbol old table) new))
(provide 'flyspell)
+
;;; flyspell.el ends here