branch: master
commit 8c2f213d911bb10c01a794eaaf0121ccb25d40ff
Author: Oleh Krehel <[email protected]>
Commit: Oleh Krehel <[email protected]>
counsel.el (counsel-yank-pop): Truncate during display
* counsel.el (counsel-yank-pop-truncate): Remove defcustom.
(counsel-yank-pop-truncate-radius): New defcustom.
(counsel--yank-pop-truncate): New defun.
(counsel--yank-pop-format-function): New defun.
During the completion, only the context around the match will be shown.
By default, the context is +2 lines above and +2 lines below the match.
It can be adjusted with `counsel-yank-pop-truncate-radius'.
Additionally, `ivy-height' is temporarily bound to 5 during completion.
This way, the maximum minibuffer height should be 1+4*5=21 lines.
Fixes #315
---
counsel.el | 61 ++++++++++++++++++++++++++++++++++++++++++------------------
1 file changed, 43 insertions(+), 18 deletions(-)
diff --git a/counsel.el b/counsel.el
index 8ace5ba..75ee2c6 100644
--- a/counsel.el
+++ b/counsel.el
@@ -1321,10 +1321,48 @@ INITIAL-INPUT can be given as the initial minibuffer
input."
(setq tmm-table-undef nil)
(counsel-tmm-prompt (tmm-get-keybind [menu-bar])))
-(defcustom counsel-yank-pop-truncate nil
+(defcustom counsel-yank-pop-truncate-radius 2
"When non-nil, truncate the display of long strings."
+ :type 'integer
:group 'ivy)
+(defun counsel--yank-pop-truncate (str)
+ (condition-case nil
+ (let* ((lines (split-string str "\n" t))
+ (n (length lines))
+ (first-match (cl-position-if
+ (lambda (s) (string-match ivy--old-re s))
+ lines))
+ (beg (max 0 (- first-match
+ counsel-yank-pop-truncate-radius)))
+ (end (min n (+ first-match
+ counsel-yank-pop-truncate-radius
+ 1)))
+ (seq (cl-subseq lines beg end)))
+ (if (null first-match)
+ (error "Could not match %s" str)
+ (when (> beg 0)
+ (setcar seq (concat "[...] " (car seq))))
+ (when (< end n)
+ (setcar (last seq)
+ (concat (car (last seq)) " [...]")))
+ (mapconcat #'identity seq "\n")))
+ (error str)))
+
+(defun counsel--yank-pop-format-function (cand-pairs)
+ (ivy--format-function-generic
+ (lambda (str _extra)
+ (mapconcat
+ (lambda (s)
+ (ivy--add-face s 'ivy-current-match))
+ (split-string
+ (counsel--yank-pop-truncate str) "\n" t)
+ "\n"))
+ (lambda (str _extra)
+ (counsel--yank-pop-truncate str))
+ cand-pairs
+ "\n"))
+
;;;###autoload
(defun counsel-yank-pop ()
"Ivy replacement for `yank-pop'."
@@ -1343,23 +1381,10 @@ INITIAL-INPUT can be given as the initial minibuffer
input."
(or (< (length s) 3)
(string-match "\\`[\n[:blank:]]+\\'" s)))
(delete-dups kill-ring))))
- (when counsel-yank-pop-truncate
- (setq candidates
- (mapcar (lambda (s)
- (if (string-match "\\`\\(.*\n.*\n.*\n.*\\)\n" s)
- (progn
- (let ((s (copy-sequence s)))
- (put-text-property
- (match-end 1)
- (length s)
- 'display
- " [...]"
- s)
- s))
- s))
- candidates)))
- (ivy-read "kill-ring: " candidates
- :action 'counsel-yank-pop-action)))
+ (let ((ivy-format-function #'counsel--yank-pop-format-function)
+ (ivy-height 5))
+ (ivy-read "kill-ring: " candidates
+ :action 'counsel-yank-pop-action))))
(defun counsel-yank-pop-action (s)
"Insert S into the buffer, overwriting the previous yank."