aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoão Távora2021-05-30 16:26:02 +0100
committerJoão Távora2021-06-01 10:40:54 +0100
commit05ab6e53e2cc82edb0b0916c880bdaa269267528 (patch)
treeee170ac1dda968069aa440a3885ef74a0cea6a69
parent062f5aa640db1b8208f9c45dd12fea08e85658d9 (diff)
downloademacs-05ab6e53e2cc82edb0b0916c880bdaa269267528.tar.gz
emacs-05ab6e53e2cc82edb0b0916c880bdaa269267528.zip
Improve icomplete-vertical-mode and fido-vertical-mode
This mode is intended to be used with Icomplete ('M-x icomplete-mode') or Fido ('M-x fido-mode'), to display the list of completions candidates vertically instead of horizontally. When used with Icomplete, completions are rotated and selection kept at the top. When used with Fido, completions scroll like a typical dropdown widget. If the dropdown behaviour is desired for Icomplete (instead of rotation), icomplete-scroll can be adjusted separately by the user. * etc/NEWS (icomplete-vertical-mode): Reword. * lisp/icomplete.el (simple): Require it. (icomplete-selected-match): New face. (icomplete-scroll): New user-visible var. (icomplete-forward-completions): Rework. (icomplete-backward-completions): Rework. (icomplete--fido-mode-setup): Prefer icomplete-scroll according to icomplete-vertical mode. (icomplete-minibuffer-setup): Initialize icomplete--scrolled-completions. (fido-vertical-mode): An alias for icomplete-vertical-mode. (icomplete-exhibit): Init icomplete--scrolled-past. Adjust overlay. (icomplete--render-vertical): New helper. (icomplete--sorted-completions): If cache is stale, also invalidate icomplete--scrolled-past. (icomplete-completions): Rework. Mostly reformat. * lisp/simple.el (max-mini-window-lines): New helper. (display-message-or-buffer): Use it.
-rw-r--r--etc/NEWS10
-rw-r--r--lisp/icomplete.el362
-rw-r--r--lisp/simple.el21
3 files changed, 257 insertions, 136 deletions
diff --git a/etc/NEWS b/etc/NEWS
index fe8789c60b3..914e6890321 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -534,9 +534,13 @@ indentation is done using SMIE or with the old ad-hoc code.
534** Icomplete 534** Icomplete
535 535
536+++ 536+++
537*** New minor mode 'icomplete-vertical-mode'. 537*** New minor mode 'icomplete-vertical-mode', alias 'fido-vertical-mode'
538This mode is intended to be used with Icomplete or Fido, to display the 538This mode is intended to be used with Icomplete ('M-x icomplete-mode')
539list of completions candidates vertically instead of horizontally. 539or Fido ('M-x fido-mode'), to display the list of completions
540candidates vertically instead of horizontally. When used with
541Icomplete, completions are rotated and selection kept at the top.
542When used with Fido, completions scroll like a typical dropdown
543widget.
540 544
541--- 545---
542** Specific warnings can now be disabled from the warning buffer. 546** Specific warnings can now be disabled from the warning buffer.
diff --git a/lisp/icomplete.el b/lisp/icomplete.el
index 91bbb600136..f813a1776e8 100644
--- a/lisp/icomplete.el
+++ b/lisp/icomplete.el
@@ -50,6 +50,8 @@
50;;; Code: 50;;; Code:
51 51
52(require 'rfn-eshadow) ; rfn-eshadow-overlay 52(require 'rfn-eshadow) ; rfn-eshadow-overlay
53(require 'simple) ; max-mini-window-lines
54(require 'cl-lib)
53 55
54(defgroup icomplete nil 56(defgroup icomplete nil
55 "Show completions dynamically in minibuffer." 57 "Show completions dynamically in minibuffer."
@@ -99,6 +101,10 @@ Otherwise this should be a list of the completion tables (e.g.,
99 "Face used by Icomplete for highlighting first match." 101 "Face used by Icomplete for highlighting first match."
100 :version "24.4") 102 :version "24.4")
101 103
104(defface icomplete-selected-match '((t :inherit highlight))
105 "Face used by `icomplete-vertical-mode' for the selected candidate."
106 :version "24.4")
107
102;;;_* User Customization variables 108;;;_* User Customization variables
103(defcustom icomplete-prospects-height 2 109(defcustom icomplete-prospects-height 2
104 ;; We used to compute how many lines 100 characters would take in 110 ;; We used to compute how many lines 100 characters would take in
@@ -215,6 +221,29 @@ the default otherwise."
215 ;; We're not at all interested in cycling here (bug#34077). 221 ;; We're not at all interested in cycling here (bug#34077).
216 (minibuffer-force-complete nil nil 'dont-cycle)) 222 (minibuffer-force-complete nil nil 'dont-cycle))
217 223
224;; Apropos `icomplete-scroll', we implement "scrolling icomplete"
225;; within classic icomplete, which is "rotating", by contrast.
226;;
227;; The two variables supporing this are
228;; `icomplete--scrolled-completions' and `icomplete--scrolled-past'.
229;; They come into play when:
230;;
231;; - The user invokes commands `icomplete-forward-completions' and
232;; `icomplete-backward-completions', thus "manually" scrolling to a
233;; given position;
234;;
235;; - The user re-filters a selection that had already been manually
236;; scrolled. The system attempts to keep the previous selection
237;; stable in the face of the new filtering. This is mostly done in
238;; `icomplete--render-vertical'.
239;;
240(defvar icomplete-scroll nil
241 "If non-nil, scroll candidates list instead of rotating it.")
242(defvar icomplete--scrolled-completions nil
243 "If non-nil, tail of completions list manually scrolled to.")
244(defvar icomplete--scrolled-past nil
245 "If non-nil, reverse tail of completions scrolled past.")
246
218(defun icomplete-forward-completions () 247(defun icomplete-forward-completions ()
219 "Step forward completions by one entry. 248 "Step forward completions by one entry.
220Second entry becomes the first and can be selected with 249Second entry becomes the first and can be selected with
@@ -223,10 +252,14 @@ Second entry becomes the first and can be selected with
223 (let* ((beg (icomplete--field-beg)) 252 (let* ((beg (icomplete--field-beg))
224 (end (icomplete--field-end)) 253 (end (icomplete--field-end))
225 (comps (completion-all-sorted-completions beg end)) 254 (comps (completion-all-sorted-completions beg end))
226 (last (last comps))) 255 (last (last comps)))
227 (when comps 256 (when (consp (cdr comps))
228 (setcdr last (cons (car comps) (cdr last))) 257 (cond (icomplete-scroll
229 (completion--cache-all-sorted-completions beg end (cdr comps))))) 258 (push (pop comps) icomplete--scrolled-past)
259 (setq icomplete--scrolled-completions comps))
260 (t
261 (setcdr (last comps) (cons (pop comps) (cdr last)))))
262 (completion--cache-all-sorted-completions beg end comps))))
230 263
231(defun icomplete-backward-completions () 264(defun icomplete-backward-completions ()
232 "Step backward completions by one entry. 265 "Step backward completions by one entry.
@@ -236,12 +269,16 @@ Last entry becomes the first and can be selected with
236 (let* ((beg (icomplete--field-beg)) 269 (let* ((beg (icomplete--field-beg))
237 (end (icomplete--field-end)) 270 (end (icomplete--field-end))
238 (comps (completion-all-sorted-completions beg end)) 271 (comps (completion-all-sorted-completions beg end))
239 (last-but-one (last comps 2)) 272 last-but-one)
240 (last (cdr last-but-one))) 273 (cond ((and icomplete-scroll icomplete--scrolled-past)
241 (when (consp last) ; At least two elements in comps 274 (push (pop icomplete--scrolled-past) comps)
242 (setcdr last-but-one (cdr last)) 275 (setq icomplete--scrolled-completions comps))
243 (push (car last) comps) 276 ((and (not icomplete-scroll)
244 (completion--cache-all-sorted-completions beg end comps)))) 277 (consp (cdr (setq last-but-one (last comps 2)))))
278 ;; At least two elements in comps
279 (push (car (cdr last-but-one)) comps)
280 (setcdr last-but-one (cdr (cdr last-but-one)))))
281 (completion--cache-all-sorted-completions beg end comps)))
245 282
246;;; Helpers for `fido-mode' (or `ido-mode' emulation) 283;;; Helpers for `fido-mode' (or `ido-mode' emulation)
247;;; 284;;;
@@ -351,6 +388,7 @@ if that doesn't produce a completion match."
351 (setq-local icomplete-tidy-shadowed-file-names t 388 (setq-local icomplete-tidy-shadowed-file-names t
352 icomplete-show-matches-on-no-input t 389 icomplete-show-matches-on-no-input t
353 icomplete-hide-common-prefix nil 390 icomplete-hide-common-prefix nil
391 icomplete-scroll (not (null icomplete-vertical-mode))
354 completion-styles '(flex) 392 completion-styles '(flex)
355 completion-flex-nospace nil 393 completion-flex-nospace nil
356 completion-category-defaults nil 394 completion-category-defaults nil
@@ -449,6 +487,7 @@ Usually run by inclusion in `minibuffer-setup-hook'."
449 (when (and icomplete-mode (icomplete-simple-completing-p)) 487 (when (and icomplete-mode (icomplete-simple-completing-p))
450 (setq-local icomplete--initial-input (icomplete--field-string)) 488 (setq-local icomplete--initial-input (icomplete--field-string))
451 (setq-local completion-show-inline-help nil) 489 (setq-local completion-show-inline-help nil)
490 (setq icomplete--scrolled-completions nil)
452 (use-local-map (make-composed-keymap icomplete-minibuffer-map 491 (use-local-map (make-composed-keymap icomplete-minibuffer-map
453 (current-local-map))) 492 (current-local-map)))
454 (add-hook 'pre-command-hook #'icomplete-pre-command-hook nil t) 493 (add-hook 'pre-command-hook #'icomplete-pre-command-hook nil t)
@@ -483,6 +522,7 @@ Usually run by inclusion in `minibuffer-setup-hook'."
483(defun icomplete--sorted-completions () 522(defun icomplete--sorted-completions ()
484 (or completion-all-sorted-completions 523 (or completion-all-sorted-completions
485 (cl-loop 524 (cl-loop
525 initially (setq icomplete--scrolled-past nil) ; Invalidate scrolled state
486 with beg = (icomplete--field-beg) 526 with beg = (icomplete--field-beg)
487 with end = (icomplete--field-end) 527 with end = (icomplete--field-end)
488 with all = (completion-all-sorted-completions beg end) 528 with all = (completion-all-sorted-completions beg end)
@@ -593,6 +633,8 @@ resized depends on `resize-mini-windows'."
593 (add-hook 'icomplete-minibuffer-setup-hook 633 (add-hook 'icomplete-minibuffer-setup-hook
594 #'icomplete--vertical-minibuffer-setup))) 634 #'icomplete--vertical-minibuffer-setup)))
595 635
636(defalias 'fido-vertical-mode 'icomplete-vertical-mode)
637
596 638
597 639
598 640
@@ -659,13 +701,85 @@ See `icomplete-mode' and `minibuffer-setup-hook'."
659 deactivate-mark) 701 deactivate-mark)
660 ;; Do nothing if while-no-input was aborted. 702 ;; Do nothing if while-no-input was aborted.
661 (when (stringp text) 703 (when (stringp text)
662 (move-overlay icomplete-overlay (point) (point) (current-buffer)) 704 (move-overlay icomplete-overlay (point-min) (point) (current-buffer))
663 ;; The current C cursor code doesn't know to use the overlay's 705 ;; The current C cursor code doesn't know to use the overlay's
664 ;; marker's stickiness to figure out whether to place the cursor 706 ;; marker's stickiness to figure out whether to place the cursor
665 ;; before or after the string, so let's spoon-feed it the pos. 707 ;; before or after the string, so let's spoon-feed it the pos.
666 (put-text-property 0 1 'cursor t text) 708 (put-text-property 0 1 'cursor t text)
709 (overlay-put
710 icomplete-overlay 'before-string
711 (and icomplete-scroll
712 (let ((past (length icomplete--scrolled-past)))
713 (format
714 "%s/%s "
715 (1+ past)
716 (+ past
717 (safe-length completion-all-sorted-completions))))))
667 (overlay-put icomplete-overlay 'after-string text)))))))) 718 (overlay-put icomplete-overlay 'after-string text))))))))
668 719
720(cl-defun icomplete--render-vertical (comps &aux scroll-above scroll-below)
721 ;; Welcome to loopapalooza!
722 ;;
723 ;; First, be mindful of `icomplete-scroll' and manual scrolls. If
724 ;; `icomplete--scrolled-completions' and `icomplete--scrolled-past'
725 ;; are:
726 ;;
727 ;; - both nil, there is no manual scroll;
728 ;; - both non-nil, there is a healthy manual scroll the doesn't need
729 ;; to be readjusted (user just moved around the minibuffer, for
730 ;; example)l
731 ;; - non-nil and nil, respectively, a refiltering took place and we
732 ;; need attempt to readjust them to the new filtered `comps'.
733 (when (and icomplete-scroll
734 icomplete--scrolled-completions
735 (null icomplete--scrolled-past))
736 (cl-loop with preds
737 for (comp . rest) on comps
738 when (equal comp (car icomplete--scrolled-completions))
739 do
740 (setq icomplete--scrolled-past preds
741 comps (cons comp rest))
742 (completion--cache-all-sorted-completions
743 (icomplete--field-beg)
744 (icomplete--field-end)
745 comps)
746 and return nil
747 do (push comp preds)
748 finally (setq icomplete--scrolled-completions nil)))
749 ;; Then, in this pretty ugly loop, collect completions to display
750 ;; above and below the selected one, considering scrolling
751 ;; positions.
752 (cl-loop with preds = icomplete--scrolled-past
753 with succs = (cdr comps)
754 with max-lines = (1- (min
755 icomplete-prospects-height
756 (truncate (max-mini-window-lines) 1)))
757 with max-above = (- max-lines
758 1
759 (cl-loop for (_ . r) on comps
760 repeat (truncate max-lines 2)
761 while (listp r)
762 count 1))
763 repeat max-lines
764 for neighbour = nil
765 if (and preds (> max-above 0)) do
766 (push (setq neighbour (pop preds)) scroll-above)
767 (cl-decf max-above)
768 else if (consp succs) collect
769 (setq neighbour (pop succs)) into scroll-below-aux
770 while neighbour
771 finally (setq scroll-below scroll-below-aux))
772 ;; Now figure out spacing and layout
773 ;;
774 (let ((selected (substring (car comps))))
775 (add-face-text-property 0 (length selected)
776 'icomplete-selected-match 'append selected)
777 (concat " " icomplete-separator
778 (mapconcat
779 #'identity
780 (nconc scroll-above (list selected) scroll-below)
781 icomplete-separator))))
782
669;;;_ > icomplete-completions (name candidates predicate require-match) 783;;;_ > icomplete-completions (name candidates predicate require-match)
670(defun icomplete-completions (name candidates predicate require-match) 784(defun icomplete-completions (name candidates predicate require-match)
671 "Identify prospective candidates for minibuffer completion. 785 "Identify prospective candidates for minibuffer completion.
@@ -703,126 +817,126 @@ matches exist."
703 predicate)) 817 predicate))
704 (md (completion--field-metadata (icomplete--field-beg))) 818 (md (completion--field-metadata (icomplete--field-beg)))
705 (comps (icomplete--sorted-completions)) 819 (comps (icomplete--sorted-completions))
706 (last (if (consp comps) (last comps)))
707 (base-size (cdr last))
708 (open-bracket (if require-match "(" "[")) 820 (open-bracket (if require-match "(" "["))
709 (close-bracket (if require-match ")" "]"))) 821 (close-bracket (if require-match ")" "]")))
710 ;; `concat'/`mapconcat' is the slow part. 822 ;; `concat'/`mapconcat' is the slow part.
711 (if (not (consp comps)) 823 (if (not (consp comps))
712 (progn ;;(debug (format "Candidates=%S field=%S" candidates name)) 824 (progn ;;(debug (format "Candidates=%S field=%S" candidates name))
713 (format " %sNo matches%s" open-bracket close-bracket)) 825 (format " %sNo matches%s" open-bracket close-bracket))
714 (if last (setcdr last nil)) 826 (if icomplete-vertical-mode
715 (let* ((most-try 827 (icomplete--render-vertical comps)
716 (if (and base-size (> base-size 0)) 828 (let* ((last (if (consp comps) (last comps)))
829 ;; Save the "base size" encoded in `comps' then
830 ;; removing making `comps' a proper list.
831 (base-size (prog1 (cdr last)
832 (if last (setcdr last nil))))
833 (most-try
834 (if (and base-size (> base-size 0))
835 (completion-try-completion
836 name candidates predicate (length name) md)
837 ;; If the `comps' are 0-based, the result should be
838 ;; the same with `comps'.
717 (completion-try-completion 839 (completion-try-completion
718 name candidates predicate (length name) md) 840 name comps nil (length name) md)))
719 ;; If the `comps' are 0-based, the result should be 841 (most (if (consp most-try) (car most-try)
720 ;; the same with `comps'. 842 (if most-try (car comps) "")))
721 (completion-try-completion 843 ;; Compare name and most, so we can determine if name is
722 name comps nil (length name) md))) 844 ;; a prefix of most, or something else.
723 (most (if (consp most-try) (car most-try) 845 (compare (compare-strings name nil nil
724 (if most-try (car comps) ""))) 846 most nil nil completion-ignore-case))
725 ;; Compare name and most, so we can determine if name is 847 (ellipsis (if (char-displayable-p ?…) "…" "..."))
726 ;; a prefix of most, or something else. 848 (determ (unless (or (eq t compare) (eq t most-try)
727 (compare (compare-strings name nil nil 849 (= (setq compare (1- (abs compare)))
728 most nil nil completion-ignore-case)) 850 (length most)))
729 (ellipsis (if (char-displayable-p ?…) "…" "...")) 851 (concat open-bracket
730 (determ (unless (or (eq t compare) (eq t most-try) 852 (cond
731 (= (setq compare (1- (abs compare))) 853 ((= compare (length name))
732 (length most))) 854 ;; Typical case: name is a prefix.
733 (concat open-bracket 855 (substring most compare))
734 (cond 856 ;; Don't bother truncating if it doesn't gain
735 ((= compare (length name)) 857 ;; us at least 2 columns.
736 ;; Typical case: name is a prefix. 858 ((< compare (+ 2 (string-width ellipsis))) most)
737 (substring most compare)) 859 (t (concat ellipsis (substring most compare))))
738 ;; Don't bother truncating if it doesn't gain 860 close-bracket)))
739 ;; us at least 2 columns. 861 ;;"-prospects" - more than one candidate
740 ((< compare (+ 2 (string-width ellipsis))) most) 862 (prospects-len (+ (string-width
741 (t (concat ellipsis (substring most compare)))) 863 (or determ (concat open-bracket close-bracket)))
742 close-bracket))) 864 (string-width icomplete-separator)
743 ;;"-prospects" - more than one candidate 865 (+ 2 (string-width ellipsis)) ;; take {…} into account
744 (prospects-len (+ (string-width 866 (string-width (buffer-string))))
745 (or determ (concat open-bracket close-bracket))) 867 (prospects-max
746 (string-width icomplete-separator) 868 ;; Max total length to use, including the minibuffer content.
747 (+ 2 (string-width ellipsis)) ;; take {…} into account 869 (* (+ icomplete-prospects-height
748 (string-width (buffer-string)))) 870 ;; If the minibuffer content already uses up more than
749 (prospects-max 871 ;; one line, increase the allowable space accordingly.
750 ;; Max total length to use, including the minibuffer content. 872 (/ prospects-len (window-width)))
751 (* (+ icomplete-prospects-height 873 (window-width)))
752 ;; If the minibuffer content already uses up more than 874 ;; Find the common prefix among `comps'.
753 ;; one line, increase the allowable space accordingly. 875 ;; We can't use the optimization below because its assumptions
754 (/ prospects-len (window-width))) 876 ;; aren't always true, e.g. when completion-cycling (bug#10850):
755 (window-width))) 877 ;; (if (eq t (compare-strings (car comps) nil (length most)
756 ;; Find the common prefix among `comps'. 878 ;; most nil nil completion-ignore-case))
757 ;; We can't use the optimization below because its assumptions 879 ;; ;; Common case.
758 ;; aren't always true, e.g. when completion-cycling (bug#10850): 880 ;; (length most)
759 ;; (if (eq t (compare-strings (car comps) nil (length most) 881 ;; Else, use try-completion.
760 ;; most nil nil completion-ignore-case)) 882 (prefix (when icomplete-hide-common-prefix
761 ;; ;; Common case. 883 (try-completion "" comps)))
762 ;; (length most) 884 (prefix-len
763 ;; Else, use try-completion. 885 (and (stringp prefix)
764 (prefix (when icomplete-hide-common-prefix 886 ;; Only hide the prefix if the corresponding info
765 (try-completion "" comps))) 887 ;; is already displayed via `most'.
766 (prefix-len 888 (string-prefix-p prefix most t)
767 (and (stringp prefix) 889 (length prefix))) ;;)
768 ;; Only hide the prefix if the corresponding info 890 prospects comp limit)
769 ;; is already displayed via `most'. 891 (prog1
770 (string-prefix-p prefix most t) 892 (if (or (eq most-try t) (and (not icomplete-scroll)
771 (length prefix))) ;;) 893 (not (consp (cdr comps)))))
772 prospects comp limit) 894 (concat determ " [Matched]")
773 (if (or (eq most-try t) (not (consp (cdr comps)))) 895 (when (member name comps)
774 (setq prospects nil) 896 ;; NAME is complete but not unique. This scenario poses
775 (when (member name comps) 897 ;; following UI issues:
776 ;; NAME is complete but not unique. This scenario poses 898 ;;
777 ;; following UI issues: 899 ;; - When `icomplete-hide-common-prefix' is non-nil, NAME
778 ;; 900 ;; is stripped empty. This would make the entry
779 ;; - When `icomplete-hide-common-prefix' is non-nil, NAME 901 ;; inconspicuous.
780 ;; is stripped empty. This would make the entry 902 ;;
781 ;; inconspicuous. 903 ;; - Due to sorting of completions, NAME may not be the
782 ;; 904 ;; first of the prospects and could be hidden deep in
783 ;; - Due to sorting of completions, NAME may not be the 905 ;; the displayed string.
784 ;; first of the prospects and could be hidden deep in 906 ;;
785 ;; the displayed string. 907 ;; - Because of `icomplete-prospects-height' , NAME may
786 ;; 908 ;; not even be displayed to the user.
787 ;; - Because of `icomplete-prospects-height' , NAME may 909 ;;
788 ;; not even be displayed to the user. 910 ;; To circumvent all the above problems, provide a visual
789 ;; 911 ;; cue to the user via an "empty string" in the try
790 ;; To circumvent all the above problems, provide a visual 912 ;; completion field.
791 ;; cue to the user via an "empty string" in the try 913 (setq determ (concat open-bracket "" close-bracket)))
792 ;; completion field. 914 (while (and comps (not limit))
793 (setq determ (concat open-bracket "" close-bracket))) 915 (setq comp
794 ;; Compute prospects for display. 916 (if prefix-len (substring (car comps) prefix-len) (car comps))
795 (while (and comps (not limit)) 917 comps (cdr comps))
796 (setq comp 918 (setq prospects-len
797 (if prefix-len (substring (car comps) prefix-len) (car comps)) 919 (+ (string-width comp)
798 comps (cdr comps)) 920 (string-width icomplete-separator)
799 (setq prospects-len 921 prospects-len))
800 (+ (string-width comp) 922 (if (< prospects-len prospects-max)
801 (string-width icomplete-separator) 923 (push comp prospects)
802 prospects-len)) 924 (setq limit t)))
803 (if (< prospects-len prospects-max) 925 (setq prospects (nreverse prospects))
804 (push comp prospects) 926 ;; Decorate first of the prospects.
805 (setq limit t)))) 927 (when prospects
806 (setq prospects (nreverse prospects)) 928 (let ((first (copy-sequence (pop prospects))))
807 ;; Decorate first of the prospects. 929 (put-text-property 0 (length first)
808 (when prospects 930 'face 'icomplete-first-match first)
809 (let ((first (copy-sequence (pop prospects)))) 931 (push first prospects)))
810 (put-text-property 0 (length first) 932 (concat determ
811 'face 'icomplete-first-match first) 933 "{"
812 (push first prospects))) 934 (mapconcat 'identity prospects icomplete-separator)
813 ;; Restore the base-size info, since completion-all-sorted-completions 935 (concat (and limit (concat icomplete-separator ellipsis))
814 ;; is cached. 936 "}")))
815 (if last (setcdr last base-size)) 937 ;; Restore the base-size info, since completion-all-sorted-completions
816 (if prospects 938 ;; is cached.
817 (concat determ 939 (if last (setcdr last base-size))))))))
818 (if icomplete-vertical-mode " \n" "{")
819 (mapconcat 'identity prospects (if icomplete-vertical-mode
820 "\n"
821 icomplete-separator))
822 (unless icomplete-vertical-mode
823 (concat (and limit (concat icomplete-separator ellipsis))
824 "}")))
825 (concat determ " [Matched]"))))))
826 940
827;;; Iswitchb compatibility 941;;; Iswitchb compatibility
828 942
diff --git a/lisp/simple.el b/lisp/simple.el
index cdd77f74c3e..6d216f74d91 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -4217,12 +4217,22 @@ impose the use of a shell (with its need to quote arguments)."
4217 (shell-command-on-region (point) (point) command 4217 (shell-command-on-region (point) (point) command
4218 output-buffer nil error-buffer))))))) 4218 output-buffer nil error-buffer)))))))
4219 4219
4220(defun max-mini-window-lines (&optional frame)
4221 "Compute maximum number of lines for echo area in FRAME.
4222As defined by `max-mini-window-height'. FRAME defaults to the
4223selected frame. Result may be a floating-point number,
4224i.e. include a fractional number of lines."
4225 (cond ((floatp max-mini-window-height) (* (frame-height frame)
4226 max-mini-window-height))
4227 ((integerp max-mini-window-height) max-mini-window-height)
4228 (t 1)))
4229
4220(defun display-message-or-buffer (message &optional buffer-name action frame) 4230(defun display-message-or-buffer (message &optional buffer-name action frame)
4221 "Display MESSAGE in the echo area if possible, otherwise in a pop-up buffer. 4231 "Display MESSAGE in the echo area if possible, otherwise in a pop-up buffer.
4222MESSAGE may be either a string or a buffer. 4232MESSAGE may be either a string or a buffer.
4223 4233
4224A pop-up buffer is displayed using `display-buffer' if MESSAGE is too long 4234A pop-up buffer is displayed using `display-buffer' if MESSAGE is too long
4225for maximum height of the echo area, as defined by `max-mini-window-height' 4235for maximum height of the echo area, as defined by `max-mini-window-lines'
4226if `resize-mini-windows' is non-nil. 4236if `resize-mini-windows' is non-nil.
4227 4237
4228Returns either the string shown in the echo area, or when a pop-up 4238Returns either the string shown in the echo area, or when a pop-up
@@ -4261,14 +4271,7 @@ and are used only if a pop-up buffer is displayed."
4261 (cond ((= lines 0)) 4271 (cond ((= lines 0))
4262 ((and (or (<= lines 1) 4272 ((and (or (<= lines 1)
4263 (<= lines 4273 (<= lines
4264 (if resize-mini-windows 4274 (if resize-mini-windows (max-mini-window-lines)
4265 (cond ((floatp max-mini-window-height)
4266 (* (frame-height)
4267 max-mini-window-height))
4268 ((integerp max-mini-window-height)
4269 max-mini-window-height)
4270 (t
4271 1))
4272 1))) 4275 1)))
4273 ;; Don't use the echo area if the output buffer is 4276 ;; Don't use the echo area if the output buffer is
4274 ;; already displayed in the selected frame. 4277 ;; already displayed in the selected frame.