cape-jinx-completion/cape-jinx-completion.el

108 lines
3.9 KiB
EmacsLisp

;;; cape-jinx-completion.el --- Completion At Point Extensions using Jinx spell checking -*- lexical-binding: t -*-
;; Copyright (C) 2023 Free Software Foundation, Inc.
;; Author: Adam Kruszewski <adam@kruszewski.name>
;; Maintainer: Adam Kruszewski <adam@kruszewski.name>
;; Created: 2023
;; Version: 1.0
;; Package-Requires: ((emacs "27.1") (compat "29.1.4.0") (cape "0.15") (jinx "0.5"))
;; Homepage: https://code.bsdgeek.org/adam/cape-jinx-completion
;; Keywords: completion, spell-check
;; This file is 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 <https://www.gnu.org/licenses/>.
;;; 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)
;; cape-jinx-completion to your completions-at-point-functions.
(require 'cape)
(require 'jinx)
;; jinx.el version 0.5 is required
(defun jinx-suggest-for-word (word)
(when (not jinx--dicts)
(when (not (fboundp #'jinx--mod-dict))
(jinx--load-module))
(jinx--load-dicts))
(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)))
;; cape-jinx (based on cape-dict)
(defgroup cape-jinx nil
"Completion At Point extensions using Jinx spell checking."
:prefix "cape-jinx"
:group 'cape-jinx)
(defcustom cape-jinx-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-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-properties
(list :annotation-function (lambda (_) " Jinx")
:company-kind (lambda (_) 'text)
:exclusive 'no)
"Completion extra properties for `cape-jinx'.")
(defun cape--jinx-list (input)
"Return all words from Jinx spell checking mechanism matching INPUT."
(unless (equal input "")
(cape--case-replace-list
cape-jinx-case-replace input
(jinx-suggest-for-word input))))
;;;###autoload
(defun cape-jinx (&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)
(pcase-let ((`(,beg . ,end) (cape--bounds 'word)))
`(,beg ,end
,(cape--table-with-properties
(completion-table-case-fold
(cape--cached-table beg end #'cape--jinx-list #'string-search)
(not (cape--case-fold-p cape-jinx-case-fold)))
:category 'cape-jinx)
,@cape--jinx-properties))))
;;; cape-jinx-completion.el ends here
(provide 'cape-jinx-completion)