diff options
| author | Philip Kaludercic | 2021-12-09 17:26:14 +0100 |
|---|---|---|
| committer | Philip Kaludercic | 2021-12-21 22:31:18 +0100 |
| commit | 15693c81163e70b5df786e7c034bd236a40794bb (patch) | |
| tree | 9c35db9a52c22db9e82763a8197e3abb29fd2437 | |
| parent | f6967d2f6666d2e8b40f502e5a948c81c3236249 (diff) | |
| download | emacs-15693c81163e70b5df786e7c034bd236a40794bb.tar.gz emacs-15693c81163e70b5df786e7c034bd236a40794bb.zip | |
Allow for next-completion to wrap around the completion buffer
* lisp/simple.el (completion-wrap-movement): Add new option.
(previous-completion): Update docstring.
(next-completion): Respect completion-wrap-movement.
(switch-to-completions): Handle backwards completion by jumping to the
end of the buffer.
* lisp/minibuffer.el: (minibuffer-local-completion-map): Bind
minibuffer-complete to backtab
(completion--in-region-1): Handle backtab to scroll backwards
| -rw-r--r-- | lisp/minibuffer.el | 15 | ||||
| -rw-r--r-- | lisp/simple.el | 92 |
2 files changed, 74 insertions, 33 deletions
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index 28bd1df59ab..112c609a0a1 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el | |||
| @@ -1379,14 +1379,18 @@ scroll the window of possible completions." | |||
| 1379 | ;; and this command is repeated, scroll that window. | 1379 | ;; and this command is repeated, scroll that window. |
| 1380 | ((and (window-live-p minibuffer-scroll-window) | 1380 | ((and (window-live-p minibuffer-scroll-window) |
| 1381 | (eq t (frame-visible-p (window-frame minibuffer-scroll-window)))) | 1381 | (eq t (frame-visible-p (window-frame minibuffer-scroll-window)))) |
| 1382 | (let ((window minibuffer-scroll-window)) | 1382 | (let ((window minibuffer-scroll-window) |
| 1383 | (reverse (equal (this-command-keys) [backtab]))) | ||
| 1383 | (with-current-buffer (window-buffer window) | 1384 | (with-current-buffer (window-buffer window) |
| 1384 | (if (pos-visible-in-window-p (point-max) window) | 1385 | (if (pos-visible-in-window-p (if reverse (point-min) (point-max)) window) |
| 1385 | ;; If end is in view, scroll up to the beginning. | 1386 | ;; If end or beginning is in view, scroll up to the |
| 1386 | (set-window-start window (point-min) nil) | 1387 | ;; beginning or end respectively. |
| 1388 | (if reverse | ||
| 1389 | (set-window-point window (point-max)) | ||
| 1390 | (set-window-start window (point-min) nil)) | ||
| 1387 | ;; Else scroll down one screen. | 1391 | ;; Else scroll down one screen. |
| 1388 | (with-selected-window window | 1392 | (with-selected-window window |
| 1389 | (scroll-up))) | 1393 | (if reverse (scroll-down) (scroll-up)))) |
| 1390 | nil))) | 1394 | nil))) |
| 1391 | ;; If we're cycling, keep on cycling. | 1395 | ;; If we're cycling, keep on cycling. |
| 1392 | ((and completion-cycling completion-all-sorted-completions) | 1396 | ((and completion-cycling completion-all-sorted-completions) |
| @@ -2651,6 +2655,7 @@ The completion method is determined by `completion-at-point-functions'." | |||
| 2651 | (let ((map (make-sparse-keymap))) | 2655 | (let ((map (make-sparse-keymap))) |
| 2652 | (set-keymap-parent map minibuffer-local-map) | 2656 | (set-keymap-parent map minibuffer-local-map) |
| 2653 | (define-key map "\t" 'minibuffer-complete) | 2657 | (define-key map "\t" 'minibuffer-complete) |
| 2658 | (define-key map [backtab] 'minibuffer-complete) | ||
| 2654 | ;; M-TAB is already abused for many other purposes, so we should find | 2659 | ;; M-TAB is already abused for many other purposes, so we should find |
| 2655 | ;; another binding for it. | 2660 | ;; another binding for it. |
| 2656 | ;; (define-key map "\e\t" 'minibuffer-force-complete) | 2661 | ;; (define-key map "\e\t" 'minibuffer-force-complete) |
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." | |||
| 9029 | (if (get-buffer-window buf) | 9029 | (if (get-buffer-window buf) |
| 9030 | (select-window (get-buffer-window buf)))))) | 9030 | (select-window (get-buffer-window buf)))))) |
| 9031 | 9031 | ||
| 9032 | (defcustom completion-wrap-movement t | ||
| 9033 | "Non-nil means to wrap around when selecting completion options. | ||
| 9034 | This affects the commands `next-completion' and | ||
| 9035 | `previous-completion'." | ||
| 9036 | :type 'boolean | ||
| 9037 | :version "29.1" | ||
| 9038 | :group 'completion) | ||
| 9039 | |||
| 9032 | (defun previous-completion (n) | 9040 | (defun previous-completion (n) |
| 9033 | "Move to the previous item in the completion list." | 9041 | "Move to the previous item in the completion list. |
| 9042 | With prefix argument N, move back N items (negative N means move | ||
| 9043 | forward)." | ||
| 9034 | (interactive "p") | 9044 | (interactive "p") |
| 9035 | (next-completion (- n))) | 9045 | (next-completion (- n))) |
| 9036 | 9046 | ||
| 9037 | (defun next-completion (n) | 9047 | (defun next-completion (n) |
| 9038 | "Move to the next item in the completion list. | 9048 | "Move to the next item in the completion list. |
| 9039 | With prefix argument N, move N items (negative N means move backward)." | 9049 | With prefix argument N, move N items (negative N means move |
| 9050 | backward)." | ||
| 9040 | (interactive "p") | 9051 | (interactive "p") |
| 9041 | (let ((beg (point-min)) (end (point-max))) | 9052 | (let ((beg (point-min)) (end (point-max))) |
| 9042 | (while (and (> n 0) (not (eobp))) | 9053 | (catch 'bound |
| 9043 | ;; If in a completion, move to the end of it. | 9054 | (while (> n 0) |
| 9044 | (when (get-text-property (point) 'mouse-face) | 9055 | ;; If in a completion, move to the end of it. |
| 9045 | (goto-char (next-single-property-change (point) 'mouse-face nil end))) | 9056 | (when (get-text-property (point) 'mouse-face) |
| 9046 | ;; Move to start of next one. | 9057 | (goto-char (next-single-property-change (point) 'mouse-face nil end))) |
| 9047 | (unless (get-text-property (point) 'mouse-face) | 9058 | ;; If at the last completion option, wrap or skip to the |
| 9048 | (goto-char (next-single-property-change (point) 'mouse-face nil end))) | 9059 | ;; minibuffer, if requested. |
| 9049 | (setq n (1- n))) | 9060 | (when (and completion-wrap-movement (eobp)) |
| 9050 | (while (and (< n 0) (not (bobp))) | 9061 | (if (and (member (this-command-keys) '("\t" [backtab])) |
| 9051 | (let ((prop (get-text-property (1- (point)) 'mouse-face))) | 9062 | completion-auto-select) |
| 9052 | ;; If in a completion, move to the start of it. | 9063 | (throw 'bound nil) |
| 9053 | (when (and prop (eq prop (get-text-property (point) 'mouse-face))) | 9064 | (goto-char (point-min)))) |
| 9054 | (goto-char (previous-single-property-change | 9065 | ;; Move to start of next one. |
| 9055 | (point) 'mouse-face nil beg))) | 9066 | (unless (get-text-property (point) 'mouse-face) |
| 9056 | ;; Move to end of the previous completion. | 9067 | (goto-char (next-single-property-change (point) 'mouse-face nil end))) |
| 9057 | (unless (or (bobp) (get-text-property (1- (point)) 'mouse-face)) | 9068 | (setq n (1- n))) |
| 9058 | (goto-char (previous-single-property-change | 9069 | (while (< n 0) |
| 9059 | (point) 'mouse-face nil beg))) | 9070 | (let ((prop (get-text-property (1- (point)) 'mouse-face))) |
| 9060 | ;; Move to the start of that one. | 9071 | ;; If in a completion, move to the start of it. |
| 9061 | (goto-char (previous-single-property-change | 9072 | (when (and prop (eq prop (get-text-property (point) 'mouse-face))) |
| 9062 | (point) 'mouse-face nil beg)) | 9073 | (goto-char (previous-single-property-change |
| 9063 | (setq n (1+ n)))))) | 9074 | (point) 'mouse-face nil beg))) |
| 9075 | ;; Move to end of the previous completion. | ||
| 9076 | (unless (or (bobp) (get-text-property (1- (point)) 'mouse-face)) | ||
| 9077 | (goto-char (previous-single-property-change | ||
| 9078 | (point) 'mouse-face nil beg))) | ||
| 9079 | ;; If at the first completion option, wrap or skip to the | ||
| 9080 | ;; minibuffer, if requested. | ||
| 9081 | (when (and completion-wrap-movement (bobp)) | ||
| 9082 | (if (and (member (this-command-keys) '("\t" [backtab])) | ||
| 9083 | completion-auto-select) | ||
| 9084 | (progn | ||
| 9085 | (goto-char (next-single-property-change (point) 'mouse-face nil end)) | ||
| 9086 | (throw 'bound nil)) | ||
| 9087 | (goto-char (point-max)))) | ||
| 9088 | ;; Move to the start of that one. | ||
| 9089 | (goto-char (previous-single-property-change | ||
| 9090 | (point) 'mouse-face nil beg)) | ||
| 9091 | (setq n (1+ n))))) | ||
| 9092 | (when (/= 0 n) | ||
| 9093 | (switch-to-minibuffer)))) | ||
| 9064 | 9094 | ||
| 9065 | (defun choose-completion (&optional event) | 9095 | (defun choose-completion (&optional event) |
| 9066 | "Choose the completion at point. | 9096 | "Choose the completion at point. |
| @@ -9285,10 +9315,16 @@ select the completion near point.\n\n"))))) | |||
| 9285 | (get-buffer-window "*Completions*" 0))))) | 9315 | (get-buffer-window "*Completions*" 0))))) |
| 9286 | (when window | 9316 | (when window |
| 9287 | (select-window window) | 9317 | (select-window window) |
| 9288 | ;; In the new buffer, go to the first completion. | 9318 | (cond |
| 9289 | ;; FIXME: Perhaps this should be done in `minibuffer-completion-help'. | 9319 | ((and (memq this-command '(completion-at-point minibuffer-complete)) |
| 9290 | (when (bobp) | 9320 | (equal (this-command-keys) [backtab]) |
| 9291 | (next-completion 1))))) | 9321 | (bobp)) |
| 9322 | (goto-char (point-max)) | ||
| 9323 | (previous-completion 1)) | ||
| 9324 | ;; In the new buffer, go to the first completion. | ||
| 9325 | ;; FIXME: Perhaps this should be done in `minibuffer-completion-help'. | ||
| 9326 | ((bobp) | ||
| 9327 | (next-completion 1)))))) | ||
| 9292 | 9328 | ||
| 9293 | (defun read-expression-switch-to-completions () | 9329 | (defun read-expression-switch-to-completions () |
| 9294 | "Select the completion list window while reading an expression." | 9330 | "Select the completion list window while reading an expression." |