1 ;;; capf-autosuggest.el --- History autosuggestions for comint and eshell -*- lexical-binding: t; -*-
3 ;; Copyright (C) 2021 Free Software Foundation, Inc.
5 ;; Filename: capf-autosuggest.el
6 ;; Author: jakanakaevangeli <jakanakaevangeli@chiru.no>
9 ;; Package-Requires: ((emacs "25.1"))
10 ;; URL: https://repo.or.cz/emacs-capf-autosuggest.git
12 ;; This file is part of GNU Emacs.
14 ;; This program is free software: you can redistribute it and/or modify
15 ;; it under the terms of the GNU General Public License as published by
16 ;; the Free Software Foundation, either version 3 of the License, or
17 ;; (at your option) any later version.
19 ;; This program is distributed in the hope that it will be useful,
20 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
21 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 ;; GNU General Public License for more details.
24 ;; You should have received a copy of the GNU General Public License
25 ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
29 ;; capf-autosuggest lets you preview the most recent matching history element,
30 ;; similar to zsh-autosuggestions or fish. It works in eshell and in modes
31 ;; derived from comint-mode, for example M-x shell and M-x run-python.
33 ;; As you type, the history auto-suggestion is shown as an overlay after point.
34 ;; Type [C-e] to insert text from this overlay or [M-f] to only insert a word
35 ;; from this overlay. [C-n] is a shorthand for [C-e] followed by [RET]: it
36 ;; inserts text from the overlay and sends it to the process.
40 ;; To install capf-autosuggest, type
41 ;; M-x package-install RET capf-autosuggest RET.
43 ;; Enable it with M-x capf-autosuggest-mode. It is best to add the following
44 ;; elisp snippet to your Emacs init file to enable `capf-autosuggest-mode'
45 ;; automatically for every comint and eshell buffer:
47 ;; (add-hook 'comint-mode-hook #'capf-autosuggest-mode)
48 ;; (add-hook 'eshell-mode-hook #'capf-autosuggest-mode)
52 ;; Use `capf-autosuggest-define-partial-accept-cmd' to make a command that can
53 ;; move point into an auto-suggested overlay.
55 ;; Example: to make [C-M-f] (forward-sexp) movable into suggested text, put the
56 ;; following into your Emacs init file:
58 ;; (with-eval-after-load 'capf-autosuggest
59 ;; (capf-autosuggest-define-partial-accept-cmd
60 ;; movable-forward-sexp forward-sexp)
61 ;; (define-key capf-autosuggest-active-mode-map
62 ;; [remap forward-sexp] #'movable-forward-sexp))
64 ;; By default, [C-n] (next-line) will accept the currently displayed suggestion
65 ;; and send input to shell/eshell. To disable this behaviour or enable it for
66 ;; other commands such as [C-c C-n] or [M-n], see the customization group
71 ;; capf-autosuggest provides a minor mode, capf-autosuggest-mode, that lets you
72 ;; preview the first completion candidate for in-buffer completion as an
73 ;; overlay. Instead of using the default hook `completion-at-point-functions',
74 ;; it uses its own hook `capf-autosuggest-capf-functions'. However, by
75 ;; default, this hook contains a function that reads the default hook, but only
76 ;; if point is at end of line, because an auto-suggested overlay can be
77 ;; annoying in the middle of a line. If you want, you can try enabling this
78 ;; minor mode in an ordinary buffer for previewing tab completion candidates at
81 ;; A completion-at-point function for comint and eshell history is also
82 ;; provided. Because it is less useful for tab completion and more useful for
83 ;; auto-suggestion preview, it is a member of
84 ;; `capf-autosuggest-capf-functions', which doesn't interfere with tab
85 ;; completion. By default, if there are no matches for history completion and
86 ;; point is at end of line, we fall back to previewing the default tab
87 ;; completion candidates, as described in the previous paragraph.
89 ;; You can customize this behaviour by customizing
90 ;; `capf-autosuggest-capf-functions'. For example, you could add
91 ;; `capf-autosuggest-orig-capf' to enable auto-suggestions of tab completion
92 ;; candidates in the middle of a line.
96 ;; There is also esh-autosuggest[1] with similar functionality. Differences:
97 ;; it is simpler and more concise, however it depends on company. It optionally
98 ;; allows having a delay and it is implemented only for eshell.
100 ;; [1]: http://github.com/dieggsy/esh-autosuggest
102 ;;;; Bugs, suggestions and patches can be sent to
104 ;; bugs-doseganje (at) groups.io
106 ;; and can be viewed at https://groups.io/g/bugs-doseganje/topics. As this
107 ;; package is stored in GNU ELPA, non-trivial patches require copyright
108 ;; assignment to the FSF, see info node "(emacs) Copyright Assignment".
117 (defvar comint-input-ring
)
118 (defvar comint-accum-marker
)
119 (defvar comint-use-prompt-regexp
)
120 (defvar eshell-history-ring
)
121 (defvar eshell-last-output-end
)
122 (declare-function eshell-bol
"esh-mode")
123 (declare-function comint-previous-matching-input-from-input
"comint")
124 (declare-function comint-after-pmark-p
"comint")
125 (declare-function comint-send-input
"comint")
126 (declare-function eshell-previous-matching-input-from-input
"em-hist")
127 (declare-function eshell-send-input
"esh-mode")
128 (declare-function eshell-interactive-process
"esh-cmd")
129 (declare-function eshell-next-prompt
"em-prompt")
130 (declare-function eshell-next-input
"em-hist")
131 (declare-function eshell-next-matching-input-from-input
"em-hist")
133 (defgroup capf-autosuggest nil
134 "Show completion at point as an overlay."
136 :prefix
"capf-autosuggest-"
138 '(url-link "https://github.com/jakanakaevangeli/emacs-capf-autosuggest"))
140 ;;; Auto-suggestion overlay
142 (defface capf-autosuggest-face
'((t :inherit file-name-shadow
))
143 "Face used for auto suggestions.")
145 (defvar capf-autosuggest-capf-functions
146 '(capf-autosuggest-history-capf capf-autosuggest-orig-if-at-eol-capf
)
147 "`completion-at-point-functions', used by capf-autosuggest.
148 It is used instead of the standard
149 `completion-at-point-functions', but the default value contains
150 `capf-autosuggest-orig-if-at-eol-capf' which searches the
151 standard capf functions, if point is at the end of line.")
153 (defvar capf-autosuggest-all-completions-only-one nil
154 "Non-nil if only the first result of `all-completions' is of interest.
155 capf-autosuggest binds this to t around calls to
156 `all-completions'. A dynamic completion table can take this as a
157 hint to only return a list of one element for optimization.")
159 (defvar-local capf-autosuggest--overlay nil
)
160 (defvar-local capf-autosuggest--str
"")
161 (defvar-local capf-autosuggest--tick nil
)
162 (defvar-local capf-autosuggest--region
'(nil)
163 "Region of `completion-at-point'.")
165 (defun capf-autosuggest-orig-capf (&optional capf-functions
)
166 "A capf that chooses from hook variable CAPF-FUNCTIONS.
167 CAPF-FUNCTIONS defaults to `completion-at-point-functions'.
168 Don't add this function to `completion-at-point-functions', as it
169 will result in an infinite loop. It is usually added to
170 `capf-autosuggest-capf-functions', making it search the standard
172 (cdr (run-hook-wrapped (or capf-functions
'completion-at-point-functions
)
173 #'completion--capf-wrapper
'all
)))
175 (defun capf-autosuggest-orig-if-at-eol-capf ()
176 "`capf-autosuggest-orig-capf' if at the end of line.
177 Otherwise, return nil."
179 (capf-autosuggest-orig-capf)))
181 (defvar capf-autosuggest-active-mode
)
183 (defun capf-autosuggest--post-h ()
184 "Create an auto-suggest overlay."
185 (when capf-autosuggest-active-mode
186 ;; `identity' is used to generate slightly faster byte-code
187 (pcase-let ((`(,beg .
,end
) (identity capf-autosuggest--region
)))
188 (unless (and (< beg
(point) end
)
189 (eq (buffer-modified-tick) capf-autosuggest--tick
))
190 (capf-autosuggest-active-mode -
1))))
192 (unless capf-autosuggest-active-mode
193 (pcase (let* ((catch-sym (make-symbol "cirf-catch"))
194 ;; `pcomplete-completions-at-point' may illegally use
195 ;; `completion-in-region' itself instead of returning a
196 ;; collection. Let's try to outsmart it.
197 (completion-in-region-function
198 (lambda (start end collection predicate
)
200 (list start end collection
:predicate predicate
))))
206 ;; `ielm-complete-filename' may illegaly move point
208 (capf-autosuggest-orig-capf
209 'capf-autosuggest-capf-functions
))))
210 ((buffer-read-only quit
) t
)))
211 (`(,beg
,end
,table .
,plist
)
212 (let* ((pred (plist-get plist
:predicate
))
213 (string (buffer-substring-no-properties beg end
))
214 ;; See `completion-emacs21-all-completions'
215 (base (car (completion-boundaries string table pred
""))))
218 (let ((capf-autosuggest-all-completions-only-one t
))
219 ;; Use `all-completions' rather than
220 ;; `completion-all-completions' to bypass completion styles
221 ;; and strictly match only on prefix. This makes sense here
222 ;; as we only use the string without the prefix for the
224 (all-completions string table pred
)))
225 ;; `all-completions' may return strings that don't strictly
226 ;; match on our prefix. Ignore them.
227 ((string-prefix-p (substring string base
) (car completions
)))
228 (str (substring (car completions
) (- end beg base
)))
231 (setq capf-autosuggest--region
(cons beg end
)
232 capf-autosuggest--str
(copy-sequence str
)
233 capf-autosuggest--tick
(buffer-modified-tick))
234 (move-overlay capf-autosuggest--overlay end end
)
235 ;; Make sure the overlay after-string doesn't start or end with a
236 ;; newline, otherwise it can behave badly with cursor placement
237 (when (eq ?
\n (aref str
0))
238 (setq str
(concat " " str
))
240 (when (eq ?
\n (aref str
(1- len
)))
241 (setq str
(concat str
(propertize " " 'display
"")))
243 (put-text-property 0 1 'cursor len str
)
244 (put-text-property 0 len
'face
'capf-autosuggest-face str
)
245 (overlay-put capf-autosuggest--overlay
'after-string str
)
246 (capf-autosuggest-active-mode)))))))
249 (define-minor-mode capf-autosuggest-mode
250 "Auto-suggest first completion at point with an overlay."
251 :group
'capf-autosuggest
252 (if capf-autosuggest-mode
254 (when capf-autosuggest--overlay
255 (capf-autosuggest-active-mode-deactivate))
256 (setq capf-autosuggest--overlay
(make-overlay (point) (point) nil t t
))
257 (add-hook 'post-command-hook
#'capf-autosuggest--post-h nil t
)
258 (add-hook 'change-major-mode-hook
259 #'capf-autosuggest-active-mode-deactivate nil t
))
260 (remove-hook 'change-major-mode-hook
261 #'capf-autosuggest-active-mode-deactivate t
)
262 (remove-hook 'post-command-hook
#'capf-autosuggest--post-h t
)
263 (capf-autosuggest-active-mode -
1)))
265 ;;; Various commands and menu-items
268 (defmacro capf-autosuggest-define-partial-accept-cmd
(name command
)
269 "Define a command NAME.
270 It will call COMMAND interactively, allowing it to move point
271 into an auto-suggested overlay. COMMAND must not modify buffer.
272 NAME must not be called if variable
273 `capf-autosuggest-active-mode' is inactive. NAME is suitable for
274 binding in `capf-autosuggest-active-mode-map'."
276 "`%s', possibly moving point into an auto-suggested overlay."
278 (unless (< (length doc
) 80)
280 Execute command, possibly moving point into an auto-suggested overlay.
282 and make it possible for this command to enter an auo-suggested overlay."
287 (capf-autosuggest-call-partial-accept-cmd #',command
))))
289 (defun capf-autosuggest-call-partial-accept-cmd (command)
290 "Call COMMAND interactively, stepping into auto-suggested overlay.
291 Temporarily convert the overlay to buffer text and call COMMAND
292 interactively. Afterwards, the added text is deleted, but only
293 the portion after point. Additionally, if point is outside of
294 the added text, the whole text is deleted."
296 (setq beg
(overlay-start capf-autosuggest--overlay
))
297 (capf-autosuggest-active-mode -
1)
298 (with-silent-modifications
299 (catch 'cancel-atomic-change
303 (insert-and-inherit capf-autosuggest--str
)
305 (call-interactively command
)
308 (setq text
(buffer-substring beg
(point))))
309 (throw 'cancel-atomic-change nil
))))
317 (declare-function evil-forward-char
"ext:evil-commands" nil t
)
318 (declare-function evil-end-of-line
"ext:evil-commands" nil t
)
319 (declare-function evil-end-of-visual-line
"ext:evil-commands" nil t
)
320 (declare-function evil-end-of-line-or-visual-line
"ext:evil-commands" nil t
)
321 (declare-function evil-middle-of-visual-line
"ext:evil-commands" nil t
)
322 (declare-function evil-last-non-blank
"ext:evil-commands" nil t
)
323 (declare-function evil-forward-word-begin
"ext:evil-commands" nil t
)
324 (declare-function evil-forward-word-end
"ext:evil-commands" nil t
)
325 (declare-function evil-forward-WORD-begin
"ext:evil-commands" nil t
)
326 (declare-function evil-forward-WORD-end
"ext:evil-commands" nil t
)
328 (capf-autosuggest-define-partial-accept-cmd capf-autosuggest-forward-word forward-word
)
329 (capf-autosuggest-define-partial-accept-cmd capf-autosuggest-forward-char forward-char
)
330 (capf-autosuggest-define-partial-accept-cmd capf-autosuggest-forward-sexp forward-sexp
)
331 (capf-autosuggest-define-partial-accept-cmd capf-autosuggest-end-of-line end-of-line
)
332 (capf-autosuggest-define-partial-accept-cmd capf-autosuggest-move-end-of-line move-end-of-line
)
333 (capf-autosuggest-define-partial-accept-cmd capf-autosuggest-end-of-visual-line end-of-visual-line
)
334 (capf-autosuggest-define-partial-accept-cmd capf-autosuggest-evil-forward-char evil-forward-char
)
335 (capf-autosuggest-define-partial-accept-cmd capf-autosuggest-evil-end-of-line evil-end-of-line
)
336 (capf-autosuggest-define-partial-accept-cmd capf-autosuggest-evil-end-of-visual-line evil-end-of-visual-line
)
337 (capf-autosuggest-define-partial-accept-cmd capf-autosuggest-evil-end-of-line-or-visual-line evil-end-of-line-or-visual-line
)
338 (capf-autosuggest-define-partial-accept-cmd capf-autosuggest-evil-middle-of-visual-line evil-middle-of-visual-line
)
339 (capf-autosuggest-define-partial-accept-cmd capf-autosuggest-evil-last-non-blank evil-last-non-blank
)
340 (capf-autosuggest-define-partial-accept-cmd capf-autosuggest-evil-forward-word-begin evil-forward-word-begin
)
341 (capf-autosuggest-define-partial-accept-cmd capf-autosuggest-evil-forward-word-end evil-forward-word-end
)
342 (capf-autosuggest-define-partial-accept-cmd capf-autosuggest-evil-forward-WORD-begin evil-forward-WORD-begin
)
343 (capf-autosuggest-define-partial-accept-cmd capf-autosuggest-evil-forward-WORD-end evil-forward-WORD-end
)
345 (defun capf-autosuggest-accept ()
346 "Accept current auto-suggestion.
347 Do not call this command if variable `capf-autosuggest-active-mode' is
350 (when capf-autosuggest-active-mode
351 (goto-char (overlay-start capf-autosuggest--overlay
))
352 (insert-and-inherit capf-autosuggest--str
)))
354 (defun capf-autosuggest-comint-previous-matching-input-from-input (n)
355 "Like `comint-previous-matching-input-from-input'.
356 If N is positive, the command isn't repeated and point is at
357 auto-suggested overlay, increase argument N by 1. This is done
358 in order to skip the history element already shown by the overlay."
360 (and (not (memq last-command
'(comint-previous-matching-input-from-input
361 comint-next-matching-input-from-input
)))
363 (= (point) (overlay-start capf-autosuggest--overlay
))
365 (comint-previous-matching-input-from-input n
)
366 (setq this-command
#'comint-previous-matching-input-from-input
))
368 (defun capf-autosuggest-eshell-previous-matching-input-from-input (n)
369 "Like `eshell-previous-matching-input-from-input'.
370 If N is positive, the command isn't repeated and point is at
371 auto-suggested overlay, increase argument N by 1. This is done
372 in order to skip the history element already shown by the overlay."
374 (and (not (memq last-command
'(eshell-previous-matching-input-from-input
375 eshell-next-matching-input-from-input
)))
377 (= (point) (overlay-start capf-autosuggest--overlay
))
379 (eshell-previous-matching-input-from-input n
)
380 (setq this-command
#'eshell-previous-matching-input-from-input
))
382 (defcustom capf-autosuggest-dwim-next-line t
383 "Whether `next-line' can accept and send current suggestion.
384 If t and point is on last line, `next-line' will accept the
385 current suggestion and send it to the process as input."
387 (defcustom capf-autosuggest-dwim-next-prompt nil
388 "Whether next-prompt commands can send current suggestion.
389 If t and point is after the last prompt, `comint-next-prompt' and
390 `eshell-next-prompt' will accept the current suggestion and send
391 it to the process as input."
393 (defcustom capf-autosuggest-dwim-next-input nil
394 "Whether next-input commands can send current suggestion.
395 If t and previous command wasn't a history command
396 \(next/previous-input or
397 previous/next-matching-input-from-input), `comint-next-input' and
398 `eshell-next-input' will accept the current suggestion and send
399 it to the process as input."
401 (defcustom capf-autosuggest-dwim-next-matching-input-from-input nil
402 "Whether next-input commands can send current suggestion.
403 If t and previous command wasn't a history matching command
404 \(previous or next-matching-input-from-input),
405 `comint-next-matching-input-from-input' and
406 `eshell-next-matching-input-from-input' will accept the current
407 suggestion and send it to the process as input."
410 (defun capf-autosuggest--accept-and-remapping (cmd)
411 "Return a command that will accept input and run CMD."
412 ;; Avoid infinite recursion when searching for the command remapping
413 (let ((capf-autosuggest-active-mode nil
))
414 (setq cmd
(or (command-remapping cmd
) cmd
)))
417 (capf-autosuggest-accept)
419 (setq this-command cmd
)
420 (call-interactively cmd
)))
422 (defvar capf-autosuggest-active-mode-map
423 (let ((map (make-sparse-keymap)))
424 (define-key map
[remap forward-word
] #'capf-autosuggest-forward-word
)
425 (define-key map
[remap forward-char
] #'capf-autosuggest-forward-char
)
426 (define-key map
[remap forward-sexp
] #'capf-autosuggest-forward-sexp
)
427 (define-key map
[remap end-of-line
] #'capf-autosuggest-end-of-line
)
428 (define-key map
[remap move-end-of-line
] #'capf-autosuggest-move-end-of-line
)
429 (define-key map
[remap end-of-visual-line
] #'capf-autosuggest-end-of-visual-line
)
431 (define-key map
[remap evil-forward-char
] #'capf-autosuggest-evil-forward-char
)
432 (define-key map
[remap evil-end-of-line
] #'capf-autosuggest-evil-end-of-line
)
433 (define-key map
[remap evil-end-of-visual-line
] #'capf-autosuggest-evil-end-of-visual-line
)
434 (define-key map
[remap evil-end-of-line-or-visual-line
] #'capf-autosuggest-evil-end-of-line-or-visual-line
)
435 (define-key map
[remap evil-middle-of-visual-line
] #'capf-autosuggest-evil-middle-of-visual-line
)
436 (define-key map
[remap evil-last-non-blank
] #'capf-autosuggest-evil-last-non-blank
)
437 (define-key map
[remap evil-forward-word-begin
] #'capf-autosuggest-evil-forward-word-begin
)
438 (define-key map
[remap evil-forward-word-end
] #'capf-autosuggest-evil-forward-word-end
)
439 (define-key map
[remap evil-forward-WORD-begin
] #'capf-autosuggest-evil-forward-WORD-begin
)
440 (define-key map
[remap evil-forward-WORD-end
] #'capf-autosuggest-evil-forward-WORD-end
)
442 (define-key map
[remap eshell-previous-matching-input-from-input
]
443 #'capf-autosuggest-eshell-previous-matching-input-from-input
)
444 (define-key map
[remap comint-previous-matching-input-from-input
]
445 #'capf-autosuggest-comint-previous-matching-input-from-input
)
447 (define-key map
[remap next-line
]
448 (list 'menu-item
"" nil
:filter
450 (and capf-autosuggest-dwim-next-line
451 (looking-at-p "[^\n]*\n?\\'")
454 ((derived-mode-p 'comint-mode
) #'comint-send-input
)
455 ((derived-mode-p 'eshell-mode
) #'eshell-send-input
)
456 ((minibufferp) #'exit-minibuffer
)))
457 (capf-autosuggest--accept-and-remapping cmd
)))))
458 (define-key map
[remap comint-next-prompt
]
459 (list 'menu-item
"" #'comint-send-input
:filter
461 (and capf-autosuggest-dwim-next-prompt
462 (comint-after-pmark-p)
463 (capf-autosuggest--accept-and-remapping cmd
)))))
464 (define-key map
[remap eshell-next-prompt
]
465 (list 'menu-item
"" #'eshell-send-input
:filter
467 (and capf-autosuggest-dwim-next-prompt
468 (>= (point) eshell-last-output-end
)
469 (capf-autosuggest--accept-and-remapping cmd
)))))
470 (define-key map
[remap comint-next-input
]
471 (list 'menu-item
"" #'comint-send-input
:filter
473 (and capf-autosuggest-dwim-next-input
474 (not (memq last-command
475 '(comint-next-matching-input-from-input
476 comint-previous-matching-input-from-input
477 comint-next-input comint-previous-input
)))
478 (capf-autosuggest--accept-and-remapping cmd
)))))
479 (define-key map
[remap eshell-next-input
]
480 (list 'menu-item
"" #'eshell-send-input
:filter
482 (and capf-autosuggest-dwim-next-input
483 (not (memq last-command
484 '(eshell-next-matching-input-from-input
485 eshell-previous-matching-input-from-input
486 eshell-next-input eshell-previous-input
)))
487 (capf-autosuggest--accept-and-remapping cmd
)))))
488 (define-key map
[remap comint-next-matching-input-from-input
]
489 (list 'menu-item
"" #'comint-send-input
:filter
491 (and capf-autosuggest-dwim-next-matching-input-from-input
492 (not (memq last-command
493 '(comint-next-matching-input-from-input
494 comint-previous-matching-input-from-input
)))
495 (capf-autosuggest--accept-and-remapping cmd
)))))
496 (define-key map
[remap eshell-next-matching-input-from-input
]
497 (list 'menu-item
"" #'eshell-send-input
:filter
499 (and capf-autosuggest-dwim-next-matching-input-from-input
500 (not (memq last-command
501 '(eshell-previous-matching-input-from-input
502 eshell-next-matching-input-from-input
)))
503 (capf-autosuggest--accept-and-remapping cmd
)))))
505 "Keymap active when an auto-suggestion is shown.")
507 (define-minor-mode capf-autosuggest-active-mode
508 "Active when auto-suggested overlay is shown."
509 :group
'capf-autosuggest
510 (unless capf-autosuggest-active-mode
511 (delete-overlay capf-autosuggest--overlay
)))
513 (defun capf-autosuggest-active-mode-deactivate ()
514 "Deactivate `capf-autosuggest-active-mode'."
515 (capf-autosuggest-active-mode -
1))
517 ;;; History completion functions
520 (defun capf-autosuggest-history-capf ()
521 "Completion-at-point function for history.
522 Supports `comint-mode', `eshell-mode' and the minibuffer. In
523 comint end eshell, it is applicable only if point is after the
526 This function is useful for inclusion in
527 `capf-autosuggest-capf-functions'."
529 ((derived-mode-p 'comint-mode
)
530 (capf-autosuggest-comint-capf))
531 ((derived-mode-p 'eshell-mode
)
532 (capf-autosuggest-eshell-capf))
534 (capf-autosuggest-minibuffer-capf))))
536 (defun capf-autosuggest-comint-capf ()
537 "Completion-at-point function for comint input history.
538 Is only applicable if point is after the last prompt."
539 (let ((ring comint-input-ring
)
541 (or (and (setq beg comint-accum-marker
)
542 (setq beg
(marker-position beg
)))
543 (and (setq beg
(get-buffer-process (current-buffer)))
544 (setq beg
(marker-position (process-mark beg
)))))
546 ;; Return nil to allow possible further capf functions
548 ((< (point) beg
) nil
)
549 ((<= (setq end
(if comint-use-prompt-regexp
553 ;; Return non-nil but empty completion table to block possible further
555 (list (point) (point) nil
))
556 ((and (ring-p ring
) (not (ring-empty-p ring
)))
557 (list beg end
(capf-autosuggest--completion-table ring
)
560 (defun capf-autosuggest-eshell-capf ()
561 "Completion-at-point function for eshell input history.
562 Is only applicable if point is after the last prompt."
563 (let ((ring eshell-history-ring
)
564 (beg (save-excursion (eshell-bol) (point)))
567 ((< (point) eshell-last-output-end
) nil
)
568 ((< (point) beg
) nil
)
569 ((and (= end beg
) (eshell-interactive-process))
570 (list (point) (point) nil
))
571 ((and (ring-p ring
) (not (ring-empty-p ring
)))
572 (list beg end
(capf-autosuggest--completion-table ring
)
575 (defun capf-autosuggest--completion-table (ring)
576 "Return a completion table to complete on RING."
580 (lambda (input predicate action
)
584 with only-one
= capf-autosuggest-all-completions-only-one
585 with regexps
= completion-regexp-list
586 for i below
(ring-size ring
)
587 for elem
= (ring-ref ring i
)
588 if
(string-prefix-p input elem
)
589 if
(cl-loop for regex in regexps
590 always
(string-match-p regex elem
))
591 if
(or (null predicate
)
592 (funcall predicate elem
))
597 (complete-with-action
598 nil
(let ((capf-autosuggest-all-completions-only-one nil
))
599 (funcall self input predicate t
))
602 (and (ring-member ring input
)
604 (funcall predicate input
))
605 (cl-loop for regex in completion-regexp-list
606 always
(string-match-p regex input
))))
607 (t (complete-with-action
608 action
(ring-elements ring
) input predicate
)))))))
610 (defun capf-autosuggest-minibuffer-capf ()
611 "Completion-at-point function for minibuffer history."
612 (let ((hist minibuffer-history-variable
)
614 (when (and (not (eq t hist
))
615 (setq hist
(symbol-value hist
)))
616 (when (eq minibuffer-history-sexp-flag
(minibuffer-depth))
617 (setq should-prin1 t
))
618 (list (minibuffer-prompt-end)
621 (lambda (input predicate action
)
623 (setq hist
(mapcar #'prin1-to-string hist
)
625 (complete-with-action action hist input predicate
))
629 (provide 'capf-autosuggest
)
630 ;;; capf-autosuggest.el ends here