Add documentation to capf functions
[emacs-capf-autosuggest.git] / history-capf.el
blobdf4a71b9d272e90b7e7c4112dd9e5e385458868d
1 ;;; history-capf.el --- Completion-at-point function for comint and eshell history -*- lexical-binding: t; -*-
3 ;; Filename: history-capf.el
4 ;; Description: Completion-at-point function for comint and eshell history
5 ;; Author: jakanakaevangeli <jakanakaevangeli@chiru.no>
6 ;; Created: 2021-07-14
7 ;; Version: 1.0
8 ;; URL: https://github.com/jakanakaevangeli/emacs-capf-autosuggest
10 ;; This file is not part of GNU Emacs.
12 ;; This program is free software: you can redistribute it and/or modify
13 ;; it under the terms of the GNU General Public License as published by
14 ;; the Free Software Foundation, either version 3 of the License, or
15 ;; (at your option) any later version.
17 ;; This program is distributed in the hope that it will be useful,
18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 ;; GNU General Public License for more details.
22 ;; You should have received a copy of the GNU General Public License
23 ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
25 ;;; Commentary:
27 ;;; Code:
29 (require 'ring)
30 (eval-when-compile (require 'cl-lib))
32 (defvar capf-autosuggest-all-completions-only-one)
33 (defvar capf-autosuggest-active-mode-map)
34 (defvar comint-input-ring)
35 (defvar comint-accum-marker)
36 (defvar comint-use-prompt-regexp)
37 (defvar eshell-history-ring)
38 (defvar eshell-last-output-end)
39 (declare-function capf-autosuggest-mode "capf-autosuggest")
40 (declare-function eshell-bol "esh-mode")
41 (declare-function comint-previous-matching-input-from-input "comint")
42 (declare-function eshell-previous-matching-input-from-input "em-hist")
44 ;;;###autoload
45 (defun history-capf-comint ()
46 "Completion-at-point function for comint input history.
47 Is only applicable if point is after the last prompt."
48 (let ((ring comint-input-ring)
49 (beg nil))
50 (and ring (ring-p ring) (not (ring-empty-p ring))
51 (or (and (setq beg comint-accum-marker)
52 (setq beg (marker-position beg)))
53 (and (setq beg (get-buffer-process (current-buffer)))
54 (setq beg (marker-position (process-mark beg)))))
55 (>= (point) beg)
56 (list beg (if comint-use-prompt-regexp
57 (line-end-position)
58 (field-end))
59 (hisotry-capf--completion-table ring)
60 :exclusive 'no))))
62 ;;;###autoload
63 (defun history-capf-eshell ()
64 "Completion-at-point function for eshell input history.
65 Is only applicable if point is after the last prompt."
66 (let ((ring eshell-history-ring)
67 (beg nil))
68 (and ring (ring-p ring) (not (ring-empty-p ring))
69 (setq beg eshell-last-output-end)
70 (setq beg (marker-position beg))
71 (>= (point) beg)
72 (list (save-excursion (eshell-bol) (point)) (point-max)
73 (hisotry-capf--completion-table ring)
74 :exclusive 'no))))
76 (defun hisotry-capf--completion-table (ring)
77 "Return a completion table to complete on RING."
78 (let (self)
79 (setq
80 self
81 (lambda (input predicate action)
82 (cond
83 ((eq action t)
84 (cl-loop
85 with only-one = capf-autosuggest-all-completions-only-one
86 for i below (ring-size ring)
87 for elem = (ring-ref ring i)
88 if (string-prefix-p input elem)
89 if (or (null predicate)
90 (funcall predicate elem))
91 if (cl-loop for regex in completion-regexp-list
92 always (string-match-p regex elem))
93 if only-one
94 return (list elem)
95 else collect elem))
96 ((eq action nil)
97 (complete-with-action
98 nil (let ((capf-autosuggest-all-completions-only-one nil))
99 (funcall self input predicate t))
100 input predicate))
101 ((eq action 'lambda)
102 (and (ring-member ring input)
103 (or (null predicate)
104 (funcall predicate input))
105 (cl-loop for regex in completion-regexp-list
106 always (string-match-p regex input))))
107 (t (complete-with-action
108 action (ring-elements ring) input predicate)))))))
110 ;;;###autoload
111 (defun history-capf-setup-autosuggest-comint ()
112 "Setup capf-autosuggest for history suggestion in comint."
113 (capf-autosuggest-mode)
114 (add-hook 'capf-autosuggest-capf #'history-capf-comint))
116 ;;;###autoload
117 (defun history-capf-setup-autosuggest-eshell ()
118 "Setup capf-autosuggest for history suggestion in eshell."
119 (capf-autosuggest-mode)
120 (add-hook 'capf-autosuggest-capf #'history-capf-eshell))
122 (with-eval-after-load 'capf-autosuggest
123 (define-key capf-autosuggest-active-mode-map
124 [remap comint-previous-matching-input-from-input]
125 #'history-capf-comint-previous-matching-input-from-input)
126 (define-key capf-autosuggest-active-mode-map
127 [remap eshell-previous-matching-input-from-input]
128 #'history-capf-eshell-previous-matching-input-from-input))
130 (defun history-capf-comint-previous-matching-input-from-input (n)
131 "Like `comint-previous-matching-input-from-input'.
132 But increase arument N by 1, if positive, but not on command
133 repetition."
134 (interactive "p")
135 (and (not (memq last-command '(comint-previous-matching-input-from-input
136 comint-next-matching-input-from-input)))
137 (> n 0)
138 (setq n (1+ n)))
139 (comint-previous-matching-input-from-input n)
140 (setq this-command #'comint-previous-matching-input-from-input))
142 (defun history-capf-eshell-previous-matching-input-from-input (n)
143 "Like `eshell-previous-matching-input-from-input'.
144 But increase arument N by 1, if positive, but not on command
145 repetition."
146 (interactive "p")
147 (and (not (memq last-command '(eshell-previous-matching-input-from-input
148 eshell-next-matching-input-from-input)))
149 (> n 0)
150 (setq n (1+ n)))
151 (eshell-previous-matching-input-from-input n)
152 (setq this-command #'eshell-previous-matching-input-from-input))
154 (provide 'history-capf)
155 ;;; history-capf.el ends here