Merge branch 'develop'
* develop: (64 commits) Prepare for v2.0.5 Temporarily disable doom-themes-visual-bell-config Fix neotree always changing root Update changelog Fix wrong-type-argument error from +org/insert-item Make +ivy-buffer-transformer autoloadable General refactor & cleanup Correct troubleshooting link in README org: set org-ellipsis to downward chevron Add elfeed-(show|search)-mode to evil-snipe-disabled-modes Autoload json library Rethink smartparens config #181 README: expand troubleshooting Fix wiki links in README (again) Correct intro in README Fix wiki links in README Prevent private commands from affecting projectile cache Remove recentf-filename-handlers fix for projectile-recentf-files lang/sh: remove unused setup.sh Convert +ivy/switch-buffer to transformers + add mode icons #169 ...
This commit is contained in:
commit
d2d71795e5
75 changed files with 1165 additions and 954 deletions
|
@ -1,93 +1,96 @@
|
|||
* :completion ivy
|
||||
#+TITLE: :completion ivy
|
||||
|
||||
This module adds the Ivy completion backend.
|
||||
This module adds Ivy, a completion backend.
|
||||
|
||||
I prefer ivy over ido and helm, for its speed and simplicity. With ivy's help and some hackery, I get the following features:
|
||||
#+begin_quote
|
||||
I prefer ivy over ido for its flexibility. I prefer ivy over helm because it's lighter.
|
||||
#+end_quote
|
||||
|
||||
+ Project-wide search & replace powered by ~rg~ and ~ag~
|
||||
+ Project-wide search & replace powered by ~rg~ or ~ag~
|
||||
+ Project jump-to navigation ala Command-T, Sublime Text's Jump-to-anywhere or Vim's CtrlP plugin.
|
||||
+ Ivy integration for ~M-x~, ~imenu~, ~recentf~ and others.
|
||||
+ A powerful, interactive in-buffer search using ~swiper~.
|
||||
+ Ivy-powered TODO/FIXME navigation
|
||||
|
||||
** Install
|
||||
* Table of Contents :TOC:
|
||||
- [[#install][Install]]
|
||||
- [[#macos][MacOS]]
|
||||
- [[#arch-linux][Arch Linux]]
|
||||
- [[#usage][Usage]]
|
||||
- [[#project-search--replace][Project search & replace]]
|
||||
- [[#jump-to-file-project-navigation][Jump-to-file project navigation]]
|
||||
- [[#in-buffer-searching][In-buffer searching]]
|
||||
- [[#task-lookup][Task lookup]]
|
||||
- [[#appendix][Appendix]]
|
||||
- [[#commands][Commands]]
|
||||
- [[#hacks][Hacks]]
|
||||
|
||||
* Install
|
||||
This module optionally depends on [[https://github.com/BurntSushi/ripgrep][ripgrep]] and [[https://github.com/ggreer/the_silver_searcher][the_silver_searcher]].
|
||||
|
||||
~rg~ is faster, but its results aren't deterministic and it doesn't support multiline search or full PCRE, that's where ~ag~ is useful.
|
||||
~rg~ is faster, but its results aren't deterministic, neither does it support multiline search or full PCRE, that's where ~ag~ is useful.
|
||||
|
||||
*** MacOS
|
||||
** MacOS
|
||||
#+BEGIN_SRC sh :tangle (if (doom-system-os 'macos) "yes")
|
||||
brew install ripgrep the_silver_searcher
|
||||
#+END_SRC
|
||||
|
||||
*** Arch Linux
|
||||
** Arch Linux
|
||||
#+BEGIN_SRC sh :dir /sudo:: :tangle (if (doom-system-os 'arch) "yes")
|
||||
sudo pacman --needed --noconfirm -S ripgrep the_silver_searcher
|
||||
#+END_SRC
|
||||
|
||||
** Usage
|
||||
*** Search & Replace
|
||||
A project-wide search can be performed with Ag (the silver searcher) or Rg
|
||||
(ripgrep) via their ex commands: ~:ag[!]~ and ~:rg[!]~ (or their
|
||||
current-directory counterparts ~:agcwd[!]~ and ~:rgcwd[!]~)
|
||||
* Usage
|
||||
Here is some insight into how I use this module. Keep in mind that the referenced commands and keybindings are defined [[/modules/private/hlissner][in my private module]].
|
||||
|
||||
** Project search & replace
|
||||
Ex interfaces to Ag (the silver searcher) and Rg (ripgrep) are available: ~:ag[!]~ and ~:rg[!]~, or their current-directory counterparts ~:agcwd[!]~ and ~:rgcwd[!]~.
|
||||
|
||||
[[/../screenshots/modules/completion/ivy/ivy-search.gif]]
|
||||
|
||||
From this session, you can press =Shift + Tab= to create an writeable occur
|
||||
buffer in wgrep mode.
|
||||
From this session, you can press =S+Tab= to create a writeable occur-buffer in wgrep mode.
|
||||
|
||||
[[/../screenshots/modules/completion/ivy/ivy-search-replace.gif]]
|
||||
|
||||
Make your modifications and press =C-c C-c= to commit them, or =C-c C-k= to
|
||||
abort.
|
||||
Make your modifications and press =C-c C-c= to commit them, or =C-c C-k= to abort.
|
||||
|
||||
*** Jump-to-file project navigation
|
||||
Inspired by Sublime Text's jump-to-anywhere, Vim's CtrlP or Unite plugins, and
|
||||
Textmate's Command-T, a marriage of ~projectile~ and ~ivy~ makes this available
|
||||
to you in Emacs. Invoke it with =<leader> /= or ~counsel-projectile-find-file~.
|
||||
** Jump-to-file project navigation
|
||||
Inspired by Sublime Text's jump-to-anywhere, Vim's CtrlP or Unite plugins, and Textmate's Command-T, a marriage of ~projectile~ and ~ivy~ makes this available to you in Emacs. Invoke it with =SPC f /=, =SPC SPC= or ~counsel-projectile-find-file~.
|
||||
|
||||
[[/../screenshots/modules/completion/ivy/ivy-projectile.gif]]
|
||||
|
||||
*** In-buffer searching
|
||||
I prefer to use ~evil-search~ (invoked by pressing =/= in normal mode) when
|
||||
jumping small/moderate (or predictable) distances. On occasion I need more
|
||||
feedback, so I turn to ~swiper~ (available directly with =M-x swiper RET=, or
|
||||
via ~:sw[iper]~).
|
||||
** In-buffer searching
|
||||
I use ~evil-search~ (invoked by pressing =/= in normal mode) when jumping small/moderate (or predictable) distances. However, there are occasions where I need more feedback, so I turn to ~swiper~ (available directly with =M-x swiper RET=, or via ~:sw[iper]~).
|
||||
|
||||
[[/../screenshots/modules/completion/ivy/ivy-swiper.gif]]
|
||||
|
||||
*** TODO-Task lookup
|
||||
I sprinkle my projects with TODO's & FIXME's. Using ivy and ripgrep, I wrote
|
||||
~+ivy/tasks~ to help me navigate to them. It can be invoked via ~:todo[!]~ as
|
||||
well.
|
||||
** Task lookup
|
||||
I sprinkle my projects with TODO's & FIXME's. You can navigate to and peruse them via ~M-x +ivy/tasks~ or ~:todo[!]~ (ex command).
|
||||
|
||||
[[/../screenshots/modules/completion/ivy/ivy-todo.gif]]
|
||||
|
||||
** Appendix
|
||||
*** Commands & Keybindings
|
||||
Here is a list of my commonly used commands, their default keybinds (defined in
|
||||
[[../../private/hlissner/+bindings.el][private/hlissner/+bindings.el]]), and their corresponding ex command (defined in
|
||||
[[../../private/hlissner/+commands.el][private/hlissner/+commands.el]]).
|
||||
* Appendix
|
||||
** Commands
|
||||
Here is a list of my commonly used commands, their default keybinds (defined in [[../../private/hlissner/+bindings.el][private/hlissner/+bindings.el]]), and their corresponding ex command (defined in [[../../private/hlissner/+commands.el][private/hlissner/+commands.el]]).
|
||||
|
||||
| command | key / ex command | description |
|
||||
|-------------------------------------+---------------------+------------------------------------------------------------------|
|
||||
| ~counsel-M-x~ | =M-x= | Smarter, smex-powered M-x |
|
||||
| ~counsel-bookmark~ | =<leader> b= | Find bookmark |
|
||||
| ~counsel-find-file~ | =<leader> .= | Browse from current directory |
|
||||
| ~counsel-projectile-find-file~ | =<leader> /= | Find file in project |
|
||||
| ~counsel-projectile-switch-project~ | =<leader> p= | Open another project |
|
||||
| ~counsel-recentf~ | =<leader> r= | Find recently opened file |
|
||||
| ~+ivy/switch-buffer~ | =<leader> ,= | Jump to buffer in current workspace |
|
||||
| ~+ivy/switch-workspace-buffer~ | =<leader> <= | Jump to buffer across workspaces |
|
||||
| ~+ivy:ag~ | ~:ag[!] [QUERY]~ | Search project (BANG = ignore gitignore) |
|
||||
| ~+ivy:ag-cwd~ | ~:agcwd[!] [QUERY]~ | Search this directory (BANG = don't recurse into subdirectories) |
|
||||
| ~+ivy:rg~ | ~:rg[!] [QUERY]~ | Search project (if BANG, ignore gitignore) |
|
||||
| ~+ivy:rg-cwd~ | ~:rgcwd[!] [QUERY]~ | Search this directory (BANG = don't recurse into subdirectories) |
|
||||
| ~+ivy:swiper~ | ~:sw[iper] [QUERY]~ | Search current buffer |
|
||||
| ~+ivy:todo~ | ~:todo[!]~ | List all TODO/FIXMEs in project (or current file if BANG) |
|
||||
| command | key / ex command | description |
|
||||
|-------------------------------------+------------------------+------------------------------------------------------------------|
|
||||
| ~counsel-M-x~ | =M-x= | Smarter, smex-powered M-x |
|
||||
| ~counsel-bookmark~ | =SPC RET= | Find bookmark |
|
||||
| ~counsel-find-file~ | =SPC f .= or =SPC .= | Browse from current directory |
|
||||
| ~counsel-projectile-find-file~ | =SPC f /= or =SPC SPC= | Find file in project |
|
||||
| ~counsel-projectile-switch-project~ | =SPC p p= | Open another project |
|
||||
| ~counsel-recentf~ | =SPC f r= | Find recently opened file |
|
||||
| ~ivy-switch-buffer~ | =SPC b b= | Jump to buffer in current workspace |
|
||||
| ~+ivy/switch-workspace-buffer~ | =SPC b B= | Jump to buffer across workspaces |
|
||||
| ~+ivy:ag~ | ~:ag[!] [QUERY]~ | Search project (BANG = ignore gitignore) |
|
||||
| ~+ivy:ag-cwd~ | ~:agcwd[!] [QUERY]~ | Search this directory (BANG = don't recurse into subdirectories) |
|
||||
| ~+ivy:rg~ | ~:rg[!] [QUERY]~ | Search project (if BANG, ignore gitignore) |
|
||||
| ~+ivy:rg-cwd~ | ~:rgcwd[!] [QUERY]~ | Search this directory (BANG = don't recurse into subdirectories) |
|
||||
| ~+ivy:swiper~ | ~:sw[iper] [QUERY]~ | Search current buffer |
|
||||
| ~+ivy:todo~ | ~:todo[!]~ | List all TODO/FIXMEs in project (or current file if BANG) |
|
||||
|
||||
While in a search (e.g. invoked from ~+ivy:ag~ or ~+ivy:rg~), these new
|
||||
keybindings are available to you:
|
||||
While in a search (e.g. invoked from ~+ivy:ag~ or ~+ivy:rg~), these new keybindings are available to you:
|
||||
|
||||
| key | description |
|
||||
|-------------+--------------------------------------------------------------------------------|
|
||||
|
@ -95,10 +98,8 @@ keybindings are available to you:
|
|||
| =C-SPC= | Preview the current candidate |
|
||||
| =M-RET= | Open the selected candidate in other-window |
|
||||
|
||||
*** Hacks
|
||||
+ Where possible, functions with ivy/counsel equivalents have been remapped
|
||||
(like ~find-file~ => ~counsel-find-file~). So a keybinding to ~find-file~ will
|
||||
invoke ~counsel-find-file~ instead.
|
||||
** Hacks
|
||||
+ Functions with ivy/counsel equivalents have been globally remapped (like ~find-file~ => ~counsel-find-file~). So a keybinding to ~find-file~ will invoke ~counsel-find-file~ instead.
|
||||
+ ~counsel-[arp]g~'s 3-character limit was reduced to 1 (mainly for the ex command)
|
||||
+ ~counsel-[arp]g~'s parentheses quoting behavior was reversed. Now, if you
|
||||
want literal parentheses, you must escape them: e.g. ~\(match\)~ is literal,
|
||||
|
|
|
@ -1,72 +1,48 @@
|
|||
;;; completion/ivy/autoload/ivy.el -*- lexical-binding: t; -*-
|
||||
|
||||
;; Show more information in ivy-switch-buffer; and only display
|
||||
;; workgroup-relevant buffers.
|
||||
(defun +ivy--get-buffers (&optional buffer-list)
|
||||
(when-let (buffer-list (delq (current-buffer) (or buffer-list (doom-buffer-list))))
|
||||
(let* ((min-name
|
||||
(+ 5 (cl-loop for buf in buffer-list
|
||||
maximize (length (buffer-name buf)))))
|
||||
(min-mode
|
||||
(+ 5 (cl-loop for buf in buffer-list
|
||||
maximize (length (symbol-name (buffer-local-value 'major-mode buf)))))))
|
||||
(cl-loop
|
||||
with project-root = (doom-project-root)
|
||||
for buf in buffer-list
|
||||
collect
|
||||
(cl-destructuring-bind (type mode path)
|
||||
(with-current-buffer buf
|
||||
(list (concat
|
||||
(let ((buffer-name (buffer-name buf)))
|
||||
(propertize
|
||||
buffer-name
|
||||
'face (cond ((string-match-p "^ ?\\*" buffer-name)
|
||||
'font-lock-comment-face)
|
||||
((not (string= project-root (doom-project-root)))
|
||||
'warning)
|
||||
(buffer-read-only
|
||||
'error))))
|
||||
(when (and buffer-file-name (buffer-modified-p))
|
||||
(propertize "[+]" 'face 'doom-modeline-buffer-modified)))
|
||||
(propertize (symbol-name major-mode) 'face 'font-lock-constant-face)
|
||||
(when buffer-file-name
|
||||
(abbreviate-file-name
|
||||
(file-name-directory buffer-file-name)))))
|
||||
(format (format "%%-%ds %%-%ds %%s" min-name min-mode)
|
||||
type mode (or path "")))))))
|
||||
|
||||
(defun +ivy--select-buffer-action (buffer)
|
||||
(ivy--switch-buffer-action
|
||||
(string-remove-suffix
|
||||
"[+]"
|
||||
(substring buffer 0 (string-match-p (regexp-quote " ") buffer)))))
|
||||
|
||||
(defun +ivy--select-buffer-other-window-action (buffer)
|
||||
(ivy--switch-buffer-other-window-action
|
||||
(string-remove-suffix
|
||||
"[+]"
|
||||
(substring buffer 0 (string-match-p (regexp-quote " ") buffer)))))
|
||||
(defsubst +ivy--icon-for-mode (mode)
|
||||
"Apply `all-the-icons-for-mode' on MODE but either return an icon or nil."
|
||||
(let ((icon (all-the-icons-icon-for-mode mode)))
|
||||
(unless (symbolp icon) icon)))
|
||||
|
||||
;;;###autoload
|
||||
(defun +ivy/switch-workspace-buffer (&optional other-window-p)
|
||||
"Switch to an open buffer in the current workspace.
|
||||
|
||||
If OTHER-WINDOW-P (universal arg), then open target in other window."
|
||||
(interactive "P")
|
||||
(+ivy/switch-buffer other-window-p t))
|
||||
(defun +ivy-buffer-transformer (str)
|
||||
(let* ((buf (get-buffer str))
|
||||
(path (buffer-file-name buf))
|
||||
(mode (buffer-local-value 'major-mode buf))
|
||||
(faces
|
||||
(with-current-buffer buf
|
||||
(cond ((string-match-p "^ ?\\*" (buffer-name buf))
|
||||
'font-lock-comment-face)
|
||||
((buffer-modified-p buf)
|
||||
'doom-modeline-buffer-modified)
|
||||
(buffer-read-only
|
||||
'error)))))
|
||||
(propertize
|
||||
(format "%-40s %s%-20s %s"
|
||||
str
|
||||
(if +ivy-buffer-icons
|
||||
(concat (propertize " " 'display
|
||||
(or (+ivy--icon-for-mode mode)
|
||||
(+ivy--icon-for-mode (get mode 'derived-mode-parent))))
|
||||
"\t")
|
||||
"")
|
||||
mode
|
||||
(or (and path (abbreviate-file-name (file-name-directory (file-truename path))))
|
||||
""))
|
||||
'face faces)))
|
||||
|
||||
;;;###autoload
|
||||
(defun +ivy/switch-buffer (&optional other-window-p workspace-only-p)
|
||||
"Switch to an open buffer in the global buffer list.
|
||||
(defun +ivy/switch-workspace-buffer (&optional arg)
|
||||
"Switch to another buffer within the current workspace.
|
||||
|
||||
If OTHER-WINDOW-P (universal arg), then open target in other window.
|
||||
If WORKSPACE-ONLY-P (universal arg), limit to buffers in the current workspace."
|
||||
If ARG (universal argument), open selection in other-window."
|
||||
(interactive "P")
|
||||
(ivy-read (format "%s buffers: " (if workspace-only-p "Workspace" "Global"))
|
||||
(+ivy--get-buffers (unless workspace-only-p (buffer-list)))
|
||||
:action (if other-window-p
|
||||
#'+ivy--select-buffer-other-window-action
|
||||
#'+ivy--select-buffer-action)
|
||||
(ivy-read "Switch to workspace buffer: "
|
||||
(mapcar #'buffer-name (delq (current-buffer) (doom-buffer-list)))
|
||||
:action (if arg
|
||||
#'ivy--switch-buffer-other-window-action
|
||||
#'ivy--switch-buffer-action)
|
||||
:matcher #'ivy--switch-buffer-matcher
|
||||
:keymap ivy-switch-buffer-map
|
||||
:caller #'+ivy/switch-workspace-buffer))
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
;;; completion/ivy/config.el -*- lexical-binding: t; -*-
|
||||
|
||||
(defvar +ivy-buffer-icons nil
|
||||
"If non-nil, show buffer mode icons in `ivy-switch-buffer' and the like.")
|
||||
|
||||
(defvar +ivy-task-tags
|
||||
'(("TODO" . warning)
|
||||
("FIXME" . error))
|
||||
|
@ -22,7 +25,8 @@ session)."
|
|||
;;
|
||||
|
||||
(def-package! ivy
|
||||
:demand t
|
||||
:commands ivy-mode
|
||||
:init (add-hook 'doom-init-hook #'ivy-mode)
|
||||
:config
|
||||
(setq ivy-height 12
|
||||
ivy-do-completion-in-region nil
|
||||
|
@ -40,13 +44,11 @@ session)."
|
|||
(after! magit (setq magit-completing-read-function #'ivy-completing-read))
|
||||
(after! yasnippet (push #'+ivy-yas-prompt yas-prompt-functions))
|
||||
|
||||
(add-hook 'doom-init-hook #'ivy-mode)
|
||||
|
||||
(map! :map ivy-mode-map
|
||||
[remap apropos] #'counsel-apropos
|
||||
[remap describe-face] #'counsel-describe-face
|
||||
[remap find-file] #'counsel-find-file
|
||||
[remap switch-to-buffer] #'+ivy/switch-buffer
|
||||
[remap switch-to-buffer] #'ivy-switch-buffer
|
||||
[remap persp-switch-to-buffer] #'+ivy/switch-workspace-buffer
|
||||
[remap recentf] #'counsel-recentf
|
||||
[remap imenu] #'counsel-imenu
|
||||
|
@ -59,6 +61,12 @@ session)."
|
|||
[remap describe-variable] #'counsel-describe-variable
|
||||
[remap describe-face] #'counsel-describe-face)
|
||||
|
||||
;; Show more buffer information in switch-buffer commands
|
||||
(ivy-set-display-transformer 'ivy-switch-buffer #'+ivy-buffer-transformer)
|
||||
(ivy-set-display-transformer 'ivy-switch-buffer-other-window #'+ivy-buffer-transformer)
|
||||
(ivy-set-display-transformer '+ivy/switch-workspace-buffer #'+ivy-buffer-transformer)
|
||||
(ivy-set-display-transformer 'counsel-recentf #'abbreviate-file-name)
|
||||
|
||||
(when (featurep! :feature workspaces)
|
||||
(nconc ivy-sort-functions-alist
|
||||
'((persp-kill-buffer . nil)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue