ivy-filthy-rich
ivy-filthy-rich copied to clipboard
Richer information for ivy candidates, fully customizable
#+TITLE: ivy-filthy-rich.el
- Important Update (<2018-12-16 Sun>): I don't use ivy anymore (moved to helm), so I won't maintain ivy-filthy-rich from now on.
ivy-rich pushed a new update that enables users to customize transformers, so there isn't much difference in functionality between ivy-filthy-rich and ivy-rich, only minor variances. I'll keep using and maintining ivy-filthy-rich. But It will not be in melpa since ivy-rich is already there.
[[./rich.png]]
This package adds more information on ivy candidates. It also allows you to customize what is the information and how are they displayed.
Inspired by [[https://github.com/Yevgnen/ivy-rich][ivy-rich]].
Features
- add information to ivy buffer
- customizable position
- cuztomizable face
- more to come if I can think of any
- Showcase
[[./m-x.png]]
[[./function.png]]
[[./face.png]]
- Install
The package is not in melpa, so you need to download and load it yourself.
- Useage
** Out of the box
#+BEGIN_SRC emacs-lisp (ivy-filthy-rich-mode) #+END_SRC
** Simple customizations
#+BEGIN_SRC emacs-lisp
(defcustom ivy-filthy-rich-padding ?\s
"The padding of ivy-filthy-rich-delimiter'. It is used when there are extra space. The length of the pad has to be one. If not,
ivy-filth-rich' will fallback to using space to pad.
Currently only support character, because `make-string' only accept that." :type 'character :group 'ivy-filthy-rich)
(defcustom ivy-filthy-rich-pad-side 'right "The side which padding is pad to. Either left or right.
Left means align right, right means align left." :type 'symbol :group 'ivy-filthy-rich)
(defcustom ivy-filthy-rich-max-length 0 "The max length of one entry (one line on ivy buffer). If it is zero, the max-length is (1- (frame-width))" :type 'number :group 'ivy-filthy-rich) #+END_SRC
** Deeper customization
Basically, there are three steps in a full customization.
*** 0. prepare some info functions
An info function is a function which you pass in a candidate and it returns some extra information about the candidate.
You can checkout default ones under #+BEGIN_SRC emacs-lisp ;; ;;; Info Function (Return info string list, used in format) ;; #+END_SRC
For example: #+BEGIN_SRC emacs-lisp (defun ivy-filthy-rich--get-major-mode (candidate) "Return major mode of buffer (CANDIDATE)." (let ((buffer (get-buffer candidate))) (if buffer (list (symbol-name (buffer-local-value 'major-mode buffer)))) '(""))) #+END_SRC
This function returns the major mode in which the candidate is. Actually, it returns a list, rather than a string. The reason is explained below.
Also, make sure your don't return an empty list and handle errors properly in info function.
*** 1. declare the format
Now you need to declare a format for a particular ivy-function.
Default ones are under #+BEGIN_SRC emacs-lisp ;; ;;; Default formaat ;; #+END_SRC
For example, #+BEGIN_SRC emacs-lisp (defvar ivy-filthy-rich-default-switch-buffer-format '(((value . (lambda (candidate) (list (ivy-switch-buffer-transformer candidate)))) (prop . 0.2) (candidate . t)) ((value . ivy-filthy-rich--get-major-mode) (prop . 0.2) (face . (:foreground "#61AFEF"))) ((value . ivy-filthy-rich--get-dir) (prop . 0.6) (face . (:foreground "#98C379")))) "The default format for `ivy-switch-buffer'.") #+END_SRC
As you see, the format is a list of alists. Each alist is a piece of extra information (except candidate). And the list represents a line in ivy buffer.
The order of the infos is the order of them in ivy buffer, from left to right. Note that candidate doesn't need to be the first one.
Avaliable keys for alists are:
-
value :: the function that returns a list of possible information strings. Those strings sorts from the longest to the shortest. =ivy-filth-rich= will try to use the longest string, if it doesn't fit, =ivy-filthy-rich= will try the next one, and so on. If the last on is still too long, it will be truncated. Original candidate is never truncated, actually, it will "eat" other parts' space if there is not enough.
Some ivy/counsel functions have default transformers, you might want to include them into your custom format. (like what I did in the example) A complete list can be found in source code under =;;;; Ivy default transformers=
-
prop :: the length that the info can occupy. It is a fraction against =ivy-filthy-rich-max-length=. =0.3= means the piece of info will get 30% of the max length. All the props don't have to add up to 1, though. For candidates, you can just assign a average number because they are never truncated. The extra space will be taken from other parts to ensure candidate will be displayed prpperly.
-
face :: The face you want the info be in.
-
candidate :: A boolean that marks which info is original candidate. There can be only one candidate. And there is no need to add =(candidate . nil)= to other infos.
*** 2. deploy your format
Make your tranformer by =lambda= and add it to =ivy-filthy-rich-transformer-alist=. Restart =ivy-filthy-rich-mode= if its already on.
#+BEGIN_SRC emacs-lisp (add-to-list 'ivy-filthy-rich-transformer-alist (ivy-filthy-rich-make-transformer 'ivy-command-you-want-to-modify 'your-custom-format)) (add-to-list 'ivy-filthy-rich-transformer-alist '(ivy-function-you-want-to-modify . (lambda (candidate) (ivy-filthy-rich--format-candidate candidate your-customized-format)))) #+END_SRC
The two expressions are equivilant. =ivy-filthy-rich--format-candidate= takes a candidate string and a format, and returns the modified string.
- Credits
- @Yevgnen for ivy-rich
- @seagle0128 for finding a bunch of bugs