Swapping out Flyspell for Jinx

This commit is contained in:
Howard Abrams 2024-06-03 21:06:16 -07:00
parent 49a294eca1
commit 13c579c354
2 changed files with 51 additions and 76 deletions

View file

@ -3,7 +3,7 @@
#+date: 2020-09-18
#+tags: emacs org
#+startup: inlineimages
#+lastmod: [2024-05-22 Wed]
#+lastmod: [2024-06-02 Sun]
A literate programming file for configuring org-mode and those files.
@ -788,100 +788,68 @@ I've been working on my own [[http://www.howardism.org/Technical/Emacs/focused-w
** Spell Checking
Let's hook some spell-checking into org files, and actually all text files. Im making this particularly delicious.
*** abbrev
First, we turn on =abbrev-mode=. While this package comes with Emacs, check out [[https://masteringemacs.org/article/correcting-typos-misspellings-abbrev][Mickey Petersen's overview]] of using this package for auto-correcting typos.
#+begin_src emacs-lisp
(setq-default abbrev-mode t)
#+end_src
In general, /fill/ the list, by moving the point to the /end/ of some word, and type ~C-x a g~ (or, in /normal state/, type ~SPC x d~):
#+begin_src emacs-lisp
(ha-leader "x d" '("add abbrev" . kadd-global-abbrev))
#+end_src
The idea is that you can correct a typo /and remember/ it. Perhaps calling [[help:edit-abbrevs][edit-abbrevs]] to making any fixes to that list.
Next, I create a special /auto-correcting function/ that takes advantage of Evils [[help:evil-prev-flyspell-error][evil-prev-flyspell-error]] to jump back to the last spelling mistake (as I often notice the mistake after entering a few words), and call the interactive [[help:ispell-word][ispell-word]]. What makes this delicious is that I then call [[help:define-global-abbrev][define-global-abbrev]] to store both the mistake and the correction so that automatically typing that mistake again, is corrected.
*** jinx
Once upon a time, I used [[https://www.emacswiki.org/emacs/FlySpell][flyspell]] mode to highlight the misspelled words, and the venerable [[https://www.emacswiki.org/emacs/InteractiveSpell][ispell]] for correcting. To be able to correct spelling mistakes /from a distance/, without navigation, I wrote a function that took advantage of Evils [[help:evil-prev-flyspell-error][evil-prev-flyspell-error]] to jump back to the last spelling mistake.
#+begin_src emacs-lisp
(defun ha-fix-last-spelling (count)
"Jump to the last misspelled word, and correct it.
This adds the correction to the global abbrev table so that any
other mistakes are automatically corrected."
(interactive "p")
(save-excursion
(when (fboundp 'evil-prev-flyspell-error)
(evil-prev-flyspell-error count))
Now, Im using [[https://github.com/minad/jinx][jinx]], as it is the /complete basket/. It spellchecks based on the fontlock face and uses an external [[https://github.com/AbiWord/enchant][enchant program]] (to make spell-checking fast and asynchronous). Like =flymake=, Jinx does on-the-fly spellchecking of code comments and strings.
(when (looking-at (rx (one-or-more (any alnum "-" "_"))))
(let ((start-word (match-beginning 0))
(bad-word (match-string 0)))
(ispell-word)
(define-global-abbrev bad-word (buffer-substring-no-properties start-word (point)))))))
I keep =jinx-correct= bound to ~C-;~ à la flyspell because it is so darn helpful. Supports checking documents with mixed languages.
Requires the =libenchant= from the [[https://abiword.github.io/enchant/][Enchant project]], so on MacOS, I install it via:
#+begin_src sh
brew install enchant
#+end_src
Since this auto-correction needs to happen in /insert/ mode, I have bound a few keys, including ~CMD-s~ and ~M-s~ (twice) to fixing this spelling mistake, and jumping back to where I am. If the spelling mistake is /obvious/, I use ~C-;~ to call [[help:flyspell-auto-correct-word][flyspell-auto-correct-word]]. However, I currently do not know how to use this cool feature with my =ha-fix-last-spelling= function (because I dont know when that function is done).
And on Linux:
#+begin_src sh
sudo apt install libenchant-2-dev
#+end_src
And the Emacs interface to that:
For this to work, we use [[https://www.emacswiki.org/emacs/FlySpell][flyspell]] mode to highlight the misspelled words, and the venerable [[https://www.emacswiki.org/emacs/InteractiveSpell][ispell]] for correcting.
#+begin_src emacs-lisp
(use-package flyspell
:hook (text-mode . flyspell-mode)
:bind (("M-S" . ha-fix-last-spelling) ; This is j-k-s on the Moonlander. Hrm.
("s-s" . ha-fix-last-spelling)) ; This is Command-s or ;-s on Moonlander
(use-package jinx
:hook (emacs-startup . global-jinx-mode)
:bind (("M-$" . jinx-correct-nearest)
("s-s" . jinx-correct-nearest))
:general
(:states 'insert :keymaps 'text-mode-map
"M-s M-s" 'ha-fix-last-spelling)
:init
;; Tell ispell.el that can be part of a word.
(setq ispell-local-dictionary-alist
`((nil "[[:alpha:]]" "[^[:alpha:]]"
"['\x2019]" nil ("-B") nil utf-8)))
(:states '(normal insert) :keymaps 'text-mode-map
"M-s M-s" 'jinx-correct)
:config
(ha-leader :keymaps 'text-mode-map
"S" '(:ignore t :which-key "spellcheck")
"S s" '("correct last misspell" . ha-fix-last-spelling)
"S b" '("check buffer" . flyspell-buffer)
"S c" '("correct word" . flyspell-auto-correct-word))
(when (fboundp 'evil-prev-flyspell-error)
(ha-leader :keymaps 'text-mode-map
"S p" '("previous misspell" . evil-prev-flyspell-error)
"S n" '("next misspell" . evil-next-flyspell-error)))
;; Let's use M-TAB for something else ...
(define-key flyspell-mode-map (kbd "M-TAB") nil))
#+end_src
Sure, the keys, ~[ s~ and ~] s~ can jump to misspelled words, and use ~M-$~ to correct them, but I'm getting used to these leaders.
According to [[http://endlessparentheses.com/ispell-and-apostrophes.html][Artur Malabarba]], we can turn on rounded apostrophe's, like == (left single quotation mark). The idea is to not send the quote to the sub-process:
#+begin_src emacs-lisp
(defun endless/replace-apostrophe (args)
"Don't send to the subprocess."
(cons (replace-regexp-in-string
"" "'" (car args))
(cdr args)))
(advice-add #'ispell-send-string :filter-args #'endless/replace-apostrophe)
(defun endless/replace-quote (args)
"Convert ' back to from the subprocess."
(if (not (derived-mode-p 'org-mode))
args
(cons (replace-regexp-in-string
"'" "" (car args))
(cdr args))))
(advice-add #'ispell-parse-output :filter-args #'endless/replace-quote)
(ha-leader
"s i" '("spellcheck buffer" . jinx-correct-all)
"S b" '("spellcheck buffer" . jinx-correct-all)))
#+end_src
The end result? No misspellings. Isnt this nice?
Jinx works really good, as the mini-buffer allows you to use letters to filter the choice, and numbers (or Return) to select the choice. Selecting ~@~ adds the word to your personal dictionary, and ~*~ adds it to the /local words/ for the file (search for =jinx-local-words=). Also, it appears that calling =jinx-correct= goes back to the first incorrect spelling, letting you correct it, and then pops the point back. That is pretty slick.
It also, supposedly, fixes =camelCase= words. This doesnt work in a text document. I appreciate that in org-mode files, text surrounded with = characters are no longer marked for misspellings.
Since this auto-correction needs to happen in /insert/ mode, I have bound a few keys, including ~CMD-s~ and ~M-s~ (twice) to fixing this spelling mistake, and jumping back to where I am.
*** Thesaurus
Of course I need a thesaurus, and I'm installing [[https://github.com/SavchenkoValeriy/emacs-powerthesaurus][powerthesaurus]]:
#+begin_src emacs-lisp
(use-package powerthesaurus
:bind ("s-t" . powerthesaurus-lookup-dwim)
;; :bind ("s-t" . powerthesaurus-lookup-dwim)
:config
(ha-leader :keymaps 'text-mode-map
(ha-leader
"S t" '("thesaurus" . powerthesaurus-lookup-dwim)
"S s" '("synonyms" . powerthesaurus-lookup-synonyms-dwim)
"S a" '("antonyms" . powerthesaurus-lookup-antonyms-dwim)
@ -889,12 +857,16 @@ Of course I need a thesaurus, and I'm installing [[https://github.com/SavchenkoV
"S S" '("sentence" . powerthesaurus-lookup-sentences-dwim)))
#+end_src
The key-bindings, keystrokes, and key-connections work well with ~M-T~ (notice the Shift), but to jump to specifics, we use a leader. Since the /definitions/ do not work, so let's use abo-abo's [[https://github.com/abo-abo/define-word][define-word]] project:
The key-bindings, keystrokes, and key-connections work well with ~M-T~ (notice the Shift), but to jump to specifics, we use a leader.
*** Definitions
Since the /definitions/ do not work, so let's use the [[https://github.com/abo-abo/define-word][define-word]] project:
#+begin_src emacs-lisp
(use-package define-word
;; :bind ("s-d" . define-word-at-point)
:config
(ha-leader :keymaps 'text-mode-map
"S d" '("define this" . define-word-at-point)
"S D" '("define word" . define-word)))
#+end_src
@ -913,8 +885,7 @@ Now that Im mostly on version 28 and above of Emacs, we can take advantage of
#+begin_src emacs-lisp
(setq dictionary-server "dict.org")
(ha-leader :keymaps 'text-mode-map
"S d" '("define word" . dictionary-search))
(ha-leader "S d" '("define this" . dictionary-search))
#+end_src
Once in the dictionary buffer, acquiesce these keybindings:
- ~q~ close the dictionary buffer
@ -1149,7 +1120,7 @@ And something else while in Evil mode:
(ha-leader "x b" '("edit sentence" . ha-sentence-break))
#+end_src
Perhaps he might get around to turning [[https://git.chrismaiorana.com/?p=sentinel.git;a=blob;f=sentin.el;h=2738eff6ac2b0877576bafe88878683a7eff3125;hb=refs/heads/master][his code]] into a package. Features needed include:
- Adding an overlay to the original text, ala help:org-src--make-source-overlay
- Adding an overlay to the original text, help:org-src--make-source-overlay
** Distraction-Free Writing
[[https://christopherfin.com/writing/emacs-writing.html][Christopher Fin's essay]] inspired me to clean my writing room.
@ -1227,3 +1198,7 @@ Before you can build this on a new system, make sure that you put the cursor ove
#+options: num:nil toc:t todo:nil tasks:nil tags:nil date:nil
#+options: skip:nil author:nil email:nil creator:nil timestamp:nil
#+infojs_opt: view:nil toc:t ltoc:t mouse:underline buttons:0 path:http://orgmode.org/org-info.js
# Local Variables:
# jinx-local-words: "Braganza Graphviz Maloranas Proselint Somers Textlint Writegood flycheck flyspell fontlock"
# End:

View file

@ -115,7 +115,7 @@ For all programming languages, I would like to now default to absolute line numb
** Spell Checking Comments
The [[https://www.emacswiki.org/emacs/FlySpell#h5o-2][flyspell-prog-mode]] checks for misspellings in comments.
#+begin_src emacs-lisp
#+begin_src emacs-lisp :tangle no
(use-package flyspell
:hook (prog-mode . flyspell-prog-mode))
#+end_src