Skip to content
Rob Weir edited this page Dec 20, 2023 · 7 revisions

Please add custom configuration snippets and commands here.

Save misspelling and correction as abbreviation

  (defun jinx--add-to-abbrev (overlay word)
    "Add abbreviation to `global-abbrev-table'.
The misspelled word is taken from OVERLAY.  WORD is the corrected word."
    (let ((abbrev (buffer-substring-no-properties
                    (overlay-start overlay)
                    (overlay-end overlay))))
      (message "Abbrev: %s -> %s" abbrev word)
      (define-abbrev global-abbrev-table abbrev word)))

  (advice-add 'jinx--correct-replace :before #'jinx--add-to-abbrev)

Use special LocalWords keyword with Jinx

Emacs’s builtin ispell (a spell-checker interface) has a “LocalWords” feature. This feature allows to mark some words as “known” in a buffer. This is done by adding the “LocalWords: ” keyword within the file and following it with space-separated words as in:

My text with no spelling mystac

LocalWords:  mystac

In this buffer, ispell will not report any error on the word “mystac” in the first line because the last one says this word is fine. Such “LocalWords” lines are added automatically by ispell-word when pressing A for “Accept for this session”. The following sections describe how to make Jinx read and write ispell’s LocalWords.

Make Jinx read from LocalWords

Jinx defines jinx-local-words and jinx--session-words that we have to fill with words from ispell’s LocalWords. Here is the code to do that:

(defun my/jinx-ispell-localwords ()
  "Return a string of ispell's local words.

Those are the words following `ispell-words-keyword' (usually
\"LocalWords\") in the current buffer."
  (require 'ispell)
  (save-excursion
    (goto-char (point-min))
    (cl-loop while (search-forward ispell-words-keyword nil t)
             collect (string-trim (buffer-substring-no-properties (point) (line-end-position))) into result
             finally return (mapconcat #'identity result " "))))

(defun my/jinx-add-ispell-localwords ()
  "Add ispell's local words to `jinx-local-words'."
  (let ((ispell-localwords (my/jinx-ispell-localwords)))
    (setq jinx-local-words (concat jinx-local-words ispell-localwords))
    (setq jinx--session-words (append jinx--session-words (split-string ispell-localwords)))))

(add-hook 'jinx-mode-hook #'my/jinx-add-ispell-localwords)

Make Jinx write LocalWords

You might want Jinx to insert unknown words after the LocalWords keyword instead of populating the jinx-local-words variable. This can be done with:

(defun my/jinx-save-as-ispell-localword (save key word)
  "Save WORD using ispell's `ispell-words-keyword'.
If SAVE is non-nil save, otherwise format candidate given action KEY."
  (if save
      (progn
        (require 'ispell)
        (ispell-add-per-file-word-list word)
        (add-to-list 'jinx--session-words word)
        (setq jinx-local-words
              (string-join
               (sort (delete-dups
                      (cons word (split-string jinx-local-words)))
                     #'string<)
               " "))))
      (list key word "File")))

(setf (alist-get ?* jinx--save-keys) #'my/jinx-save-as-ispell-localword)

Ignore case while spell-checking

If you’re like @mekeor and you stick to lower-case for informal documents, and you still would like to have spell-checking, but it should disregard the case of words, the following code provides a command that you can invoke in the buffer of such an informal document:

(defun my-jinx--lower-case-word-valid-p (start)
  "Return non-nil if word, that is assumed to be in lower case, at
START is valid, or would be valid if capitalized or upcased."
  (let ((word (buffer-substring-no-properties start (point))))
    (or (member word jinx--session-words)
      (cl-loop for dict in jinx--dicts thereis
        (or
          (jinx--mod-check dict (upcase word))
          (jinx--mod-check dict (capitalize word))
          (jinx--mod-check dict word))))))

(defun my-jinx-lower-case-only ()
  "Make `jinx-mode' assume that everything in the current buffer is
written in lower case and it ignore casing while spell-checking."
  (interactive)
  (jinx-mode 0)
  (set (make-local-variable 'jinx--predicates)
    (cl-substitute
      #'my-jinx--lower-case-word-valid-p
      #'jinx--word-valid-p
      jinx--predicates))
  (jinx-mode 1))

Source: https://github.com/minad/jinx/discussions/119