130 lines
5.4 KiB
Org Mode
130 lines
5.4 KiB
Org Mode
:PROPERTIES:
|
|
:ID: cce/ivy_and_counsel
|
|
:ROAM_ALIASES: Swiper Counsel Ivy "Ivy and Counsel"
|
|
:END:
|
|
#+TITLE: Emacs Control Via Ivy
|
|
#+ARCOLOGY_KEY: cce/ivy-config
|
|
#+filetags: :CCE:
|
|
|
|
#+PROPERTY: header-args :mkdirp yes :results none
|
|
#+PROPERTY: header-args:emacs-lisp :tangle ivy-config.el
|
|
|
|
,#+ARROYO_EMACS_MODULE: ivy-config
|
|
#+ARROYO_MODULE_WANTS: cce/diminish.org
|
|
|
|
#+begin_src emacs-lisp
|
|
(provide 'cce/ivy-config)
|
|
#+end_src
|
|
|
|
[[https://oremacs.com/swiper/][Ivy]] is a [[id:a7420bb9-395f-4afa-92fb-8eaa0b8a4cd8][Tool]] for interactive text completion in [[id:cce/emacs][Emacs]]. It's built for quick string matching within a list of completion candidates, such as commands to run, the auto-completion value for a function signature, et cetera. It's a replacement for a large swath of Emacs functionality, making it quicker and more intuitive to work with than it is with the default interface, and a bit more responsive than, in my experience, than [[https://github.com/emacs-helm/helm][Helm]].
|
|
|
|
Out of the box, Ivy does little more than replace =ido= functionality, but there are a wealth of connectors, both in the collection of Counsel commands in the package, and elsewhere within ELPA, GitHub and the rest of the Emacs ecosystem. Here I configure the base commands, and in sister documents I will configure specific functionalities past that.
|
|
|
|
In short:
|
|
|
|
- Install Ivy
|
|
- configure Magit and Projectile to use it.
|
|
- bind =C-x b= and =<NORMAL><SPC>b= to =ivy-switch-buffer=
|
|
- bind =M-u= to =ivy-resume= which will re-display any previous Ivy command and possibly re-start it (this works with Counsel commands at least)
|
|
|
|
#+begin_src emacs-lisp
|
|
(use-package ivy
|
|
:demand
|
|
:config
|
|
(ivy-mode 1)
|
|
(setq ivy-height 15
|
|
projectile-completion-system 'ivy
|
|
magit-completing-read-funciton 'ivy-completing-read)
|
|
:bind
|
|
("M-u" . ivy-resume)
|
|
("C-x b" . ivy-switch-buffer)
|
|
:bind (:map evil-leader--default-map
|
|
("b" . 'ivy-switch-buffer))
|
|
:diminish ivy-mode)
|
|
#+end_src
|
|
|
|
In short:
|
|
- =counsel-find-files= and related commands will auto-fill if there is a file under the cursor.
|
|
- Ignore files that end with a =~= or start with a =.=, or end or start with a =#=.
|
|
- Bind =/= and =?= to Swiper in Normal Mode
|
|
- Bind =<NORMAL><SPC><SPC>= and =M-x= to =counsel-M-x=, which is an interactive command launcher but with Ivy
|
|
- Bind =C-c C-q= to a tag selector in =org-mode= and =org-agenda=.
|
|
|
|
#+begin_src emacs-lisp
|
|
(use-package counsel
|
|
:demand
|
|
:after (org org-agenda ivy)
|
|
:commands (counsel-M-x swiper swiper-backward counsel-org-tag counsel-org-tag-agenda)
|
|
:config
|
|
(setq counsel-find-file-at-point t
|
|
counsel-find-file-ignore-regexp (concat "\\(?:\\`[#.]\\)" "\\|\\(?:[#~]\\'\\)"))
|
|
:bind (:map evil-leader--default-map ;; prefix to SPC
|
|
("<SPC>" . counsel-M-x))
|
|
(:map evil-normal-state-map ;; evil normal mode
|
|
("/" . swiper)
|
|
("?" . swiper-backward))
|
|
(:map org-mode-map ;; org-mode
|
|
("C-c C-q" . counsel-org-tag))
|
|
(:map org-agenda-mode-map ;; org-agenda
|
|
("C-c C-q" . counsel-org-tag-agenda))
|
|
:bind ;; global keys
|
|
("M-x" . counsel-M-x)
|
|
("C-x C-f" . counsel-find-file)
|
|
("C-x d" . counsel-dired)
|
|
("M-`" . counsel-tmm)
|
|
:diminish counsel-mode)
|
|
#+end_src
|
|
|
|
I have a special [[id:cce/hydra][Hydra]] interface, which exposes some common Ivy actions in a Hydra which I can access from within Ivy itself. I should source this code properly, it's not a thing I wrote, it may've been lifted from the Ivy documentation.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defun ivy--matcher-desc () ; used in `hydra-ivy'
|
|
(if (eq ivy--regex-function
|
|
'ivy--regex-fuzzy)
|
|
"fuzzy"
|
|
"ivy"))
|
|
|
|
(defhydra hydra-ivy (:hint nil :color pink)
|
|
"
|
|
^^_,_ _f_ollow occ_u_r _g_o ^^_c_alling %-7s(if ivy-calling \"on\" \"off\") _w_/_s_/_a_: %-14s(ivy-action-name)
|
|
_p_/_n_ _d_one ^^ _i_nsert ^^_m_atcher %-7s(ivy--matcher-desc)^^^^^^^^^^^^ _C_ase-fold: %-10`ivy-case-fold-search
|
|
^^_._ _D_o it! ^^ _q_uit _<_/_>_ shrink/grow^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _t_runcate: %-11`truncate-lines
|
|
"
|
|
;; arrows
|
|
("," ivy-beginning-of-buffer) ; default h
|
|
("p" ivy-previous-line) ; default j
|
|
("n" ivy-next-line) ; default k
|
|
("." ivy-end-of-buffer) ; default l
|
|
;; quit ivy
|
|
("q" keyboard-escape-quit :exit t) ; default o
|
|
("C-g" keyboard-escape-quit :exit t)
|
|
;; quit hydra
|
|
("i" nil)
|
|
("C-o" nil)
|
|
;; actions
|
|
("f" ivy-alt-done :exit nil)
|
|
;; Exchange the default bindings for C-j and C-m
|
|
("C-m" ivy-alt-done :exit nil) ; RET, default C-j
|
|
("C-j" ivy-done :exit t) ; default C-m
|
|
("d" ivy-done :exit t)
|
|
("g" ivy-call)
|
|
("D" ivy-immediate-done :exit t)
|
|
("c" ivy-toggle-calling)
|
|
("m" ivy-toggle-fuzzy)
|
|
(">" ivy-minibuffer-grow)
|
|
("<" ivy-minibuffer-shrink)
|
|
("w" ivy-prev-action)
|
|
("s" ivy-next-action)
|
|
("a" ivy-read-action)
|
|
("t" (setq truncate-lines (not truncate-lines)))
|
|
("C" ivy-toggle-case-fold)
|
|
("u" ivy-occur :exit t))
|
|
|
|
(with-eval-after-load 'ivy
|
|
(define-key ivy-minibuffer-map (kbd "C-m") 'ivy-alt-done) ; RET, default C-j
|
|
(define-key ivy-minibuffer-map (kbd "C-j") 'ivy-done) ; default C-m
|
|
(define-key ivy-minibuffer-map (kbd "C-S-m") 'ivy-immediate-done)
|
|
(define-key ivy-minibuffer-map (kbd "C-t") 'ivy-toggle-fuzzy)
|
|
(define-key ivy-minibuffer-map (kbd "C-o") 'hydra-ivy/body))
|
|
#+END_SRC
|