branch: externals/ivy
commit 36f68985dec5cb7a90518040efb85a91219a983c
Merge: 6cd8350655 6227843101
Author: Basil L. Contovounesios <[email protected]>
Commit: Basil L. Contovounesios <[email protected]>
Merge branch 'master' into externals/ivy
---
.mailmap | 1 +
CONTRIBUTING.org | 6 +--
colir.el | 46 ++++++++--------
doc/ivy-ox.el | 2 +-
doc/ivy.org | 14 ++---
doc/ivy.texi | 8 +--
doc/scripts.el | 2 +-
ivy-faces.el | 2 +-
ivy-overlay.el | 2 +-
ivy-test.el | 112 +++++++++++++++++++++++++++++++++------
ivy.el | 158 ++++++++++++++++++++++++++++++++++---------------------
11 files changed, 237 insertions(+), 116 deletions(-)
diff --git a/.mailmap b/.mailmap
index fa38b3f201..eb78d6ffb0 100644
--- a/.mailmap
+++ b/.mailmap
@@ -19,6 +19,7 @@
<[email protected]> <[email protected]>
<[email protected]> <[email protected]>
<[email protected]> <[email protected]>
+Christopher Floess <[email protected]>
Daanturo <[email protected]> <[email protected]>
Diego A. Mundo <[email protected]>
Earl Hyatt <[email protected]> <[email protected]>
diff --git a/CONTRIBUTING.org b/CONTRIBUTING.org
index 6fcc7278ea..772e9ec4ca 100644
--- a/CONTRIBUTING.org
+++ b/CONTRIBUTING.org
@@ -14,9 +14,9 @@ init file.
This shortcut will start =emacs -Q= for you with =ivy-mode= already
loaded:
#+begin_src sh
-git clone https://github.com/abo-abo/swiper/
-cd swiper
-make plain
+ git clone 'https://github.com/abo-abo/swiper.git'
+ cd swiper
+ make deps plain
#+end_src
* Contributing code
diff --git a/colir.el b/colir.el
index f371ef3839..a30046f0cc 100644
--- a/colir.el
+++ b/colir.el
@@ -1,6 +1,6 @@
;;; colir.el --- Color blending library -*- lexical-binding: t -*-
-;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2025 Free Software Foundation, Inc.
;; Author: Oleh Krehel <[email protected]>
@@ -35,7 +35,7 @@
(require 'color)
(defcustom colir-compose-method #'colir-compose-alpha
- "Select a method to compose two color channels."
+ "The method `colir-blend' uses to compose two color channels."
:group 'ivy
:type '(radio
(function-item colir-compose-alpha)
@@ -43,22 +43,25 @@
(function-item colir-compose-soft-light)))
(defun colir-compose-soft-light (a b)
- "Compose A and B channels."
+ "Compose color channels A and B in Soft Light blend mode.
+See URL `https://en.wikipedia.org/wiki/Blend_modes#Soft_Light'."
(if (< b 0.5)
(+ (* 2 a b) (* a a (- 1 b b)))
- (+ (* 2 a (- 1 b)) (* (sqrt a) (- (* 2 b) 1)))))
+ (+ (* 2 a (- 1 b)) (* (sqrt a) (+ b b -1)))))
(defun colir-compose-overlay (a b)
- "Compose A and B channels."
+ "Compose color channels A and B in Overlay blend mode.
+See URL `https://en.wikipedia.org/wiki/Blend_modes#Overlay'."
(if (< a 0.5)
(* 2 a b)
(- 1 (* 2 (- 1 a) (- 1 b)))))
+;; Generalizes Emacs 31 `color-blend'.
(defun colir-compose-alpha (a b &optional alpha gamma)
- "Compose A and B channels.
-Optional argument ALPHA is a number between 0.0 and 1.0 which corresponds
-to the influence of A on the result. Default value is 0.5.
-Optional argument GAMMA is used for gamma correction. Default value is 2.2."
+ "Compose color channels A and B using alpha blending.
+Optional argument ALPHA controls the influence of A on the result.
+It is a number between 0.0 and 1.0, inclusive (default 0.5).
+Optional argument GAMMA controls gamma correction (default 2.2)."
(setq alpha (or alpha 0.5))
(setq gamma (or gamma 2.2))
(+ (* (expt a gamma) alpha) (* (expt b gamma) (- 1 alpha))))
@@ -69,8 +72,8 @@ C1 and C2 are triples of floats in [0.0 1.0] range."
(apply #'color-rgb-to-hex
(cl-mapcar
(if (eq (frame-parameter nil 'background-mode) 'dark)
- ;; this method works nicely for dark themes
- 'colir-compose-soft-light
+ ;; This method works nicely for dark themes.
+ #'colir-compose-soft-light
colir-compose-method)
c1 c2)))
@@ -85,17 +88,16 @@ C1 and C2 are triples of floats in [0.0 1.0] range."
(defun colir--blend-background (start next prevn face object)
(let ((background-prev (face-background prevn)))
- (progn
- (put-text-property
- start next 'face
- (if background-prev
- (cons `(background-color
- . ,(colir-blend
- (colir-color-parse background-prev)
- (colir-color-parse (face-background face nil t))))
- prevn)
- (list face prevn))
- object))))
+ (put-text-property
+ start next 'face
+ (if background-prev
+ (cons `(background-color
+ . ,(colir-blend
+ (colir-color-parse background-prev)
+ (colir-color-parse (face-background face nil t))))
+ prevn)
+ (list face prevn))
+ object)))
(defun colir-blend-face-background (start end face &optional object)
"Append to the face property of the text from START to END the face FACE.
diff --git a/doc/ivy-ox.el b/doc/ivy-ox.el
index fd33b453fd..863e7dce92 100644
--- a/doc/ivy-ox.el
+++ b/doc/ivy-ox.el
@@ -1,6 +1,6 @@
;;; ivy-ox.el --- org-export settings for Ivy -*- lexical-binding: t -*-
-;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2025 Free Software Foundation, Inc.
;; Author: Oleh Krehel
diff --git a/doc/ivy.org b/doc/ivy.org
index cb1191d1d4..d54cdaf1f6 100644
--- a/doc/ivy.org
+++ b/doc/ivy.org
@@ -18,8 +18,8 @@
#+STARTUP: indent
* Setup
:noexport:
#+BEGIN_SRC elisp :exports results :results silent
-(add-to-list 'load-path default-directory)
-(require 'ivy-ox)
+ (add-to-list 'load-path (directory-file-name default-directory))
+ (require 'ivy-ox)
#+END_SRC
* Writing this manual
:noexport:
To highlight a section without introducing a new subheading use
@@ -70,7 +70,7 @@ final candidate is either through simple keyboard character
inputs or
through powerful regular expressions.
#+TEXINFO: @end ifnottex
-Copyright (C) 2015--2024 Free Software Foundation, Inc.
+Copyright (C) 2015--2025 Free Software Foundation, Inc.
#+BEGIN_QUOTE
Permission is granted to copy, distribute and/or modify this document
@@ -189,15 +189,15 @@ For package manager details, see [[info:emacs#Packages]].
First clone the Swiper repository with:
#+begin_src sh
- cd ~/git && git clone https://github.com/abo-abo/swiper
- cd swiper && make compile
+ cd ~/git && git clone 'https://github.com/abo-abo/swiper.git'
+ cd swiper && make deps compile
#+end_src
Second, add these lines to the Emacs init file:
#+begin_src elisp
- (add-to-list 'load-path "~/git/swiper/")
- (require 'ivy)
+ (add-to-list 'load-path "~/git/swiper")
+ (require 'ivy)
#+end_src
Then, update the code with:
diff --git a/doc/ivy.texi b/doc/ivy.texi
index 90c5fa2e16..cb2a609127 100644
--- a/doc/ivy.texi
+++ b/doc/ivy.texi
@@ -20,7 +20,7 @@ final candidate is either through simple keyboard character
inputs or
through powerful regular expressions.
@end ifnottex
-Copyright (C) 2015--2024 Free Software Foundation, Inc.
+Copyright (C) 2015--2025 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
@@ -261,14 +261,14 @@ Contribute to Ivy's development; send patches; pull
requests
First clone the Swiper repository with:
@example
-cd ~/git && git clone https://github.com/abo-abo/swiper
-cd swiper && make compile
+cd ~/git && git clone 'https://github.com/abo-abo/swiper.git'
+cd swiper && make deps compile
@end example
Second, add these lines to the Emacs init file:
@lisp
-(add-to-list 'load-path "~/git/swiper/")
+(add-to-list 'load-path "~/git/swiper")
(require 'ivy)
@end lisp
diff --git a/doc/scripts.el b/doc/scripts.el
index 6e00b162ff..97b1827af6 100644
--- a/doc/scripts.el
+++ b/doc/scripts.el
@@ -1,4 +1,4 @@
-;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2025 Free Software Foundation, Inc.
(setq org-confirm-babel-evaluate nil)
(defun org-to-texi (fname)
(find-file fname)
diff --git a/ivy-faces.el b/ivy-faces.el
index c2195ed294..1a25cfc0a9 100644
--- a/ivy-faces.el
+++ b/ivy-faces.el
@@ -1,6 +1,6 @@
;;; ivy-faces.el --- Faces for Ivy -*- lexical-binding: t -*-
-;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2025 Free Software Foundation, Inc.
;; Author: Oleh Krehel <[email protected]>
;; Keywords: convenience
diff --git a/ivy-overlay.el b/ivy-overlay.el
index ad359fc83d..f52b5ecbee 100644
--- a/ivy-overlay.el
+++ b/ivy-overlay.el
@@ -1,6 +1,6 @@
;;; ivy-overlay.el --- Overlay display functions for Ivy -*- lexical-binding:
t -*-
-;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2025 Free Software Foundation, Inc.
;; Author: Oleh Krehel <[email protected]>
;; Keywords: convenience
diff --git a/ivy-test.el b/ivy-test.el
index 87dda1854b..f850bbe736 100644
--- a/ivy-test.el
+++ b/ivy-test.el
@@ -1,6 +1,6 @@
;;; ivy-test.el --- tests for ivy -*- lexical-binding: t -*-
-;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2025 Free Software Foundation, Inc.
;; Author: Oleh Krehel
@@ -1007,20 +1007,102 @@ Since `execute-kbd-macro' doesn't pick up a let-bound
`default-directory'.")
(ivy-mode ivy-mode-reset-arg))))
(ert-deftest ivy-completion-common-length ()
- (should (= 2
- (ivy-completion-common-length
- #("test/"
- 0 2 (face completions-common-part)
- 2 3 (face (completions-first-difference))))))
- (should (= 5
- (ivy-completion-common-length
- #("Math/E"
- 0 5 (face (completions-common-part))
- 5 6 (face (completions-first-difference))))))
- (should (= 3
- (ivy-completion-common-length
- #("vec"
- 0 3 (face (completions-common-part)))))))
+ (mapc (lambda (pair)
+ (dolist (str (cdr pair))
+ (ert-info ((format "%S" str) :prefix "String: ")
+ (should (= (ivy-completion-common-length str) (car pair))))))
+ '((0 ""
+ #("a" 0 1 (face completions-first-difference))
+ #("ab" 0 1 (face completions-first-difference))
+ #("abc" 0 1 (face completions-first-difference))
+ #("a" 0 1 (face (completions-first-difference)))
+ #("ab" 0 1 (face (completions-first-difference)))
+ #("abc" 0 1 (face (completions-first-difference)))
+ #("a" 0 1 (font-lock-face (completions-first-difference)))
+ #("ab" 0 1 (font-lock-face (completions-first-difference)))
+ #("abc" 0 1 (font-lock-face (completions-first-difference)))
+ #("abc"
+ 0 1 (face completions-first-difference)
+ 1 2 (face default))
+ #("abc"
+ 0 1 (face completions-first-difference)
+ 2 3 (face default))
+ #("abc"
+ 0 1 (face (completions-first-difference))
+ 1 2 (face default))
+ #("abc"
+ 0 1 (face (completions-first-difference))
+ 2 3 (face default)))
+ (1 "a"
+ #("a" 0 1 (face default))
+ #("ab" 1 2 (face completions-first-difference))
+ #("ab" 0 2 (face completions-first-difference))
+ #("abc" 1 2 (face completions-first-difference))
+ #("abc" 0 2 (face completions-first-difference))
+ #("ab" 1 2 (face (completions-first-difference)))
+ #("ab" 0 2 (face (completions-first-difference)))
+ #("abc" 1 2 (face (completions-first-difference)))
+ #("abc" 0 2 (face (completions-first-difference)))
+ #("ab" 1 2 (font-lock-face (completions-first-difference)))
+ #("ab" 0 2 (font-lock-face (completions-first-difference)))
+ #("abc" 1 2 (font-lock-face (completions-first-difference)))
+ #("abc" 0 2 (font-lock-face (completions-first-difference)))
+ #("abc"
+ 0 1 (face default)
+ 1 2 (face completions-first-difference))
+ #("abc"
+ 1 2 (face completions-first-difference)
+ 2 3 (face default))
+ #("abc"
+ 0 1 (face default)
+ 1 2 (face (completions-first-difference)))
+ #("abc"
+ 1 2 (face (completions-first-difference))
+ 2 3 (face default)))
+ (2 "ab"
+ #("ab" 0 1 (face default))
+ #("ab" 1 2 (face default))
+ #("ab" 0 2 (face default))
+ #("abc" 2 3 (face completions-first-difference))
+ #("abc" 1 3 (face completions-first-difference))
+ #("abc" 0 3 (face completions-first-difference))
+ #("abc" 2 3 (face (completions-first-difference)))
+ #("abc" 1 3 (face (completions-first-difference)))
+ #("abc" 0 3 (face (completions-first-difference)))
+ #("abc" 2 3 (font-lock-face (completions-first-difference)))
+ #("abc" 1 3 (font-lock-face (completions-first-difference)))
+ #("abc" 0 3 (font-lock-face (completions-first-difference)))
+ #("abc"
+ 0 1 (face default)
+ 2 3 (face completions-first-difference))
+ #("abc"
+ 1 2 (face default)
+ 2 3 (face completions-first-difference))
+ #("abc"
+ 0 1 (face default)
+ 2 3 (face (completions-first-difference)))
+ #("abc"
+ 1 2 (face default)
+ 2 3 (face (completions-first-difference)))
+ #("test/"
+ 0 2 (face completions-common-part)
+ 2 3 (face completions-first-difference))
+ #("test/"
+ 0 2 (face completions-common-part)
+ 2 3 (face (completions-first-difference))))
+ (3 "abc"
+ #("abc" 0 1 (face default))
+ #("abc" 1 2 (face default))
+ #("abc" 2 3 (face default))
+ #("abc" 0 2 (face default))
+ #("abc" 1 3 (face default))
+ #("abc" 0 3 (face default)))
+ (5 #("Math/E"
+ 0 5 (face completions-common-part)
+ 5 6 (face completions-first-difference))
+ #("Math/E"
+ 0 5 (face completions-common-part)
+ 5 6 (face (completions-first-difference)))))))
(ert-deftest ivy--sort-function ()
"Test `ivy--sort-function' behavior."
diff --git a/ivy.el b/ivy.el
index 15bf9bbe55..66e71ae32c 100644
--- a/ivy.el
+++ b/ivy.el
@@ -1,6 +1,6 @@
;;; ivy.el --- Incremental Vertical completYon -*- lexical-binding: t -*-
-;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2025 Free Software Foundation, Inc.
;; Author: Oleh Krehel <[email protected]>
;; Maintainer: Basil L. Contovounesios <[email protected]>
@@ -2037,6 +2037,8 @@ Directories come first."
(seq (cl-mapcan
(lambda (f)
(unless (member f '("./" "../"))
+ ;; FIXME: Use `substitute-in-file-name'?
+ ;; Re: #2012, #3060.
(setq f (ivy--string-replace "$$" "$" f))
(list (if (and dirs-first (ivy--dirname-p f))
(propertize f 'ivy--dir (directory-file-name f))
@@ -2620,10 +2622,11 @@ The previous string is between `ivy-completion-beg' and
`ivy-completion-end'."
(ivy-state-collection ivy-last)))
(minibuffer-completion-predicate (if (boundp 'ivy--minibuffer-pred)
ivy--minibuffer-pred
- (ivy-state-predicate
ivy-last))))
- (completion--done str (cond ((eq ivy--minibuffer-try t) 'finished)
- ((eq ivy-exit 'done) 'unknown)
- ('exact))))
+ (ivy-state-predicate ivy-last)))
+ (newstr (or (car-safe ivy--minibuffer-try) str)))
+ (completion--done newstr (cond ((eq ivy--minibuffer-try t) 'finished)
+ ((eq ivy-exit 'done) 'unknown)
+ ('exact))))
(setq ivy-completion-end (point))
(save-excursion
(dolist (cursor fake-cursors)
@@ -2636,24 +2639,46 @@ The previous string is between `ivy-completion-beg' and
`ivy-completion-end'."
(set-marker (overlay-get cursor 'point) (point))
(set-marker (overlay-get cursor 'mark) (point)))))))
+(defalias 'ivy--face-list-p
+ (if (fboundp 'face-list-p)
+ #'face-list-p
+ (lambda (face)
+ (and (listp face)
+ (listp (cdr face))
+ (not (keywordp (car face))))))
+ "Compatibility shim for Emacs 25 `face-list-p'.")
+
+;; FIXME: Should this return the smallest such index instead?
+;; Usually the two are equal, but perhaps there exist more
+;; exotic applications of `completions-first-difference'.
+;;
+;; Completing files under a directory foo/ can have a first difference at
+;; index 0 in some Emacs versions, and no such property in other versions.
+;; So perhaps this function should return 0 instead of (length str) when no
+;; property is found? That still follows the 'largest index' definition.
(defun ivy-completion-common-length (str)
- "Return the amount of characters that match in STR.
-
-`completion-all-completions' computes this and returns the result
-via text properties.
-
-The first non-matching part is propertized:
-- either with: (face (completions-first-difference))
-- or: (font-lock-face completions-first-difference)."
- (let ((char-property-alias-alist '((face font-lock-face)))
- (i (1- (length str))))
- (catch 'done
- (while (>= i 0)
- (when (equal (get-text-property i 'face str)
- '(completions-first-difference))
- (throw 'done i))
- (cl-decf i))
- (throw 'done (length str)))))
+ "Return the length of the completion-matching prefix of STR.
+
+That is, return the largest index into STR at which either the
+`face' or `font-lock-face' property value contains the face
+`completions-first-difference'.
+If no such index is found, return the length of STR.
+
+Typically the completion-matching parts of STR have previously been
+propertized by `completion-all-completions', but then the base-size
+returned by that function should be preferred over
+`ivy-completion-common-length'."
+ (let* ((char-property-alias-alist '((face font-lock-face)))
+ (cmn (length str))
+ (i cmn))
+ (when (> i 0)
+ (while (if (let ((face (get-text-property (1- i) 'face str)))
+ (or (eq 'completions-first-difference face)
+ (and (ivy--face-list-p face)
+ (memq 'completions-first-difference face))))
+ (ignore (setq cmn (1- i)))
+ (setq i (previous-single-property-change i 'face str)))))
+ cmn))
(defun ivy-completion-in-region (start end collection &optional predicate)
"An Ivy function suitable for `completion-in-region-function'.
@@ -2661,43 +2686,57 @@ The function completes the text between START and END
using COLLECTION.
PREDICATE (a function called with no arguments) says when to exit.
See `completion-in-region' for further information."
(let* ((enable-recursive-minibuffers t)
+ (reg (- end start))
(str (buffer-substring-no-properties start end))
(completion-ignore-case (ivy--case-fold-p str))
(md (completion-metadata str collection predicate))
- (reg (- end start))
- (comps (completion-all-completions str collection predicate reg md))
(try (completion-try-completion str collection predicate reg md))
+ (comps (completion-all-completions str collection predicate reg md))
+ (last (last comps))
+ (base-size (cdr last))
(ivy--minibuffer-table collection)
(ivy--minibuffer-pred predicate))
- (cond ((null comps)
- (message "No matches"))
- ((progn
- (nconc comps nil)
- (and (null (cdr comps))
- (string= str (car comps))))
- (message "Sole match"))
+ (when last (setcdr last ()))
+ (cond ((not try)
+ (and (not completion-fail-discreetly)
+ completion-show-inline-help
+ (minibuffer-message "No matches"))
+ nil)
+ ((eq try t)
+ (goto-char end)
+ (let ((minibuffer-completion-table collection)
+ (minibuffer-completion-predicate predicate))
+ (completion--done str 'finished "Sole match"))
+ t)
(t
(when (eq collection 'crm--collection-fn)
(setq comps (delete-dups comps)))
- (let* ((len (ivy-completion-common-length (car comps)))
- (initial (cond ((= len 0)
+ (let* ((cmn (ivy-completion-common-length (car comps)))
+ ;; Translate a 'not found' result to 0. Do this here
(instead
+ ;; of fixing `ivy-completion-common-length') for backward
+ ;; compatibility, since it's a potentially public function.
+ (cmn (if (= cmn (length (car comps))) 0 cmn))
+ (initial (cond (base-size (substring str base-size))
+ ;; The remaining clauses should hopefully
never
+ ;; be taken, since they rely on
+ ;; `ivy-completion-common-length'.
+ ((= cmn 0)
"")
- ((let ((str-len (length str)))
- (when (> len str-len)
- (setq len str-len)
- str)))
+ ((>= cmn reg)
+ (setq cmn reg)
+ str)
(t
- (substring str (- len))))))
- (delete-region (- end len) end)
- (setq ivy-completion-beg (- end len))
+ (substring str (- cmn)))))
+ (base-pos (if base-size (+ start base-size) (- end cmn))))
+ (delete-region base-pos end)
+ (setq ivy-completion-beg base-pos)
(setq ivy-completion-end ivy-completion-beg)
(if (null (cdr comps))
- (progn
+ (let ((ivy--minibuffer-try try))
(unless (minibuffer-window-active-p (selected-window))
(setf (ivy-state-window ivy-last) (selected-window)))
- (let ((ivy--minibuffer-try try))
- (ivy-completion-in-region-action
- (substring-no-properties (car comps)))))
+ (ivy-completion-in-region-action
+ (substring-no-properties (car comps))))
(dolist (s comps)
;; Remove face `completions-first-difference'.
(ivy--remove-props s 'face))
@@ -2711,6 +2750,9 @@ See `completion-in-region' for further information."
(setq predicate nil))
(ivy-read (format "(%s): " str) collection
:predicate predicate
+ ;; FIXME: The anchor is intrusive and not easily
+ ;; configurable by `ivy-initial-inputs-alist' or
+ ;; `ivy-hooks-alist'.
:initial-input (concat
(and (derived-mode-p
#'emacs-lisp-mode)
"^")
@@ -2722,7 +2764,7 @@ See `completion-in-region' for further information."
(when initial
(insert initial))))
:caller 'ivy-completion-in-region)))
- ;; Return value should be non-nil on valid completion;
+ ;; Return value should be t on valid completion;
;; see `completion-in-region'.
t))))
@@ -3187,23 +3229,17 @@ parts beyond their respective faces `ivy-confirm-face'
and
(std-props '(front-sticky t rear-nonsticky t field t read-only t))
(n-str
(concat
- (if (and (bound-and-true-p minibuffer-depth-indicate-mode)
- (> (minibuffer-depth) 1))
- (format "[%d] " (minibuffer-depth))
- "")
- (concat
- (if (string-match "%d.*%d" ivy-count-format)
- (format head
- (1+ ivy--index)
- (or (and (ivy-state-dynamic-collection ivy-last)
+ (and (bound-and-true-p minibuffer-depth-indicate-mode)
+ (> (minibuffer-depth) 1)
+ (format "[%d] " (minibuffer-depth)))
+ (let ((count (or (and (ivy-state-dynamic-collection ivy-last)
ivy--full-length)
- ivy--length))
- (format head
- (or (and (ivy-state-dynamic-collection ivy-last)
- ivy--full-length)
- ivy--length)))
- ivy--prompt-extra
- tail)))
+ ivy--length)))
+ (if (string-match-p "%d.*%d" ivy-count-format)
+ (format head (min (1+ ivy--index) count) count)
+ (format head count)))
+ ivy--prompt-extra
+ tail))
(d-str (if ivy--directory
(abbreviate-file-name ivy--directory)
"")))