Emacs 是如何实现快速查找和定位代码的?
Posted Emacs
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Emacs 是如何实现快速查找和定位代码的?相关的知识,希望对你有一定的参考价值。
实际编程时,不仅需要写代码,还需要快速地查找代码,定位日志等。这些事情在命令行下可以使用 find 和 grep 等工具的编合来完成。很多 IDE 也都集成了这些功能。平时主要还是使用 Emacs,还是希望在 Emacs 中实现这些功能。平时以下功能对我很重要:
根据文件名查找文件。
根据字符串搜索代码。
快速、快速、快速。
之前我主要使用 helm-ls-git-ls
和 helm-grep-do-git-grep
来实现。但是发现一般只要 Emacs 工作一天,打开的文件很多。到下午的时候,helm 就会变得很卡。于是想使用 ivy 试试。
也是两个函数:
counsel-git:在一个 git 项目中 find-file。
counsel-git-grep:在一个 git 项目中 grep。
我希望的是,到一个我常用的项目目录里执行这两个函数。最初的想法是直接 find-file
到对应目录。然后调函数就可以了。如:
(defun test ()
(interactive)
(find-file "projectdir")
(counsel-git))
但是有一个很麻烦的事情:如果我在执行两个函数的时候后悔了,不想找了。按下 C-g
不会回到我原来的 buffer,而是停留在我打开的 projectdir
。所以我的需求是如果按下 C-g
,取消的同时还要把 projectdir
这个 buffer 干掉。
最后发现, ivy-read
函数本来就有一个 unwind
选项,可以在 C-g=后也执行对应的函数。所以直接把 =counsel-git
和 counsel-git-grep=函数拿来改一下就可以了(需要注意的是:peng-root-dir 不能以 =/
结束,因为我需要使用 file-name-base
来找到打开 project 后的 buffer-name):
(defcustom peng-root-dir "~/src/project"
"the root directorie of your project"
:type 'string
)
(defun peng-asp-engine-project-and-ivy-ls ()
"Find file in the current Git repository."
(interactive)
(find-file peng-root-dir)
(setq peng-temp-buffer-name (file-name-base peng-root-dir))
(setq counsel--git-dir (locate-dominating-file
default-directory ".git"))
(ivy-set-prompt 'counsel-git counsel-prompt-function)
(if (null counsel--git-dir)
(error "Not in a git repository")
(setq counsel--git-dir (expand-file-name
counsel--git-dir))
(let* ((default-directory counsel--git-dir)
(cands (split-string
(shell-command-to-string counsel-git-cmd)
"\n"
t)))
(ivy-read "Find file" cands
:action #'counsel-git-action
:caller 'counsel-git
:unwind #'(lambda ()
(kill-buffer peng-temp-buffer-name))))))
(defun peng-asp-engine-project-and-ivy-grep (&optional cmd initial-input)
"Grep for a string in the current git repository.
When CMD is a string, use it as a \"git grep\" command.
When CMD is non-nil, prompt for a specific \"git grep\" command.
INITIAL-INPUT can be given as the initial minibuffer input."
(interactive "P")
(find-file peng-root-dir)
(setq peng-temp-buffer-name (file-name-base peng-root-dir))
(ivy-set-prompt 'counsel-git-grep counsel-prompt-function)
(let ((dd (expand-file-name default-directory))
proj)
(cond
((stringp cmd)
(setq counsel-git-grep-cmd cmd))
(cmd
(if (setq proj
(cl-find-if
(lambda (x)
(string-match (car x) dd))
counsel-git-grep-projects-alist))
(setq counsel-git-grep-cmd (cdr proj))
(setq counsel-git-grep-cmd
(ivy-read "cmd: " counsel-git-grep-cmd-history
:history 'counsel-git-grep-cmd-history
:re-builder #'ivy--regex
:unwind #'(lambda ()
(kill-buffer peng-temp-buffer-name))))
(setq counsel-git-grep-cmd-history
(delete-dups counsel-git-grep-cmd-history))))
(t
(setq counsel-git-grep-cmd counsel-git-grep-cmd-default)))
(setq counsel--git-grep-dir
(if proj
(car proj)
(locate-dominating-file default-directory ".git")))
(if (null counsel--git-grep-dir)
(error "Not in a git repository")
(unless proj
(setq counsel--git-grep-count
(if (eq system-type 'windows-nt)
0
(counsel--gg-count "" t))))
(ivy-read "git grep" (if proj
'counsel-git-grep-proj-function
'counsel-git-grep-function)
:initial-input initial-input
:matcher #'counsel-git-grep-matcher
:dynamic-collection (or proj (> counsel--git-grep-count 20000))
:keymap counsel-git-grep-map
:action #'counsel-git-grep-action
;; :unwind #'swiper--cleanup
:history 'counsel-git-grep-history
:caller 'counsel-git-grep
:unwind #'(lambda ()
(kill-buffer peng-temp-buffer-name)
(swiper--cleanup))))))
最后再来一个函数,预定几个 project 后,一调用就可以方便地在几个 project 中切换啦:
(defun peng-set-root-project ()
"selete a projec through `ivy-read'"
(interactive)
(let* ((project-list (ivy-read "Please selete a project: "
(list
;; do not end with slash
"~/src/xxx"
"~/src/yyy"
"~/src/zzz"
))))
(setq peng-root-dir project-list)))
最后附加 ivy 的一些实用的按键绑定介绍,也算是总结(基本就是把翻译了一些 ivy-help
里面的东西):
M-i
(ivy-insert-current
) :插入当前选中的目标。
M-j
(ivy-yank-word
) : 插入当前光标下的 word。
S-SPC
(ivy-restrict-to-matches
) : 保持当前输入过滤候选项,并清空当前输入。这个功能很实用。一般找文件,如果有重名,选输入文件名后,按下 S-SPC
后简单再过滤一下目录就出来了。
C-c C-o
(ivy-occur
) :把当前候选项保存到一个 buffer 中。然后你可以慢慢查找你想要的,最后回车即可。
C-o
(hydra-ivy/body
) :可以调出一个辅助小窗口,基本都有提示,kj 上下移动等等。
本期编辑: geekplux
欢迎投稿
投稿方式
向emacsist项目提交 Pull Request (投稿的文章请放在 tougao/这个目录下);
投稿时请:
注明你的昵称,或 ID,总之是你想显示的作者名;
如投稿的文章已经再其他地方发表,可以附上原文链接
以上是关于Emacs 是如何实现快速查找和定位代码的?的主要内容,如果未能解决你的问题,请参考以下文章