• R/O
  • SSH

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

Commit MetaInfo

Revisión4b95b5b6d767f14d17265b6c81804fe36c8b661e (tree)
Tiempo2010-12-02 20:39:40
Autorlorenzo
Commiterlorenzo

Log Message

I added another file needed to obtain support for multiple dictionaries in latex documents.

Cambiar Resumen

Diferencia incremental

diff -r 06b57f37d1b8 -r 4b95b5b6d767 emacs_files/ispell-multi.el
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emacs_files/ispell-multi.el Thu Dec 02 11:39:40 2010 +0000
@@ -0,0 +1,445 @@
1+;; ispell-multi.el -- multiple ispell processes and multiple flyspell languages
2+;;
3+;; Copyright (C) 2005 P J Heslin
4+;;
5+;; Author: Peter Heslin <p.j.heslin@dur.ac.uk>
6+;; URL: http://www.dur.ac.uk/p.j.heslin/Software/Emacs/Download/ispell-multi.el
7+;; Version: 1.2
8+;;
9+;; This program is free software; you can redistribute it and/or modify
10+;; it under the terms of the GNU General Public License as published by
11+;; the Free Software Foundation; either version 2, or (at your option)
12+;; any later version.
13+;;
14+;; This program is distributed in the hope that it will be useful,
15+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+;; GNU General Public License for more details.
18+;;
19+;; If you do not have a copy of the GNU General Public License, you
20+;; can obtain one by writing to the Free Software Foundation, Inc., 59
21+;; Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22+
23+;;; Overview:
24+;;
25+;; ispell-multi.el enables Emacs to keep a number of ispell processes
26+;; alive in order to spell-check text efficiently in multiple
27+;; languages, and it provides a hook that tells flyspell to switch
28+;; languages depending on the value of a particular text property.
29+;;
30+;; Normally, ispell.el only ever keeps one ispell/aspell process
31+;; alive. So if you have one buffer in which an English local
32+;; dictionary is used and another in which a German dictionary is
33+;; used, the ispell process will be killed and restarted every time
34+;; you run ispell in the other buffer. This is not really a problem,
35+;; since doing a spellcheck is infrequent and slow anyway. If you are
36+;; using flyspell-mode, however, the ispell process will be restarted
37+;; every time you switch buffers. Even this may not matter too much
38+;; to many people, since switching buffers is also a somewhat slow
39+;; operation.
40+;;
41+;; Where the need for multiple ispell processes becomes really acute
42+;; is in buffers that have multiple languages in them and a way of
43+;; telling flyspell to switch local dictionaries depending on where
44+;; point is. In this case, the starting and stopping of ispell
45+;; processes very visibly impedes the fluid movement of the cursor.
46+;;
47+;; I have written two packages that provide this sort of behavior.
48+;; One is flyspell-xml-lang.el, which tells flyspell what the local
49+;; language is in xml files depending on xml:lang attributes, and
50+;; another is flyspell-babel.el, which does the same with Babel
51+;; commands in LaTeX files.
52+;;
53+;; The present package modifies ispell.el (via defadvice) so that
54+;; multiple ispell processes are kept alive to check different
55+;; languages. It requires version 3.6 of ispell, so users of Emacs
56+;; 21.3 and earlier will have to upgrade. This has only been tested
57+;; with GNU Emacs.
58+;;
59+;; To install this package, just put it somewhere in your load-path
60+;; and put a (require 'ispell-multi) statement in your .emacs file.
61+
62+;;; Using ispell-multi
63+;;
64+;; If all you want to do is to change the behavior of ispell so that
65+;; it uses multiple ispell processes for different buffers, then
66+;; (require 'ispell-multi) is all you need to do. The rest of this
67+;; section is for those who want to modify flyspell to switch
68+;; languages within a buffer. See flyspell-xml-lang.el and
69+;; flyspell-babel.el for examples of the usage of all of the
70+;; facilities described below.
71+;;
72+;; Flyspell-mode provides a hook that runs before checking each word;
73+;; this allows you to change the value of ispell-local-dictionary to a
74+;; different language, depending on the context. If you have a
75+;; package that parses a buffer and figures out what languages are in
76+;; it and where they are, you can tell flyspell about it by setting
77+;; the text property `ispell-multi-lang' to the correct ispell
78+;; language (this can be any value that ispell-change-dictionary
79+;; accepts). Your package should set the value of the buffer-local
80+;; variable `flyspell-generic-check-word-predicate' to the symbol
81+;; `ispell-multi-verify'; do this *after* you have turned on
82+;; flyspell-mode.
83+
84+;; If you the set the buffer-local variable
85+;; `ispell-multi-nil-callback' to a symbol, the associated
86+;; function will be called every time flyspell is called to check a
87+;; word, and the `ispell-multi-lang' text property returns nil. This
88+;; function can be used to parse the buffer incrementally and set the
89+;; text-property lazily as the user moves through the buffer.
90+;;
91+;; Since the parser callback is only invoked when the text-property is
92+;; nil, there is a possibility that the already-set text-property and
93+;; the changed contents of the buffer will get out of sync. To fix
94+;; this you will probably also want to arrange for the parser to be
95+;; run by an idle-timer. You can arrange for this by calling the
96+;; function `ispell-multi-idler-setup' with a single argument, giving
97+;; the delay. This will run the function specified by
98+;; `ispell-multi-idler-callback' after the specified idle time.
99+;;
100+;; If you want to indicate that some text should not be spell-checked,
101+;; set the `ispell-multi-lang' text property to the string "void". To
102+;; indicate a reversion to the default ispell dictionary, use the
103+;; string "default".
104+
105+;;; Aspell vs. Ispell
106+;;
107+;; ispell.el and ispell-multi.el will work happily with aspell instead
108+;; of ispell, since the former can emulate the latter. Aspell has
109+;; many advantages over ispell, including a very large selection of
110+;; language dictionaries, and it is much better able to suggest the
111+;; correct spelling (which is quite handy when using
112+;; flyspell-auto-correct-previous-word). If you prefer to use aspell,
113+;; you can put the following into your .emacs:
114+;;
115+;; (setq ispell-program-name "aspell")
116+;; (setq ispell-really-aspell t)
117+;; (setq ispell-extra-args '("--sug-mode=fast"))
118+;;
119+;; The first two lines tell ispell.el to run aspell instead of ispell,
120+;; and the third line tells aspell not to use its default algorithm
121+;; for suggesting spellings, but to use a faster one; the default is
122+;; very accurate, but can be a bit slow for use with flyspell. If
123+;; this is not fast enough, try "ultra" instead of "fast" (but even
124+;; ultra mode is still two times slower than ispell).
125+;;
126+;; If you are installing a new aspell dictionary that ispell.el does
127+;; not know about, you will have to add it to
128+;; ispell-local-dictionary-alist; see the documentation of
129+;; flyspell-xml-lang.el for an example.
130+
131+;;; Bugs and Limitations
132+;;
133+;; If you change ispell dictionaries by using the function
134+;; `ispell-change-dictionary', then an ispell process will be killed,
135+;; where it would not have been if you had simply set
136+;; ispell-local-dictionary. That's because this package just modifies
137+;; the way ispell deals with local variables like
138+;; ispell-local-dictionary; it doesn't touch the
139+;; ispell-change-dictionary function. Maybe it should. The necessary
140+;; ispell process will be re-started next time you need it, so this is
141+;; not really a bug so much as a slight performance issue.
142+;;
143+;; We try to share ispell processes between buffers, so that a single
144+;; process can service all buffers or regions in a given language.
145+;; But if you put buffer-local variables that modify the behavior of
146+;; ispell for a given buffer (such as LocalWords), then that buffer's
147+;; ispell processes will not be shared.
148+;;
149+;; flyspell-large-region, which is the fast mode of flyspell that it
150+;; uses when checking the entirety of a large buffer, does not work at
151+;; all, since it depends on launching a single ispell process for this
152+;; purpose and so cannot cope with multiple languages. For this
153+;; reason, flyspell-large-region should be disabled in buffers using
154+;; this package.
155+;;
156+;; It might have been nice to put in here the code to inspect a
157+;; text-property to find out the language of the text, so that ispell
158+;; (as opposed to flyspell) would obey the property and change
159+;; dictionary accordingly. This won't work, though, since
160+;; ispell-region works on a line-by-line basis, which would fail in
161+;; the case of a mid-line language-switch.
162+
163+;;; Changes
164+;;
165+;; 1.0 Pre-release
166+;; 1.1 Worked around ispell-current-dictionary / ispell-dictionary
167+;; inconsistency in Emacs CVS / stand-alone ispell.el
168+;; 1.2 Protect better against errors when switching to an undefined or
169+;; uninstalled dictionary -- errors in post-command-hook will
170+;; switch off flyspell, cua, etc.
171+;; 1.3 Changed process management so that an ispell process without
172+;; buffer-local modifications will only be killed when all buffers
173+;; that have used that process have been killed.
174+
175+(require 'ispell)
176+;; For Emacs 21.3, we have to use an updated ispell.el (3.6 or from
177+;; Emacs CVS), and for some reason we may have to load it again to get
178+;; ispell-dictionary-alist set properly.
179+(unless (assoc "english" ispell-dictionary-alist)
180+ (load "ispell"))
181+;; For updated ispell.el with emacs < 21.3.5
182+(when (not (fboundp 'set-process-query-on-exit-flag))
183+ (defun set-process-query-on-exit-flag (one two) ()))
184+
185+; In current Emacs CVS, the variable ispell-current-dictionary is used
186+; to indicate the dictionary associated with the current ispell
187+; process, while in the current, separately distributed version of
188+; ispell.el (3.7beta), this variable does not exist, and
189+; ispell-dictionary serves this purpose.
190+(defvar ispell-multi-current-dictionary-var
191+ (if (boundp 'ispell-current-dictionary)
192+ 'ispell-current-dictionary
193+ 'ispell-dictionary))
194+
195+(defvar ispell-multi-dict nil
196+ "The language that this package thinks is current in this
197+ buffer. We don't set ispell-local-dictionary directly, since
198+ we want that to contain the default fall-back in case
199+ ispell-multi-dict is not set.")
200+(make-variable-buffer-local 'ispell-multi-dict)
201+
202+
203+(defvar ispell-multi-lang-process nil
204+ "Alist mapping languages to ispell processes. Only for
205+ processes without any buffer-local modifications")
206+
207+(defvar ispell-multi-lang-process-local nil
208+ "As ispell-multi-lang-process, but a buffer-local alist, to use
209+ for processes with buffer-local modifications")
210+(make-variable-buffer-local 'ispell-multi-lang-process-local)
211+
212+(defvar ispell-multi-flyspell-verify-default nil
213+ "The original value of `flyspell-generic-check-word-predicate',
214+ before it was overridden in order to invoke this package; taken
215+ from the the `flyspell-mode-predicate' property of the major
216+ mode name.")
217+(make-variable-buffer-local 'ispell-multi-flyspell-verify-default)
218+
219+(defvar ispell-multi-nil-callback nil
220+ "Buffer local variable that indicates a function to call when
221+ flyspell is checking a word and the text property
222+ `ispell-multi-lang' is nil. This function will normally set
223+ that property at point and for some of the text in the
224+ neighborhood")
225+(make-variable-buffer-local 'ispell-multi-nil-callback)
226+
227+(defvar ispell-multi-idler-callback nil
228+ "Buffer local variable that indicates a function to call when
229+ idle. Can be used to parse part or all of the buffer.")
230+(make-variable-buffer-local 'ispell-multi-idler-callback)
231+
232+(defvar ispell-multi-verbose nil
233+ "If non-nil, print diagnostic messages about switching dictionaries")
234+
235+(defvar ispell-multi-valid-dictionary-list nil
236+ "Cached value of ispell-valid-dictionary-list.")
237+(when (fboundp 'ispell-valid-dictionary-list)
238+ (setq ispell-multi-valid-dictionary-list
239+ (ispell-valid-dictionary-list)))
240+
241+(defvar ispell-multi-bad-language nil
242+ "A list of languages that ispell has choked on. After the
243+ first attempt, we stop trying to start ispell processes for
244+ this language, since flyspell will try to do so incessantly and
245+ cursor motion will get sluggish")
246+
247+;; Reset on re-load
248+(setq ispell-multi-bad-language nil)
249+
250+;; This is our hook into ispell.el.
251+(defadvice ispell-accept-buffer-local-defs (around ispell-multi-advice activate)
252+ "Advice that changes ispell to enable multiple ispell processes."
253+ ;; Bind ispell-local-dictionary
254+ (let* ((ispell-local-dictionary
255+ (if (or (equal ispell-multi-dict "void")
256+ (equal ispell-multi-dict "default")
257+ (null ispell-multi-dict))
258+ ispell-local-dictionary
259+ ispell-multi-dict))
260+ (local-mods (ispell-multi-buffer-local-modifications-p))
261+ (alist (if local-mods
262+ 'ispell-multi-lang-process-local
263+ 'ispell-multi-lang-process))
264+ (stored-process (cdr (assoc ispell-local-dictionary (symbol-value alist)))))
265+
266+ ;; Store the currently running process if we haven't already
267+ (when (and ispell-process
268+ (eq (process-status ispell-process) 'run))
269+ (when (not (rassq ispell-process (symbol-value alist)))
270+ (set alist (cons (cons (symbol-value ispell-multi-current-dictionary-var) ispell-process)
271+ (symbol-value alist))))
272+ ;; Make a note that this buffer has used this process
273+ (when (not (memq (current-buffer)
274+ (process-get ispell-process 'ispell-multi-buffers)))
275+ (process-put ispell-process 'ispell-multi-buffers
276+ (cons (current-buffer)
277+ (process-get ispell-process 'ispell-multi-buffers)))))
278+
279+ ;; Do we already have a process for this language?
280+ (if (and stored-process
281+ (eq (process-status stored-process) 'run))
282+ (progn
283+ (setq ispell-process stored-process)
284+ ;; When ispell-current-dictionary / ispell-dictionary is
285+ ;; the same as ispell-local-dictionary, ispell.el will
286+ ;; refrain from killing the process
287+ (set ispell-multi-current-dictionary-var ispell-local-dictionary))
288+
289+ ;; This is to fool ispell into not killing the old process when
290+ ;; it starts the new one. But we don't want a new process if
291+ ;; the current one is correct, or if the default dict is void.
292+ (unless (or (equal (symbol-value ispell-multi-current-dictionary-var) ispell-local-dictionary)
293+ (equal ispell-local-dictionary "void"))
294+ (setq ispell-process nil))
295+
296+ ;; Possibly start a new process
297+ (unless (equal ispell-local-dictionary "void") ; ensure against error
298+ ad-do-it))))
299+
300+
301+(defun ispell-multi-kill-processes-hook ()
302+ "Kill orphaned ispell processes."
303+ (dolist (proc (process-list))
304+ (let* ((old-list (process-get proc 'ispell-multi-buffers))
305+ (new-list (delete (current-buffer) old-list)))
306+ (when (and old-list (not new-list)
307+ (eq (process-status proc) 'run))
308+ (setq ispell-process proc)
309+ (ispell-kill-ispell))))
310+ (ispell-multi-processes-alist-cleanup))
311+
312+(add-hook 'kill-buffer-hook 'ispell-multi-kill-processes-hook)
313+
314+(defun ispell-multi-processes-alist-cleanup ()
315+ "Remove any defunct processes from the global alist"
316+ (let ((newlist))
317+ (while ispell-multi-lang-process
318+ (when (eq (process-status (cdar ispell-multi-lang-process)) 'run)
319+ (setq newlist (cons (car ispell-multi-lang-process) newlist)))
320+ (setq ispell-multi-lang-process (cdr ispell-multi-lang-process)))
321+ (setq ispell-multi-lang-process (nreverse newlist))))
322+
323+(defvar ispell-multi-local-regexp
324+ (mapconcat 'regexp-quote (list ispell-dictionary-keyword
325+ ispell-pdict-keyword
326+ ispell-words-keyword) "\\|"))
327+
328+(defun ispell-multi-buffer-local-modifications-p ()
329+ (save-excursion
330+ (goto-char (point-max))
331+ (re-search-backward ispell-multi-local-regexp nil t)))
332+
333+(defun ispell-multi-verify ()
334+ ;; Possibly initialize value of default function
335+ (unless ispell-multi-flyspell-verify-default
336+ (setq ispell-multi-flyspell-verify-default
337+ (or (get major-mode 'flyspell-mode-predicate)
338+ 'none)))
339+ (let ((do-check t)
340+ ;; NB. Adding text properties via the callback will call
341+ ;; after-change-functions, to which flyspell adds a function
342+ ;; that can trigger an infinite loop: flyspell-word changes
343+ ;; the buffer, which can add a value to flyspell-changes, so
344+ ;; that list never goes to nil
345+ (after-change-functions nil))
346+ ;; Don't switch language if we're not supposed to check this bit anyway
347+ (when (not (eq ispell-multi-flyspell-verify-default 'none))
348+ (setq do-check (funcall ispell-multi-flyspell-verify-default)))
349+ (when do-check
350+ (let* ((current-position (point))
351+ (lang (get-text-property current-position 'ispell-multi-lang)))
352+ (when (and (not lang)
353+ ispell-multi-nil-callback)
354+ (ispell-multi-message "parsing ...")
355+ (save-excursion
356+ (funcall ispell-multi-nil-callback))
357+ (ispell-multi-message "finished parsing.")
358+ (setq lang (get-text-property current-position 'ispell-multi-lang)))
359+ (when lang
360+ (unless (string= ispell-multi-dict lang)
361+ (let ((old-lang ispell-multi-dict))
362+ (cond
363+ ((string= lang "void")
364+ (setq do-check nil)
365+; (ispell-multi-message "current dictionary is void: not checking")
366+ )
367+ ((and ispell-multi-valid-dictionary-list
368+ (member lang ispell-multi-valid-dictionary-list)
369+ (not (member lang ispell-multi-bad-language)))
370+ (ispell-multi-message (concat "dictionary changing to: " lang))
371+ (setq ispell-multi-dict lang)
372+ ;; Be paranoid, since this can be called from a post-command hook
373+ (condition-case nil
374+ (ispell-accept-buffer-local-defs)
375+ (error (progn
376+ (ispell-multi-message
377+ (concat "Error: ispell didn't like language " lang) t)
378+ (setq ispell-multi-bad-language (cons lang ispell-multi-bad-language))
379+ (setq do-check nil)
380+ (setq ispell-multi-dict old-lang)))))
381+ (t
382+ (ispell-multi-message
383+ (concat "Warning: no dictionary defined for " lang))
384+ (setq do-check nil))))))))
385+ do-check))
386+
387+(defvar ispell-multi-ticker 0)
388+(defvar ispell-multi-old-point 0)
389+(make-variable-buffer-local 'ispell-multi-ticker)
390+(make-variable-buffer-local 'ispell-multi-old-point)
391+
392+(defun ispell-multi-idler ()
393+ (when (and flyspell-mode
394+ (eq flyspell-generic-check-word-predicate 'ispell-multi-verify)
395+ (not (= (buffer-modified-tick) ispell-multi-ticker))
396+ (not (= (point) ispell-multi-old-point)))
397+ (let ((old-lang (get-text-property (point) 'ispell-multi-lang))
398+ new-lang)
399+ (when ispell-multi-idler-callback
400+ (ispell-multi-message "parsing (idle) ...")
401+ (let ((after-change-functions nil))
402+ (save-excursion
403+ (funcall ispell-multi-idler-callback)))
404+ (ispell-multi-message "finished parsing.")
405+ (setq new-lang (get-text-property (point) 'ispell-multi-lang))
406+ (unless (or (equal old-lang new-lang)
407+ (equal new-lang "void"))
408+ (setq ispell-multi-dict new-lang)
409+ (ispell-accept-buffer-local-defs)))
410+ (setq ispell-multi-ticker (buffer-modified-tick))
411+ (setq ispell-multi-old-point (point)))))
412+
413+(defvar ispell-multi-idle-timer nil)
414+(defun ispell-multi-idler-setup (delay)
415+ (unless ispell-multi-idle-timer
416+ (setq ispell-multi-idle-timer
417+ (run-with-idle-timer 5 t 'ispell-multi-idler))))
418+
419+(defun ispell-multi-idler-cancel ()
420+ (cancel-timer ispell-multi-idle-timer)
421+ (setq ispell-multi-idle-timer nil))
422+
423+(defun ispell-multi-unhack-flyspell-modeline ()
424+ "Remove the flyspell modeline entry"
425+ (setq minor-mode-alist
426+ (delq (assq 'flyspell-mode minor-mode-alist) minor-mode-alist)))
427+
428+(defun ispell-multi-hack-flyspell-modeline ()
429+ "Add a modeline entry for flyspell that indicates the current
430+ language in parentheses."
431+ (ispell-multi-unhack-flyspell-modeline)
432+ (setq minor-mode-alist
433+ (cons '(flyspell-mode
434+ (:eval
435+ (let ((lang (get-text-property (point) 'ispell-multi-lang)))
436+ (concat flyspell-mode-line-string
437+ (when lang
438+ (concat " (" (capitalize lang) ")")))))) minor-mode-alist)))
439+
440+(defun ispell-multi-message (mess &optional force)
441+ (when (or ispell-multi-verbose force)
442+ (message "ispell-multi -- %s" mess)))
443+
444+(provide 'ispell-multi)
445+