-;;; 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, 2003, 2004, 2005 Free Software Foundation, Inc.
-;; Author: Manuel Serrano <Manuel.Serrano@unice.fr>
+;; Author: Manuel Serrano <Manuel.Serrano@sophia.inria.fr>
+;; Maintainer: FSF
;; 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
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
;;; Commentary:
;;
;; 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)'.
-;;
+;;
;; Some user variables control the behavior of flyspell. They are
;; those defined under the `User variables' comment.
;;; Code:
+
(require 'ispell)
;*---------------------------------------------------------------------*/
;* Group ... */
;*---------------------------------------------------------------------*/
(defgroup flyspell nil
- "Spellchecking on the fly."
+ "Spell checking on the fly."
:tag "FlySpell"
:prefix "flyspell-"
+ :group 'ispell
:group 'processes)
+;*---------------------------------------------------------------------*/
+;* Which emacs are we currently running */
+;*---------------------------------------------------------------------*/
+(defvar flyspell-emacs
+ (cond
+ ((string-match "XEmacs" emacs-version)
+ 'xemacs)
+ (t
+ 'emacs))
+ "The type of Emacs we are currently running.")
+
;*---------------------------------------------------------------------*/
;* User configuration ... */
;*---------------------------------------------------------------------*/
(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
"*The maximum distance for finding duplicates of unrecognized words.
This applies to the feature that when a word is not found in the dictionary,
if the same spelling occurs elsewhere in the buffer,
-Flyspell uses a different face (`flyspell-duplicate-face') to highlight it.
+Flyspell uses a different face (`flyspell-duplicate') to highlight it.
This variable specifies how far to search to find such a duplicate.
-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
delete-backward-char
backward-or-forward-delete-char
delete-char
- scrollbar-vertical-drag)
+ scrollbar-vertical-drag
+ backward-delete-char-untabify)
"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
:group 'flyspell
:type 'boolean)
+(defcustom flyspell-issue-message-flag t
+ "*Non-nil means that Flyspell emits messages when checking words."
+ :group 'flyspell
+ :type 'boolean)
+
(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."
+ nil
+ "*If non-nil, 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."
+ "*If non-nil, prefer global abbrev table to local abbrev table."
:group 'flyspell
+ :version "21.1"
:type 'boolean)
-
-;;;###autoload
+
(defcustom flyspell-mode-line-string " Fly"
"*String displayed on the modeline when flyspell is active.
Set this to nil if you don't want a modeline indicator."
:group 'flyspell
- :type 'string)
+ :type '(choice string (const :tag "None" nil)))
(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.
+If the region is smaller than this number of characters,
+`flyspell-region' checks the words sequentially using regular
+flyspell methods. Else, if the region is large, a new Ispell process is
+spawned for speed.
+
+If `flyspell-large-region' is nil, all regions are treated as small."
:group 'flyspell
- :type 'number)
+ :version "21.1"
+ :type '(choice number boolean))
+
+(defcustom flyspell-insert-function (function insert)
+ "*Function for inserting word by flyspell upon correction."
+ :group 'flyspell
+ :type 'function)
+
+(defcustom flyspell-before-incorrect-word-string nil
+ "String used to indicate an incorrect word starting."
+ :group 'flyspell
+ :type '(choice string (const nil)))
+
+(defcustom flyspell-after-incorrect-word-string nil
+ "String used to indicate an incorrect word ending."
+ :group 'flyspell
+ :type '(choice string (const nil)))
+
+(defcustom flyspell-use-meta-tab t
+ "*Non-nil means that flyspell uses META-TAB to correct word."
+ :group 'flyspell
+ :type 'boolean)
+
+(defcustom flyspell-auto-correct-binding
+ [(control ?\;)]
+ "The key binding for flyspell auto correction."
+ :group 'flyspell)
;*---------------------------------------------------------------------*/
;* Mode specific options */
(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 ((header-end (save-excursion
+ (goto-char (point-min))
+ (re-search-forward
+ (concat "^"
+ (regexp-quote mail-header-separator)
+ "$")
+ nil t)
+ (point)))
+ (signature-begin (save-excursion
+ (goto-char (point-max))
+ (re-search-backward message-signature-separator
+ nil t)
+ (point))))
+ (cond ((< (point) header-end)
+ (and (save-excursion (beginning-of-line)
+ (looking-at "^Subject:"))
+ (> (point) (match-end 0))))
+ ((> (point) signature-begin)
+ 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 ()
"Turn on `flyspell-mode' for comments and strings."
(interactive)
(setq flyspell-generic-check-word-p 'flyspell-generic-progmode-verify)
- (flyspell-mode 1))
+ (flyspell-mode 1)
+ (run-hooks 'flyspell-prog-mode-hook))
;*---------------------------------------------------------------------*/
;* Overlay compatibility */
(autoload 'overlay-get "overlay" "Overlay compatibility kit." t)
(autoload 'previous-overlay-change "overlay" "Overlay compatibility kit." t)
-;*---------------------------------------------------------------------*/
-;* Which emacs are we currently running */
-;*---------------------------------------------------------------------*/
-(defvar flyspell-emacs
- (cond
- ((string-match "XEmacs" emacs-version)
- 'xemacs)
- (t
- 'emacs))
- "The type of Emacs we are currently running.")
-
-(defvar flyspell-use-local-map
- (or (eq flyspell-emacs 'xemacs)
- (not (string< emacs-version "20"))))
-
;*---------------------------------------------------------------------*/
;* The minor mode declaration. */
;*---------------------------------------------------------------------*/
-(defvar flyspell-mode nil)
-(make-variable-buffer-local 'flyspell-mode)
-
(defvar flyspell-mouse-map
(let ((map (make-sparse-keymap)))
- (cond
- ((eq flyspell-emacs 'xemacs)
- (define-key map [(button2)]
- #'flyspell-correct-word/mouse-keymap)
- (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 "\M-\t" #'flyspell-auto-correct-word)))
- map))
-
-;;;###autoload
-(defvar flyspell-mode-map (make-sparse-keymap))
-
-;; mouse, keyboard bindings and misc definition
-(when (or (assoc 'flyspell-mode minor-mode-map-alist)
- (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 map (if (featurep 'xemacs) [button2] [down-mouse-2])
+ #'flyspell-correct-word)
+ map)
+ "Keymap for Flyspell to put on erroneous words.")
-
-;; 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-mode-map
+ (let ((map (make-sparse-keymap)))
+ (if flyspell-use-meta-tab
+ (define-key map "\M-\t" 'flyspell-auto-correct-word))
+ (define-key map flyspell-auto-correct-binding 'flyspell-auto-correct-previous-word)
+ (define-key map [(control ?\,)] 'flyspell-goto-next-error)
+ (define-key map [(control ?\.)] 'flyspell-auto-correct-word)
+ map)
+ "Minor mode keymap for Flyspell mode--for the whole buffer.")
;; dash character machinery
(defvar flyspell-consider-dash-as-word-delimiter-flag nil
;*---------------------------------------------------------------------*/
;* Highlighting */
;*---------------------------------------------------------------------*/
-(defface flyspell-incorrect-face
+(defface flyspell-incorrect
'((((class color)) (:foreground "OrangeRed" :bold t :underline t))
(t (:bold t)))
"Face used for marking a misspelled word in Flyspell."
:group 'flyspell)
+;; backward-compatibility alias
+(put 'flyspell-incorrect-face 'face-alias 'flyspell-incorrect)
-(defface flyspell-duplicate-face
+(defface flyspell-duplicate
'((((class color)) (:foreground "Gold3" :bold t :underline t))
(t (:bold t)))
"Face used for marking a misspelled word that appears twice in the buffer.
See also `flyspell-duplicate-distance'."
:group 'flyspell)
+;; backward-compatibility alias
+(put 'flyspell-duplicate-face 'face-alias 'flyspell-duplicate)
(defvar flyspell-overlay nil)
;* flyspell-mode ... */
;*---------------------------------------------------------------------*/
;;;###autoload
-(defun flyspell-mode (&optional arg)
+(define-minor-mode flyspell-mode
"Minor mode performing on-the-fly spelling checking.
-Ispell is automatically spawned on background for each entered words.
+This spawns a single Ispell process and checks each word.
The default flyspell behavior is to highlight incorrect words.
With no argument, this command toggles Flyspell mode.
With a prefix argument ARG, turn Flyspell minor mode on iff ARG is positive.
-
+
Bindings:
\\[ispell-word]: correct words (using Ispell).
\\[flyspell-auto-correct-word]: automatically correct word.
-\\[flyspell-correct-word] (or mouse-2): popup correct words.
+\\[flyspell-auto-correct-previous-word]: automatically correct the last misspelled word.
+\\[flyspell-correct-word] (or down-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."
- (interactive "P")
- (let ((old-flyspell-mode flyspell-mode))
- ;; Mark the mode as on or off.
- (setq flyspell-mode (not (or (and (null arg) flyspell-mode)
- (<= (prefix-numeric-value arg) 0))))
- ;; Do the real work.
- (unless (eq flyspell-mode old-flyspell-mode)
- (if flyspell-mode
- (flyspell-mode-on)
- (flyspell-mode-off))
- ;; Force modeline redisplay.
- (set-buffer-modified-p (buffer-modified-p)))))
-
-;*---------------------------------------------------------------------*/
-;* 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))))
-
+\\[flyspell-region] checks all words inside a region.
+\\[flyspell-buffer] checks the whole buffer."
+ :lighter flyspell-mode-line-string
+ :keymap flyspell-mode-map
+ :group 'flyspell
+ (if flyspell-mode
+ (flyspell-mode-on)
+ (flyspell-mode-off)))
;*---------------------------------------------------------------------*/
;* flyspell-buffers ... */
;* For remembering buffers running flyspell */
;*---------------------------------------------------------------------*/
(defvar flyspell-buffers nil)
-
+
;*---------------------------------------------------------------------*/
;* flyspell-minibuffer-p ... */
;*---------------------------------------------------------------------*/
;* flyspell-accept-buffer-local-defs ... */
;*---------------------------------------------------------------------*/
(defun flyspell-accept-buffer-local-defs ()
- (ispell-accept-buffer-local-defs)
+ ;; strange problem. If buffer in current window has font-lock turned on,
+ ;; but SET-BUFFER was called to point to an invisible buffer, this ispell
+ ;; call will reset the buffer to the buffer in the current window. However,
+ ;; it only happens at startup (fix by Albert L. Ting).
+ (let ((buf (current-buffer)))
+ (ispell-accept-buffer-local-defs)
+ (set-buffer buf))
(if (not (and (eq flyspell-dash-dictionary ispell-dictionary)
(eq flyspell-dash-local-dictionary ispell-local-dictionary)))
- ;; the dictionary as changed
+ ;; The dictionary has changed
(progn
(setq flyspell-dash-dictionary ispell-dictionary)
(setq flyspell-dash-local-dictionary ispell-local-dictionary)
;*---------------------------------------------------------------------*/
;* flyspell-mode-on ... */
;*---------------------------------------------------------------------*/
-(eval-when-compile (defvar flyspell-local-mouse-map))
-
(defun flyspell-mode-on ()
"Turn Flyspell mode on. Do not use this; use `flyspell-mode' instead."
- (setq ispell-highlight-face 'flyspell-incorrect-face)
+ (setq ispell-highlight-face 'flyspell-incorrect)
;; local dictionaries setup
- (ispell-change-dictionary
- (or ispell-local-dictionary ispell-dictionary flyspell-default-dictionary))
+ (or ispell-local-dictionary ispell-dictionary
+ (if flyspell-default-dictionary
+ (ispell-change-dictionary flyspell-default-dictionary)))
;; we have to force ispell to accept the local definition or
;; otherwise it could be too late, the local dictionary may
;; be forgotten!
(flyspell-accept-buffer-local-defs)
- ;; we put the `flyspel-delayed' property on some commands
+ ;; we put the `flyspell-delayed' property on some commands
(flyspell-delay-commands)
- ;; we put the `flyspel-deplacement' property on some commands
+ ;; we put the `flyspell-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 (and flyspell-issue-welcome-flag (interactive-p))
+ (if (and flyspell-issue-message-flag
+ 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))
(defvar flyspell-word-cache-start nil)
(defvar flyspell-word-cache-end nil)
(defvar flyspell-word-cache-word nil)
+(defvar flyspell-word-cache-result '_)
(make-variable-buffer-local 'flyspell-word-cache-start)
(make-variable-buffer-local 'flyspell-word-cache-end)
(make-variable-buffer-local 'flyspell-word-cache-word)
+(make-variable-buffer-local 'flyspell-word-cache-result)
;*---------------------------------------------------------------------*/
;* The flyspell pre-hook, store the current position. In the */
;* flyspell-check-pre-word-p ... */
;*---------------------------------------------------------------------*/
(defun flyspell-check-pre-word-p ()
- "Return non-nil if we should to check the word before point.
+ "Return non-nil if we should check the word before point.
More precisely, it applies to the word that was before point
before the current command."
(cond
(= flyspell-pre-point (+ (point) 1)))
nil)
((and (symbolp this-command)
+ (not executing-kbd-macro)
(or (get this-command 'flyspell-delayed)
(and (get this-command 'flyspell-deplacement)
(eq flyspell-previous-command this-command)))
The answer depends of several criteria.
Mostly we check word delimiters."
(cond
- ((and (eq (char-after start) ?\n) (> stop start))
+ ((and (memq (char-after start) '(?\n ? )) (> stop start))
t)
((not (numberp flyspell-pre-point))
t)
((get this-command 'flyspell-delayed)
;; the current command is not delayed, that
;; is that we must check the word now
- (if (fboundp 'about-xemacs)
- (sit-for flyspell-delay nil)
- (sit-for flyspell-delay 0 nil)))
+ (sit-for flyspell-delay))
(t t)))
(t 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)
(insert (format " cache-start: %S\n" flyspell-word-cache-start))
(insert (format " cache-end : %S\n" flyspell-word-cache-end))
(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)
;; when a word is not checked because of a delayed command
;; we do not disable the ispell cache.
(if (and (symbolp this-command) (get this-command 'flyspell-delayed))
- (setq flyspell-word-cache-end -1))))
+ (progn
+ (setq flyspell-word-cache-end -1)
+ (setq flyspell-word-cache-result '_)))))
(while (consp flyspell-changes)
(let ((start (car (car flyspell-changes)))
(stop (cdr (car flyspell-changes))))
(if flyspell-sort-corrections
(sort (car (cdr (cdr poss))) 'string<)
(car (cdr (cdr poss)))))))
- (message (format "mispelling `%s' %S" word replacements))))
+ (if flyspell-issue-message-flag
+ (message (format "mispelling `%s' %S" word replacements)))))
+
+;*---------------------------------------------------------------------*/
+;* flyspell-word-search-backward ... */
+;*---------------------------------------------------------------------*/
+(defun flyspell-word-search-backward (word bound)
+ (save-excursion
+ (let ((r '())
+ p)
+ (while (and (not r) (setq p (search-backward word bound t)))
+ (let ((lw (flyspell-get-word '())))
+ (if (and (consp lw) (string-equal (car lw) word))
+ (setq r p)
+ (goto-char p))))
+ r)))
+
+;*---------------------------------------------------------------------*/
+;* flyspell-word-search-forward ... */
+;*---------------------------------------------------------------------*/
+(defun flyspell-word-search-forward (word bound)
+ (save-excursion
+ (let ((r '())
+ p)
+ (while (and (not r) (setq p (search-forward word bound t)))
+ (let ((lw (flyspell-get-word '())))
+ (if (and (consp lw) (string-equal (car lw) word))
+ (setq r p)
+ (goto-char (1+ p)))))
+ r)))
;*---------------------------------------------------------------------*/
;* flyspell-word ... */
;*---------------------------------------------------------------------*/
(defun flyspell-word (&optional following)
"Spell check a word."
- (interactive (list current-prefix-arg))
- (if (interactive-p)
- (setq following ispell-following-word))
+ (interactive (list 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)
(if (or (eq flyspell-word nil)
(and (fboundp flyspell-generic-check-word-p)
(not (funcall flyspell-generic-check-word-p))))
- '()
+ t
(progn
;; destructure return flyspell-word info list.
(setq start (car (cdr flyspell-word))
;; before checking in the directory, we check for doublons.
(cond
((and (or (not (eq ispell-parser 'tex))
- (not (eq (char-after start) ?\\)))
+ (and (> start (point-min))
+ (not (memq (char-after (1- start)) '(?\} ?\\)))))
flyspell-mark-duplications-flag
(save-excursion
- (goto-char start)
- (word-search-backward word
- (- start
- (+ 1 (- end start)))
- t)))
+ (goto-char (1- start))
+ (let ((p (flyspell-word-search-backward
+ word
+ (- start (1+ (- end start))))))
+ (and p (/= p (1- start))))))
;; yes, this is a doublon
- (flyspell-highlight-incorrect-region start end 'doublon))
+ (flyspell-highlight-incorrect-region start end 'doublon)
+ nil)
((and (eq flyspell-word-cache-start start)
(eq flyspell-word-cache-end end)
(string-equal flyspell-word-cache-word word))
;; this word had been already checked, we skip
- nil)
+ flyspell-word-cache-result)
((and (eq ispell-parser 'tex)
(flyspell-tex-command-p flyspell-word))
;; this is a correct word (because a tex command)
(concat "^" word "\n"))
;; we mark the ispell process so it can be killed
;; when emacs is exited without query
- (if (fboundp 'process-kill-without-query)
- (process-kill-without-query ispell-process))
+ (set-process-query-on-exit-flag ispell-process nil)
;; wait until ispell has processed word
(while (progn
(accept-process-output ispell-process)
(setq ispell-filter (cdr ispell-filter))
(if (consp ispell-filter)
(setq poss (ispell-parse-output (car ispell-filter))))
- (cond ((eq poss t)
- ;; correct
- (flyspell-unhighlight-at start)
- (if (> end start)
- (flyspell-unhighlight-at (- end 1)))
- t)
- ((and (stringp poss) flyspell-highlight-flag)
- ;; correct
- (flyspell-unhighlight-at start)
- (if (> end start)
- (flyspell-unhighlight-at (- end 1)))
- t)
- ((null poss)
- (flyspell-unhighlight-at start)
- (if (> end start)
- (flyspell-unhighlight-at (- end 1))))
- ((or (and (< flyspell-duplicate-distance 0)
- (or (save-excursion
- (goto-char start)
- (word-search-backward word
- (point-min)
- t))
- (save-excursion
- (goto-char end)
- (word-search-forward word
- (point-max)
- t))))
- (and (> flyspell-duplicate-distance 0)
- (or (save-excursion
- (goto-char start)
- (word-search-backward
- word
- (- start
- flyspell-duplicate-distance)
- t))
- (save-excursion
- (goto-char end)
- (word-search-forward
- word
- (+ end
- flyspell-duplicate-distance)
- t)))))
- (if flyspell-highlight-flag
- (flyspell-highlight-duplicate-region start end)
- (message (format "duplicate `%s'" word))))
- (t
- ;; incorrect highlight the location
- (if flyspell-highlight-flag
- (flyspell-highlight-incorrect-region start end poss)
- (flyspell-notify-misspell start end word poss))))
- ;; return to original location
- (goto-char cursor-location)
- (if ispell-quit (setq ispell-quit nil)))))))))
+ (let ((res (cond ((eq poss t)
+ ;; correct
+ (setq flyspell-word-cache-result t)
+ (flyspell-unhighlight-at start)
+ (if (> end start)
+ (flyspell-unhighlight-at (- end 1)))
+ t)
+ ((and (stringp poss) flyspell-highlight-flag)
+ ;; correct
+ (setq flyspell-word-cache-result t)
+ (flyspell-unhighlight-at start)
+ (if (> end start)
+ (flyspell-unhighlight-at (- end 1)))
+ t)
+ ((null poss)
+ (setq flyspell-word-cache-result t)
+ (flyspell-unhighlight-at start)
+ (if (> end start)
+ (flyspell-unhighlight-at (- end 1)))
+ t)
+ ((or (and (< flyspell-duplicate-distance 0)
+ (or (save-excursion
+ (goto-char start)
+ (flyspell-word-search-backward
+ word
+ (point-min)))
+ (save-excursion
+ (goto-char end)
+ (flyspell-word-search-forward
+ word
+ (point-max)))))
+ (and (> flyspell-duplicate-distance 0)
+ (or (save-excursion
+ (goto-char start)
+ (flyspell-word-search-backward
+ word
+ (- start
+ flyspell-duplicate-distance)))
+ (save-excursion
+ (goto-char end)
+ (flyspell-word-search-forward
+ word
+ (+ end
+ flyspell-duplicate-distance))))))
+ (setq flyspell-word-cache-result nil)
+ (if flyspell-highlight-flag
+ (flyspell-highlight-duplicate-region
+ start end poss)
+ (message (format "duplicate `%s'" word)))
+ nil)
+ (t
+ (setq flyspell-word-cache-result nil)
+ ;; incorrect highlight the location
+ (if flyspell-highlight-flag
+ (flyspell-highlight-incorrect-region
+ start end poss)
+ (flyspell-notify-misspell start end word poss))
+ nil))))
+ ;; return to original location
+ (goto-char cursor-location)
+ (if ispell-quit (setq ispell-quit nil))
+ res))))))))
;*---------------------------------------------------------------------*/
;* flyspell-tex-math-initialized ... */
;* time that function is called. */
;*---------------------------------------------------------------------*/
(defun flyspell-math-tex-command-p ()
- (cond
- (flyspell-check-tex-math-command
- nil)
- ((eq flyspell-tex-math-initialized t)
- (texmathp))
- ((eq flyspell-tex-math-initialized 'error)
- nil)
- (t
- (setq flyspell-tex-math-initialized t)
- (condition-case nil
- (texmathp)
- (error (progn
- (setq flyspell-tex-math-initialized 'error)
- nil))))))
+ (when (fboundp 'texmathp)
+ (cond
+ (flyspell-check-tex-math-command
+ nil)
+ ((eq flyspell-tex-math-initialized t)
+ (texmathp))
+ ((eq flyspell-tex-math-initialized 'error)
+ nil)
+ (t
+ (setq flyspell-tex-math-initialized t)
+ (condition-case nil
+ (texmathp)
+ (error (progn
+ (setq flyspell-tex-math-initialized 'error)
+ nil)))))))
;*---------------------------------------------------------------------*/
;* flyspell-tex-command-p ... */
(setq flyspell-ispell-casechars-cache ispell-casechars)
(setq flyspell-casechars-cache ispell-casechars)
flyspell-casechars-cache))))
-
+
;*---------------------------------------------------------------------*/
;* flyspell-get-not-casechars-cache ... */
;*---------------------------------------------------------------------*/
;*---------------------------------------------------------------------*/
;* flyspell-get-word ... */
;*---------------------------------------------------------------------*/
-(defun flyspell-get-word (following)
+(defun flyspell-get-word (following &optional extra-otherchars)
"Return the word for spell-checking according to Ispell syntax.
-If argument FOLLOWING is non-nil or if `ispell-following-word'
+If optional argument FOLLOWING is non-nil or if `flyspell-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
many times.
-Word syntax described by `ispell-dictionary-alist' (which see)."
+Word syntax described by `flyspell-dictionary-alist' (which see)."
(let* ((flyspell-casechars (flyspell-get-casechars))
(flyspell-not-casechars (flyspell-get-not-casechars))
(ispell-otherchars (ispell-get-otherchars))
(ispell-many-otherchars-p (ispell-get-many-otherchars-p))
- (word-regexp (if (string< "" ispell-otherchars)
- (concat flyspell-casechars
- "+\\("
- ispell-otherchars
- "?"
- flyspell-casechars
- "+\\)"
- (if ispell-many-otherchars-p
- "*" "?"))
- (concat flyspell-casechars "+")))
- did-it-once
+ (word-regexp (concat flyspell-casechars
+ "+\\("
+ (if (not (string= "" ispell-otherchars))
+ (concat ispell-otherchars "?"))
+ (if extra-otherchars
+ (concat extra-otherchars "?"))
+ flyspell-casechars
+ "+\\)"
+ (if (or ispell-many-otherchars-p
+ extra-otherchars)
+ "*" "?")))
+ did-it-once prevpt
start end word)
;; find the word
(if (not (looking-at flyspell-casechars))
(re-search-backward flyspell-casechars (point-min) t)))
;; move to front of word
(re-search-backward flyspell-not-casechars (point-min) 'start)
- (let ((pos nil))
- (if (string< "" ispell-otherchars)
- (while (and (looking-at ispell-otherchars)
- (not (bobp))
- (or (not did-it-once)
- ispell-many-otherchars-p)
- (not (eq pos (point))))
- (setq pos (point))
- (setq did-it-once t)
+ (while (and (or (and (not (string= "" ispell-otherchars))
+ (looking-at ispell-otherchars))
+ (and extra-otherchars (looking-at extra-otherchars)))
+ (not (bobp))
+ (or (not did-it-once)
+ ispell-many-otherchars-p)
+ (not (eq prevpt (point))))
+ (if (and extra-otherchars (looking-at extra-otherchars))
+ (progn
(backward-char 1)
(if (looking-at flyspell-casechars)
- (re-search-backward flyspell-not-casechars (point-min) 'move)
- (backward-char -1)))))
+ (re-search-backward flyspell-not-casechars (point-min) 'move)))
+ (setq did-it-once t
+ prevpt (point))
+ (backward-char 1)
+ (if (looking-at flyspell-casechars)
+ (re-search-backward flyspell-not-casechars (point-min) 'move)
+ (backward-char -1))))
;; Now mark the word and save to string.
- (if (eq (re-search-forward word-regexp (point-max) t) nil)
+ (if (not (re-search-forward word-regexp (point-max) t))
nil
(progn
(setq start (match-beginning 0)
end (point)
- word (buffer-substring start end))
+ word (buffer-substring-no-properties start end))
(list word start end)))))
;*---------------------------------------------------------------------*/
(goto-char beg)
(let ((count 0))
(while (< (point) end)
- (if (= count 100)
+ (if (and flyspell-issue-message-flag (= count 100))
(progn
(message "Spell Checking...%d%%"
(* 100 (/ (float (- (point) beg)) (- end beg))))
(if (and (< (point) end) (> (point) (+ cur 1)))
(backward-char 1)))))
(backward-char 1)
- (message "Spell Checking completed.")
+ (if flyspell-issue-message-flag (message "Spell Checking completed."))
(flyspell-word)))
;*---------------------------------------------------------------------*/
;* flyspell-external-ispell-process ... */
;*---------------------------------------------------------------------*/
(defvar flyspell-external-ispell-process '()
- "The external Flyspell ispell process")
+ "The external Flyspell Ispell process.")
;*---------------------------------------------------------------------*/
;* flyspell-external-ispell-buffer ... */
(defun flyspell-external-point-words ()
(let ((buffer flyspell-external-ispell-buffer))
(set-buffer buffer)
- (beginning-of-buffer)
- (let ((size (- flyspell-large-region-end flyspell-large-region-beg))
- (start flyspell-large-region-beg))
+ (goto-char (point-min))
+ (let ((pword "")
+ (pcount 1))
;; now we are done with ispell, we have to find the word in
;; the initial buffer
(while (< (point) (- (point-max) 1))
;; we have to fetch the incorrect word
(if (re-search-forward "\\([^\n]+\\)\n" (point-max) t)
(let ((word (match-string 1)))
+ (if (string= word pword)
+ (setq pcount (1+ pcount))
+ (progn
+ (setq pword word)
+ (setq pcount 1)))
(goto-char (match-end 0))
+ (if flyspell-issue-message-flag
+ (message "Spell Checking...%d%% [%s]"
+ (* 100 (/ (float (point)) (point-max)))
+ word))
(set-buffer flyspell-large-region-buffer)
(goto-char flyspell-large-region-beg)
- (message "Spell Checking...%d%% [%s]"
- (* 100 (/ (float (- (point) start)) size))
- word)
- (if (search-forward word flyspell-large-region-end t)
+ (let ((keep t)
+ (n 0))
+ (while (and (or (< n pcount) keep)
+ (search-forward word flyspell-large-region-end t))
(progn
- (setq flyspell-large-region-beg (point))
(goto-char (- (point) 1))
- (flyspell-word)))
+ (setq n (1+ n))
+ (setq keep (flyspell-word))))
+ (if (= n pcount)
+ (setq flyspell-large-region-beg (point))))
(set-buffer buffer))
(goto-char (point-max)))))
;; we are done
- (message "Spell Checking completed.")
+ (if flyspell-issue-message-flag (message "Spell Checking completed."))
;; ok, we are done with pointing out incorrect words, we just
;; have to kill the temporary buffer
(kill-buffer flyspell-external-ispell-buffer)
(setq flyspell-external-ispell-buffer nil)))
-
+
;*---------------------------------------------------------------------*/
;* flyspell-large-region ... */
;*---------------------------------------------------------------------*/
(setq flyspell-large-region-end end)
(set-buffer buffer)
(erase-buffer)
- ;; this is done, we can start ckecking...
- (message "Checking region...")
+ ;; this is done, we can start checking...
+ (if flyspell-issue-message-flag (message "Checking region..."))
(set-buffer curbuf)
(let ((c (apply 'call-process-region beg
end
nil
buffer
nil
- "-l"
+ (if ispell-really-aspell "list" "-l")
(let (args)
;; Local dictionary becomes the global dictionary in use.
(if ispell-local-dictionary
ispell-personal-dictionary)))))
(setq args (append args ispell-extra-args))
args))))
- (if (= c 0)
+ (if (eq c 0)
(flyspell-external-point-words)
(error "Can't check region...")))))
;* 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")
(let ((old beg))
(setq beg end)
(setq end old)))
- (if (> (- end beg) flyspell-large-region)
+ (if (and flyspell-large-region (> (- end beg) flyspell-large-region))
(flyspell-large-region beg end)
(flyspell-small-region beg end)))))
;*---------------------------------------------------------------------*/
;* 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)
(overlay-put flyspell-overlay 'face face)
(overlay-put flyspell-overlay 'mouse-face mouse-face)
(overlay-put flyspell-overlay 'flyspell-overlay t)
- (if flyspell-use-local-map
- (overlay-put flyspell-overlay
- flyspell-overlay-keymap-property-name
- flyspell-local-mouse-map))
+ (overlay-put flyspell-overlay 'evaporate t)
+ (overlay-put flyspell-overlay 'help-echo "mouse-2: correct word at point")
+ (overlay-put flyspell-overlay 'keymap flyspell-mouse-map)
+ (when (eq face 'flyspell-incorrect)
+ (and (stringp flyspell-before-incorrect-word-string)
+ (overlay-put flyspell-overlay 'before-string
+ flyspell-before-incorrect-word-string))
+ (and (stringp flyspell-after-incorrect-word-string)
+ (overlay-put flyspell-overlay 'after-string
+ flyspell-after-incorrect-word-string)))
flyspell-overlay))
-
+
;*---------------------------------------------------------------------*/
;* flyspell-highlight-incorrect-region ... */
;*---------------------------------------------------------------------*/
(defun flyspell-highlight-incorrect-region (beg end poss)
"Set up an overlay on a misspelled word, in the buffer from BEG to END."
- (unless (run-hook-with-args-until-success
- 'flyspell-incorrect-hook beg end poss)
- (if (or flyspell-highlight-properties (not (flyspell-properties-at-p beg)))
- (progn
- ;; we cleanup current overlay at the same position
- (if (and (not flyspell-persistent-highlight)
- (overlayp flyspell-overlay))
- (delete-overlay flyspell-overlay)
- (let ((overlays (overlays-at beg)))
- (while (consp overlays)
- (if (flyspell-overlay-p (car overlays))
- (delete-overlay (car overlays)))
- (setq overlays (cdr overlays)))))
- ;; now we can use a new overlay
- (setq flyspell-overlay
- (make-flyspell-overlay beg end
- 'flyspell-incorrect-face 'highlight))))))
+ (let ((inhibit-read-only t))
+ (unless (run-hook-with-args-until-success
+ 'flyspell-incorrect-hook beg end poss)
+ (if (or flyspell-highlight-properties
+ (not (flyspell-properties-at-p beg)))
+ (progn
+ ;; we cleanup all the overlay that are in the region, not
+ ;; beginning at the word start position
+ (if (< (1+ beg) end)
+ (let ((os (overlays-in (1+ beg) end)))
+ (while (consp os)
+ (if (flyspell-overlay-p (car os))
+ (delete-overlay (car os)))
+ (setq os (cdr os)))))
+ ;; we cleanup current overlay at the same position
+ (if (and (not flyspell-persistent-highlight)
+ (overlayp flyspell-overlay))
+ (delete-overlay flyspell-overlay)
+ (let ((os (overlays-at beg)))
+ (while (consp os)
+ (if (flyspell-overlay-p (car os))
+ (delete-overlay (car os)))
+ (setq os (cdr os)))))
+ ;; now we can use a new overlay
+ (setq flyspell-overlay
+ (make-flyspell-overlay
+ beg end 'flyspell-incorrect 'highlight)))))))
;*---------------------------------------------------------------------*/
;* flyspell-highlight-duplicate-region ... */
;*---------------------------------------------------------------------*/
-(defun flyspell-highlight-duplicate-region (beg end)
- "Set up an overlay on a duplicated word, in the buffer from BEG to END."
- (if (or flyspell-highlight-properties (not (flyspell-properties-at-p beg)))
- (progn
- ;; we cleanup current overlay at the same position
- (if (and (not flyspell-persistent-highlight)
- (overlayp flyspell-overlay))
- (delete-overlay flyspell-overlay)
- (let ((overlays (overlays-at beg)))
- (while (consp overlays)
- (if (flyspell-overlay-p (car overlays))
- (delete-overlay (car overlays)))
- (setq overlays (cdr overlays)))))
- ;; now we can use a new overlay
- (setq flyspell-overlay
- (make-flyspell-overlay beg end
- 'flyspell-duplicate-face 'highlight)))))
+(defun flyspell-highlight-duplicate-region (beg end poss)
+ "Set up an overlay on a duplicated word, in the buffer from BEG to END.
+??? What does POSS mean?"
+ (let ((inhibit-read-only t))
+ (unless (run-hook-with-args-until-success
+ 'flyspell-incorrect-hook beg end poss)
+ (if (or flyspell-highlight-properties
+ (not (flyspell-properties-at-p beg)))
+ (progn
+ ;; we cleanup current overlay at the same position
+ (if (and (not flyspell-persistent-highlight)
+ (overlayp flyspell-overlay))
+ (delete-overlay flyspell-overlay)
+ (let ((overlays (overlays-at beg)))
+ (while (consp overlays)
+ (if (flyspell-overlay-p (car overlays))
+ (delete-overlay (car overlays)))
+ (setq overlays (cdr overlays)))))
+ ;; now we can use a new overlay
+ (setq flyspell-overlay
+ (make-flyspell-overlay beg end
+ 'flyspell-duplicate
+ 'highlight)))))))
;*---------------------------------------------------------------------*/
;* flyspell-auto-correct-cache ... */
;* 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 ... */
(let ((num (car pos)))
(put-text-property num
(+ num (length flyspell-auto-correct-word))
- 'face
- 'flyspell-incorrect-face
+ 'face 'flyspell-incorrect
string))
(setq pos (cdr pos)))
(if (fboundp 'display-message)
(defun flyspell-abbrev-table ()
(if flyspell-use-global-abbrev-table-p
global-abbrev-table
- local-abbrev-table))
+ (or local-abbrev-table global-abbrev-table)))
+
+;*---------------------------------------------------------------------*/
+;* flyspell-define-abbrev ... */
+;*---------------------------------------------------------------------*/
+(defun flyspell-define-abbrev (name expansion)
+ (let ((table (flyspell-abbrev-table)))
+ (when table
+ (define-abbrev table name expansion))))
;*---------------------------------------------------------------------*/
;* flyspell-auto-correct-word ... */
;; we have already been using the function at the same location
(let* ((start (car flyspell-auto-correct-region))
(len (cdr flyspell-auto-correct-region)))
+ (flyspell-unhighlight-at start)
(delete-region start (+ start len))
(setq flyspell-auto-correct-ring (cdr flyspell-auto-correct-ring))
(let* ((word (car flyspell-auto-correct-ring))
(flyspell-change-abbrev (flyspell-abbrev-table)
flyspell-auto-correct-word
word)
- (define-abbrev (flyspell-abbrev-table)
- flyspell-auto-correct-word word)))
- (insert word)
+ (flyspell-define-abbrev flyspell-auto-correct-word word)))
+ (funcall flyspell-insert-function word)
(flyspell-word)
(flyspell-display-next-corrections flyspell-auto-correct-ring))
(flyspell-ajust-cursor-point pos (point) old-max)
(setq flyspell-auto-correct-pos (point)))
;; fetch the word to be checked
- (let ((word (flyspell-get-word nil))
- start end poss)
- ;; destructure return word info list.
- (setq start (car (cdr word))
- end (car (cdr (cdr word)))
- word (car word))
- (setq flyspell-auto-correct-word word)
- ;; now check spelling of word.
- (process-send-string ispell-process "%\n") ;put in verbose mode
- (process-send-string ispell-process (concat "^" word "\n"))
- ;; wait until ispell has processed word
- (while (progn
- (accept-process-output ispell-process)
- (not (string= "" (car ispell-filter)))))
- (setq ispell-filter (cdr ispell-filter))
- (if (consp ispell-filter)
- (setq poss (ispell-parse-output (car ispell-filter))))
- (cond ((or (eq poss t) (stringp poss))
- ;; don't correct word
- t)
- ((null poss)
- ;; ispell error
- (error "Ispell: error in Ispell process"))
- (t
- ;; the word is incorrect, we have to propose a replacement
- (let ((replacements (if flyspell-sort-corrections
- (sort (car (cdr (cdr poss))) 'string<)
- (car (cdr (cdr poss))))))
- (setq flyspell-auto-correct-region nil)
- (if (consp replacements)
- (progn
- (let ((replace (car replacements)))
- (let ((new-word replace))
- (if (not (equal new-word (car poss)))
- (progn
- ;; the save the current replacements
- (setq flyspell-auto-correct-region
- (cons start (length new-word)))
- (let ((l replacements))
- (while (consp (cdr l))
- (setq l (cdr l)))
- (rplacd l (cons (car poss) replacements)))
- (setq flyspell-auto-correct-ring
- replacements)
- (delete-region start end)
- (insert new-word)
- (if flyspell-abbrev-p
- (if (flyspell-already-abbrevp
- (flyspell-abbrev-table) word)
- (flyspell-change-abbrev
- (flyspell-abbrev-table)
- word
- new-word)
- (define-abbrev (flyspell-abbrev-table)
- word new-word)))
- (flyspell-word)
- (flyspell-display-next-corrections
- (cons new-word flyspell-auto-correct-ring))
- (flyspell-ajust-cursor-point pos
- (point)
- old-max))))))))))
- (setq flyspell-auto-correct-pos (point))
- (ispell-pdict-save t)))))
+ (let ((word (flyspell-get-word nil)))
+ (if (consp word)
+ (let ((start (car (cdr word)))
+ (end (car (cdr (cdr word))))
+ (word (car word))
+ poss)
+ (setq flyspell-auto-correct-word word)
+ ;; now check spelling of word.
+ (process-send-string ispell-process "%\n") ;put in verbose mode
+ (process-send-string ispell-process (concat "^" word "\n"))
+ ;; wait until ispell has processed word
+ (while (progn
+ (accept-process-output ispell-process)
+ (not (string= "" (car ispell-filter)))))
+ (setq ispell-filter (cdr ispell-filter))
+ (if (consp ispell-filter)
+ (setq poss (ispell-parse-output (car ispell-filter))))
+ (cond
+ ((or (eq poss t) (stringp poss))
+ ;; don't correct word
+ t)
+ ((null poss)
+ ;; ispell error
+ (error "Ispell: error in Ispell process"))
+ (t
+ ;; the word is incorrect, we have to propose a replacement
+ (let ((replacements (if flyspell-sort-corrections
+ (sort (car (cdr (cdr poss))) 'string<)
+ (car (cdr (cdr poss))))))
+ (setq flyspell-auto-correct-region nil)
+ (if (consp replacements)
+ (progn
+ (let ((replace (car replacements)))
+ (let ((new-word replace))
+ (if (not (equal new-word (car poss)))
+ (progn
+ ;; the save the current replacements
+ (setq flyspell-auto-correct-region
+ (cons start (length new-word)))
+ (let ((l replacements))
+ (while (consp (cdr l))
+ (setq l (cdr l)))
+ (rplacd l (cons (car poss) replacements)))
+ (setq flyspell-auto-correct-ring
+ replacements)
+ (flyspell-unhighlight-at start)
+ (delete-region start end)
+ (funcall flyspell-insert-function new-word)
+ (if flyspell-abbrev-p
+ (if (flyspell-already-abbrevp
+ (flyspell-abbrev-table) word)
+ (flyspell-change-abbrev
+ (flyspell-abbrev-table)
+ word
+ new-word)
+ (flyspell-define-abbrev word
+ new-word)))
+ (flyspell-word)
+ (flyspell-display-next-corrections
+ (cons new-word flyspell-auto-correct-ring))
+ (flyspell-ajust-cursor-point pos
+ (point)
+ old-max))))))))))
+ (setq flyspell-auto-correct-pos (point))
+ (ispell-pdict-save t)))))))
+
+;*---------------------------------------------------------------------*/
+;* flyspell-auto-correct-previous-pos ... */
+;*---------------------------------------------------------------------*/
+(defvar flyspell-auto-correct-previous-pos nil
+ "Holds the start of the first incorrect word before point.")
+
+;*---------------------------------------------------------------------*/
+;* flyspell-auto-correct-previous-hook ... */
+;*---------------------------------------------------------------------*/
+(defun flyspell-auto-correct-previous-hook ()
+ "Hook to track successive calls to `flyspell-auto-correct-previous-word'.
+Sets `flyspell-auto-correct-previous-pos' to nil"
+ (interactive)
+ (remove-hook 'pre-command-hook (function flyspell-auto-correct-previous-hook) t)
+ (unless (eq this-command (function flyspell-auto-correct-previous-word))
+ (setq flyspell-auto-correct-previous-pos nil)))
;*---------------------------------------------------------------------*/
-;* flyspell-correct-word ... */
+;* flyspell-auto-correct-previous-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.
+(defun flyspell-auto-correct-previous-word (position)
+ "*Auto correct the first mispelled word that occurs before point.
+But don't look beyond what's visible on the screen."
+ (interactive "d")
-Word syntax described by `ispell-dictionary-alist' (which see).
+ (let (top bot)
+ (save-excursion
+ (move-to-window-line 0)
+ (setq top (point))
+ (move-to-window-line -1)
+ (setq bot (point)))
+ (save-excursion
+ (save-restriction
+ (narrow-to-region top bot)
+ (overlay-recenter (point))
+
+ (add-hook 'pre-command-hook
+ (function flyspell-auto-correct-previous-hook) t t)
+
+ (unless flyspell-auto-correct-previous-pos
+ ;; only reset if a new overlay exists
+ (setq flyspell-auto-correct-previous-pos nil)
+
+ (let ((overlay-list (overlays-in (point-min) position))
+ (new-overlay 'dummy-value))
+
+ ;; search for previous (new) flyspell overlay
+ (while (and new-overlay
+ (or (not (flyspell-overlay-p new-overlay))
+ ;; check if its face has changed
+ (not (eq (get-char-property
+ (overlay-start new-overlay) 'face)
+ 'flyspell-incorrect))))
+ (setq new-overlay (car-safe overlay-list))
+ (setq overlay-list (cdr-safe overlay-list)))
+
+ ;; if nothing new exits new-overlay should be nil
+ (if new-overlay ;; the length of the word may change so go to the start
+ (setq flyspell-auto-correct-previous-pos
+ (overlay-start new-overlay)))))
+
+ (when flyspell-auto-correct-previous-pos
+ (save-excursion
+ (goto-char flyspell-auto-correct-previous-pos)
+ (let ((ispell-following-word t)) ;; point is at start
+ (if (numberp flyspell-auto-correct-previous-pos)
+ (goto-char flyspell-auto-correct-previous-pos))
+ (flyspell-auto-correct-word))
+ ;; the point may have moved so reset this
+ (setq flyspell-auto-correct-previous-pos (point))))))))
-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)
+;*---------------------------------------------------------------------*/
+;* flyspell-correct-word ... */
+;*---------------------------------------------------------------------*/
+(defun flyspell-correct-word (event)
"Pop up a menu of possible corrections for a misspelled word.
The word checked is the word at the mouse position."
(interactive "e")
(let ((save (point)))
(mouse-set-point event)
(let ((cursor-location (point))
- (word (flyspell-get-word nil))
- start end poss replace)
- ;; destructure return word info list.
- (setq start (car (cdr word))
- end (car (cdr (cdr word)))
- word (car word))
- ;; now check spelling of word.
- (process-send-string ispell-process "%\n") ;put in verbose mode
- (process-send-string ispell-process (concat "^" word "\n"))
- ;; wait until ispell has processed word
- (while (progn
- (accept-process-output ispell-process)
- (not (string= "" (car ispell-filter)))))
- (setq ispell-filter (cdr ispell-filter))
- (if (consp ispell-filter)
- (setq poss (ispell-parse-output (car ispell-filter))))
- (cond ((or (eq poss t) (stringp poss))
- ;; don't correct word
- t)
- ((null poss)
- ;; ispell error
- (error "Ispell: error in Ispell process"))
- ((string-match "GNU" (emacs-version))
- ;; the word is incorrect, we have to propose a replacement
- (setq replace (flyspell-emacs-popup event poss word))
- (cond ((eq replace 'ignore)
- (goto-char save)
- nil)
- ((eq replace 'save)
- (goto-char save)
- (process-send-string ispell-process (concat "*" word "\n"))
- (flyspell-unhighlight-at cursor-location)
- (setq ispell-pdict-modified-p '(t)))
- ((or (eq replace 'buffer) (eq replace 'session))
- (process-send-string ispell-process (concat "@" word "\n"))
- (if (null ispell-pdict-modified-p)
- (setq ispell-pdict-modified-p
- (list ispell-pdict-modified-p)))
- (flyspell-unhighlight-at cursor-location)
- (goto-char save)
- (if (eq replace 'buffer)
- (ispell-add-per-file-word-list word)))
- (replace
- (let ((new-word (if (atom replace)
- replace
- (car replace)))
- (cursor-location (+ (- (length word) (- end start))
- cursor-location)))
- (if (not (equal new-word (car poss)))
- (let ((old-max (point-max)))
- (delete-region start end)
- (insert new-word)
- (if flyspell-abbrev-p
- (define-abbrev (flyspell-abbrev-table)
- word
- new-word))
- (flyspell-ajust-cursor-point save
- cursor-location
- old-max)))))
- (t
- (goto-char save)
- nil)))
- ((eq flyspell-emacs 'xemacs)
- (flyspell-xemacs-popup
- event poss word cursor-location start end save)
- (goto-char save)))
- (ispell-pdict-save t))))
-
-;*---------------------------------------------------------------------*/
-;* flyspell-xemacs-correct ... */
-;*---------------------------------------------------------------------*/
-(defun flyspell-xemacs-correct (replace poss word cursor-location start end save)
- "The xemacs popup menu callback."
+ (word (flyspell-get-word nil)))
+ (if (consp word)
+ (let ((start (car (cdr word)))
+ (end (car (cdr (cdr word))))
+ (word (car word))
+ poss)
+ ;; now check spelling of word.
+ (process-send-string ispell-process "%\n") ;put in verbose mode
+ (process-send-string ispell-process (concat "^" word "\n"))
+ ;; wait until ispell has processed word
+ (while (progn
+ (accept-process-output ispell-process)
+ (not (string= "" (car ispell-filter)))))
+ (setq ispell-filter (cdr ispell-filter))
+ (if (consp ispell-filter)
+ (setq poss (ispell-parse-output (car ispell-filter))))
+ (cond
+ ((or (eq poss t) (stringp poss))
+ ;; don't correct word
+ t)
+ ((null poss)
+ ;; ispell error
+ (error "Ispell: error in Ispell process"))
+ ((featurep 'xemacs)
+ (flyspell-xemacs-popup
+ event poss word cursor-location start end save))
+ (t
+ ;; The word is incorrect, we have to propose a replacement.
+ (flyspell-do-correct (flyspell-emacs-popup event poss word)
+ poss word cursor-location start end save)))
+ (ispell-pdict-save t))))))
+
+;*---------------------------------------------------------------------*/
+;* flyspell-do-correct ... */
+;*---------------------------------------------------------------------*/
+(defun flyspell-do-correct (replace poss word cursor-location start end save)
+ "The popup menu callback."
+ ;; Originally, the XEmacs code didn't do the (goto-char save) here and did
+ ;; it instead right after calling the function.
(cond ((eq replace 'ignore)
+ (goto-char save)
nil)
((eq replace 'save)
- (process-send-string ispell-process (concat "*" word "\n"))
- (process-send-string ispell-process "#\n")
+ (goto-char save)
+ (ispell-send-string (concat "*" word "\n"))
+ ;; This was added only to the XEmacs side in revision 1.18 of
+ ;; flyspell. I assume its absence on the Emacs side was an
+ ;; oversight. --Stef
+ (ispell-send-string "#\n")
(flyspell-unhighlight-at cursor-location)
(setq ispell-pdict-modified-p '(t)))
((or (eq replace 'buffer) (eq replace 'session))
- (process-send-string ispell-process (concat "@" word "\n"))
+ (ispell-send-string (concat "@" word "\n"))
(flyspell-unhighlight-at cursor-location)
(if (null ispell-pdict-modified-p)
(setq ispell-pdict-modified-p
(list ispell-pdict-modified-p)))
+ (goto-char save)
(if (eq replace 'buffer)
(ispell-add-per-file-word-list word)))
(replace
+ ;; This was added only to the Emacs side. I assume its absence on
+ ;; the XEmacs side was an oversight. --Stef
+ (flyspell-unhighlight-at cursor-location)
(let ((old-max (point-max))
(new-word (if (atom replace)
replace
(car replace)))
(cursor-location (+ (- (length word) (- end start))
cursor-location)))
- (if (not (equal new-word (car poss)))
- (progn
- (delete-region start end)
- (goto-char start)
- (insert new-word)
- (if flyspell-abbrev-p
- (define-abbrev (flyspell-abbrev-table)
- word
- new-word))))
- (flyspell-ajust-cursor-point save cursor-location old-max)))))
+ (unless (equal new-word (car poss))
+ (delete-region start end)
+ (goto-char start)
+ (funcall flyspell-insert-function new-word)
+ (if flyspell-abbrev-p
+ (flyspell-define-abbrev word new-word)))
+ ;; In the original Emacs code, this was only called in the body
+ ;; of the if. I arbitrarily kept the XEmacs behavior instead.
+ (flyspell-ajust-cursor-point save cursor-location old-max)))
+ (t
+ (goto-char save)
+ nil)))
;*---------------------------------------------------------------------*/
;* flyspell-ajust-cursor-point ... */
mouse-pos
(set-mouse-position (car mouse-pos)
(/ (frame-width) 2) 2)
- (unfocus-frame)
(mouse-position))))
(setq event (list (list (car (cdr mouse-pos))
(1+ (cdr (cdr mouse-pos))))
(list
(list (concat "Save affix: " (car affix))
'save)
- '("Accept (session)" accept)
+ '("Accept (session)" session)
'("Accept (buffer)" buffer))
'(("Save word" save)
("Accept (session)" session)
;* 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)))))
(cor-menu (if (consp corrects)
(mapcar (lambda (correct)
(vector correct
- (list 'flyspell-xemacs-correct
+ (list 'flyspell-do-correct
correct
(list 'quote poss)
word
(menu (let ((save (if (consp affix)
(vector
(concat "Save affix: " (car affix))
- (list 'flyspell-xemacs-correct
+ (list 'flyspell-do-correct
''save
(list 'quote poss)
word
t)
(vector
"Save word"
- (list 'flyspell-xemacs-correct
+ (list 'flyspell-do-correct
''save
(list 'quote poss)
word
save)
t)))
(session (vector "Accept (session)"
- (list 'flyspell-xemacs-correct
+ (list 'flyspell-do-correct
''session
(list 'quote poss)
word
save)
t))
(buffer (vector "Accept (buffer)"
- (list 'flyspell-xemacs-correct
+ (list 'flyspell-do-correct
''buffer
(list 'quote poss)
word
menu))))
;*---------------------------------------------------------------------*/
-;* Some example functions for real autocrrecting xb */
+;* 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.
-This function is meant to be added to 'flyspell-incorrect-hook'."
+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
(let ((str (buffer-substring beg end))
nil)))
(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)
+This function is meant to be added to `flyspell-incorrect-hook'."
+ (when (consp poss)
(catch 'done
(let ((str (buffer-substring beg end))
(i 0) (len (- end beg)))
;*---------------------------------------------------------------------*/
(defun flyspell-change-abbrev (table old new)
(set (abbrev-symbol old table) new))
-
+
(provide 'flyspell)
+
+;; arch-tag: 05d915b9-e9cf-44fb-9137-fc28f5eaab2a
;;; flyspell.el ends here