]> code.delx.au - gnu-emacs/blobdiff - lisp/textmodes/flyspell.el
Switch to recommended form of GPLv3 permissions notice.
[gnu-emacs] / lisp / textmodes / flyspell.el
index 0b5dfa4cc54ba30fc93648de75a6e926a615a470..0267dfda7ca93ac41e951b870757bb528e039b1c 100644 (file)
@@ -1,7 +1,7 @@
 ;;; flyspell.el --- on-the-fly spell checker
 
 ;; Copyright (C) 1998, 2000, 2001, 2002, 2003, 2004,
-;;   2005, 2006, 2007 Free Software Foundation, Inc.
+;;   2005, 2006, 2007, 2008 Free Software Foundation, Inc.
 
 ;; Author: Manuel Serrano <Manuel.Serrano@sophia.inria.fr>
 ;; Maintainer: FSF
@@ -9,10 +9,10 @@
 
 ;; This file is part of GNU Emacs.
 
-;; GNU Emacs is free software; you can redistribute it and/or modify
+;; 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
-;; the Free Software Foundation; either version 3, or (at your option)
-;; any later version.
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
 
 ;; GNU Emacs is distributed in the hope that it will be useful,
 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -20,9 +20,7 @@
 ;; GNU General Public License for more details.
 
 ;; 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., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
 
 ;;; Commentary:
 ;;
@@ -67,11 +65,21 @@ Non-nil means use highlight, nil means use minibuffer messages."
 
 (defcustom flyspell-mark-duplications-flag t
   "Non-nil means Flyspell reports a repeated word as an error.
+See `flyspell-mark-duplications-exceptions' to add exceptions to this rule.
 Detection of repeated words is not implemented in
 \"large\" regions; see `flyspell-large-region'."
   :group 'flyspell
   :type 'boolean)
 
+(defcustom flyspell-mark-duplications-exceptions
+  '(("francais" . ("nous" "vous")))
+  "A list of exceptions for duplicated words.
+It should be a list of (LANGUAGE . EXCEPTION-LIST).  LANGUAGE is matched
+against the current dictionary and EXCEPTION-LIST is a list of strings.
+The duplicated word is downcased before it is compared with the exceptions."
+  :group 'flyspell
+  :type '(alist :key-type string :value-type (repeat string)))
+
 (defcustom flyspell-sort-corrections nil
   "Non-nil means, sort the corrections alphabetically before popping them."
   :group 'flyspell
@@ -88,7 +96,8 @@ This variable specifies how far to search to find such a duplicate.
 0 means do not search for duplicate unrecognized spellings."
   :group 'flyspell
   :version "21.1"
-  :type 'number)
+  :type '(choice (const :tag "no limit" -1)
+                number))
 
 (defcustom flyspell-delay 3
   "The number of seconds to wait before checking, after a \"delayed\" command."
@@ -286,6 +295,7 @@ property of the major mode name.")
 ;;*--- mail mode -------------------------------------------------------*/
 (put 'mail-mode 'flyspell-mode-predicate 'mail-mode-flyspell-verify)
 (put 'message-mode 'flyspell-mode-predicate 'mail-mode-flyspell-verify)
+(defvar message-signature-separator)
 (defun mail-mode-flyspell-verify ()
   "Function used for `flyspell-generic-check-word-predicate' in Mail mode."
   (let ((header-end (save-excursion
@@ -338,6 +348,7 @@ property of the major mode name.")
 ;;*--- sgml mode -------------------------------------------------------*/
 (put 'sgml-mode 'flyspell-mode-predicate 'sgml-mode-flyspell-verify)
 (put 'html-mode 'flyspell-mode-predicate 'sgml-mode-flyspell-verify)
+(put 'nxml-mode 'flyspell-mode-predicate 'sgml-mode-flyspell-verify)
 
 (defun sgml-mode-flyspell-verify ()
   "Function used for `flyspell-generic-check-word-predicate' in SGML mode."
@@ -467,7 +478,7 @@ Bindings:
 \\[flyspell-correct-word] (or down-mouse-2): popup correct words.
 
 Hooks:
-This runs `flyspell-mode-hook' after flyspell is entered.
+This runs `flyspell-mode-hook' after flyspell mode is entered or exit.
 
 Remark:
 `flyspell-mode' uses `ispell-mode'.  Thus all Ispell options are
@@ -485,7 +496,10 @@ in your .emacs file.
   :keymap flyspell-mode-map
   :group 'flyspell
   (if flyspell-mode
-      (flyspell-mode-on)
+      (condition-case ()
+         (flyspell-mode-on)
+       (error (message "Enabling Flyspell mode gave an error")
+              (flyspell-mode -1)))
     (flyspell-mode-off)))
 
 ;;;###autoload
@@ -563,7 +577,7 @@ in your .emacs file.
 ;;*---------------------------------------------------------------------*/
 (defun flyspell-mode-on ()
   "Turn Flyspell mode on.  Do not use this; use `flyspell-mode' instead."
-  (ispell-maybe-find-aspell-dictionaries)
+  (ispell-set-spellchecker-params) ; Initialize variables and dicts alists
   (setq ispell-highlight-face 'flyspell-incorrect)
   ;; local dictionaries setup
   (or ispell-local-dictionary ispell-dictionary
@@ -602,16 +616,14 @@ in your .emacs file.
         (if binding
             (format "Welcome to flyspell. Use %s or Mouse-2 to correct words."
                     (key-description binding))
-          "Welcome to flyspell. Use Mouse-2 to correct words."))))
-  ;; we end with the flyspell hooks
-  (run-hooks 'flyspell-mode-hook))
+          "Welcome to flyspell. Use Mouse-2 to correct words.")))))
 
 ;;*---------------------------------------------------------------------*/
 ;;*    flyspell-delay-commands ...                                      */
 ;;*---------------------------------------------------------------------*/
 (defun flyspell-delay-commands ()
   "Install the standard set of Flyspell delayed commands."
-  (mapcar 'flyspell-delay-command flyspell-default-delayed-commands)
+  (mapc 'flyspell-delay-command flyspell-default-delayed-commands)
   (mapcar 'flyspell-delay-command flyspell-delayed-commands))
 
 ;;*---------------------------------------------------------------------*/
@@ -630,7 +642,7 @@ It will be checked only after `flyspell-delay' seconds."
 ;;*---------------------------------------------------------------------*/
 (defun flyspell-deplacement-commands ()
   "Install the standard set of Flyspell deplacement commands."
-  (mapcar 'flyspell-deplacement-command flyspell-default-deplacement-commands)
+  (mapc 'flyspell-deplacement-command flyspell-default-deplacement-commands)
   (mapcar 'flyspell-deplacement-command flyspell-deplacement-commands))
 
 ;;*---------------------------------------------------------------------*/
@@ -1001,6 +1013,7 @@ Mostly we check word delimiters."
 (defun flyspell-word (&optional following)
   "Spell check a word."
   (interactive (list ispell-following-word))
+  (ispell-set-spellchecker-params)    ; Initialize variables and dicts alists
   (save-excursion
     ;; use the correct dictionary
     (flyspell-accept-buffer-local-defs)
@@ -1022,6 +1035,13 @@ Mostly we check word delimiters."
                     (and (> start (point-min))
                          (not (memq (char-after (1- start)) '(?\} ?\\)))))
                 flyspell-mark-duplications-flag
+                (not (catch 'exception
+                       (dolist (except flyspell-mark-duplications-exceptions)
+                         (and (string= (or ispell-local-dictionary
+                                           ispell-dictionary)
+                                       (car except))
+                              (member (downcase word) (cdr except))
+                              (throw 'exception t)))))
                 (save-excursion
                   (goto-char start)
                   (let* ((bound
@@ -1509,30 +1529,43 @@ The buffer to mark them in is `flyspell-large-region-buffer'."
     ;; this is done, we can start checking...
     (if flyspell-issue-message-flag (message "Checking region..."))
     (set-buffer curbuf)
-    (ispell-check-version)
-    (let ((c (apply 'ispell-call-process-region beg
-                   end
-                   ispell-program-name
-                   nil
-                   buffer
-                   nil
-                   (if ispell-really-aspell "list" "-l")
-                   (let (args)
-                     ;; Local dictionary becomes the global dictionary in use.
-                     (if ispell-local-dictionary
-                         (setq ispell-dictionary ispell-local-dictionary))
-                     (setq args (ispell-get-ispell-args))
-                     (if ispell-dictionary ; use specified dictionary
-                         (setq args
-                               (append (list "-d" ispell-dictionary) args)))
-                     (if ispell-personal-dictionary ; use specified pers dict
-                         (setq args
-                               (append args
-                                       (list "-p"
-                                             (expand-file-name
-                                              ispell-personal-dictionary)))))
-                     (setq args (append args ispell-extra-args))
-                     args))))
+    (ispell-set-spellchecker-params)  ; Initialize variables and dicts alists
+    ;; Local dictionary becomes the global dictionary in use.
+    (setq ispell-current-dictionary
+         (or ispell-local-dictionary ispell-dictionary))
+    (setq ispell-current-personal-dictionary
+         (or ispell-local-pdict ispell-personal-dictionary))
+    (let ((args (ispell-get-ispell-args))
+         (encoding (ispell-get-coding-system))
+         c)
+      (if (and ispell-current-dictionary  ; use specified dictionary
+              (not (member "-d" args)))  ; only define if not overridden
+         (setq args
+               (append (list "-d" ispell-current-dictionary) args)))
+      (if ispell-current-personal-dictionary ; use specified pers dict
+         (setq args
+               (append args
+                       (list "-p"
+                             (expand-file-name
+                              ispell-current-personal-dictionary)))))
+      (setq args (append args ispell-extra-args))
+      (if (and ispell-really-aspell
+              ispell-aspell-supports-utf8)
+         (setq args
+               (append args
+                       (list
+                        (concat "--encoding="
+                                (symbol-name
+                                 encoding))))))
+      (let ((process-coding-system-alist (list (cons "\\.*" encoding))))
+       (setq c (apply 'ispell-call-process-region beg
+                      end
+                      ispell-program-name
+                      nil
+                      buffer
+                      nil
+                      (if ispell-really-aspell "list" "-l")
+                      args)))
       (if (eq c 0)
          (progn
            (flyspell-process-localwords buffer)
@@ -1555,6 +1588,7 @@ The buffer to mark them in is `flyspell-large-region-buffer'."
 (defun flyspell-region (beg end)
   "Flyspell text between BEG and END."
   (interactive "r")
+  (ispell-set-spellchecker-params)  ; Initialize variables and dicts alists
   (if (= beg end)
       ()
     (save-excursion