快速导航
ivy默认的配置已经足够了,但还是可以通过一些技巧来提升使用体验
ivy中的tab
ivy提供了好几个有关补全的命令,分别是ivy-done, ivy-partial-or-done, ivy-immediate-done, ivy-dispatching-done, 但不幸,想要获得高效的补全,我不得不记住这n多个命令,这常常使效率变得更低,
所以,我自定义了一个 maple/ivy-done, 仅使用 tab 这一个按键就可以获得以上所有的体验
1(defun maple/ivy-done()
2 (interactive)
3 (let ((dir ivy--directory))
4 (ivy-partial-or-done)
5 (when (string= dir ivy--directory)
6 (ivy-insert-current)
7 (when (and (eq (ivy-state-collection ivy-last) #'read-file-name-internal)
8 (setq dir (ivy-expand-file-if-directory (ivy-state-current ivy-last))))
9 (ivy--cd dir)
10 (setq this-command 'ivy-cd)))))
-
预设场景一 dirs目录下有
1init-a.el 2init-b.el 3init-c.el等多个文件, 我需要把init-c.el重命名为init-c.el.bak, 默认的ivy会怎么做呢
-
输入 init c 进行查找
-
使用
C-M-j(ivy-immediate-done) 插入当前选中项 -
修改
而使用 maple/ivy-done 后呢
-
输入 init c 进行查找
-
使用
tab插入当前选中项 -
修改
-
-
预设场景二 有一个n级子目录,需要切换到第n个子目录下, 默认的ivy会怎么做呢
-
使用
tab选中 -
再次使用
tab切换目录
而使用 maple/ivy-done 后呢
-
使用
tab选中并切换目录
-
ivy中的C-h
由于我是邪恶的 evil 用户, 所以我正常情况会使用 C-j, C-k来选择待选项,同样的,我希望能够使用 C-h 来进行某些操作,比如在counsel-ag中使用C-h代替backspace删除输入的字符,而在counsel-find-file中使用C-h切换到上一级目录
ivy默认提供了 counsel-up-directory 命令可以切换到上级目录, 我希望能更进一步,当有插入的字符时, 调用C-h能够直接清除插入的字符,再次调用才切换到上一级目录
1(defun maple/ivy-c-h ()
2 (interactive)
3 (if (eq (ivy-state-collection ivy-last) #'read-file-name-internal)
4 (if (string-equal (ivy--input) "")
5 (counsel-up-directory)
6 (delete-minibuffer-contents))
7 (ivy-backward-delete-char)))
ivy-occur批量操作
自动打开wgrep-mode
ivy默认调用ivy-occur后, 还需要调用ivy-wgrep-change-to-wgrep-mode才能进行批量修改
1;; ivy-occur custom
2(defun maple/ivy-edit ()
3 "Edit the current search results in a buffer using wgrep."
4 (interactive)
5 (run-with-idle-timer 0 nil 'ivy-wgrep-change-to-wgrep-mode)
6 (ivy-occur))
批量修改文件名
预设场景: 当某个项目下有许多使用 aaa.py的文件,我需要把 aaa.py 全部修改为 bbb.py, 也许某个 aaa.py 需要修改成 ccc.py,我在使用 projectile-find-file 搜索完全部的 aaa.py 后,打开ivy默认的ivy-occur并不能对文件进行修改(提示Text read only), 所以我采用 find-name-dired 来批量修改文件名(目前还有些问题)
1(defun maple/ivy-dired-occur()
2 (interactive)
3 (find-name-dired
4 (or (projectile-project-root) default-directory) (concat (ivy--input) "*"))
5 (ivy-exit-with-action
6 (lambda (_)
7 (pop-to-buffer (get-buffer "*Find*"))
8 (dired-hide-details-mode)
9 (wdired-change-to-wdired-mode)
10 (when (bound-and-true-p evil-local-mode) (evil-normal-state)))))
counsel-find-file
重命名
预设场景: 有一个dirs目录, 我需要在同级目录下创建一个 dirs-aa.el 的文件, 默认的ivy会怎么做呢
-
切换到 dirs 目录的上级目录
-
使用 ivy-immediate-done 插入目录名
-
新建文件
但还有一种方式
-
切换到 dirs 目录
-
使用
backspace键删除目录末尾的/ -
新建文件
不幸的是,ivy中 backspace 的按键绑定了 ivy-backward-delete-char, 在 counsel-find-file 中使用 ivy会直接返回上级目录, 所以需要对 ivy-backward-delete-char 作简单的修改
1(defun maple/ivy-backward-delete-char ()
2 (interactive)
3 (let ((dir ivy--directory)
4 (p (and ivy--directory (= (minibuffer-prompt-end) (point)))))
5 (ivy-backward-delete-char)
6 (when p (insert (file-name-nondirectory (directory-file-name dir))))))
自动创建不存在的目录
不仅用于ivy, 其它文件操作命令也需要
1(defun maple/ivy-make-directory-maybe ()
2 "Create parent directory if not exists while visiting file."
3 (let ((dir (file-name-directory buffer-file-name)))
4 (unless (file-exists-p dir)
5 (if (y-or-n-p (format "Directory %s does not exist,do you want you create it? " dir))
6 (make-directory dir t)
7 (keyboard-quit)))))
8
9(add-to-list 'find-file-not-found-functions 'maple/ivy-make-directory-maybe nil #'eq)
ivy自动使用选中的内容
在使用 counsel-ag 或者 swiper, 我需要快速搜索选中的关键词,然而,ivy默认并不支持这么做,ivy需要打开counsel-ag后使用 M-n 插入选中的关键词,当然,也许是作者认为这样的方式很方便,但我并不认同,我为何需要重复一次操作呢,为何还需要记住 M-n 这样的按键呢?
1(defun maple/region-string()
2 "Get region string."
3 (if (not (use-region-p)) ""
4 (let* ((beg (region-beginning))
5 (end (region-end))
6 (eol (save-excursion (goto-char beg) (line-end-position))))
7 (deactivate-mark) (buffer-substring-no-properties beg (min end eol)))))
8
9;; custom counsel-ag
10(defun maple/counsel-ag(-counsel-ag &optional initial-input initial-directory extra-ag-args ag-prompt)
11 (funcall -counsel-ag
12 (or initial-input (maple/region-string))
13 (or initial-directory default-directory)
14 extra-ag-args
15 ag-prompt))
16
17(advice-add 'counsel-ag :around #'maple/counsel-ag)
这样,调用 counsel-ag 时,如何已经有选中的关键词,就会直接调用该关键词进行查找,避免重复操作, 同样的对于swiper 也可以使用另一种方式
1(defun maple/ivy-search-at-point (func)
2 (let ((ivy-initial-inputs-alist (list (cons func (maple/region-string)))))
3 (funcall func)))
4
5(defun maple/swiper()
6 (interactive)
7 (maple/ivy-search-at-point 'swiper))
搜索某个目录
counsel-ag默认搜索当前目录,想要搜索某个目录,需要切换到该目录下调用counsel-ag,无疑的,这非常不方便,所以,我希望可以选择某个目录进行搜索
1(defun maple/counsel-ag-directory()
2 (interactive)
3 (counsel-ag nil (read-directory-name "Search in directory: ")))
ivy的显示避免出现在视线外
详见 自定义helm式的ivy.html 中的
吐嘈六: minibuffer
counsel-ag指定文件后缀
1关键词 -- -Ggo
知识共享署名-非商业性使用-相同方式共享4.0国际许可协议