diff options
| -rw-r--r-- | etc/NEWS | 20 | ||||
| -rw-r--r-- | lisp/icomplete.el | 123 |
2 files changed, 140 insertions, 3 deletions
| @@ -1591,6 +1591,26 @@ width of the 'speedbar-window' when it is closed and then restored. | |||
| 1591 | --- | 1591 | --- |
| 1592 | *** 'speedbar-easymenu-definition-trailer' is now a function. | 1592 | *** 'speedbar-easymenu-definition-trailer' is now a function. |
| 1593 | 1593 | ||
| 1594 | ** Icomplete | ||
| 1595 | |||
| 1596 | *** New user options for 'icomplete-vertical-mode'. | ||
| 1597 | New user options have been added to enhance 'icomplete-vertical-mode': | ||
| 1598 | - 'icomplete-vertical-in-buffer-adjust-list' aligns in-buffer | ||
| 1599 | completion to the original cursor column. | ||
| 1600 | - 'icomplete-vertical-render-prefix-indicator' adds a prefix indicator | ||
| 1601 | to completion candidates. | ||
| 1602 | - 'icomplete-vertical-selected-prefix-indicator' specifies the prefix | ||
| 1603 | string for the selected candidate. | ||
| 1604 | - 'icomplete-vertical-unselected-prefix-indicator' specifies the prefix | ||
| 1605 | string for unselected candidates. | ||
| 1606 | |||
| 1607 | *** New faces for 'icomplete-vertical-mode'. | ||
| 1608 | New faces have been added to 'icomplete-vertical-mode': | ||
| 1609 | - 'icomplete-vertical-selected-prefix-indicator-face' controls the | ||
| 1610 | appearance of the selected candidate prefix. | ||
| 1611 | - 'icomplete-vertical-unselected-prefix-indicator-face' controls the | ||
| 1612 | appearance of unselected candidate prefixes. | ||
| 1613 | |||
| 1594 | ** Miscellaneous | 1614 | ** Miscellaneous |
| 1595 | 1615 | ||
| 1596 | --- | 1616 | --- |
diff --git a/lisp/icomplete.el b/lisp/icomplete.el index c58bffbb36b..d0cc5674ba7 100644 --- a/lisp/icomplete.el +++ b/lisp/icomplete.el | |||
| @@ -115,6 +115,18 @@ Otherwise this should be a list of the completion tables (e.g., | |||
| 115 | "Face used by `icomplete-vertical-mode' for the section title." | 115 | "Face used by `icomplete-vertical-mode' for the section title." |
| 116 | :version "28.1") | 116 | :version "28.1") |
| 117 | 117 | ||
| 118 | (defface icomplete-vertical-selected-prefix-indicator-face | ||
| 119 | '((t :inherit font-lock-keyword-face :weight bold :foreground "slate blue")) | ||
| 120 | "Face used by `icomplete-vertical-selected-prefix-indicator'." | ||
| 121 | :group 'icomplete | ||
| 122 | :version "31.1") | ||
| 123 | |||
| 124 | (defface icomplete-vertical-unselected-prefix-indicator-face | ||
| 125 | '((t :inherit font-lock-keyword-face :weight normal :foreground "gray")) | ||
| 126 | "Face used by `icomplete-vertical-unselected-prefix-indicator'." | ||
| 127 | :group 'icomplete | ||
| 128 | :version "31.1") | ||
| 129 | |||
| 118 | ;;;_* User Customization variables | 130 | ;;;_* User Customization variables |
| 119 | (defcustom icomplete-prospects-height 2 | 131 | (defcustom icomplete-prospects-height 2 |
| 120 | ;; We used to compute how many lines 100 characters would take in | 132 | ;; We used to compute how many lines 100 characters would take in |
| @@ -166,6 +178,50 @@ will constrain Emacs to a maximum minibuffer height of 3 lines when | |||
| 166 | icompletion is occurring." | 178 | icompletion is occurring." |
| 167 | :type 'hook) | 179 | :type 'hook) |
| 168 | 180 | ||
| 181 | (defcustom icomplete-vertical-in-buffer-adjust-list nil | ||
| 182 | "Control whether in-buffer completion should align the cursor position. | ||
| 183 | If this is t and `icomplete-in-buffer' is t, and `icomplete-vertical-mode' | ||
| 184 | is activated, the in-buffer vertical completions are shown aligned to the | ||
| 185 | cursor position when the completion started, not on the first column, as | ||
| 186 | the default behavior." | ||
| 187 | :type 'boolean | ||
| 188 | :group 'icomplete | ||
| 189 | :version "31.1") | ||
| 190 | |||
| 191 | (defcustom icomplete-vertical-render-prefix-indicator nil | ||
| 192 | "Control whether an indicator is added as a prefix to each candidate. | ||
| 193 | If this is t and `icomplete-vertical-mode' is activated, an indicator, | ||
| 194 | controlled by `icomplete-vertical-selected-prefix-indicator' is shown | ||
| 195 | as a prefix to the current under selection candidate, while the | ||
| 196 | remaining of the candidates will receive the indicator controlled | ||
| 197 | by `icomplete-vertical-unselected-prefix-indicator'." | ||
| 198 | :type 'boolean | ||
| 199 | :group 'icomplete | ||
| 200 | :version "31.1") | ||
| 201 | |||
| 202 | (defcustom icomplete-vertical-selected-prefix-indicator | ||
| 203 | (if (char-displayable-p ?») "» " "> ") | ||
| 204 | "Prefix string used to mark the selected completion candidate. | ||
| 205 | If `icomplete-vertical-render-prefix-indicator' is t, this string | ||
| 206 | is used as a prefix of the currently selected entry in the list. | ||
| 207 | It can be further customized by the face | ||
| 208 | `icomplete-vertical-selected-prefix-indicator-face'. | ||
| 209 | |||
| 210 | By default, this is set to \"» \" if the character is displayable, | ||
| 211 | otherwise, it falls back to \"> \"." | ||
| 212 | :type 'string | ||
| 213 | :group 'icomplete | ||
| 214 | :version "31.1") | ||
| 215 | |||
| 216 | (defcustom icomplete-vertical-unselected-prefix-indicator " " | ||
| 217 | "Prefix string used on the unselected completion candidates. | ||
| 218 | If `icomplete-vertical-render-prefix-indicator' is t, the string | ||
| 219 | defined here is used as a prefix for all unselected entries in the list. | ||
| 220 | list. It can be further customized by the face | ||
| 221 | `icomplete-vertical-unselected-prefix-indicator-face'." | ||
| 222 | :type 'string | ||
| 223 | :group 'icomplete | ||
| 224 | :version "31.1") | ||
| 169 | 225 | ||
| 170 | ;;;_* Initialization | 226 | ;;;_* Initialization |
| 171 | 227 | ||
| @@ -828,6 +884,58 @@ by `group-function''s second \"transformation\" protocol." | |||
| 828 | else collect (list tr prefix suffix )) | 884 | else collect (list tr prefix suffix )) |
| 829 | annotated))) | 885 | annotated))) |
| 830 | 886 | ||
| 887 | (defun icomplete-vertical--adjust-lines-for-column (lines buffer data) | ||
| 888 | "Adjust the LINES to align with the column in BUFFER based on DATA." | ||
| 889 | (if icomplete-vertical-in-buffer-adjust-list | ||
| 890 | (let* ((column (current-column)) | ||
| 891 | (prefix-indicator-width | ||
| 892 | (if icomplete-vertical-render-prefix-indicator | ||
| 893 | (max (length icomplete-vertical-selected-prefix-indicator) | ||
| 894 | (length icomplete-vertical-unselected-prefix-indicator)) | ||
| 895 | 0)) | ||
| 896 | (wrapped-line (with-current-buffer buffer | ||
| 897 | (save-excursion | ||
| 898 | (goto-char (car data)) | ||
| 899 | (beginning-of-line) | ||
| 900 | (count-screen-lines (point) (car data))))) | ||
| 901 | (window-width (+ (window-hscroll) (window-body-width))) | ||
| 902 | (longest-line-width (apply #'max (mapcar #'length lines))) | ||
| 903 | (spaces-to-add | ||
| 904 | (if (> wrapped-line 1) | ||
| 905 | (- column (* (- wrapped-line 1) (- window-width 5))) | ||
| 906 | column)) | ||
| 907 | (spaces-to-add-avoiding-scrolling | ||
| 908 | (if (>= (+ spaces-to-add longest-line-width prefix-indicator-width) window-width) | ||
| 909 | (- spaces-to-add longest-line-width) | ||
| 910 | spaces-to-add))) | ||
| 911 | |||
| 912 | (mapcar (lambda (line) | ||
| 913 | (concat (make-string spaces-to-add-avoiding-scrolling ?\s) line)) | ||
| 914 | lines)) | ||
| 915 | lines)) | ||
| 916 | |||
| 917 | (defun icomplete-vertical--ensure-visible-lines-inside-buffer () | ||
| 918 | "Ensure the completion list is visible in regular buffers only. | ||
| 919 | Scrolls the screen to be at least `icomplete-prospects-height' real lines | ||
| 920 | away from the bottom. Counts wrapped lines as real lines." | ||
| 921 | (unless (minibufferp) | ||
| 922 | (let* ((window-height (window-body-height)) | ||
| 923 | (current-line (count-screen-lines (window-start) (point))) | ||
| 924 | (lines-to-bottom (- window-height current-line))) | ||
| 925 | (when (< lines-to-bottom icomplete-prospects-height) | ||
| 926 | (scroll-up (- icomplete-prospects-height lines-to-bottom)))))) | ||
| 927 | |||
| 928 | (defun icomplete-vertical--add-indicator-to-selected (comp) | ||
| 929 | "Add indicators to the selected/unselected COMP completions." | ||
| 930 | (if (and icomplete-vertical-render-prefix-indicator | ||
| 931 | (get-text-property 0 'icomplete-selected comp)) | ||
| 932 | (concat (propertize icomplete-vertical-selected-prefix-indicator | ||
| 933 | 'face 'icomplete-vertical-selected-prefix-indicator-face) | ||
| 934 | comp) | ||
| 935 | (concat (propertize icomplete-vertical-unselected-prefix-indicator | ||
| 936 | 'face 'icomplete-vertical-unselected-prefix-indicator-face) | ||
| 937 | comp))) | ||
| 938 | |||
| 831 | (cl-defun icomplete--render-vertical | 939 | (cl-defun icomplete--render-vertical |
| 832 | (comps md &aux scroll-above scroll-below | 940 | (comps md &aux scroll-above scroll-below |
| 833 | (total-space ; number of mini-window lines available | 941 | (total-space ; number of mini-window lines available |
| @@ -843,12 +951,17 @@ by `group-function''s second \"transformation\" protocol." | |||
| 843 | ;; - both nil, there is no manual scroll; | 951 | ;; - both nil, there is no manual scroll; |
| 844 | ;; - both non-nil, there is a healthy manual scroll that doesn't need | 952 | ;; - both non-nil, there is a healthy manual scroll that doesn't need |
| 845 | ;; to be readjusted (user just moved around the minibuffer, for | 953 | ;; to be readjusted (user just moved around the minibuffer, for |
| 846 | ;; example)l | 954 | ;; example); |
| 847 | ;; - non-nil and nil, respectively, a refiltering took place and we | 955 | ;; - non-nil and nil, respectively, a refiltering took place and we |
| 848 | ;; may need to readjust them to the new filtered `comps'. | 956 | ;; may need to readjust them to the new filtered `comps'. |
| 849 | (when (and icomplete-scroll | 957 | (when (and icomplete-scroll |
| 958 | (not icomplete--scrolled-completions) | ||
| 959 | (not icomplete--scrolled-past)) | ||
| 960 | (icomplete-vertical--ensure-visible-lines-inside-buffer)) | ||
| 961 | (when (and icomplete-scroll | ||
| 850 | icomplete--scrolled-completions | 962 | icomplete--scrolled-completions |
| 851 | (null icomplete--scrolled-past)) | 963 | (null icomplete--scrolled-past)) |
| 964 | (icomplete-vertical--ensure-visible-lines-inside-buffer) | ||
| 852 | (cl-loop with preds | 965 | (cl-loop with preds |
| 853 | for (comp . rest) on comps | 966 | for (comp . rest) on comps |
| 854 | when (equal comp (car icomplete--scrolled-completions)) | 967 | when (equal comp (car icomplete--scrolled-completions)) |
| @@ -900,6 +1013,7 @@ by `group-function''s second \"transformation\" protocol." | |||
| 900 | ;; of lines to render | 1013 | ;; of lines to render |
| 901 | (cl-loop | 1014 | (cl-loop |
| 902 | for (comp prefix suffix section) in tuples | 1015 | for (comp prefix suffix section) in tuples |
| 1016 | do (setq comp (icomplete-vertical--add-indicator-to-selected comp)) | ||
| 903 | when section | 1017 | when section |
| 904 | collect (propertize section 'face 'icomplete-section) into lines-aux | 1018 | collect (propertize section 'face 'icomplete-section) into lines-aux |
| 905 | and count 1 into nsections-aux | 1019 | and count 1 into nsections-aux |
| @@ -907,9 +1021,9 @@ by `group-function''s second \"transformation\" protocol." | |||
| 907 | do (add-face-text-property 0 (length comp) | 1021 | do (add-face-text-property 0 (length comp) |
| 908 | 'icomplete-selected-match 'append comp) | 1022 | 'icomplete-selected-match 'append comp) |
| 909 | collect (concat prefix | 1023 | collect (concat prefix |
| 910 | (make-string (- max-prefix-len (length prefix)) ? ) | 1024 | (make-string (max 0 (- max-prefix-len (length prefix))) ? ) |
| 911 | (completion-lazy-hilit comp) | 1025 | (completion-lazy-hilit comp) |
| 912 | (make-string (- max-comp-len (length comp)) ? ) | 1026 | (make-string (max 0 (- max-comp-len (length comp))) ? ) |
| 913 | suffix) | 1027 | suffix) |
| 914 | into lines-aux | 1028 | into lines-aux |
| 915 | finally (setq lines lines-aux | 1029 | finally (setq lines lines-aux |
| @@ -924,6 +1038,9 @@ by `group-function''s second \"transformation\" protocol." | |||
| 924 | ((> (length scroll-above) (length scroll-below)) nsections) | 1038 | ((> (length scroll-above) (length scroll-below)) nsections) |
| 925 | (t (min (ceiling nsections 2) (length scroll-above)))) | 1039 | (t (min (ceiling nsections 2) (length scroll-above)))) |
| 926 | lines)) | 1040 | lines)) |
| 1041 | (when icomplete--in-region-buffer | ||
| 1042 | (setq lines (icomplete-vertical--adjust-lines-for-column | ||
| 1043 | lines icomplete--in-region-buffer completion-in-region--data))) | ||
| 927 | ;; At long last, render final string return value. This may still | 1044 | ;; At long last, render final string return value. This may still |
| 928 | ;; kick out lines at the end. | 1045 | ;; kick out lines at the end. |
| 929 | (concat " \n" | 1046 | (concat " \n" |