diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index 641a2e5315..7c5025b11c 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -753,6 +753,12 @@ minibuffer-message-clear-timeout (integer :tag "Wait for the number of seconds" 2)) :version "27.1") +(defcustom minibuffer-tab-go-completion t + "If a second `TAB' jump to completion buffer." + :type 'boolean + :version "28.1" + :group 'completion) + (defvar minibuffer-message-timer nil) (defvar minibuffer-message-overlay nil) @@ -940,6 +946,8 @@ completion-styles :type completion--styles-type :version "23.1") + + (defvar completion-category-defaults '((buffer (styles . (basic substring))) (unicode-name (styles . (basic substring))) @@ -1288,8 +1296,12 @@ completion--in-region-1 (let ((window minibuffer-scroll-window)) (with-current-buffer (window-buffer window) (if (pos-visible-in-window-p (point-max) window) - ;; If end is in view, scroll up to the beginning. - (set-window-start window (point-min) nil) + (if (and minibuffer-tab-go-completion + (pos-visible-in-window-p (point-min) window)) + ;; If all completions are visible move cursor there + (switch-to-completions) + ;; If end is in view, scroll up to the beginning. + (set-window-start window (point-min) nil)) ;; Else scroll down one screen. (with-selected-window window (scroll-up))) diff --git a/lisp/simple.el b/lisp/simple.el index b45fb87887..c203efe16d 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -8359,6 +8359,12 @@ set-variable ;; Define the major mode for lists of completions. +(defcustom completion-highlight-candidate t + "Non-nil means show help message in *Completions* buffer." + :type 'boolean + :version "28.1" + :group 'completion) + (defvar completion-list-mode-map (let ((map (make-sparse-keymap))) (define-key map [mouse-2] 'choose-completion) @@ -8372,6 +8378,12 @@ completion-list-mode-map (define-key map [backtab] 'previous-completion) (define-key map "q" 'quit-window) (define-key map "z" 'kill-current-buffer) + + (define-key map (kbd "C-g") 'quit-window) + (define-key map (kbd "") 'previous-line-completion) + (define-key map (kbd "C-p") 'previous-line-completion) + (define-key map (kbd "") 'next-line-completion) + (define-key map (kbd "C-n") 'next-line-completion) map) "Local map for completion list buffers.") @@ -8410,6 +8422,19 @@ completion-base-size If nil, Emacs determines which part of the tail end of the buffer's text is involved in completion by comparing the text directly.") + +(defvar completion-overlay nil + "Use a face to highlight completion candidate.") + +(defun move-completion-overlay () + "Update completion overlay to highlight current candidate." + (let* ((obeg (point)) + (oend (next-single-property-change obeg 'mouse-face nil (point-max)))) + (unless (overlayp completion-overlay) + (setq completion-overlay (make-overlay 0 0)) + (overlay-put completion-overlay 'face 'highlight)) + (move-overlay completion-overlay obeg oend))) + (make-obsolete-variable 'completion-base-size 'completion-base-position "23.2") (defun delete-completion-window () @@ -8428,7 +8453,7 @@ previous-completion (interactive "p") (next-completion (- n))) -(defun next-completion (n) +(defun next-completion (n &optional no-move-overlay) "Move to the next item in the completion list. With prefix argument N, move N items (negative N means move backward)." (interactive "p") @@ -8454,7 +8479,25 @@ next-completion ;; Move to the start of that one. (goto-char (previous-single-property-change (point) 'mouse-face nil beg)) - (setq n (1+ n)))))) + (setq n (1+ n))))) + + (when (and completion-highlight-candidate + (not no-move-overlay)) + (move-completion-overlay))) + +(defun next-line-completion (&optional arg try-vscroll) + "Go to completion candidate in line bellow current." + (interactive "^p\np") + (line-move arg t nil try-vscroll) + (next-completion 1 t) + (next-completion -1)) + +(defun previous-line-completion (&optional arg try-vscroll) + "Go to completion candidate in line above current." + (interactive "^p\np") + (line-move (- arg) t nil try-vscroll) + (next-completion -1 t) + (next-completion 1)) (defun choose-completion (&optional event) "Choose the completion at point.