;;; +ispell.el --- Customizations for `ispell' -*- lexical-binding: t; -*- ;;; Commentary: ;;; Code: (require 'cl-lib) (require 'seq) ;; Utility function TODO: move elsewhere (defun +ispell-append-removing-duplicates (&rest lists) "Append LISTS, removing duplicates from the result. Any keyword arguments to `cl-remove-duplicates' should come before the LISTS." (let (cl-remove-duplicates-args) (while (keywordp (car lists)) (push (pop lists) cl-remove-duplicates-args) (push (pop lists) cl-remove-duplicates-args)) (apply #'cl-remove-duplicates (apply #'append lists) (nreverse cl-remove-duplicates-args)))) ;;; Ispell in .dir-locals ;; Let Emacs know a list of strings is safe (defun +ispell-safe-local-p (list) (and (listp list) (seq-every-p #'stringp list))) ;; Can I instruct ispell to insert LocalWords in a different file? ;; https://emacs.stackexchange.com/q/31396/2264 ;; How can I move all my file-local LocalWords to .dir-locals.el? ;; https://emacs.stackexchange.com/q/31419 ;; Adapted from ispell.el:ispell-buffer-local-words (defun +ispell-buffer-local-words-list () (let (words) (or ispell-buffer-local-name (setq ispell-buffer-local-name (buffer-name))) (save-excursion (goto-char (point-min)) (while (search-forward ispell-words-keyword nil t) (let ((end (point-at-eol)) (ispell-casechars (ispell-get-casechars)) string) (while (re-search-forward " *\\([^ ]+\\)" end t) (setq string (match-string-no-properties 1)) (if (and (< 1 (length string)) (equal 0 (string-match ispell-casechars string))) (push string words)))))) words)) ;;;###autoload (defun +ispell-move-buffer-words-to-dir-locals (&optional arg) "Move the current buffer-local words to .dir-locals.el. This function prompts the user to save .dir-locals.el, unless prefix ARG is non-nil; then it just saves them." (interactive "P") (unless (buffer-file-name) (user-error "Buffer not attached to file")) (hack-dir-local-variables) (let ((print-level nil) (print-length nil)) (when-let ((new-words (cl-remove-if (lambda (el) (eq el '\.\.\.)) ; XXX: NO IDEA ; where this came from (+ispell-append-removing-duplicates :test #'string= ispell-buffer-session-localwords (alist-get 'ispell-buffer-session-localwords dir-local-variables-alist) (alist-get 'ispell-buffer-session-localwords file-local-variables-alist) (+ispell-buffer-local-words-list))))) (save-excursion (add-dir-local-variable major-mode 'ispell-buffer-session-localwords (setq ispell-buffer-session-localwords new-words)) (when (or arg (y-or-n-p "Save .dir-locals.el?")) (save-buffer)) (bury-buffer)) (or ispell-buffer-local-name (setq ispell-buffer-local-name (buffer-name))) (save-excursion (goto-char (point-min)) (while (search-forward ispell-words-keyword nil t) (delete-region (point-at-bol) (1+ (point-at-eol)))))))) ;;;###autoload (defun +ispell-move-buffer-words-to-dir-locals-hook () "Convenience function for binding to a hook." (+ispell-move-buffer-words-to-dir-locals t)) (provide '+ispell) ;;; +ispell.el ends here