(let ((map minibuffer-local-map))
(define-key map "\C-g" 'abort-minibuffers)
(define-key map "\M-<" 'minibuffer-beginning-of-buffer)
-
+ (define-key map "\C-x\M-k" 'minibuffer-kill-from-history)
+ (define-key map "\C-x\M-h" 'minibuffer-alternate-history)
;; Put RET last so that it is shown in doc strings in preference to
;; C-j, when using the \\[exit-minibuffer] notation.
(define-key map "\n" 'exit-minibuffer)
"C-x C->" #'minibuffer-last-completion
"C-x n" 'minibuffer-narrow-completions-map
"C-x /" #'minibuffer-set-completion-styles
+ "C-x j" #'minibuffer-set-completion-action
"C-x ~" #'minibuffer-toggle-exceptional-candidates
"C-x C-a" #'minibuffer-toggle-completions-annotations
+ "C-x C-." #'minibuffer-hint-mode
"C-j" #'minibuffer-apply
"C-p" #'minibuffer-previous-line-or-completion
"C-n" #'minibuffer-next-line-or-completion
(with-current-buffer buf
(save-excursion
(goto-char (point-min))
- (when-let ((pm (text-property-search-forward
- 'completion--string input t)))
+ (when-let ((pm (or (and
+ (get-text-property 0 'completion-identity input)
+ (text-property-search-forward
+ 'completion-identity
+ (get-text-property 0 'completion-identity input)
+ #'eq))
+ (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))
(setq done t)
(message "Done"))))))
+(defvar minibuffer-action-history nil
+ "History list for `minibuffer-set-completion-action'.")
+
+(defun minibuffer-set-completion-action (action-fn)
+ "Set minibuffer completion action of current minibuffer to ACTION-FN."
+ (interactive
+ (let ((enable-recursive-minibuffers t))
+ (list (completing-read "Action function: " obarray #'fboundp
+ nil nil 'minibuffer-action-history)))
+ minibuffer-mode)
+ (when (stringp action-fn) (setq action-fn (read action-fn)))
+ (setq-local minibuffer-completion-action
+ (cons action-fn
+ (or (and (symbolp action-fn)
+ (cdr (minibuffer--get-action action-fn)))
+ "custom action"))))
+
;;; Old-style completion, used in Emacs-21 and Emacs-22.
(defun completion-emacs21-try-completion (string table pred _point)
the minibuffer with the candidate that the hint shows, use \
\\<minibuffer-local-completion-map>\\[minibuffer-force-complete-and-exit].
If there are no matching completion candidates, the hint tells you so."
- :interactive nil
+ :interactive (minibuffer-mode)
(if minibuffer-hint-mode
(if (not minibuffer-completion-table)
(setq minibuffer-hint-mode nil)
;; (put-text-property (point-min) (point) prop val)))
;; (goto-char (- (point-max) tniop))))
+(defvar read-history-variable-history nil
+ "History list for `read-history-variable-history'.")
+
+(defun read-history-variable (prompt)
+ "Prompt with PROMPT for a history variable and return its name as a string."
+ (completing-read prompt obarray
+ (lambda (s)
+ (and (boundp s)
+ (consp (symbol-value s))
+ (stringp (car (symbol-value s)))
+ (string-match "-\\(history\\|ring\\)\\'"
+ (symbol-name s))))
+ t nil 'read-history-variable-history))
+
+(defun minibuffer-alternate-history (hist-var)
+ "Set history variable of current minibuffer to HIST-VAR."
+ (interactive (let ((enable-recursive-minibuffers t))
+ (list (read-history-variable "Use history variable: ")))
+ minibuffer-mode)
+ ;; TODO: Make `minibuffer-history-variable' (mini)buffer-local.
+ (setq minibuffer-history-variable (if (stringp hist-var)
+ (intern hist-var)
+ hist-var)))
+
+(defun minibuffer-kill-from-history (input)
+ "Remove INPUT from current minibuffer history."
+ (interactive
+ (if (eq minibuffer-history-variable t)
+ (user-error "No history available")
+ (list
+ (let ((enable-recursive-minibuffers t))
+ (minibuffer-with-setup-hook
+ (lambda ()
+ (setq-local history-add-new-input nil
+ ;; All candidates are previous inputs by
+ ;; definition, so no need to highlight them.
+ completions-highlight-previous-inputs nil))
+ (completing-read
+ "Delete from history: "
+ (completion-table-dynamic
+ (lambda (&rest _)
+ (mapcar
+ (lambda (cand)
+ (if (and (stringp cand) (not (string-empty-p cand)))
+ (propertize cand 'completion-identity cand)
+ cand))
+ (symbol-value minibuffer-history-variable))))
+ nil t nil
+ ;; HACK: Use the history variable of the original minibuffer
+ ;; also in the recursive minibuffer s.t. `minibuffer-apply' in
+ ;; the recursive minibuffer deletes from the original history.
+ minibuffer-history-variable)))))
+ minibuffer-mode)
+ (if (eq minibuffer-history-variable t) (error "No history available")
+ (let* ((hist (cons nil (symbol-value minibuffer-history-variable)))
+ (temp hist)
+ (res nil))
+ ;; First check with `eq' in favor of `minibuffer-apply' on a
+ ;; non-first occurrence of a history entry.
+ (while (and temp (not res))
+ (if (not (eq (get-text-property 0 'completion-identity input)
+ (cadr temp)))
+ (setq temp (cdr temp))
+ ;; It's a match, delete it.
+ (setcdr temp (cddr temp))
+ (setq res t)))
+ ;; If `res' is still nil that means we found nothing when
+ ;; comparing with `eq', so try again with `equal'.
+ (setq temp hist)
+ (while (and temp (not res))
+ (if (not (equal input (cadr temp)))
+ (setq temp (cdr temp))
+ (setcdr temp (cddr temp))
+ (setq res t)))
+ (if res
+ (progn
+ (set minibuffer-history-variable (cdr hist))
+ (message "Deleted \"%s\" from history `%s'"
+ input minibuffer-history-variable))
+ (message "Input \"%s\" not in history `%s'"
+ input minibuffer-history-variable)))))
+
+(put 'minibuffer-kill-from-history 'minibuffer-action "delete")
+
(provide 'minibuffer)
;;; minibuffer.el ends here