;;; cape-jinx-completion.el --- Completion At Point Extensions using Jinx spell checking -*- lexical-binding: t -*- ;; Copyright (C) 2021-2023 Adam Kruszewski ;; Author: Adam Kruszewski ;; Maintainer: Adam Kruszewski ;; Created: 2023 ;; Version: 1.0 ;; Package-Requires: ((emacs "28.1") (compat "29.1.4.0") (cape "0.15") (jinx "0.5")) ;; Homepage: https://code.bsdgeek.org/adam/cape-jinx-completion ;; Keywords: convenience, completion, spell-check ;; 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 3 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 . ;;; Commentary: ;; Additional completion backend in the form of Capfs ;; (completion-at-point-functions), using underlying C module provided ;; by Jinx just-in-time spell-checking package ;; (see https://github.com/minad/jinx ). ;; ;; It doesn't need Jinx enabled, but it uses its configuration ;; and C module bridge to enchant library. ;; ;; Having jinx and cape configured you just need to add: ;; (add-to-list 'completion-at-point-functions #'cape-jinx-completion) ;; cape-jinx-completion to your completions-at-point-functions. ;;; Code: (require 'cape) (require 'jinx) (eval-when-compile (require 'cl-lib) (require 'jinx)) ;; jinx.el version 0.5 is required (defun cape-jinx-completion-suggest-for-word (word) "Return suggestions as a list for `WORD'." (when (not jinx--dicts) (when (not (fboundp 'jinx--mod-dict)) (jinx--load-module)) (jinx--load-dicts)) (if (fboundp 'jinx--mod-suggest) (let* ((result '())) (dolist (dict jinx--dicts) (dolist (el (jinx--mod-suggest dict word)) (when (string-prefix-p word el) (cl-pushnew el result)))) (delete-dups result)) ;; this should never happen, as jinx--load-module will bind jinx--mod-suggest as well. '())) ;; cape-jinx-completion (based on cape-dict) (defgroup cape-jinx-completion nil "Completion At Point extensions using Jinx spell checking." :prefix "cape-jinx-completion" :group 'cape-jinx-completion) (defcustom cape-jinx-completion-case-replace 'case-replace "Preserve case of input. See `dabbrev-case-replace' for details." :type '(choice (const :tag "off" nil) (const :tag "use `case-replace'" case-replace) (other :tag "on" t))) (defcustom cape-jinx-completion-case-fold 'case-fold-search "Case fold search during search. See `dabbrev-case-fold-search' for details." :type '(choice (const :tag "off" nil) (const :tag "use `case-fold-search'" case-fold-search) (other :tag "on" t))) (defvar cape-jinx-completion--properties (list :annotation-function (lambda (_) " Jinx") :company-kind (lambda (_) 'text) :exclusive 'no) "Completion extra properties for `cape-jinx-completion'.") (defun cape-jinx-completion--list (input) "Return all words from Jinx spell checking mechanism matching INPUT." (unless (equal input "") (cape--case-replace-list cape-jinx-completion-case-replace input (cape-jinx-completion-suggest-for-word input)))) ;;;###autoload (defun cape-jinx-completion (&optional interactive) "Complete word from Jinx spell checking at point. If INTERACTIVE is nil the function acts like a Capf." (interactive (list t)) (if interactive (cape-interactive #'cape-jinx-completion) (pcase-let ((`(,beg . ,end) (cape--bounds 'word))) `(,beg ,end ,(cape--table-with-properties (completion-table-case-fold (cape--cached-table beg end #'cape-jinx-completion--list #'string-search) (not (cape--case-fold-p cape-jinx-completion-case-fold))) :category 'cape-jinx-completion) ,@cape-jinx-completion--properties)))) (provide 'cape-jinx-completion) ;;; cape-jinx-completion.el ends here