From b46af4439952accf8119d471c17f9b6a035692cf Mon Sep 17 00:00:00 2001 From: Eshel Yaron Date: Wed, 21 Feb 2024 17:23:57 +0100 Subject: [PATCH] New command 'minibuffer-apply' * lisp/minibuffer.el (completions-used-input): New face. (minibuffer-completion-action): New variable and function. (minibuffer-completion-command): New variable. (completing-read-default): Set it to 'this-command'. (minibuffer-current-input): New function. (minibuffer-apply): New command. (minibuffer-local-completion-map): Bind it to 'C-j'. (minibuffer-local-must-match-map): Unbind 'C-j'. * lisp/cus-edit.el (customize-toggle-option): Set 'minibuffer-action' property to non-nil. * etc/NEWS: Announce it. --- etc/NEWS | 6 +++++ lisp/cus-edit.el | 2 ++ lisp/minibuffer.el | 60 +++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 65 insertions(+), 3 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index 23aa469a8df..c1bbd466556 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -802,6 +802,12 @@ Bound to '' and '' arrow keys, respectively, they navigate the "*Completions*" buffer vertically by lines, wrapping at the top/bottom when 'completion-auto-wrap' is non-nil. +*** New command 'minibuffer-apply'. +This command, bound to 'C-j' in the minibuffer during completion, acts +on the current input without exiting the minibuffer. The action that +this command performs mirrors what the command that initiated the +minibuffer does. + +++ *** New value 'historical' for user option 'completions-sort'. When 'completions-sort' is set to 'historical', completion candidates diff --git a/lisp/cus-edit.el b/lisp/cus-edit.el index ff634b666ce..200ca387014 100644 --- a/lisp/cus-edit.el +++ b/lisp/cus-edit.el @@ -1285,6 +1285,8 @@ prefix argument, completion candidates include all user options instead." (propertize "ON" 'face 'success) (propertize "OFF" 'face 'error))))) +(put 'customize-toggle-option 'minibuffer-action t) + ;;;###autoload (defalias 'toggle-option #'customize-toggle-option) diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index 4fc95f4e7b4..1de425b3640 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -2600,6 +2600,9 @@ when you select this sort order." (defface completions-previous-input '((t :underline "violet")) "Face for highlighting previous inputs in the *Completions* buffer.") +(defface completions-used-input '((t :inherit link-visited)) + "Face for highlighting used inputs in the *Completions* buffer.") + (defcustom completions-highlight-previous-inputs t "Whether to highlight previously used inputs in the *Completions* buffer." :version "30.1" @@ -3431,13 +3434,13 @@ The completion method is determined by `completion-at-point-functions'." "M-RET" #'minibuffer-choose-completion "C-x C-v" #'minibuffer-sort-completions "C-x n" 'minibuffer-narrow-completions-map - "C-x /" #'minibuffer-set-completion-styles) + "C-x /" #'minibuffer-set-completion-styles + "C-j" #'minibuffer-apply) (defvar-keymap minibuffer-local-must-match-map :doc "Local keymap for minibuffer input with completion, for exact match." :parent minibuffer-local-completion-map - "RET" #'minibuffer-complete-and-exit - "C-j" #'minibuffer-complete-and-exit) + "RET" #'minibuffer-complete-and-exit) (defvar-keymap minibuffer-local-filename-completion-map :doc "This variable is obsolete and no longer used.") @@ -4176,6 +4179,54 @@ possible completions." (define-obsolete-function-alias 'internal-complete-buffer 'completion-buffer-name-table "30.1") +(defvar-local minibuffer-completion-action nil + "Function that `minibuffer-apply' applies to the current input, or nil.") + +(defvar-local minibuffer-completion-command nil + "The command currently reading input from the minibuffer.") + +(defun minibuffer-current-input () + (let* ((beg-end (minibuffer--completion-boundaries)) + (beg (car beg-end)) (end (cdr beg-end)) + (str (buffer-substring beg end)) + (prf (buffer-substring (minibuffer-prompt-end) beg))) + (when-let ((adjust-fn (alist-get 'adjust-base-function + (completion-metadata + (concat prf str) + minibuffer-completion-table + minibuffer-completion-predicate)))) + (setq prf (funcall adjust-fn prf))) + (cons str prf))) + +(defun minibuffer-completion-action () + "Return the completion action function for the current minibuffer." + (or minibuffer-completion-action + (and (symbolp minibuffer-completion-command) + (get minibuffer-completion-command + 'minibuffer-action) + minibuffer-completion-command) + (error "No applicable action"))) + +(defun minibuffer-apply (action input &optional prefix) + "Apply ACTION to current minibuffer INPUT prefixed by PREFIX." + (interactive (let* ((input-prefix (minibuffer-current-input)) + (input (car input-prefix)) + (prefix (cdr input-prefix))) + (list (minibuffer-completion-action) input prefix))) + (funcall action (concat prefix input)) + (when-let ((buf (get-buffer "*Completions*")) + (win (get-buffer-window buf 0))) + (with-current-buffer buf + (save-excursion + (goto-char (point-min)) + (when-let ((pm (text-property-search-forward + 'completion--string input t))) + (goto-char (prop-match-beginning pm)) + (setq pm (text-property-search-forward 'cursor-face)) + (let ((inhibit-read-only t)) + (add-face-text-property (prop-match-beginning pm) (point) + 'completions-used-input))))))) + ;;; Old-style completion, used in Emacs-21 and Emacs-22. (defun completion-emacs21-try-completion (string table pred _point) @@ -5174,6 +5225,9 @@ See `completing-read' for the meaning of the arguments." (result (minibuffer-with-setup-hook (lambda () + (setq-local minibuffer-completion-command + (car (last (cons this-command + (function-alias-p this-command))))) (setq-local minibuffer-completion-table collection) (setq-local minibuffer-completion-predicate predicate) ;; FIXME: Remove/rename this var, see the next one. -- 2.39.5