File: auto-dictionary.el

package info (click to toggle)
auto-dictionary-mode 1.1-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, sid
  • size: 120 kB
  • sloc: lisp: 613; makefile: 2
file content (757 lines) | stat: -rw-r--r-- 41,235 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
;;; auto-dictionary.el --- automatic dictionary switcher for flyspell
;;-*-coding: utf-8;-*-
;;
;; Copyright (C) 2006-2008, 2011, 2013 Nikolaj Schumacher
;;
;; Author: Nikolaj Schumacher <bugs * nschum de>
;; Version: 1.1
;; Keywords: wp
;; URL: http://nschum.de/src/emacs/auto-dictionary/
;; Compatibility: GNU Emacs 22.x, GNU Emacs 23.x, GNU Emacs 24.x
;;
;; This file is NOT part of GNU Emacs.
;;
;; This program 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 2
;; of the License, or (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
;;
;;; Commentary:
;;
;; Add the following to your .emacs file:
;; (require 'auto-dictionary)
;; (add-hook 'flyspell-mode-hook (lambda () (auto-dictionary-mode 1)))
;;
;; Then just type.  When you stop for a few moments `auto-dictionary-mode' will
;; start evaluating the content.
;;
;; You can also force a check using `adict-guess-dictionary', whether or not
;; `auto-dictionary-mode' is enabled.
;;
;; If you're unhappy with the results, call `adict-change-dictionary' to
;; change it and stop automatic checks.
;;
;; You can use `adict-change-dictionary-hook' to hook into any of these changes,
;; or `adict-conditional-insert' to insert text (like signatures) that will
;; automatically conform to the language.
;;
;;; Change Log:
;;
;; 2013-06-26 (1.1)
;;    Support for nb, nn, dk, hi, el, and grc.  (thanks to Tore Ferner)
;;    `adict-dictionary-list' now has an easier to customize format.
;;    `adict-guess-dictionary' no longer changes the dictionary if aborted.
;;
;; 2013-03-26 (1.0.2)
;;    The initial guess is now triggered without any buffer changes.
;;
;; 2007-05-28 (1.0.1)
;;    Speed improvements.
;;    Defined functions before variables that use them.
;;    Improved Swedish word list.  (thanks to Joakim Verona)
;;    Support for Portuguese.  (thanks to Nelson Ferreira)
;;
;; 2007-05-28 (1.0)
;;    Added support for `flyspell-prog-mode'.
;;    Added `adict-' prefix to functions without.
;;    Support for Hungarian and Romanian.  (thanks to Maria Muschinski).
;;    Support for Slovenian.  (thanks to Gregor Gorjanc)
;;    Bug fixes for Emacs 21.  (thanks to Gregor Gorjanc)
;;    Added `adict-conditional-' functions.
;;
;;; Code:

(require 'flyspell)
(require 'ispell)
(eval-when-compile (require 'cl))

(defgroup auto-dictionary nil
  "Automatic dictionary switcher for Flyspell."
  :group 'wp)

(defcustom adict-idle-time 2
  "*Seconds of idle time before `adict-guess-dictionary-maybe' is run.
If this is nil, it is not never automatically."
  :group 'auto-dictionary
  :type 'number)

(defcustom adict-change-threshold .02
  "*Amount of buffer change required before the dictionary is guessed again.
This is the quotient of changes to `buffer-modified-tick' and the buffer size.
Higher values mean fewer checks."
  :group 'auto-dictionary
  :type 'number)

(defface adict-conditional-text-face
  '((((class color) (background dark))
     (:background "MediumBlue"))
    (((class color) (background light))
     (:background "turquoise")))
  "*Face used for text inserted by `adict-conditional-insert'."
  :group 'auto-dictionary)

(defcustom adict-change-dictionary-hook
  '((lambda () (with-local-quit (when flyspell-mode (flyspell-buffer)))))
  "*List of functions to be called when the buffer language is changed.
This is called when `auto-dictionary-mode' changes its mind or
`adict-change-dictionary' is called."
  :group 'auto-dictionary
  :type 'hook)

(defun adict-guess-dictionary-name (names &optional list)
  "Return the element in NAMES found in `ispell-valid-dictionary-list'."
  (unless list
    (setq list (ispell-valid-dictionary-list)))
  (or (car (member (car names) list))
      (when (cdr names)
        (adict-guess-dictionary-name (cdr names) list))))

(defun adict--guess-dictionary-cons (names)
  (cons (car names) (adict-guess-dictionary-name names)))

(defconst adict-language-list
  '(nil "en" "de" "fr" "es" "sv" "sl" "hu" "ro" "pt" "nb" "dk" "grc" "el" "hi"
        "nn")
  "The languages, in order, which `adict-hash' contains.")

(defun adict--dictionary-alist-type ()
  `(repeat (cons (choice . ,(mapcar (lambda (lang) `(const ,lang))
                                    (cdr adict-language-list)))
                 (choice (const :tag "Off" nil)
                         (string :tag "Dictionary name")))))

(defcustom adict-dictionary-list
  ;; we can't be sure of the actual dictionary names
  (mapcar 'adict--guess-dictionary-cons
          '(("en" "english")
            ("de" "deutsch" "german")
            ("fr" "francais" "french")
            ("es" "español" "spanish")
            ("sv" "svenska" "swedish")
            ("sl" "slovenian" "slovene")
            ("hu" "magyar" "hungarian")
            ("ro" "românâ" "româneşte" "romanian")
            ("pt" "português" "portuguese")
            ("nb" "bokmål" "norwegian bokmål")
            ("dk" "dansk" "danish")
            ("grc" "ἑλληνικά" "classical greek")
            ("el" "νέα ελληνικά" "modern greek")
            ("hi" "हिन्दी" "hindi")
            ("nn" "nynorsk" "norwegian nynorsk")))
  "The dictionaries `auto-dictionary-mode' uses.
Change the second part of each pair to specify a specific dictionary for
that language. You can use this to specify a different region for your
language (e.g. \"en_US\" or \"american\").  Setting it to nil prevents
that language from being used.

Each pair's car corresponds to a value in `adict-language-list'"
  :group 'auto-dictionary
  :type (adict--dictionary-alist-type))

(defvar adict-lighter nil)
(make-variable-buffer-local 'adict-lighter)

(defvar adict-timer nil)
(make-variable-buffer-local 'adict-timer)

(defvar adict-last-check :never)
(make-variable-buffer-local 'adict-last-check)

(defvar adict-stop-updating-on-dictionary-change t
  "*If this is true, calling `ispell-change-dictionary' will disable checks.")

(defalias 'switch-language-hook 'adict-change-dictionary-hook)

;;;###autoload
(define-minor-mode auto-dictionary-mode
  "A minor mode that automatically sets `ispell-dictionary`."
  nil adict-lighter nil
  (if auto-dictionary-mode
      (progn
        (adict-update-lighter)
        (unless adict-timer
          (setq adict-timer
                (when adict-idle-time
                  (run-with-idle-timer adict-idle-time t
                                       'adict-guess-dictionary-maybe
                                       (current-buffer)))))
        (add-hook 'kill-buffer-hook 'adict--cancel-timer nil t))
    (adict--cancel-timer)
    (remove-hook 'kill-buffer-hook 'adict--cancel-timer t)
    (kill-local-variable 'adict-lighter)
    (kill-local-variable 'adict-last-check)))

(defalias 'adict-mode 'auto-dictionary-mode)

;;;###autoload
(defun adict-guess-dictionary (&optional idle-only)
  "Automatically change ispell dictionary based on buffer language.
Calls `ispell-change-dictionary' and runs `adict-change-dictionary-hook'.  If
BUFFER is nil, the current buffer is used.  If IDLE-ONLY is set, abort
when an input event occurs."
  (interactive)
  (let ((lang (adict--evaluate-buffer-find-dictionary idle-only)))
    (unless (and idle-only (input-pending-p))
      (when lang
        (setq adict-last-check (buffer-modified-tick))
        (unless (or (equal ispell-local-dictionary lang)
                    (and (null ispell-local-dictionary)
                         (equal ispell-dictionary lang)))
          (let (adict-stop-updating-on-dictionary-change)
            (adict-change-dictionary lang)))
        lang))))

(defun adict--cancel-timer ()
  (when adict-timer
    (cancel-timer adict-timer))
  (kill-local-variable 'adict-timer))

(defsubst adict-valid-dictionary-p (lang)
  "Test if LANG is a legal dictionary."
  (member lang
          (if (fboundp 'ispell-valid-dictionary-list)
              (ispell-valid-dictionary-list)
            (mapcar 'car ispell-dictionary-alist))))

;;;###autoload
(defun adict-change-dictionary (&optional lang)
  "Set buffer language to LANG and stop detecting it automatically."
  (interactive)
  (if lang
      (if (adict-valid-dictionary-p lang)
          (progn (message "Buffer dictionary was %s"
                          (or ispell-local-dictionary ispell-dictionary))
                 (ispell-change-dictionary lang)
                 (message "Buffer dictionary is now %s" lang))
        (error "Dictionary \"%s\" not found" lang))
    (call-interactively 'ispell-change-dictionary))
  (adict-update-lighter)
  (run-hook-with-args 'adict-change-dictionary-hook)
  (when (and adict-timer adict-stop-updating-on-dictionary-change)
    (adict--cancel-timer)))

(defun adict-guess-dictionary-maybe (timer-buffer)
  "Call `adict-guess-dictionary' or not based on `adict-change-threshold'."
  (when (and (eq (current-buffer) timer-buffer)
             (> (buffer-modified-tick) (adict--next-guess-tick)))
    (ignore-errors (adict-guess-dictionary t))))

(defun adict--next-guess-tick ()
  "The `buffer-modified-tick' until which the buffer language is not guessed."
  (if (eq adict-last-check :never)
      0
    (+ (* adict-change-threshold (buffer-size)) adict-last-check)))

(defun adict-update-lighter ()
  (setq adict-lighter
        (format " %s" (adict--shorten-dict (or ispell-local-dictionary
                                               ispell-dictionary "??")))))

(defun adict--shorten-dict (dict)
  (if (> (length dict) 3) (substring dict 0 2) dict))

(defun adict-foreach-word (beg end maxlength function &optional idle-only)
  "Execute FUNCTION for every word between BEG and END of length <= MAXLENGTH.
If IDLE-ONLY is set, abort when an input event occurs."
  (save-excursion
    (goto-char beg)
    (while (and (< (point) end)
                (not (and idle-only (input-pending-p))))
      (skip-syntax-forward "^w")
      (if (or (and flyspell-generic-check-word-p
                   (null (funcall flyspell-generic-check-word-p)))
              (memq nil
                    (mapcar (lambda (ov)
                              (not (overlay-get ov 'adict-conditional-list)))
                            (overlays-at (point)))))
          (skip-syntax-forward "w")
        (setq beg (point))
        (when (<= (skip-syntax-forward "w") maxlength)
          (funcall function (buffer-substring-no-properties beg (point))))))))

(defmacro adict-add-word (hash lang &rest words)
  `(dolist (word '(,@words))
     (when (gethash word hash)
       (message "Warning: adict-mode defined %s twice" word))
     (puthash word ,lang ,hash)))

(defvar adict-hash
  ;; Good words are frequent and unique to a language...
  ;; http://www.verbix.com/languages/
  (let ((hash (make-hash-table :test 'equal)))
    ;; all words should be downcase
    (adict-add-word hash 1 "and" "are" "at" "been" "but" "dear" "get" "have"
                    "he" "hello" "it" "me" "my" "not" "on" "of" "off" "put"
                    "regarding" "set" "she" "some" "that" "than" "the" "there"
                    "us" "was" "we" "while" "with" "yes" "you" "your" "yours")
    ;; Don't use these words, because they are also very common in
    ;; Scandinavia: "for" "to" "by"
    (adict-add-word hash 2 "eins" "zwei" "drei" "vier" "fünf" "sechs" "sieben"
                    "acht" "neun" "zehn" "aber" "als" "andere" "anderem"
                    "anderen" "anderes" "auf" "aus" "bei" "beide" "beidem"
                    "beiden" "beides" "beim" "bereits" "bevor" "bis" "bisher"
                    "bzw" "dabei" "dadurch" "dagegen" "daher" "damit" "danach"
                    "dann" "daran" "darauf" "daraus" "darin" "darunter" "das"
                    "davon" "dazu" "demselben" "denen" "denselben" "derart"
                    "deren" "derer" "derselben" "desselben" "dessen" "diese"
                    "diesem" "diesen" "dieser" "dieses" "dir" "doch" "dort"
                    "durch" "eben" "ebenfalls" "einem" "einen" "einer" "eines"
                    "einzeln" "einzelne" "entweder" "erst" "etwa" "etwas"
                    "falls" "freundlichen" "ganz" "gegen" "gemeinsam" "genau"
                    "haben" "hinter" "ich" "ihnen" "ihre" "ihrem" "ihren"
                    "ihrer" "ihres" "im" "immer" "indem" "infolge" "insgesamt"
                    "ist" "jede" "jedem" "jeden" "jeder" "jedes" "jedoch" "kann"
                    "kein" "keine" "keinem" "keinen" "keiner" "keines" "mehr"
                    "mehrere" "mehreren" "mehrerer" "mit" "mittels" "nach"
                    "nacheinander" "neben" "nicht" "noch" "nur" "oberhalb"
                    "oder" "ohne" "schreibe" "sehr" "selbst" "sich" "sie" "sind"
                    "sobald" "sodass" "sofern" "sofort" "solange" "somit"
                    "sondern" "sowie" "sowohl" "statt" "teils" "teilweise" "um"
                    "und" "unter" "unterhalb" "vom" "usw" "von" "vor" "vorher"
                    "warum" "wegen" "weil" "weiter" "weiterhin" "weitgehend"
                    "welche" "welchem" "welchen" "welcher" "welches"
                    "wenigstens" "wenn" "werden" "wie" "wieder" "wird" "wo"
                    "wobei" "wodurch" "worauf" "worden" "worin" "wurde" "zu"
                    "zueinander" "zugleich" "zum" "zumindest" "zur" "zusammen"
                    "zwar" "zwecks" "zwischen" "bezüglich" "dafür" "für"
                    "gegenüber" "gemäß" "schließlich" "über" "während" "würde"
                    "zunächst" "zusätzlich")
    ;; Also common in non-German languages, don't use:
    ;; "dass" "ab" "ob" "er" "der" "dem" "hat" "mal" "ein" "eine" "anders"
    (adict-add-word hash 3 "allez" "allons" "alors" "aux" "avoir" "bonjour"
                    "ces" "cet" "cette" "combien" "comme" "dire" "disent"
                    "disons" "dites" "elle" "faire" "fais" "faisons" "fait"
                    "faites" "il" "ils" "je" "là" "mais" "ne" "oui" "où" "parce"
                    "pas" "plaît" "pour" "pourquoi" "quand" "qui" "revoir" "une"
                    "des" "vais" "voient" "voir" "vois" "voit" "vont" "vous"
                    "voyez" "voyons" "à" "ça" "être")
    ;; Don't use:
    ;;  "dit" "aller" "dans" "dis" "vas" "et" "au" "elles"
    (adict-add-word hash 4 "además" "ahora" "al" "algo" "algunos" "antes"
                    "aquí" "así" "aunque" "año" "años" "bueno" "cada" "casa"
                    "casi" "caso" "como" "con" "contra" "cosas" "creo" "cuando"
                    "cómo" "decimos" "decir" "decis" "desde" "después" "dicen"
                    "dices" "digo" "dijo" "donde" "dos" "día" "días" "ejemplo"
                    "ella" "ellos" "entonces" "entre" "era" "eres" "eso" "esta"
                    "estaba" "estado" "estas" "esto" "estos" "está" "están"
                    "forma" "fue" "gente" "gobierno" "había" "hace" "hacemos"
                    "hacen" "hacer" "haces" "hacia" "hacéis" "hago" "hay"
                    "hecho" "hombre" "hoy" "luego" "mayor" "mejor" "menos"
                    "mientras" "mismo" "momento" "mucho" "mujer" "mundo" "muy"
                    "más" "mí" "nada" "ni" "nos" "nosotros" "otra" "otras"
                    "otro" "otros" "parece" "parte" "país" "pero" "personas"
                    "poco" "poder" "política" "porque" "primera" "puede"
                    "pueden" "qué" "sea" "según" "siempre" "sino" "sois" "somos"
                    "son" "soy" "su" "sus" "sí" "sólo" "también" "tan" "tanto"
                    "tenemos" "tener" "tengo" "tenéis" "tenía" "tiempo" "tiene"
                    "tienen" "tienes" "toda" "todas" "todo" "todos" "trabajo"
                    "una" "uno" "unos" "usted" "vamos" "veces" "veo" "ver" "ves"
                    "vida" "y" "ya" "yo" "él")
    ;; Don't use:
    ;;  "general" "lo" "las" "ven" "ve" "veis" "tal"  "ser" "si" "los" "gran"
    ;;  "del"  "han" "hasta" "no" "time" "tres" "esa" "ese"
    (adict-add-word hash 5
                    ;; Swedish (sv)
                    ;; Many, many of the most frequent words are common
                    ;; in Swedish, Danish and Norwegian. Therefore: word list
                    ;; is made longer since many core words are exluded.
                    ;;
                    ;; Based on:
                    ;; http://sskkii.gu.se/jens/publications/bfiles/B62.pdf
                    ;; http://rl.se/tusen.html
                    ;; More or less listed with descending frequency, some
                    ;; random:
                    "och" "att" "är" "första" "andra"
                    "två" "fyra" "åtta" "nio" "tio" "tålv" "då" "också" "väl"
                    "jag" "inte" "vad" "hej" "bara" "något" "sej" "för" "finns"
                    "från" "ska" "klotter" "sig" "vara" "vill" "konst"
                    "mycket" "måste" "deras" "här" "sina"
                    "hur" "sedan" "någon" "mej" "utan" "när" "tycker" "säga"
                    "kanske" "göra" "gör" "alla" "just" "upp" "sådant"
                    "hon" "menar" "menade" "någonting" "säger" "sade" "väldigt"
                    "sätt" "honom" "ihop" "gick" "kunna" "nog" "fick" "många"
                    "över" "annat" "nä" "fläta" "koppla" "möta" "räkna" "träffa"
                    "väga" "väva" "mina" "alltså" "kunnat" "varit" "avstånd"
                    "rätt" "kuggades" "flagga" "undertryckt" "knuffade" "omkull"
                    "överrumplad" "iväg" "nåt" "tillräckligt" "kostar" "kostade"
                    "halva" "vägen" "glömt" "glömma" "exempel" "liknande"
                    "avskrekkande" "förekomma" "flera" "haft" "senare" "arbete"
                    "arbetet" "arbeten" "arbeta" "läsa" "typ" "motiverad"
                    "erfarenhet" "ungefär" "även" "kronor" "detta" "procent"
                    "svenska" "allt" "mellan" "stora" "enligt" "redan" "inom"
                    "ju" "samma" "själv" "tidigare" "miljoner" "dock" "olika"
                    "plats" "gäller" "därför" "dessutom" "eftersom" "trots"
                    "människor" "bättre" "ändå" "inför" "senaste" "samtidigt"
                    "ännu" "större" "nästa" "pengar" "stället" "tillbaka"
                    "själva" "tillsammans" "nästan" "längre" "förra" "svårt"
                    "bästa" "handlar" "länge" "frågan" "spelar" "fortfarande"
                    "bakom" "berättar" "början" "varför" "företag"
                    "fanns" "egna" "utanför" "långt" "framför" "båda" "behöver"
                    "miljarder" "största" "polisen" "världen" "direkt" "innebär"
                    "bör" "vidare" "håller" "lätt" "ytterligare" "kvinnor"
                    "kvinna" "särskilt" "började" "däremot" "känner" "beslut"
                    "egentligen" "länder" "börjar" "väder" "hjälp" "ordförande"
                    "tilbaka" "medarbetare" "viktiga")
    ;; Don't use for Swedish, because they are also *very* common in
    ;; Norwegian and/or Danish:
    ;;  "barn" "eller" "en" "som" "det" "av" "på" "tre" "fem" "sex" "sju"
    ;;  "om" "du" "har" "kan" "så" "få" "skulle" "kommer" "ett" "jag"
    ;;  "sverige" "nej" "vill" "till" "medan"
    (adict-add-word hash 6
                    ;; (based on http://bos.zrc-sazu.si/a_top2000_si.html)
                    "ali" "ampak" "bi" "biti" "bodo" "bolj" "brez" "čas" "če"
                    "celo" "čeprav" "čez" "dan" "danes" "deset" "dobro" "dolgo"
                    "dovolj" "drugače" "drugi" "dva" "enkrat" "gotovo" "gre"
                    "hitro" "hvala" "ima" "iz" "jasno" "jaz" "jih" "jim" "kaj"
                    "kajti" "kako" "kateri" "kdaj" "kdo" "ker" "kje" "kljub"
                    "kmalu" "ko" "koliko" "konec" "kot" "lahko" "lep" "malo"
                    "manj" "močno" "mogoče" "mu" "nad" "naj" "največ" "nam"
                    "namreč" "naprej" "nas" "naš" "nazaj" "nekaj" "nič" "nihče"
                    "nikoli" "niso" "niti" "nov" "očitno" "od" "okoli" "oziroma"
                    "pa" "pač" "po" "počasi" "pod" "poleg" "potem" "pozdrav"
                    "prav" "pred" "predvsem" "prej" "pri" "prosim" "proti"
                    "prvi" "ravno" "res" "saj" "sam" "še" "sedaj" "šele" "sem"
                    "seveda" "sicer" "skoraj" "skupaj" "smo" "spet" "sploh"
                    "ste" "število" "štiri" "stran" "svoj" "tako" "takoj"
                    "takrat" "tega" "teh" "tem" "težko" "tisoč" "tisto" "tokrat"
                    "toliko" "torej" "treba" "tudi" "tukaj" "več" "vedno"
                    "veliko" "velja" "vendar" "vsaj" "vsak" "vse" "vsi" "za"
                    "zadnji" "zakaj" "zakon" "zaradi" "zato" "zdaj" "že" "zelo"
                    "zgolj")
    ;; Don't use: "bil" "bo" "bom" "do" "ena" "ga" "glede" "kar" "let"
    ;;  "pet" "pol" "primer" "so" "sta" "sto" "ta" "tam"
    (adict-add-word hash 7 "az" "èn" "ti" "ök" "csak" "hogy" "nem" "igen" "és"
                    "így" "úgy" "s" "jól" "van" "nincs" "nekem" "neki" "amely"
                    "ki" "ezek" "azok" "ezen" "azon" "közé" "még" "azaz" "aki"
                    "egyéb" "vagy" "ennek" "annak" "talán")
    ;; "ö" "fel" "meg"  "volt"
    (adict-add-word hash 8 "ea" "noi" "voi" "să" "în" "peste" "şi" "despre"
                    "cele" "dintre" "avem" "vă" "oricare" "acest" "fi" "pe"
                    "care" "dacă" "cum" "numai" "fost" "când" "aţi" "pentru"
                    "acum" "acesta" "ca" "sub" "ani")
    ;; Don't use:
    ;;  "nu" "ei" "se" "mai" "te" "sunt" "am"  "la" "unless" "din"
    (adict-add-word hash 9
                    ;; http://home.unilang.org/main/wiki2/index.php
                    ;; /Portuguese_wordlist
                    "e" "são" "em" "têm" "mas" "querido" "querida" "caro" "cara"
                    "para" "obter" "pegar" "oi" "aquilo" "coisa" "meu" "não"
                    "pôr" "colocar" "acerca" "algum" "alguns" "alguma" "algumas"
                    "lá" "além" "nós" "eles" "ela" "elas" "teu" "enquanto" "com"
                    "contigo" "você" "vosso" "sim" "olá" "tchau" "adeus"
                    "bem-vindo" "obrigado" "obrigada" "já" "também" "sempre"
                    "bonito" "certamente" "claramente" "cedo" "longe" "tarde"
                    "provavelmente" "alto" "talvez" "muito" "perto" "agora"
                    "apenas" "possivelmente" "raramente" "ainda" "acolá" "hoje"
                    "amanhã" "improvável" "bem" "errado" "ontem")
    ;; Don't use because they're ambiguous:
    ;; a i des du bien en es les que se tu un va el le te mi be is az da este
    ;; or ce le o de den ha med na sido para soble eu ele nunca ter lugar
    ;; "meter"
    (adict-add-word hash 10
                    ;; Norwegian bokmål (nb)
                    ;; Look at comment above on Swedish.
                    ;;
                    ;; Based on:
                    ;; http://helmer.aksis.uib.no/nta/ord10000.txt
                    ;; (Some words are just opposed to words in the Swedish or
                    ;; Danish lists.)
                    "nei" "å" "femti" "seksti" "sytti" "åtti" "nitti" "vil"
                    "andre" "annet" "fra" "ble" "hadde" "henne" "hennes"
                    "etter" "bare" "nå" "dette" "være" "opp" "må" "selv" "denne"
                    "før" "vært" "slik" "gikk" "gang" "hele" "sammen"
                    "godt" "måtte" "hvordan" "sier" "fikk" "noen" "kanskje"
                    "meg" "avstand" "skip" "prest" "flagg" "nevnt" "halve"
                    "vegen" "nesten" "måte" "avskrekkende" "forekomme"
                    "utmerket" "arbeid" "arbeide" "arbeidet" "kjøre" "kjørte"
                    "kjører" "lese" "leser" "leste" "omtrent" "gjøre" "ifølge"
                    "gjennom" "disse" "fortsatt" "allerede" "viser" "gamle"
                    "ønsker" "gjort" "likevel" "aldri" "heller" "beste" "svært"
                    "dermed" "bør" "dagbladet" "aftenposten" "løpet" "samtidig"
                    "tillegg" "mennesker" "regjeringen" "selskapet"
                    "funnet" "tilbake" "møte" "vanskelig" "gråte" "kjedelig"
                    "uke" "viktig" "viktige" "siste" "derimot" "betyr" "utsagn"
                    "feil" "medarbeider" "spurt" "spørsmål" "erkjenner"
                    "bakgrunn" "slike" "drept" "skjedde" "akkurat"
                    "optelling" "unnskylte" "flertydighet" "kjennsgjerning"
                    "etterpå" "redd" "språk" "språklig" "språklige"
                    "undersøke" "tekstene" "fått" "unnskyld"
                    "opptelling" "opptellingen" "sist" "innkjøp"
                    "kjøp" "avgrense" "avgrensede" "alminnelig" "alminnelige"
                    "henger" "likegyldig" "vesentlige" "vesentlig")
    ;; Don't use:
    ;;  "ham" "og" "i" "det" "på" "at" "ikke" "jeg"  "også" "bare"
    ;;  "hvor"  "siden" "hun"
    (adict-add-word hash 11
                    ;; Danish (dk)
                    ;; Look at comment above on Swedish.
                    ;;
                    ;; Based on:
                    ;; http://korpus.dsl.dk/e-resurser/frekvens150.php?lang=dk
                    ;; Can only use 1 word among the first 37! And so it goes...
                    ;;
                    ;; http://sskkii.gu.se/jens/publications/bfiles/B62.pdf
                    "noget" "af" "hvad" "havde" "nogen" "ud" "lige" "måske"
                    "mig" "lidt" "op" "ind" "gik" "mod" "sagde" "bliver" "os"
                    "gør" "siger" "andet" "cykle" "fælde" "finde" "fløjte"
                    "hænge" "kæde" "knække" "køre" "læse" "opholde" "svejse"
                    "tage" "tager" "træffe" "præst" "lit" "afstand" "skib" "jer"
                    "flag" "generet" "nævnt" "hellere" "børn" "børnene" "uden"
                    "vejen" "næsten" "derinde" "oven" "købet" "måde"
                    "afskrækkende" "udmærket" "ik" "arbejde" "dænske" "udgave"
                    "nogle" "mellem" "sit" "fået" "undskyld" "tres" "firs"
                    "fems" "halvtres" "halvfjers" "halvfems" "undskyldte"
                    "bagefter" "græde" "forkert" "træls" "bange" "uge" "sprog"
                    "vigtig" "vigtige" "undersøge" "teksterne" "tilbage"
                    "optælling" "optællingen" "hendes" "sidste" "sidst" "indkøb"
                    "køb" "niece" "afgrænse" "afgrænsede" "almindelig"
                    "almindelige" "hænger" "kit" "verber" "udsagn" "ligegyldigt"
                    "derimod" "almindeligt" "optræder" "fejl" "beder"
                    "medarbejder" "spurgt" "spørgsmål" "optræden" "erkender"
                    "begået" "modtage" "flertydighed" "streger" "kendsgerning"
                    "læser" "læsere" "væsentlige" "væsentlig" "ægte"
                    "erkendelse" "udkom" "månedligt" "sproglige" "iagttagelse"
                    "iagttagelser" "udgivet" "oprigtigt" "sproglig" "efter")
    ;; Don't use: ;;  "ham" "og" "i" "det" "på" "at" "ikke" "jeg"  "også" "bare"
    ;;  "nej" "ham" "og" "i" "det" "på"  "blev" "sig" "hende"
    ;;  "betyder" "aldrig"
    (adict-add-word hash 12
                    ;; Classical Greek (grc)    (Precomposed letters)
                    ;;
                    ;; Based on (only showing root forms):
                    ;; http://www.perseus.tufts.edu/hopper/vocablist
                    ;;
                    ;; Some Greek speaking person should remove words from here
                    ;; that overlap with modern Greek.  (Got lazy, didn't
                    ;; complete the selected verbs... Feel free...)
                    ;;
                    ;; Need a grc dictionary? See:
                    ;; ftp://ftp.gnu.org/gnu/aspell/dict/0index.html
                    "ὁ" "ἡ" "τὸ" "τὸν" "τὴν" "τοῦ" "τῆς" "τῷ" "τῇ" "οἱ" "αἱ"
                    "τὰ" "τοὺς" "τὰς"  "τά" "τῶν" "τοῖς" "ταῖς" "ὦ" "ἕν" "ἕνα"
                    "μιᾷ" "ἑνί" "ἐγώ" "ἐγώγε" "ἔγωγε" "σύ" "ἕ" "μέν" "οὖν" "τε"
                    "καί" "καὶ" "τίς" "τί" "τίνες" "τίνα" "τίνος" "τίνων" "τίνι"
                    "τίσι" "τίσιν" "τίνας" "ἐν" "ἐπί" "ἐπὶ" "εἰς" "πρός" "πρὸς"
                    "ἐκ" "ἐξ" "μετὰ" "κατὰ" "κατά" "δέ" "δὲ" "ὡς" "δεῖ" "ἄν"
                    "ἀλλά" "ἀλλὰ" "ἄλλα" "ἀνά" "ἀνὰ" "δέω" "ὅστις" "διὰ" "διά"
                    "σοῦ" "ἐμοῦ" "εἰμί" "εἶ" "ἐστί" "ἐστὶ" "ἐστίν" "ἐστὶν"
                    "ἐσμέν" "ἐσμεν" "ἐστέ" "ἐστε" "ἐστὲ" "εἰσί" "εἰσίν" "ἴσθι"
                    "ἔσθε" "εἶναι" "ἔσομαι" "ἔσῃ" "ἔσει" "ἔσται" "ἐσόμεθα"
                    "ἔσεσθε" "ἔσονται" "ἦ" "ἦν" "ἦσθα" "ἦμεν" "ἦτε" "ἦσαν" "ὤν"
                    "οὖσα" "ὄν" "ὄντα" "οὖσαν" "ὄντος" "οὔσης" "ὄντι" "οὔσῃ"
                    "ὄντων" "οὖσι" "οὖσιν" "ὄντας" "οὖσαι" "οὔσας" "οὐσῶν"
                    "οὔσαις" "εἶμι" "εἰσι" "εἰσιν" "ἴμεν" "ἴτε" "ἴασι" "ἴασιν"
                    "ἴθι" "ἰέναι" "ἰών" "ἰοῦσα" "ἰόν" "ἰόντος" "ὅς" "ἥ" "ὅ" "ὅν"
                    "ἥν" "οὗ" "ἧς" "ᾧ" "ᾗ" "οἵ" "αἵ" "ἅ" "οὕς" "ἅς" "ὧν" "οἷς"
                    "αἷς")
    ;; Don't use:
    ;;  "τινες" "τινα" "τινος" "τινων" "τινι" "τισι" "τισιν" "τινας"
    ;;  "μετά"  "τούς" "τις" "τι" "τό" "τόν" "τήν" "τάς"
    (adict-add-word hash 13
                    ;; Modern Greek (el)
                    "έλληνας" "ελληνίδα" "ελληνικά" "ελληνικής" "ελλήνων"
                    "έλληνες" "καλημέρα" "εκείνος" "καλησπέρα" "αυτή" "κείνο"
                    "εκείνο" "αυτό" "αυτής" "αυτά" "ετούτο" "εκείνες" "εκείνη"
                    "καληνύχτα" "και" "ή" "αντίο" "γεια" "σας" "παρακαλώ" "έχει"
                    "έχεις" "έχοντας" "έχουν" "εδώ" "όλη" "έκτη" "ναι" "όχι"
                    "εις" "υγείαν" "μας" "ίσως" "κι" "νερό" "κρασί" "οι" "τα"
                    "σε" "την" "στον" "για" "μη" "στους" "ό" "τη" "της" "στο"
                    "στη" "στις" "των" "ως" "το" "πιο" "είναι" "ένα" "ότι"
                    "ίσοι" "στην" "να" "τους" "μια" "έτσι" "ώστε")
    ;; Don't use:
    ;;  "σε" "νέας" "μου" "σου" "ο" "η" "κυρία" "κύριε" "μέσα" "που"
    ;;  "χυμός" "με" "του"
    (adict-add-word hash 14
                    ;; Hindi (hi)
                    ;; Based on (not authoritative, but looks reasonable):
                    ;; http://kirkkittell.com/language/hindi/common
                    "में" "है" "हैं" "नहीं" "लिए" "गया" "विशेष" "बड़ी" "अथवा"
                    "गए" "गई" "तथा" "अपने" "कुछ" "साथ" "होता" "था" "दिया" "हुए"
                    "कोई" "रूप" "से" "सभी" "मैं" "रहा" "हुआ" "बात" "कहा" "समय"
                    "क्या" "अपनी" "होती" "प्रकार" "बहुत" "तरह" "बाद" "फिर" "रहे"
                    "द्वारा" "अधिक" "रही" "होने" "एवं" "हुई" "थे" "उनके" "थी"
                    "वाले" "चाहिए" "चाहिये" "दिन" "लेकिन" "काम" "हूँ" "होते"
                    "इसके" "उन्हें" "गये" "नाम" "कभी" "आदि" "लोग" "बार" "यहाँ"
                    "दोनों" "उन्होंने" "कार्य" "पास" "वहाँ" "भारत" "लिया"
                    "प्राप्त" "उनकी" "लोगों" "गयी" "लगा" "अन्य" "होगा" "इसी"
                    "देश" "यदि" "वर्ष" "ऐसा" "विकास" "अपना" "ऐसे" "दूसरे" "हाथ"
                    "भाषा" "मेरे" "मैंने" "तुम" "बीच" "वाली" "बड़े" "प्रति"
                    "व्यक्ति" "उनका" "लिये" "इसलिए" "तीन" "इसका" "ऐसी")
    (adict-add-word hash 15 ;; Norwegian nynorsk (nn)
                    ;; Look at comment above on Swedish.
                    ;;
                    ;; Based on (please change if you find a better list):
                    ;; http://www.raudebergskule.no/peiling/OveOrdNyn/Lese100ord
                    ;; /Oversikt.htm
                    ;; https://no.wiktionary.org/wiki/Wiktionary:Frekvenslister
                    ;; /Norsk
                    "sidan" "sjølv" "kva" "berre" "kvar" "kjem" "dykkar" "deira"
                    "fekk" "noko" "desse" "gong" "vere" "ikkje" "nokon" "eit"
                    "mykje" "frå" "bryggje" "dagar" "korleis" "kven" "inkje"
                    "nokre" "leike" "kaffi" "stova" "meir" "sjå" "såg" "dei"
                    "helsar" "kvifor" "garden" "dårleg" "bere" "gjere" "høyre"
                    "blei"  "saum" "låg" "ho" "tek" "spurde" "hundar" "herleg"
                    "hausten" "heiter" "følgje" "gutar" "såleis" "attmed"
                    "gøyme" "ringjer" "trufast" "kyrkja" "skunde" "hugse"
                    "vaknar" "hugsa" "auge" "vore" "seinare" "finst" "medan"
                    "nytta" "kjend" "heile" "aust" "innbyggjarar" "fødd" "dømes"
                    "døydde" "særleg" "songen" "høgaste" "sokn" "kjende" "vatn"
                    "vanleg" "byrja" "inneheld" "artar" "einaste" "øyane"
                    "høyrer" "vanlegvis" "leiar" "nordlege" "kvarandre"
                    "byrjinga" "søraust" "oftast" "difor" "auka" "såkalla"
                    "eigne" "strekkjer" "vestlege" "talet" "hovudstaden"
                    "nyttar" "innbyggjarane" "skil" "austsida" "vitja"
                    "noverande" "mogleg" "umogleg" "tilgjengelig" "brukast"
                    "heilage" "kjelder" "austlege" "vanskeleg" "òg" "noreg"
                    "gjekk" "budde" "utgjer" "vatnet" "tidlegare" "namn" "kvart"
                    "heilt" "framleis" "hovudsakleg" "hennar" "særs" "munnar"
                    "attende" "gut" "gutane" "månadene" "skilnadene" "skilnader"
                    "skilnaden" "føtene" "søner" "sønene" "brør" "brørne"
                    "menner" "venen" "vener" "venene" "føremon" "meining"
                    "meininga" "meiningar" "hending" "hendinga" "øyra" "øyro"
                    "døme" "vori" "skrivi" "lesi"
                    ;; Don't use: ;; "ein" "sidan" "utan" "elles"
                    )
    ;; adding another language? email me to make it available to everyone!
    hash))

(defun adict-evaluate-word (word)
  "Determine language of WORD using ``adict-hash''."
  (gethash (downcase word) adict-hash 0))

(defun adict-evaluate-buffer (&optional idle-only)
  "Evaluate all words in the current buffer to find out the text's language.
If IDLE-ONLY is set, abort when an input event occurs."
  (let ((counts (make-vector (length adict-language-list) 0)))
    (adict-foreach-word
     (point-min) (point-max) 8
     (lambda (word)
       ;; increase language count of WORD by one
       (callf incf (elt counts (adict-evaluate-word word))))
     idle-only)
    counts))

(defun adict--evaluate-buffer-find-max-index (idle-only)
  (let* ((vector (adict-evaluate-buffer idle-only))
         (index (- (length vector) 1))
         (pos index)
         (max (elt vector pos)))
    (decf index)
    (while (> index 0)
      (let ((val (elt vector index)))
        (when (>= val max)
          (setq max val)
          (setq pos index))
        (decf index)))
    pos))

(defun adict--evaluate-buffer-find-dictionary (idle-only)
  (if (consp (car adict-dictionary-list))
      ;; current format
      (cdr (assoc (adict--evaluate-buffer-find-lang idle-only)
                  adict-dictionary-list))
    ;; old format (<= 1.0.2)
    (nth (adict--evaluate-buffer-find-max-index idle-only)
         adict-dictionary-list)))

(defun adict--evaluate-buffer-find-lang (idle-only)
  (nth (adict--evaluate-buffer-find-max-index idle-only)
       adict-language-list))

;;; Conditional Insertion ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defvar adict-conditional-overlay-list nil)
(make-variable-buffer-local 'adict-conditional-overlay-list)
(defun adict-conditional-insert (&rest language-text-pairs)

  "Insert text based on dictionary and update it on dictionary changes.
LANGUAGE-TEXT-PAIRS is a list of dictionaries and strings.  The correct
string for the currently active dictionary will be used.  Whenever
`auto-dictionary-mode' changes the dictionary the inserted text will be
changed again.

Use `t' as a dictionary in the last place to catch all remaining
dictionaries.

To highlight this volatile text, `adict-conditional-text-face' is used.


You can use this, for instance, to localize the \" writes\" text in Gnus:

  (defun my-message-insert-citation-line ()
    \"Insert a simple citation line in the correct language.\"
    (when message-reply-headers
      (insert (mail-header-from message-reply-headers) \" \")
      (adict-conditional-insert \"nb\" \"skrev\"
                                \"de\" \"schreibt\"
                                \"fr\" \"a écrit\"
                                t \"wrote\")
      (newline)
      (newline)))
  (setq message-citation-line-function 'my-message-insert-citation-line)"
  (let ((overlay (make-overlay 0 0)))
    (adict-conditional-insert-1 language-text-pairs overlay)
    (overlay-put overlay 'evaporate t)
    (overlay-put overlay 'modification-hooks
                 '(adict-conditional-modification))
    (overlay-put overlay 'adict-conditional-list language-text-pairs)
    (overlay-put overlay 'face 'adict-conditional-text-face)
    (add-hook 'adict-change-dictionary-hook
              'adict-conditional-update nil t)
    (push overlay adict-conditional-overlay-list)))

(defun adict-conditional-insert-1 (language-text-pairs overlay)
  (let ((dict (or ispell-local-dictionary ispell-dictionary))
        (beg (point)))
    (while language-text-pairs
      (when (or (eq (car language-text-pairs) t)
                (equal (car language-text-pairs) dict))
        (insert (cadr language-text-pairs))
        (setq language-text-pairs nil))
      (setq language-text-pairs (cddr language-text-pairs)))
    (move-overlay overlay beg (point))))

(defun adict-conditional-modification (overlay afterp beg end
                                               &optional pre-length)
  (when afterp
    (delete-overlay overlay)
    (unless (setq adict-conditional-overlay-list
                  (delq overlay adict-conditional-overlay-list))
      (kill-local-variable 'adict-conditional-overlay-list)
      (remove-hook 'adict-change-dictionary-hook 'adict-conditional-update t))))

(defun adict-conditional-update ()
  (save-excursion
    (let ((inhibit-modification-hooks t))
      (dolist (ov adict-conditional-overlay-list)
        (when (overlay-buffer ov)
          (goto-char (overlay-start ov))
          (delete-region (point) (overlay-end ov))
          (adict-conditional-insert-1 (overlay-get ov 'adict-conditional-list)
                                      ov))))))


;;; Functions for 3rd Party Use ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defun adict-guess-word-language (word)
  "Determine language of WORD using ``adict-hash''."
  (elt adict-language-list (adict-evaluate-word word)))

(defun adict-guess-buffer-language (&optional idle-only)
  "Guess the language of the current-buffer using the data in ``adict-hash''.
If IDLE-ONLY is set, abort when an input event occurs."
  (let ((lang (adict--evaluate-buffer-find-lang idle-only)))
    (unless (and idle-only (input-pending-p))
      lang)))

(provide 'auto-dictionary)

;;; auto-dictionary.el ends here