home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 2 / FFMCD02.bin / useful / lib / emacs / site-lisp / ispell.el
Lisp/Scheme  |  1993-09-30  |  18KB  |  542 lines

  1. ;;   This is the GNU EMACS interface to GNU ISPELL version 4.
  2. ;;   Copyright (C) 1990, 1993 Free Software Foundation, Inc.
  3. ;;
  4. ;;   This file is part of GNU ISPELL.
  5. ;;
  6. ;;   This program is free software; you can redistribute it and/or modify
  7. ;;   it under the terms of the GNU General Public License as published by
  8. ;;   the Free Software Foundation; either version 2, or (at your option)
  9. ;;   any later version.
  10. ;;
  11. ;;   This program is distributed in the hope that it will be useful,
  12. ;;   but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. ;;   GNU General Public License for more details.
  15. ;;
  16. ;;   You should have received a copy of the GNU General Public License
  17. ;;   along with this program; if not, write to the Free Software
  18. ;;   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  
  20. (defvar ispell-have-new-look t
  21.   "T if default 'look' program has the -r flag.")
  22.  
  23. (defvar ispell-enable-tex-parser nil
  24.   "T to enable experimental tex parser in ispell for tex buffers.")
  25.  
  26. (defvar ispell-process nil "The process running ISPELL")
  27. (defvar ispell-next-message nil
  28.   "An integer telling where in the *ispell* buffer where
  29. to look for the next message from the ISPELL program.")
  30.  
  31. ;Each marker in this list points to the start of a word that
  32. ;ispell thought was bad last time it did the :file command.
  33. ;Notice that if the user accepts or inserts a word into his
  34. ;private dictionary, then some "good" words will be on the list.
  35. ;We would like to deal with this by looking up the words again just before
  36. ;presenting them to the user, but that is too slow on machines
  37. ;without the select system call.  Therefore, see the variable
  38. ;ispell-recently-accepted.
  39. (defvar ispell-bad-words nil
  40.   "A list of markers corresponding to the output of the ISPELL :file command.")
  41.  
  42. ;list of words that the user has accepted, but that might still
  43. ;be on the bad-words list
  44. (defvar ispell-recently-accepted nil)
  45.  
  46. ;t when :dump command needed
  47. (defvar ispell-dump-needed nil)
  48.  
  49. (defun ispell-flush-bad-words ()
  50.   (while ispell-bad-words
  51.     (if (markerp (car ispell-bad-words))
  52.         (set-marker (car ispell-bad-words) nil))
  53.     (setq ispell-bad-words (cdr ispell-bad-words)))
  54.   (setq ispell-recently-accepted nil))
  55.  
  56. (defun kill-ispell ()
  57.   "Kill the ispell process.  Any changes the your private dictionay
  58. that have not already been dumped will be lost."
  59.   (interactive)
  60.   (if ispell-process
  61.       (delete-process ispell-process))
  62.   (setq ispell-process nil)
  63.   (ispell-flush-bad-words))
  64.  
  65. (put 'ispell-startup-error 'error-conditions
  66.      '(ispell-startup-error error))
  67. (put 'ispell-startup-error 'error-message
  68.      "Problem starting ispell - see buffer *ispell*")
  69.  
  70. (defun start-ispell ()
  71.   "Start an ispell subprocess; check the version; and display the greeting."
  72.   (message "Starting ispell ...")
  73.   (let ((buf (get-buffer "*ispell*")))
  74.     (if buf
  75.     (kill-buffer buf)))
  76.   (condition-case err
  77.       (setq ispell-process (start-process "ispell" "*ispell*" "ispell" "-S"))
  78.     (file-error (signal 'ispell-startup-error nil)))
  79.   (process-kill-without-query ispell-process)
  80.   (buffer-flush-undo (process-buffer ispell-process))
  81.   (accept-process-output ispell-process)
  82.   (let (last-char)
  83.     (save-excursion
  84.       (set-buffer (process-buffer ispell-process))
  85.       (bury-buffer (current-buffer))
  86.       (setq last-char (- (point-max) 1))
  87.       (while (not (eq (char-after last-char) ?=))
  88.     (cond ((not (eq (process-status ispell-process) 'run))
  89.            (kill-ispell)
  90.            (signal 'ispell-startup-error nil)))
  91.     (accept-process-output ispell-process)
  92.     (setq last-char (- (point-max) 1)))
  93.       (goto-char (point-min))
  94.       (let ((greeting (read (current-buffer))))
  95.     (if (not (= (car greeting) 1))
  96.         (error "Bad ispell version: wanted 1, got %d" (car greeting)))
  97.     (message (car (cdr greeting))))
  98.       (delete-region (point-min) last-char))))
  99.   
  100. ;leaves buffer set to *ispell*, point at '='
  101. (defun ispell-sync (intr)
  102.   "Make sure ispell is ready for a command."
  103.   (if (or (null ispell-process)
  104.       (not (eq (process-status ispell-process) 'run)))
  105.       (start-ispell))
  106.   (if intr
  107.       (interrupt-process ispell-process))
  108.   (let (last-char)
  109.     (set-buffer (process-buffer ispell-process))
  110.     (bury-buffer (current-buffer))
  111.     (setq last-char (- (point-max) 1))
  112.     (while (not (eq (char-after last-char) ?=))
  113.       (accept-process-output ispell-process)
  114.       (setq last-char (- (point-max) 1)))
  115.     (goto-char last-char)))
  116.  
  117. (defun ispell-cmd (&rest strings)
  118.   "Send a command to ispell.  Choices are:
  119.  
  120. word        any word is checked for spelling.  Result is
  121.  
  122.             nil            not found
  123.             t            spelled ok
  124.             list of strings        near misses
  125.  
  126. :file filename    scan the named file, and print the file offsets of
  127.         any misspelled words
  128.  
  129. :insert word    put word in private dictonary
  130.  
  131. :accept word    don't complain about word any more this session
  132.  
  133. :dump        write out the current private dictionary, if necessary.
  134.  
  135. :reload        reread ~/ispell.words
  136.  
  137. :tex
  138. :troff
  139. :generic    set type of parser to use when scanning whole files
  140. "
  141.   (save-excursion
  142.     (ispell-sync t)
  143.     (set-buffer (process-buffer ispell-process))
  144.     (bury-buffer (current-buffer))
  145.     (erase-buffer)
  146.     (setq ispell-next-message (point-min))
  147.     (while strings
  148.       (process-send-string ispell-process (car strings))
  149.       (setq strings (cdr strings)))
  150.     (process-send-string ispell-process "\n")
  151.     (accept-process-output ispell-process)
  152.     (ispell-sync nil)))
  153.  
  154. (defun ispell-dump ()
  155.   (cond (ispell-dump-needed
  156.      (setq ispell-dump-needed nil)
  157.      (ispell-cmd ":dump"))))
  158.  
  159. (defun ispell-insert (word)
  160.   (ispell-cmd ":insert " word)
  161.   (if ispell-bad-words
  162.       (setq ispell-recently-accepted (cons word ispell-recently-accepted)))
  163.   (setq ispell-dump-needed t))
  164.  
  165. (defun ispell-accept (word)
  166.   (ispell-cmd ":accept " word)
  167.   (if ispell-bad-words
  168.       (setq ispell-recently-accepted (cons word ispell-recently-accepted))))
  169.  
  170.  
  171. (defun ispell-next-message ()
  172.   "Return the next message sent by the ispell subprocess."
  173.   (save-excursion
  174.     (set-buffer (process-buffer ispell-process))
  175.     (bury-buffer (current-buffer))
  176.     (save-restriction
  177.       (goto-char ispell-next-message)
  178.       (narrow-to-region (point)
  179.                         (progn (forward-sexp 1) (point)))
  180.       (setq ispell-next-message (point))
  181.       (goto-char (point-min))
  182.       (read (current-buffer)))))
  183.  
  184. (defun ispell-tex-buffer-p ()
  185.   (memq major-mode '(plain-TeX-mode LaTeX-mode)))
  186.  
  187. (defun ispell (&optional buf start end)
  188.   "Run ispell over a buffer.  (Actually over the buffer's file.)
  189. First the file is scanned for misspelled words, then ispell
  190. enters a loop with the following commands for every misspelled word:
  191.  
  192. DIGIT    Near miss selector.  If the misspelled word is 'close' to
  193.     some words in the dictionary, they are offered as near misses.
  194. r    Replace.  Replace the word with a string you type.  Each word
  195.     of your new string is also checked.
  196. i    Insert.  Insert this word in your private dictonary (kept in
  197.     $HOME/ispell.words)
  198. a    Accept.  Accept this word for the rest of this editing session,
  199.      but don't put it in your private dictonary.
  200. l    Lookup.  Look for a word in the dictionary by fast binary
  201.     search, or search for a regular expression in the dictionary
  202.     using grep.
  203. SPACE    Accept the word this time, but complain if it is seen again.
  204. q, C-G    Leave the command loop.  You can come back later with \\[ispell-next]."
  205.   (interactive)
  206.   (if (null start)
  207.       (setq start 0))
  208.   (if (null end)
  209.       (setq end 0))
  210.  
  211.   (if (null buf)
  212.       (setq buf (current-buffer)))
  213.   (setq buf (get-buffer buf))
  214.   (if (null buf)
  215.       (error "Can't find buffer"))
  216.   (save-excursion
  217.     (set-buffer buf)
  218.     (let ((filename buffer-file-name)
  219.           (delete-temp nil))
  220.       (unwind-protect
  221.       (progn
  222.         (cond ((null filename)
  223.            (setq filename (make-temp-name "/usr/tmp/ispell"))
  224.            (setq delete-temp t)
  225.            (write-region (point-min) (point-max) filename))
  226.           ((and (buffer-modified-p buf)
  227.             (y-or-n-p (format "Save file %s? " filename)))
  228.            (save-buffer)))
  229.         (message "Ispell scanning file...")
  230.         (if (and ispell-enable-tex-parser
  231.              (ispell-tex-buffer-p))
  232.         (ispell-cmd ":tex")
  233.           (ispell-cmd ":generic"))