From 66137caf8ab8ef0bdd36204d542297e64bbdade2 Mon Sep 17 00:00:00 2001 From: Brian Leung Date: Tue, 22 Dec 2020 09:37:59 -0800 Subject: [PATCH 1/2] Support C-c C-x within comint and eshell If the eshell history contains > echo a > echo b > echo c then after using consult-history to select 'echo a' and subsequently submitting 'echo a' to the prompt, the user should be able to press C-c C-x to retrieve 'echo b'. This PR performs the necessary reassignments. --- consult.el | 83 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 53 insertions(+), 30 deletions(-) diff --git a/consult.el b/consult.el index d4c3f57b..4902c68d 100644 --- a/consult.el +++ b/consult.el @@ -76,12 +76,21 @@ :type 'function) (defcustom consult-mode-histories - '((eshell-mode . eshell-history-ring) - (comint-mode . comint-input-ring) - (term-mode . term-input-ring)) - "Alist of (mode . history) pairs of mode histories. -The histories can be rings or lists." - :type '(list (cons symbol symbol))) + '((eshell-mode eshell-history-ring eshell-history-index) + (comint-mode comint-input-ring comint-input-ring-index) + (term-mode term-input-ring)) + "Alist of (mode history-ring history-index?) triples of mode histories. +The histories can be rings or lists. + +When the optional history-index variable is a non-nil symbol, +then during a `consult-history' invocation, the value of that +symbol will be set to a zero-based index corresponding to the +candidate selected during that invocation. This is useful to +replay input history within `comint' and `eshell'. + +If the history-index variable in a triple is nil or absent, then +no index reassignment is performed." + :type '(list (list symbol))) (defcustom consult-themes nil "List of themes to be presented for selection. @@ -1203,42 +1212,56 @@ for which the command history is used." ;; Alternatively you might want to use `consult-complex-command', ;; which can also be bound to "C-x M-:"! ((eq last-command 'repeat-complex-command) - (mapcar #'prin1-to-string command-history)) + (cons (mapcar #'prin1-to-string command-history) + nil)) ;; In the minibuffer we use the current minibuffer history, ;; which can be configured by setting `minibuffer-history-variable'. ((minibufferp) - (symbol-value minibuffer-history-variable)) ;; (minibuffer-history-value) is Emacs 27 only + (cons (symbol-value minibuffer-history-variable) ;; (minibuffer-history-value) is Emacs 27 only + nil)) ;; Otherwise we use a mode-specific history, see `consult-mode-histories'. - (t (when-let (history - (or (seq-find (lambda (ring) - (and (derived-mode-p (car ring)) - (boundp (cdr ring)))) - consult-mode-histories) - (user-error - "No history configured for `%s', see `consult-mode-histories'" - major-mode))) - (symbol-value (cdr history)))))) + (t (pcase-let ((`(,history ,index-variable) + (or (cdr-safe (seq-find (pcase-lambda (`(,mode ,hist-ring ,_)) + (and (derived-mode-p mode) + (boundp hist-ring))) + consult-mode-histories)) + (user-error + "No history configured for `%s', see `consult-mode-histories'" + major-mode)))) + (cons (symbol-value history) + index-variable))))) ;; This command has been adopted from https://github.com/oantolin/completing-history/. ;;;###autoload (defun consult-history (&optional history) "Insert string from buffer HISTORY." (interactive) - (let* ((enable-recursive-minibuffers t) - (str (consult--read "History: " - (let ((history (or history (consult--current-history)))) - (or (consult--remove-dups (if (ring-p history) - (ring-elements history) - history)) - (user-error "History is empty"))) - :history t ;; disable history - :category ;; Report command category for M-x history - (and (minibufferp) - (eq minibuffer-history-variable 'extended-command-history) - 'command) - :sort nil))) + (pcase-let* ((enable-recursive-minibuffers t) + (`(,dup-cands . ,maybe-index-variable) (if history + (cons history nil) + (consult--current-history))) + (cands-as-seq (if (ring-p dup-cands) + (ring-elements dup-cands) + dup-cands)) + (cands-with-indices (seq-map-indexed #'cons cands-as-seq)) + (unique-cands-with-indices (consult--remove-dups cands-with-indices #'car)) + (candidate-index + (consult--read "History: " + (or unique-cands-with-indices + (user-error "History is empty")) + :history t ;; disable history + :lookup #'consult--lookup-candidate + :category ;; Report command category for M-x history + (and (minibufferp) + (eq minibuffer-history-variable 'extended-command-history) + 'command) + :sort nil)) + (str (seq-elt cands-as-seq + candidate-index))) (when (minibufferp) (delete-minibuffer-contents)) + (when maybe-index-variable + (setf (symbol-value maybe-index-variable) candidate-index)) (insert (substring-no-properties str)))) (defun consult--minor-mode-candidates () From 5ea1978a3525ee87e7697e1ad695ad469b6f35cd Mon Sep 17 00:00:00 2001 From: Daniel Mendler Date: Tue, 22 Dec 2020 20:39:44 +0100 Subject: [PATCH 2/2] consult-history: some adjustments --- consult.el | 82 ++++++++++++++++++++++++++---------------------------- 1 file changed, 39 insertions(+), 43 deletions(-) diff --git a/consult.el b/consult.el index 4902c68d..40af69a6 100644 --- a/consult.el +++ b/consult.el @@ -82,11 +82,12 @@ "Alist of (mode history-ring history-index?) triples of mode histories. The histories can be rings or lists. -When the optional history-index variable is a non-nil symbol, -then during a `consult-history' invocation, the value of that -symbol will be set to a zero-based index corresponding to the -candidate selected during that invocation. This is useful to -replay input history within `comint' and `eshell'. +When the optional history-index variable is a non-nil symbol, then during a +`consult-history' invocation, the value of that symbol will be set to a +zero-based index corresponding to the candidate selected during that invocation. +This is useful to replay input history via `comint-get-next-from-history' within +`comint', or equivalently for `eshell'. For `term-mode', the index adjustment is +not configured, since there is no equivalent replay keybinding. If the history-index variable in a triple is nil or absent, then no index reassignment is performed." @@ -1212,57 +1213,52 @@ for which the command history is used." ;; Alternatively you might want to use `consult-complex-command', ;; which can also be bound to "C-x M-:"! ((eq last-command 'repeat-complex-command) - (cons (mapcar #'prin1-to-string command-history) - nil)) + (cons (mapcar #'prin1-to-string command-history) nil)) ;; In the minibuffer we use the current minibuffer history, ;; which can be configured by setting `minibuffer-history-variable'. + ;; `minibuffer-history-value' is Emacs 27 only, therefore we use `symbol-value' ((minibufferp) - (cons (symbol-value minibuffer-history-variable) ;; (minibuffer-history-value) is Emacs 27 only - nil)) + (cons (symbol-value minibuffer-history-variable) nil)) ;; Otherwise we use a mode-specific history, see `consult-mode-histories'. - (t (pcase-let ((`(,history ,index-variable) - (or (cdr-safe (seq-find (pcase-lambda (`(,mode ,hist-ring ,_)) - (and (derived-mode-p mode) - (boundp hist-ring))) - consult-mode-histories)) + (t (pcase-let ((`(_ ,h ,i) + (or (seq-find (pcase-lambda (`(,m ,h _)) + (and (derived-mode-p m) (boundp h))) + consult-mode-histories) (user-error "No history configured for `%s', see `consult-mode-histories'" major-mode)))) - (cons (symbol-value history) - index-variable))))) + (cons (symbol-value h) i))))) ;; This command has been adopted from https://github.com/oantolin/completing-history/. ;;;###autoload -(defun consult-history (&optional history) - "Insert string from buffer HISTORY." +(defun consult-history (&optional history index) + "Insert string from buffer HISTORY. +INDEX is an optional history variable." (interactive) - (pcase-let* ((enable-recursive-minibuffers t) - (`(,dup-cands . ,maybe-index-variable) (if history - (cons history nil) - (consult--current-history))) - (cands-as-seq (if (ring-p dup-cands) - (ring-elements dup-cands) - dup-cands)) - (cands-with-indices (seq-map-indexed #'cons cands-as-seq)) - (unique-cands-with-indices (consult--remove-dups cands-with-indices #'car)) - (candidate-index - (consult--read "History: " - (or unique-cands-with-indices - (user-error "History is empty")) - :history t ;; disable history - :lookup #'consult--lookup-candidate - :category ;; Report command category for M-x history - (and (minibufferp) - (eq minibuffer-history-variable 'extended-command-history) - 'command) - :sort nil)) - (str (seq-elt cands-as-seq - candidate-index))) + (unless history + (pcase-let ((`(,h . ,i) (consult--current-history))) + (setq history h index i))) + (let* ((cands-list (if (ring-p history) + (ring-elements history) + history)) + (cands-indexed (consult--remove-dups + (seq-map-indexed #'cons cands-list) + #'car)) + (enable-recursive-minibuffers t) + (selected (consult--read "History: " + (or cands-indexed (user-error "History is empty")) + :history t ;; disable history + :lookup #'consult--lookup-candidate + :category ;; Report command category for M-x history + (and (minibufferp) + (eq minibuffer-history-variable 'extended-command-history) + 'command) + :sort nil))) (when (minibufferp) (delete-minibuffer-contents)) - (when maybe-index-variable - (setf (symbol-value maybe-index-variable) candidate-index)) - (insert (substring-no-properties str)))) + (when index + (setf (symbol-value index) selected)) + (insert (substring-no-properties (nth selected cands-list))))) (defun consult--minor-mode-candidates () "Return list of minor-mode candidate strings."