summaryrefslogtreecommitdiff
path: root/lisp/simple.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/simple.el')
-rw-r--r--lisp/simple.el92
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."