aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJimmy Aguilar Mena2020-09-19 10:10:01 +0200
committerJimmy Aguilar Mena2020-09-25 05:00:46 +0200
commit95e298e03181ad3c96f2969911d90d70048fca0c (patch)
treefd652f7ea0cabafc790fb265ab161fbeea0e661a
parent976b8464fb3d33a83432053d7f907cb763580cea (diff)
downloademacs-feature/icomplete-vertical.tar.gz
emacs-feature/icomplete-vertical.zip
icomplete-vertical simplest approachfeature/icomplete-vertical
* lisp/icomplete.el (icomplete--vertical-prospects) : New functions to assert format and correct number of candidates in vertical format. (icomplete--horizontal-prospects) : New functions to assert format and correct number of candidates in horizontal format. (icomplete-minibuffer-setup-hook) : Conditionally initialize the variables for vertical format. (icomplete-completions) : Simplify to separate some calculations unneeded in vertical format. Moved part of its code to icomplete--horizontal-prospects.
-rw-r--r--lisp/icomplete.el155
1 files changed, 110 insertions, 45 deletions
diff --git a/lisp/icomplete.el b/lisp/icomplete.el
index 4e546807b7f..933faa5a070 100644
--- a/lisp/icomplete.el
+++ b/lisp/icomplete.el
@@ -50,6 +50,7 @@
50;;; Code: 50;;; Code:
51 51
52(require 'rfn-eshadow) ; rfn-eshadow-overlay 52(require 'rfn-eshadow) ; rfn-eshadow-overlay
53(require 'cl-lib)
53 54
54(defgroup icomplete nil 55(defgroup icomplete nil
55 "Show completions dynamically in minibuffer." 56 "Show completions dynamically in minibuffer."
@@ -139,6 +140,19 @@ icompletion is occurring."
139 :group 'icomplete) 140 :group 'icomplete)
140 141
141 142
143(defvar-local icomplete--ellipsis nil
144 "Ellipsis symbol to indicate continuation.")
145
146(defvar-local icomplete--list-indicators-format nil
147 "Indicator for when multiple prospects are available.
148means that further input is required to distinguish a single one")
149
150(defvar-local icomplete--prospects nil)
151(defvar-local icomplete--match-braket nil)
152(defvar-local icomplete--prospects-max-height nil)
153(defvar-local icomplete--lines-per-candidate 0)
154
155
142;;;_* Initialization 156;;;_* Initialization
143 157
144;;;_ + Internal Variables 158;;;_ + Internal Variables
@@ -437,6 +451,62 @@ Conditions are:
437 (member table icomplete-with-completion-tables)))))) 451 (member table icomplete-with-completion-tables))))))
438 452
439;;;_ > icomplete-minibuffer-setup () 453;;;_ > icomplete-minibuffer-setup ()
454
455(defun icomplete--vertical-prospects (prefix-len _determ comps)
456 "List of vertical completions limited."
457 ;; Max total rows to use, including the minibuffer content.
458 (let* (;; Needed for prospects-max-height-pixel
459 (single-line-height (line-pixel-height))
460 ;; in general this should be done for every line
461 (line-height (* icomplete--lines-per-candidate single-line-height))
462 (prospects-rows (+ (cdr (window-text-pixel-size))
463 (* (cl-count ?\n icomplete--list-indicators-format) single-line-height)))
464 limit prospects comp comp-len)
465
466 (while (and comps (not limit))
467 (setq comp (substring (pop comps) prefix-len)
468 comp-len (> (length comp) 0))
469
470 (if comp-len
471 (setq prospects-rows (+ prospects-rows line-height)))
472
473 (if (< prospects-rows icomplete--prospects-max-height)
474 (if comp-len
475 (push comp prospects))
476 (push icomplete--ellipsis prospects)
477 (setq limit t)))
478 (nreverse prospects)))
479
480
481(defun icomplete--horizontal-prospects (prefix-len determ comps)
482 "List of horizontal completions limited."
483
484 (let* (;; Max total length to use, including the minibuffer content.
485 (separator-width (string-width icomplete-separator))
486 (prospects-len (+ (string-width (or determ (format icomplete--match-braket "")))
487 (string-width icomplete-separator)
488 (+ 2 (string-width icomplete--ellipsis)) ;; take {…} into account
489 (string-width (buffer-string))))
490 (prospects-max-len (* (+ icomplete-prospects-height
491 ;; If the minibuffer content already uses up more than
492 ;; one line, increase the allowable space accordingly.
493 (/ prospects-len (window-width)))
494 (window-width)))
495 limit prospects comp)
496
497 (while (and comps (not limit))
498 (setq comp (substring (pop comps) prefix-len))
499
500 (when (> (length comp) 0)
501 (setq prospects-len (+ prospects-len (string-width comp) separator-width)))
502
503 (if (< prospects-len prospects-max-len)
504 (push comp prospects)
505 (push icomplete--ellipsis prospects)
506 (setq limit t)))
507 (nreverse prospects)))
508
509
440(defun icomplete-minibuffer-setup () 510(defun icomplete-minibuffer-setup ()
441 "Run in minibuffer on activation to establish incremental completion. 511 "Run in minibuffer on activation to establish incremental completion.
442Usually run by inclusion in `minibuffer-setup-hook'." 512Usually run by inclusion in `minibuffer-setup-hook'."
@@ -446,7 +516,29 @@ Usually run by inclusion in `minibuffer-setup-hook'."
446 (current-local-map))) 516 (current-local-map)))
447 (add-hook 'pre-command-hook #'icomplete-pre-command-hook nil t) 517 (add-hook 'pre-command-hook #'icomplete-pre-command-hook nil t)
448 (add-hook 'post-command-hook #'icomplete-post-command-hook nil t) 518 (add-hook 'post-command-hook #'icomplete-post-command-hook nil t)
449 (run-hooks 'icomplete-minibuffer-setup-hook))) 519 (run-hooks 'icomplete-minibuffer-setup-hook)
520
521 (setq icomplete--ellipsis (if (char-displayable-p ?…) "…" "...")
522 icomplete--lines-per-candidate (cl-count ?\n icomplete-separator))
523
524 (if (> icomplete--lines-per-candidate 0)
525 (setq-local icomplete--list-indicators-format " \n%s"
526 icomplete--prospects 'icomplete--vertical-prospects
527 icomplete--prospects-max-height
528 (let ((minibuffer-parameter (frame-parameter nil 'minibuffer)))
529 (min (cond
530 ((eq minibuffer-parameter t)
531 (if (floatp max-mini-window-height)
532 (* max-mini-window-height (frame-pixel-height))
533 (* max-mini-window-height (frame-char-height))))
534 ;; TODO: minibuffer-parameter can be nil, what to do then?.
535 ((eq minibuffer-parameter 'only)
536 (frame-pixel-height)))
537 (* (+ 2 icomplete-prospects-height) (line-pixel-height)))))
538
539 (setq-local icomplete--list-indicators-format "{%s}"
540 icomplete--prospects 'icomplete--horizontal-prospects))))
541
450 542
451(defvar icomplete--in-region-buffer nil) 543(defvar icomplete--in-region-buffer nil)
452 544
@@ -639,8 +731,6 @@ one of (), [], or {} pairs. The choice of brackets is as follows:
639 731
640 (...) - a single prospect is identified and matching is enforced, 732 (...) - a single prospect is identified and matching is enforced,
641 [...] - a single prospect is identified but matching is optional, or 733 [...] - a single prospect is identified but matching is optional, or
642 {...} - multiple prospects, separated by commas, are indicated, and
643 further input is required to distinguish a single one.
644 734
645If there are multiple possibilities, `icomplete-separator' separates them. 735If there are multiple possibilities, `icomplete-separator' separates them.
646 736
@@ -665,13 +755,13 @@ matches exist."
665 (md (completion--field-metadata (icomplete--field-beg))) 755 (md (completion--field-metadata (icomplete--field-beg)))
666 (comps (icomplete--sorted-completions)) 756 (comps (icomplete--sorted-completions))
667 (last (if (consp comps) (last comps))) 757 (last (if (consp comps) (last comps)))
668 (base-size (cdr last)) 758 (base-size (cdr last)))
669 (open-bracket (if require-match "(" "[")) 759
670 (close-bracket (if require-match ")" "]"))) 760 (setq-local icomplete--match-braket (if require-match "(%s)" "[%s]"))
671 ;; `concat'/`mapconcat' is the slow part. 761 ;; `concat'/`mapconcat' is the slow part.
672 (if (not (consp comps)) 762 (if (not (consp comps))
673 (progn ;;(debug (format "Candidates=%S field=%S" candidates name)) 763 (progn ;;(debug (format "Candidates=%S field=%S" candidates name))
674 (format " %sNo matches%s" open-bracket close-bracket)) 764 (format icomplete--match-braket "No matches"))
675 (if last (setcdr last nil)) 765 (if last (setcdr last nil))
676 (let* ((most-try 766 (let* ((most-try
677 (if (and base-size (> base-size 0)) 767 (if (and base-size (> base-size 0))
@@ -687,33 +777,18 @@ matches exist."
687 ;; a prefix of most, or something else. 777 ;; a prefix of most, or something else.
688 (compare (compare-strings name nil nil 778 (compare (compare-strings name nil nil
689 most nil nil completion-ignore-case)) 779 most nil nil completion-ignore-case))
690 (ellipsis (if (char-displayable-p ?…) "…" "..."))
691 (determ (unless (or (eq t compare) (eq t most-try) 780 (determ (unless (or (eq t compare) (eq t most-try)
692 (= (setq compare (1- (abs compare))) 781 (= (setq compare (1- (abs compare)))
693 (length most))) 782 (length most)))
694 (concat open-bracket 783 (format icomplete--match-braket
695 (cond 784 (cond
696 ((= compare (length name)) 785 ((= compare (length name))
697 ;; Typical case: name is a prefix. 786 ;; Typical case: name is a prefix.
698 (substring most compare)) 787 (substring most compare))
699 ;; Don't bother truncating if it doesn't gain 788 ;; Don't bother truncating if it doesn't gain
700 ;; us at least 2 columns. 789 ;; us at least 2 columns.
701 ((< compare (+ 2 (string-width ellipsis))) most) 790 ((< compare (+ 2 (string-width icomplete--ellipsis))) most)
702 (t (concat ellipsis (substring most compare)))) 791 (t (concat icomplete--ellipsis (substring most compare)))))))
703 close-bracket)))
704 ;;"-prospects" - more than one candidate
705 (prospects-len (+ (string-width
706 (or determ (concat open-bracket close-bracket)))
707 (string-width icomplete-separator)
708 (+ 2 (string-width ellipsis)) ;; take {…} into account
709 (string-width (buffer-string))))
710 (prospects-max
711 ;; Max total length to use, including the minibuffer content.
712 (* (+ icomplete-prospects-height
713 ;; If the minibuffer content already uses up more than
714 ;; one line, increase the allowable space accordingly.
715 (/ prospects-len (window-width)))
716 (window-width)))
717 ;; Find the common prefix among `comps'. 792 ;; Find the common prefix among `comps'.
718 ;; We can't use the optimization below because its assumptions 793 ;; We can't use the optimization below because its assumptions
719 ;; aren't always true, e.g. when completion-cycling (bug#10850): 794 ;; aren't always true, e.g. when completion-cycling (bug#10850):
@@ -725,12 +800,13 @@ matches exist."
725 (prefix (when icomplete-hide-common-prefix 800 (prefix (when icomplete-hide-common-prefix
726 (try-completion "" comps))) 801 (try-completion "" comps)))
727 (prefix-len 802 (prefix-len
728 (and (stringp prefix) 803 (and icomplete-hide-common-prefix
804 (stringp prefix)
729 ;; Only hide the prefix if the corresponding info 805 ;; Only hide the prefix if the corresponding info
730 ;; is already displayed via `most'. 806 ;; is already displayed via `most'.
731 (string-prefix-p prefix most t) 807 (string-prefix-p prefix most t)
732 (length prefix))) ;;) 808 (length prefix)))
733 prospects comp limit) 809 prospects)
734 (if (or (eq most-try t) (not (consp (cdr comps)))) 810 (if (or (eq most-try t) (not (consp (cdr comps))))
735 (setq prospects nil) 811 (setq prospects nil)
736 (when (member name comps) 812 (when (member name comps)
@@ -751,20 +827,11 @@ matches exist."
751 ;; To circumvent all the above problems, provide a visual 827 ;; To circumvent all the above problems, provide a visual
752 ;; cue to the user via an "empty string" in the try 828 ;; cue to the user via an "empty string" in the try
753 ;; completion field. 829 ;; completion field.
754 (setq determ (concat open-bracket "" close-bracket))) 830 (setq determ (format icomplete--match-braket "")))
755 ;; Compute prospects for display. 831 ;; Compute prospects for display.
756 (while (and comps (not limit)) 832 (setq prospects
757 (setq comp 833 (funcall icomplete--prospects prefix-len determ comps)))
758 (if prefix-len (substring (car comps) prefix-len) (car comps)) 834
759 comps (cdr comps))
760 (setq prospects-len
761 (+ (string-width comp)
762 (string-width icomplete-separator)
763 prospects-len))
764 (if (< prospects-len prospects-max)
765 (push comp prospects)
766 (setq limit t))))
767 (setq prospects (nreverse prospects))
768 ;; Decorate first of the prospects. 835 ;; Decorate first of the prospects.
769 (when prospects 836 (when prospects
770 (let ((first (copy-sequence (pop prospects)))) 837 (let ((first (copy-sequence (pop prospects))))
@@ -776,10 +843,8 @@ matches exist."
776 (if last (setcdr last base-size)) 843 (if last (setcdr last base-size))
777 (if prospects 844 (if prospects
778 (concat determ 845 (concat determ
779 "{" 846 (format icomplete--list-indicators-format
780 (mapconcat 'identity prospects icomplete-separator) 847 (mapconcat 'identity prospects icomplete-separator)))
781 (and limit (concat icomplete-separator ellipsis))
782 "}")
783 (concat determ " [Matched]")))))) 848 (concat determ " [Matched]"))))))
784 849
785;;; Iswitchb compatibility 850;;; Iswitchb compatibility