diff options
Diffstat (limited to 'lisp/simple.el')
-rw-r--r-- | lisp/simple.el | 92 |
1 files changed, 64 insertions, 28 deletions
diff --git a/lisp/simple.el b/lisp/simple.el index 62a9f264d67..e2d140af891 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -9029,38 +9029,68 @@ Go to the window from which completion was requested." (if (get-buffer-window buf) (select-window (get-buffer-window buf)))))) +(defcustom completion-wrap-movement t + "Non-nil means to wrap around when selecting completion options. +This affects the commands `next-completion' and +`previous-completion'." + :type 'boolean + :version "29.1" + :group 'completion) + (defun previous-completion (n) - "Move to the previous item in the completion list." + "Move to the previous item in the completion list. +With prefix argument N, move back N items (negative N means move +forward)." (interactive "p") (next-completion (- n))) (defun next-completion (n) "Move to the next item in the completion list. -With prefix argument N, move N items (negative N means move backward)." +With prefix argument N, move N items (negative N means move +backward)." (interactive "p") (let ((beg (point-min)) (end (point-max))) - (while (and (> n 0) (not (eobp))) - ;; If in a completion, move to the end of it. - (when (get-text-property (point) 'mouse-face) - (goto-char (next-single-property-change (point) 'mouse-face nil end))) - ;; Move to start of next one. - (unless (get-text-property (point) 'mouse-face) - (goto-char (next-single-property-change (point) 'mouse-face nil end))) - (setq n (1- n))) - (while (and (< n 0) (not (bobp))) - (let ((prop (get-text-property (1- (point)) 'mouse-face))) - ;; If in a completion, move to the start of it. - (when (and prop (eq prop (get-text-property (point) 'mouse-face))) - (goto-char (previous-single-property-change - (point) 'mouse-face nil beg))) - ;; Move to end of the previous completion. - (unless (or (bobp) (get-text-property (1- (point)) 'mouse-face)) - (goto-char (previous-single-property-change - (point) 'mouse-face nil beg))) - ;; Move to the start of that one. - (goto-char (previous-single-property-change - (point) 'mouse-face nil beg)) - (setq n (1+ n)))))) + (catch 'bound + (while (> n 0) + ;; If in a completion, move to the end of it. + (when (get-text-property (point) 'mouse-face) + (goto-char (next-single-property-change (point) 'mouse-face nil end))) + ;; If at the last completion option, wrap or skip to the + ;; minibuffer, if requested. + (when (and completion-wrap-movement (eobp)) + (if (and (member (this-command-keys) '("\t" [backtab])) + completion-auto-select) + (throw 'bound nil) + (goto-char (point-min)))) + ;; Move to start of next one. + (unless (get-text-property (point) 'mouse-face) + (goto-char (next-single-property-change (point) 'mouse-face nil end))) + (setq n (1- n))) + (while (< n 0) + (let ((prop (get-text-property (1- (point)) 'mouse-face))) + ;; If in a completion, move to the start of it. + (when (and prop (eq prop (get-text-property (point) 'mouse-face))) + (goto-char (previous-single-property-change + (point) 'mouse-face nil beg))) + ;; Move to end of the previous completion. + (unless (or (bobp) (get-text-property (1- (point)) 'mouse-face)) + (goto-char (previous-single-property-change + (point) 'mouse-face nil beg))) + ;; If at the first completion option, wrap or skip to the + ;; minibuffer, if requested. + (when (and completion-wrap-movement (bobp)) + (if (and (member (this-command-keys) '("\t" [backtab])) + completion-auto-select) + (progn + (goto-char (next-single-property-change (point) 'mouse-face nil end)) + (throw 'bound nil)) + (goto-char (point-max)))) + ;; Move to the start of that one. + (goto-char (previous-single-property-change + (point) 'mouse-face nil beg)) + (setq n (1+ n))))) + (when (/= 0 n) + (switch-to-minibuffer)))) (defun choose-completion (&optional event) "Choose the completion at point. @@ -9285,10 +9315,16 @@ select the completion near point.\n\n"))))) (get-buffer-window "*Completions*" 0))))) (when window (select-window window) - ;; In the new buffer, go to the first completion. - ;; FIXME: Perhaps this should be done in `minibuffer-completion-help'. - (when (bobp) - (next-completion 1))))) + (cond + ((and (memq this-command '(completion-at-point minibuffer-complete)) + (equal (this-command-keys) [backtab]) + (bobp)) + (goto-char (point-max)) + (previous-completion 1)) + ;; In the new buffer, go to the first completion. + ;; FIXME: Perhaps this should be done in `minibuffer-completion-help'. + ((bobp) + (next-completion 1)))))) (defun read-expression-switch-to-completions () "Select the completion list window while reading an expression." |