[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/mct 17abf47 33/70: Make cycling robust for all completi
From: |
ELPA Syncer |
Subject: |
[elpa] externals/mct 17abf47 33/70: Make cycling robust for all completions-format |
Date: |
Thu, 11 Nov 2021 03:57:46 -0500 (EST) |
branch: externals/mct
commit 17abf4729f55422bf586aea08049d9899fc69218
Author: Protesilaos Stavrou <info@protesilaos.com>
Commit: Protesilaos Stavrou <info@protesilaos.com>
Make cycling robust for all completions-format
This should improve the state of affairs with more intuitive motions
when using a 'mct-completions-format' other than 'one-column' (the
default). In particular:
+ When using C-n/C-p in a grid ('mct-next-completion-or-mini' or
'mct-previous-completion-or-mini'), retain the column number so that
the motion is {down,up}ward instead of going to the next/previous
completion. The reason is that the next/previous in a grid does not
necessarily correspond to our spacial intuition.
+ While using C-n/C-p in the Completions' buffer switch to the
minibuffer if point moves past the last/first line. This is to ensure
that we get spacial motions throughout, otherwise the key bindings
would exhibit a different behaviour at those edges of going to the
next/previous completion before switching to the minibuffer.
The defaults should be the same as before, though the code has been made
more modular.
---
mct.el | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 111 insertions(+), 23 deletions(-)
diff --git a/mct.el b/mct.el
index 921959d..5b0d435 100644
--- a/mct.el
+++ b/mct.el
@@ -430,18 +430,59 @@ by `mct-completion-windows-regexp'."
;;;;; Cyclic motions between minibuffer and completions' buffer
+(defun mct--first-completion-point ()
+ "Find the `point' of the first completion."
+ (save-excursion
+ (goto-char (point-min))
+ (next-completion 1)
+ (point)))
+
+(defun mct--last-completion-point ()
+ "Find the `point' of the last completion."
+ (save-excursion
+ (goto-char (point-max))
+ (next-completion -1)
+ (point)))
+
+(defun mct--completions-line-boundary (boundary)
+ "Determine if current line has reached BOUNDARY.
+BOUNDARY is a line position at the top or bottom of the
+Completions' buffer. See `mct--first-completion-point' or
+`mct--last-completion-point'.
+
+This check only applies when `completions-format' is not assigned
+a `one-column' value."
+ (and (= (line-number-at-pos) (line-number-at-pos boundary))
+ (not (eq completions-format 'one-column))))
+
+(defun mct--completions-no-completion-line-p (arg)
+ "Check if ARGth line has a completion candidate."
+ (save-excursion
+ (vertical-motion arg)
+ (get-text-property (point) 'completion--string)))
+
(defun mct--switch-to-completions ()
"Subroutine for switching to the completions' buffer."
(unless (mct--get-completion-window)
(mct--show-completions))
(switch-to-completions))
+(defun mct--restore-old-point-in-grid (line)
+ "Restore old point in window if LINE is on its line."
+ (unless (eq completions-format 'one-column)
+ (let (old-line old-point)
+ (when-let ((window (mct--get-completion-window)))
+ (setq old-point (window-old-point window)
+ old-line (line-number-at-pos old-point))
+ (when (= (line-number-at-pos line) old-line)
+ (goto-char old-point))))))
+
(defun mct-switch-to-completions-top ()
"Switch to the top of the completions' buffer."
(interactive nil mct-mode)
(mct--switch-to-completions)
- (goto-char (point-min))
- (next-completion 1))
+ (goto-char (mct--first-completion-point))
+ (mct--restore-old-point-in-grid (point)))
(defun mct-switch-to-completions-bottom ()
"Switch to the bottom of the completions' buffer."
@@ -449,14 +490,28 @@ by `mct-completion-windows-regexp'."
(mct--switch-to-completions)
(goto-char (point-max))
(next-completion -1)
- (when (eq mct-completions-format 'one-column)
- (goto-char (point-at-bol))
- (recenter
- (- -1
- (min (max 0 scroll-margin)
- (truncate (/ (window-body-height) 4.0))))
- t)))
-
+ (goto-char (point-at-bol))
+ (mct--restore-old-point-in-grid (point))
+ (recenter
+ (- -1
+ (min (max 0 scroll-margin)
+ (truncate (/ (window-body-height) 4.0))))
+ t))
+
+(defun mct--bottom-of-completions-p (arg)
+ "Test if point is at the notional bottom of the Completions.
+ARG is a numeric argument for `next-completion', as described in
+`mct-next-completion-or-mini'."
+ (or (eobp)
+ (mct--completions-line-boundary (mct--last-completion-point))
+ (= (save-excursion (next-completion arg) (point)) (point-max))
+ ;; The empty final line case...
+ (save-excursion
+ (goto-char (point-at-bol))
+ (and (not (bobp))
+ (or (beginning-of-line (1+ arg)) t)
+ (save-match-data
+ (looking-at "[\s\t]*$"))))))
(defun mct-next-completion-or-mini (&optional arg)
"Move to the next completion or switch to the minibuffer.
@@ -464,11 +519,34 @@ This performs a regular motion for optional ARG lines,
but when
point can no longer move in that direction it switches to the
minibuffer."
(interactive "p" mct-mode)
- (if (or (eobp)
- (= (point-max) (save-excursion (next-completion (or arg t))
(point))))
- (mct-focus-minibuffer)
- (next-completion (or arg 1)))
- (setq this-command 'next-line))
+ (cond
+ ((mct--bottom-of-completions-p (or arg 1))
+ (mct-focus-minibuffer))
+ (t
+ (if (not (eq completions-format 'one-column))
+ ;; Retaining the column number ensures that things work
+ ;; intuitively in a grid view.
+ (let ((col (current-column)))
+ ;; The `unless' is meant to skip past lines that do not
+ ;; contain completion candidates, such as those with
+ ;; `completions-group-format'.
+ (unless (mct--completions-no-completion-line-p (or arg 1))
+ (if arg
+ (setq arg (1+ arg))
+ (setq arg 2)))
+ (vertical-motion (or arg 1))
+ (unless (eq col (save-excursion (goto-char (point-at-bol))
(current-column)))
+ (line-move-to-column col)))
+ (next-completion (or arg 1))))
+ (setq this-command 'next-line)))
+
+(defun mct--top-of-completions-p (arg)
+ "Test if point is at the notional top of the Completions.
+ARG is a numeric argument for `previous-completion', as described in
+`mct-previous-completion-or-mini'."
+ (or (bobp)
+ (mct--completions-line-boundary (mct--first-completion-point))
+ (= (save-excursion (previous-completion arg) (point)) (point-min))))
(defun mct-previous-completion-or-mini (&optional arg)
"Move to the next completion or switch to the minibuffer.
@@ -476,14 +554,24 @@ This performs a regular motion for optional ARG lines,
but when
point can no longer move in that direction it switches to the
minibuffer."
(interactive "p" mct-mode)
- (if (or (bobp)
- (save-excursion
- (previous-completion 1)
- (and (get-text-property (point) 'completion--string)
- (= (point) (point-min))))
- (eq (point) (1+ (point-min)))) ; see hack in `mct--clean-completions'
- (mct-focus-minibuffer)
- (previous-completion (if (natnump arg) arg 1))))
+ (cond
+ ((mct--top-of-completions-p (if (natnump arg) arg 1))
+ (mct-focus-minibuffer))
+ ((if (not (eq completions-format 'one-column))
+ ;; Retaining the column number ensures that things work
+ ;; intuitively in a grid view.
+ (let ((col (current-column)))
+ ;; The `unless' is meant to skip past lines that do not
+ ;; contain completion candidates, such as those with
+ ;; `completions-group-format'.
+ (unless (mct--completions-no-completion-line-p (or (- arg) -1))
+ (if arg
+ (setq arg (1+ arg))
+ (setq arg 2)))
+ (vertical-motion (or (- arg) -1))
+ (unless (eq col (save-excursion (goto-char (point-at-bol))
(current-column)))
+ (line-move-to-column col)))
+ (previous-completion (if (natnump arg) arg 1))))))
;;;;; Candidate selection
- [elpa] externals/mct 0d98ba7 30/70: Include mct-display-buffer-action in the manual, (continued)
- [elpa] externals/mct 0d98ba7 30/70: Include mct-display-buffer-action in the manual, ELPA Syncer, 2021/11/11
- [elpa] externals/mct 08f806e 29/70: Do not set completions-detailed, ELPA Syncer, 2021/11/11
- [elpa] externals/mct 25f876c 34/70: Do not use line-based completion in grid views, ELPA Syncer, 2021/11/11
- [elpa] externals/mct 8522a67 38/70: Add mct-choose-completion-no-exit command, ELPA Syncer, 2021/11/11
- [elpa] externals/mct 2e8c44a 40/70: Tweak mct-beginning-of-buffer, ELPA Syncer, 2021/11/11
- [elpa] externals/mct 099e204 42/70: Make mct-choose-completion-dwim never exit, ELPA Syncer, 2021/11/11
- [elpa] externals/mct be15b4b 44/70: Re-order mct-completion-list-mode-map, ELPA Syncer, 2021/11/11
- [elpa] externals/mct 640ce43 24/70: Update code sample in mct-display-buffer-action, ELPA Syncer, 2021/11/11
- [elpa] externals/mct d21edfb 26/70: Make mct--fit-completions-window more robust, ELPA Syncer, 2021/11/11
- [elpa] externals/mct dc3c224 32/70: Update Acknowledgements in the manual, ELPA Syncer, 2021/11/11
- [elpa] externals/mct 17abf47 33/70: Make cycling robust for all completions-format,
ELPA Syncer <=
- [elpa] externals/mct 613252a 27/70: Use internal function to fit Completions' window, ELPA Syncer, 2021/11/11
- [elpa] externals/mct 6db7f29 36/70: Rewrite mct-edit-completion for greater accuracy, ELPA Syncer, 2021/11/11
- [elpa] externals/mct b16f582 37/70: Make completion metadata functions work everywhere, ELPA Syncer, 2021/11/11
- [elpa] externals/mct e7f13ee 43/70: Make TAB in the Completions never exit, ELPA Syncer, 2021/11/11
- [elpa] externals/mct 97d7855 45/70: Use correct internals for commit 099e204, ELPA Syncer, 2021/11/11
- [elpa] externals/mct 532656b 54/70: Merge branch 'crm-separator-heuristic' into 'main', ELPA Syncer, 2021/11/11
- [elpa] externals/mct 78f3e77 57/70: Clear trailing space, ELPA Syncer, 2021/11/11
- [elpa] externals/mct 573a324 60/70: Document numeric arg for cyclic commands, ELPA Syncer, 2021/11/11
- [elpa] externals/mct d333057 59/70: Update keys for group navigation, ELPA Syncer, 2021/11/11
- [elpa] externals/mct 981dba1 68/70: Fix typo, ELPA Syncer, 2021/11/11