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>
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/>.
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")
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
)
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
)))))
56 (list beg
(if comint-use-prompt-regexp
59 (hisotry-capf--completion-table ring
)
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
)
68 (and ring
(ring-p ring
) (not (ring-empty-p ring
))
69 (setq beg eshell-last-output-end
)
70 (setq beg
(marker-position beg
))
72 (list (save-excursion (eshell-bol) (point)) (point-max)
73 (hisotry-capf--completion-table ring
)
76 (defun hisotry-capf--completion-table (ring)
77 "Return a completion table to complete on RING."
81 (lambda (input predicate action
)
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
))
98 nil
(let ((capf-autosuggest-all-completions-only-one nil
))
99 (funcall self input predicate t
))
102 (and (ring-member ring input
)
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
)))))))
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
))
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
135 (and (not (memq last-command
'(comint-previous-matching-input-from-input
136 comint-next-matching-input-from-input
)))
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
147 (and (not (memq last-command
'(eshell-previous-matching-input-from-input
148 eshell-next-matching-input-from-input
)))
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