From f9f397dafad26e7e38bd5aa9bb226b572df93386 Mon Sep 17 00:00:00 2001 From: Rahul Martim Juliato Date: Wed, 22 Jan 2025 20:46:41 -0300 Subject: [PATCH] feat(icomplete): markers and vertical alignment Add two enhancements to icomplete-mode: - Vertical alignment when using icomplete-vertical-mode with in-buffer completion, so candidates are aligned with the column where the cursor was when completion started. - Customizable markers to icomplete-vertical-mode, providing each candidate a prefix if currently selected and another prefix for the rest of the list. Faces can also be customized. --- lisp/icomplete.el | 89 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 86 insertions(+), 3 deletions(-) diff --git a/lisp/icomplete.el b/lisp/icomplete.el index d1d1d4a9d81..d9b26950d44 100644 --- a/lisp/icomplete.el +++ b/lisp/icomplete.el @@ -115,6 +115,18 @@ icomplete-section "Face used by `icomplete-vertical-mode' for the section title." :version "28.1") +(defface icomplete-vertical-selected-prefix-face + '((t :inherit font-lock-keyword-face :weight bold :foreground "cyan")) + "Face used for the prefix set by `icomplete-vertical-selected-prefix-marker'." + :group 'icomplete + :version "31") + +(defface icomplete-vertical-unselected-prefix-face + '((t :inherit font-lock-keyword-face :weight normal :foreground "gray")) + "Face used for the prefix set by `icomplete-vertical-unselected-prefix-marker'." + :group 'icomplete + :version "31") + ;;;_* User Customization variables (defcustom icomplete-prospects-height 2 ;; We used to compute how many lines 100 characters would take in @@ -166,6 +178,47 @@ icomplete-minibuffer-setup-hook icompletion is occurring." :type 'hook) +(defcustom icomplete-vertical-in-buffer-adjust-list t + "Control whether in-buffer completion should align the cursor position. +If this is t and `icomplete-in-buffer' is t, and `icomplete-vertical-mode' +is activated, the in-buffer vertical completions are shown aligned to the +cursor position when the completion started, not on the first column, as +the default behaviour." + :type 'boolean + :group 'icomplete + :version "31") + +(defcustom icomplete-vertical-render-prefix-marker t + "Control whether a marker is added as a prefix to each candidate. +If this is t and `icomplete-vertical-mode' is activated, a marker, +controlled by `icomplete-vertical-selected-prefix-marker' is shown +as a prefix to the current under selection candidate, while the +remaining of the candidates will receive the marker controlled +by `icomplete-vertical-unselected-prefix-marker'." + :type 'boolean + :group 'icomplete + :version "31") + +(defcustom icomplete-vertical-selected-prefix-marker "ยป " + "Prefix string used to mark the selected completion candidate. +If `icomplete-vertical-render-prefix-marker' is t, the string +setted here is used as a prefix of the currently selected entry in the +list. It can be further customized by the face +`icomplete-vertical-selected-prefix-face'." + :type 'string + :group 'icomplete + :version "31") + +(defcustom icomplete-vertical-unselected-prefix-marker " " + "Prefix string used on the unselected completion candidates. +If `icomplete-vertical-render-prefix-marker' is t, the string +setted here is used as a prefix for all unselected entries in the list. +list. It can be further customized by the face +`icomplete-vertical-unselected-prefix-face'." + :type 'string + :group 'icomplete + :version "31") + ;;;_* Initialization @@ -828,6 +881,32 @@ icomplete--augment else collect (list tr prefix suffix )) annotated))) +(defun icomplete-vertical--adjust-lines-for-column (lines buffer data) + "Adjust the LINES to align with the column in BUFFER based on DATA." + (if icomplete-vertical-in-buffer-adjust-list + (let ((column + (with-current-buffer buffer + (save-excursion + (goto-char (car data)) + (current-column))))) + (dolist (l lines) + (add-text-properties + 0 1 `(display ,(concat (make-string column ?\s) (substring l 0 1))) + l)) + lines) + lines)) + +(defun icomplete-vertical--add-marker-to-selected (comp) + "Add markers to the selected/unselected COMP completions." + (if (and icomplete-vertical-render-prefix-marker + (get-text-property 0 'icomplete-selected comp)) + (concat (propertize icomplete-vertical-selected-prefix-marker + 'face 'icomplete-vertical-selected-prefix-face) + comp) + (concat (propertize icomplete-vertical-unselected-prefix-marker + 'face 'icomplete-vertical-unselected-prefix-face) + comp))) + (cl-defun icomplete--render-vertical (comps md &aux scroll-above scroll-below (total-space ; number of mini-window lines available @@ -843,7 +922,7 @@ icomplete--render-vertical ;; - both nil, there is no manual scroll; ;; - both non-nil, there is a healthy manual scroll that doesn't need ;; to be readjusted (user just moved around the minibuffer, for - ;; example)l + ;; example); ;; - non-nil and nil, respectively, a refiltering took place and we ;; may need to readjust them to the new filtered `comps'. (when (and icomplete-scroll @@ -903,13 +982,14 @@ icomplete--render-vertical when section collect (propertize section 'face 'icomplete-section) into lines-aux and count 1 into nsections-aux + for comp = (icomplete-vertical--add-marker-to-selected comp) when (get-text-property 0 'icomplete-selected comp) do (add-face-text-property 0 (length comp) 'icomplete-selected-match 'append comp) collect (concat prefix - (make-string (- max-prefix-len (length prefix)) ? ) + (make-string (max 0 (- max-prefix-len (length prefix))) ? ) (completion-lazy-hilit comp) - (make-string (- max-comp-len (length comp)) ? ) + (make-string (max 0 (- max-comp-len (length comp))) ? ) suffix) into lines-aux finally (setq lines lines-aux @@ -924,6 +1004,9 @@ icomplete--render-vertical ((> (length scroll-above) (length scroll-below)) nsections) (t (min (ceiling nsections 2) (length scroll-above)))) lines)) + (when icomplete--in-region-buffer + (setq lines (icomplete-vertical--adjust-lines-for-column + lines icomplete--in-region-buffer completion-in-region--data))) ;; At long last, render final string return value. This may still ;; kick out lines at the end. (concat " \n" -- 2.39.5