[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[nongnu] elpa/spell-fu e62cfc4f08 34/86: Add support for personal dictio
From: |
ELPA Syncer |
Subject: |
[nongnu] elpa/spell-fu e62cfc4f08 34/86: Add support for personal dictionary management |
Date: |
Thu, 7 Jul 2022 12:03:41 -0400 (EDT) |
branch: elpa/spell-fu
commit e62cfc4f08fc4743d6961fe3402adbf2260d7e70
Author: Campbell Barton <ideasman42@gmail.com>
Commit: Campbell Barton <ideasman42@gmail.com>
Add support for personal dictionary management
---
changelog.rst | 18 +++++
readme.rst | 6 ++
spell-fu.el | 210 +++++++++++++++++++++++++++++++++++++++++++++++++++++-----
3 files changed, 217 insertions(+), 17 deletions(-)
diff --git a/changelog.rst b/changelog.rst
new file mode 100644
index 0000000000..2e61a47fea
--- /dev/null
+++ b/changelog.rst
@@ -0,0 +1,18 @@
+
+##########
+Change Log
+##########
+
+- In development
+
+ - <none>
+
+- Version 0.2 (2020-04-26)
+
+ - Add support personal dictionary manipulation: ``spell-fu-word-add``,
``spell-fu-word-remove``.
+ - Add support for stepping over errors with: ``spell-fu-goto-next-error``,
``spell-fu-goto-previous-error``.
+ - Add support for checking the whole buffer with: ``spell-fu-buffer``.
+
+- Version 0.1 (2020-04-14)
+
+ Initial release.
diff --git a/readme.rst b/readme.rst
index cc429f8284..286f7022ce 100644
--- a/readme.rst
+++ b/readme.rst
@@ -160,6 +160,12 @@ there are some commands provided which may come in handy.
``spell-fu-buffer``
Checks spelling for the entire buffer, reporting the number of misspelled
words found.
+``spell-fu-word-add``
+ Add the word under the cursor to the personal dictionary.
+
+``spell-fu-word-remove``
+ Remove the word under the cursor from the personal dictionary.
+
Other Packages
==============
diff --git a/spell-fu.el b/spell-fu.el
index e6b51d76d4..39ffc4729e 100644
--- a/spell-fu.el
+++ b/spell-fu.el
@@ -6,7 +6,7 @@
;; URL: https://gitlab.com/ideasman42/emacs-spell-fu-mode
;; Keywords: convenience
-;; Version: 0.1
+;; Version: 0.2
;; Package-Requires: ((emacs "26.2"))
;; This program is free software; you can redistribute it and/or modify
@@ -399,26 +399,28 @@ On failure of any kind, return nil, the caller will need
to regenerate the cache
;;
;; Top level function, called when enabling the mode.
-(defun spell-fu--init-dictionary (dict)
+(defun spell-fu--ensure-dict (dict)
"Setup the dictionary, initializing new files as necessary with dictionary
DICT."
- ;; Ensure our path exists.
- (unless (file-directory-p spell-fu-directory)
- (make-directory spell-fu-directory))
+ ;; First use the dictionary if it's in memory.
+ ;; Once Emacs is running, this is used for all new buffers.
+ (setq spell-fu--cache-table (assoc-default dict spell-fu--cache-table-alist))
- (let
- ( ;; Get the paths of both files, ensure the cache file is newer,
- ;; otherwise regenerate it.
- (words-file (spell-fu--words-file dict))
- (cache-file (spell-fu--cache-file dict)))
+ ;; Not loaded yet, initialize it.
+ (unless spell-fu--cache-table
+
+ ;; Ensure our path exists.
+ (unless (file-directory-p spell-fu-directory)
+ (make-directory spell-fu-directory))
- (spell-fu--word-list-ensure words-file dict)
+ (let
+ ( ;; Get the paths of both files, ensure the cache file is newer,
+ ;; otherwise regenerate it.
+ (words-file (spell-fu--words-file dict))
+ (cache-file (spell-fu--cache-file dict)))
- ;; Use previously loaded dictionary from language 'dict' where possible.
- (setq spell-fu--cache-table (assoc-default dict
spell-fu--cache-table-alist))
+ (spell-fu--word-list-ensure words-file dict)
- ;; Not loaded yet, initialize it.
- (unless spell-fu--cache-table
;; Load cache or create it, creating it returns the cache
;; to avoid some slow-down on first load.
(setq spell-fu--cache-table
@@ -430,7 +432,7 @@ On failure of any kind, return nil, the caller will need to
regenerate the cache
(spell-fu--cache-from-word-list words-file cache-file)))
;; Add to to `spell-fu--cache-table-alist' for reuse on next load.
- (push '(dict . spell-fu--cache-table) spell-fu--cache-table-alist))))
+ (push (cons dict spell-fu--cache-table) spell-fu--cache-table-alist))))
;; ---------------------------------------------------------------------------
@@ -759,6 +761,180 @@ when checking the entire buffer for example."
(interactive)
(spell-fu--goto-next-or-previous-error -1))
+
+;; ---------------------------------------------------------------------------
+;; Personal Dictionary Management
+;;
+
+(defun spell-fu--buffers-refresh-with-cache-table (cache-table)
+ "Reset spell-checked overlays for buffers using the dictionary from
CACHE-TABLE."
+ (dolist (buf (buffer-list))
+ (with-current-buffer buf
+ (when (bound-and-true-p spell-fu-mode)
+ (when (eq cache-table (bound-and-true-p spell-fu--cache-table))
+ ;; For now simply clear syntax highlighting.
+ (unless (<= spell-fu-idle-delay 0.0)
+ (spell-fu--idle-remove-overlays))
+ (spell-fu--remove-overlays)
+ (font-lock-flush))))))
+
+(defun spell-fu--word-add-or-remove (word words-file action)
+ "Apply ACTION to WORD from the personal dictionary WORDS-FILE.
+
+Return t when the action succeeded."
+ (catch 'result
+ (spell-fu--with-message-prefix "Spell-fu: "
+ (unless word
+ (message "word not found!")
+ (throw 'result nil))
+ (unless words-file
+ (message "personal dictionary not defined!")
+ (throw 'result nil))
+
+ (let ((this-cache-table spell-fu--cache-table))
+ (with-temp-buffer
+ (insert-file-contents-literally words-file)
+
+ ;; Ensure newline at EOF,
+ ;; not essential but complicates sorted add if we don't do this.
+ ;; also ensures we can step past the header which _could_ be a
single line
+ ;; without anything below it.
+ (goto-char (point-max))
+ (unless
+ (string-blank-p
+ (buffer-substring-no-properties (line-beginning-position)
(line-end-position)))
+ (insert "\n"))
+ ;; Delete extra blank lines.
+ ;; So we can use line count as word count.
+ (while
+ (and
+ (eq 0 (forward-line -1))
+ (string-blank-p
+ (buffer-substring-no-properties (line-beginning-position)
(line-end-position))))
+ (delete-region
+ (line-beginning-position)
+ (progn
+ (forward-line -1)
+ (point))))
+
+ (goto-char (point-min))
+
+ ;; Case insensitive.
+ (let
+ (
+ (changed nil)
+ (header-match
+ (save-match-data
+ (when
+ ;; Match a line like: personal_ws-1.1 en 66
+ (looking-at
+ (concat
+ "personal_ws\\-[[:digit:]\\.]+"
+ "[[:blank:]]+"
+ "[A-Za-z_]+"
+ "[[:blank:]]+"
+ "\\([[:digit:]]+\\)"))
+ (forward-line 1)
+ (match-data))))
+ (word-point
+ (save-match-data
+ (let ((case-fold-search t))
+ (when
+ (re-search-forward (concat "^" (regexp-quote word)
"[[:blank:]]*$") nil t)
+ (match-beginning 0))))))
+
+ (cond
+ ((eq action 'add)
+ (when word-point
+ (message "\"%s\" already in the personal dictionary." word)
+ (throw 'result nil))
+
+
+ (let ((keep-searching t))
+ (while
+ (and
+ keep-searching
+ (string-lessp
+ (buffer-substring-no-properties
+ (line-beginning-position)
+ (line-end-position))
+ word))
+ (setq keep-searching (eq 0 (forward-line 1)))))
+
+ (insert word "\n")
+
+ (puthash (downcase word) t this-cache-table)
+
+ (message "\"%s\" successfully added!" word)
+ (setq changed t))
+
+ ((eq action 'remove)
+ (unless word-point
+ (message "\"%s\" not in the personal dictionary." word)
+ (throw 'result nil))
+
+ ;; Delete line.
+ (goto-char word-point)
+ (delete-region
+ (line-beginning-position)
+ (or (and (eq 0 (forward-line 1)) (point))
(line-end-position)))
+
+ (remhash (downcase word) this-cache-table)
+
+ (message "\"%s\" successfully removed!" word)
+ (setq changed t))
+
+ (t ;; Internal error, should never happen.
+ (error "Invalid action %S" action)))
+
+ (when changed
+ (when header-match
+ (save-match-data
+ (set-match-data header-match)
+ (replace-match
+ (number-to-string (1- (count-lines (point-min)
(point-max))))
+ t
+ nil
+ nil
+ 1)))
+
+ (write-region nil nil words-file nil 0)
+
+ (spell-fu--buffers-refresh-with-cache-table this-cache-table)
+ t)))))))
+
+(defun spell-fu--word-at-point ()
+ "Return the word at the current point or nil."
+ (let
+ (
+ (point-init (point))
+ (point-start (line-beginning-position))
+ (point-end (line-end-position)))
+ (save-excursion
+ (goto-char point-start)
+ (catch 'result
+ (with-syntax-table spell-fu-syntax-table
+ (save-match-data
+ (while (re-search-forward spell-fu-word-regexp point-end t)
+ (when (and (<= (match-beginning 0) point-init) (<= point-init
(match-end 0)))
+ (throw 'result (match-string-no-properties 0))))))
+ (throw 'result nil)))))
+
+(defun spell-fu-word-add ()
+ "Add the current word to the personal dictionary.
+
+Return t when the word has been added."
+ (interactive)
+ (spell-fu--word-add-or-remove (spell-fu--word-at-point)
ispell-personal-dictionary 'add))
+
+(defun spell-fu-word-remove ()
+ "Remove the current word from the personal dictionary.
+
+Return t when the word is removed."
+ (interactive)
+ (spell-fu--word-add-or-remove (spell-fu--word-at-point)
ispell-personal-dictionary 'remove))
+
+
;; ---------------------------------------------------------------------------
;; Define Minor Mode
;;
@@ -767,7 +943,7 @@ when checking the entire buffer for example."
(defun spell-fu-mode-enable ()
"Turn on option `spell-fu-mode' for the current buffer."
- (spell-fu--init-dictionary (spell-fu--dictionary))
+ (spell-fu--ensure-dict (spell-fu--dictionary))
;; We may want defaults for other modes,
;; although keep this general.
- [nongnu] elpa/spell-fu 1b765f8029 58/86: Cleanup: replace setq with let binding, (continued)
- [nongnu] elpa/spell-fu 1b765f8029 58/86: Cleanup: replace setq with let binding, ELPA Syncer, 2022/07/07
- [nongnu] elpa/spell-fu 1159eeec13 63/86: Fix including trailing single-quote in the word, ELPA Syncer, 2022/07/07
- [nongnu] elpa/spell-fu 32fcbd9e8e 68/86: Initial changes for multiple dictionaries, ELPA Syncer, 2022/07/07
- [nongnu] elpa/spell-fu 1f3e5b8f05 72/86: readme: Fix typos, ELPA Syncer, 2022/07/07
- [nongnu] elpa/spell-fu 2f2fd6de00 83/86: Change URL to codeberg, ELPA Syncer, 2022/07/07
- [nongnu] elpa/spell-fu 00b75e5741 25/86: Cleanup: docstring, ELPA Syncer, 2022/07/07
- [nongnu] elpa/spell-fu 1bc18879b6 27/86: Add license file, ELPA Syncer, 2022/07/07
- [nongnu] elpa/spell-fu d0700095ea 28/86: Add header to cache loading & error checking for cache content, ELPA Syncer, 2022/07/07
- [nongnu] elpa/spell-fu f6c849f860 30/86: Fix disabling spell-fu when used without a timer, ELPA Syncer, 2022/07/07
- [nongnu] elpa/spell-fu 502d523b46 31/86: Fix unintended modification of the standard syntax table, ELPA Syncer, 2022/07/07
- [nongnu] elpa/spell-fu e62cfc4f08 34/86: Add support for personal dictionary management,
ELPA Syncer <=
- [nongnu] elpa/spell-fu 86d46cf63e 37/86: fix: encode word to utf8, ELPA Syncer, 2022/07/07
- [nongnu] elpa/spell-fu 9180a77865 48/86: Fix #15: don't enable (when used globally) for application buffers, ELPA Syncer, 2022/07/07
- [nongnu] elpa/spell-fu 41a133d119 52/86: Fix #16: Fails to spellcheck when whitespace-mode splits a word, ELPA Syncer, 2022/07/07
- [nongnu] elpa/spell-fu 7c2542e109 73/86: Merge branch 'multiple-dictionaries' into 'master', ELPA Syncer, 2022/07/07
- [nongnu] elpa/spell-fu 50be652a6e 77/86: Fix overlay faces masking other faces (when checking faces-at-point), ELPA Syncer, 2022/07/07
- [nongnu] elpa/spell-fu cbe5cd84c3 86/86: Correct URL, ELPA Syncer, 2022/07/07
- [nongnu] elpa/spell-fu 41a7ebcbab 23/86: Cleanup: replace cl-letf with advice macro, ELPA Syncer, 2022/07/07
- [nongnu] elpa/spell-fu 251e63eacc 29/86: readme: update, clarify TODO, ELPA Syncer, 2022/07/07
- [nongnu] elpa/spell-fu ad139f6fac 40/86: Cleanup: quiet checkdoc warning, ELPA Syncer, 2022/07/07
- [nongnu] elpa/spell-fu 2caa9fc6f0 44/86: Update changelog, ELPA Syncer, 2022/07/07