[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/ivy 7c5d49f 1/2: Improve manual line wrapping in long p
From: |
Basil L. Contovounesios |
Subject: |
[elpa] externals/ivy 7c5d49f 1/2: Improve manual line wrapping in long prompts |
Date: |
Tue, 18 May 2021 14:20:33 -0400 (EDT) |
branch: externals/ivy
commit 7c5d49f84f0919bbf00c53a9db48630adf8b2fbe
Author: Basil L. Contovounesios <contovob@tcd.ie>
Commit: Basil L. Contovounesios <contovob@tcd.ie>
Improve manual line wrapping in long prompts
* ivy.el (ivy--break-lines): New function.
(ivy--insert-prompt): Use it to break long lines based on
string-width rather than length (#2869).
* ivy-test.el (ivy--break-lines): New test.
---
ivy-test.el | 35 +++++++++++++++++++++++++++++++++++
ivy.el | 29 +++++++++++++++++++++--------
2 files changed, 56 insertions(+), 8 deletions(-)
diff --git a/ivy-test.el b/ivy-test.el
index 2062b81..44f293e 100644
--- a/ivy-test.el
+++ b/ivy-test.el
@@ -1688,6 +1688,41 @@ a buffer visiting a file."
"k789"))
(should (equal ivy-text "k7"))))
+(ert-deftest ivy--break-lines ()
+ "Test `ivy--break-lines' behavior."
+ (dolist (width '(-1 0))
+ (dolist (str '("" "\n" "a" "a\nb"))
+ (should (equal (ivy--break-lines str width) str))))
+ (should (equal (ivy--break-lines "" 1) ""))
+ (should (equal (ivy--break-lines "a" 1) "a"))
+ (should (equal (ivy--break-lines "a" 2) "a"))
+ (should (equal (ivy--break-lines "ab" 1) "a\nb"))
+ (should (equal (ivy--break-lines "ab" 2) "ab"))
+ (should (equal (ivy--break-lines "abc" 1) "a\nb\nc"))
+ (should (equal (ivy--break-lines "abc" 2) "ab\nc"))
+ (should (equal (ivy--break-lines "abc" 3) "abc"))
+ (should (equal (ivy--break-lines "\^X" 1) "\^X"))
+ (should (equal (ivy--break-lines "\^X" 2) "\^X"))
+ (should (equal (ivy--break-lines "a\^X" 1) "a\n\^X"))
+ (should (equal (ivy--break-lines "a\^X" 2) "a\n\^X"))
+ (should (equal (ivy--break-lines "a\^X" 3) "a\^X"))
+ (should (equal (ivy--break-lines "\^X\^X" 1) "\^X\n\^X"))
+ (should (equal (ivy--break-lines "\^X\^X" 2) "\^X\n\^X"))
+ (should (equal (ivy--break-lines "\^X\^X" 3) "\^X\n\^X"))
+ (should (equal (ivy--break-lines "\^X\^X" 4) "\^X\^X"))
+ (should (equal (ivy--break-lines "\nfoo\n\^X\^X\^X\nbar\n" 1)
+ "\nf\no\no\n\^X\n\^X\n\^X\nb\na\nr\n"))
+ (should (equal (ivy--break-lines "\nfoo\n\^X\^X\^X\nbar\n" 2)
+ "\nfo\no\n\^X\n\^X\n\^X\nba\nr\n"))
+ (should (equal (ivy--break-lines "\nfoo\n\^X\^X\^X\nbar\n" 3)
+ "\nfoo\n\^X\n\^X\n\^X\nbar\n"))
+ (should (equal (ivy--break-lines "\nfoo\n\^X\^X\^X\nbar\n" 4)
+ "\nfoo\n\^X\^X\n\^X\nbar\n"))
+ (should (equal (ivy--break-lines "\nfoo\n\^X\^X\^X\nbar\n" 5)
+ "\nfoo\n\^X\^X\n\^X\nbar\n"))
+ (should (equal (ivy--break-lines "\nfoo\n\^X\^X\^X\nbar\n" 6)
+ "\nfoo\n\^X\^X\^X\nbar\n")))
+
(defun ivy-test-run-tests ()
(let ((test-sets
'(
diff --git a/ivy.el b/ivy.el
index a8d2682..655d777 100644
--- a/ivy.el
+++ b/ivy.el
@@ -3068,6 +3068,26 @@ parts beyond their respective faces `ivy-confirm-face'
and
(funcall fn (ivy-state-prompt ivy-last))))
ivy--prompt)))
+(defun ivy--break-lines (str width)
+ "Break each line in STR with newlines to fit into WIDTH columns."
+ (if (<= width 0)
+ str
+ (let (lines)
+ (dolist (line (split-string str "\n"))
+ (while (and line (> (string-width line) width))
+ (let ((prefix "") (extra 0))
+ (while (string-empty-p prefix)
+ ;; Grow `width' until it fits at least one char from `line'.
+ (setq prefix (truncate-string-to-width line (+ width extra)))
+ (setq extra (1+ extra)))
+ ;; Avoid introducing spurious newline if `prefix' and `line' are
+ ;; equal, i.e., if `line' couldn't be truncated to `width'.
+ (setq line (and (> (length line) (length prefix))
+ (substring line (length prefix))))
+ (push prefix lines)))
+ (when line (push line lines)))
+ (string-join (nreverse lines) "\n"))))
+
(defun ivy--insert-prompt ()
"Update the prompt according to `ivy--prompt'."
(when (setq ivy--prompt (ivy-prompt))
@@ -3122,14 +3142,7 @@ parts beyond their respective faces `ivy-confirm-face'
and
(setq n-str (concat (funcall ivy-pre-prompt-function) n-str)))
(when ivy-add-newline-after-prompt
(setq n-str (concat n-str "\n")))
- ;; FIXME: This does not take character widths into account!
- ;; Should ideally let the display engine wrap text, otherwise
- ;; use `window-text-pixel-size'. See e.g. #2869.
- (let ((regex (format "\\([^\n]\\{%d\\}\\)[^\n]" (window-width))))
- (while (string-match regex n-str)
- (setq n-str (replace-match
- (concat (match-string 1 n-str) "\n")
- nil t n-str 1))))
+ (setq n-str (ivy--break-lines n-str (window-width)))
(set-text-properties 0 (length n-str)
`(face minibuffer-prompt ,@std-props)
n-str)
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [elpa] externals/ivy 7c5d49f 1/2: Improve manual line wrapping in long prompts,
Basil L. Contovounesios <=