这个方法现在只有在 linux 起作用,因为使用了 grep 和 find 这两个外部工具。Windows 下只有借助于 cygwin 的帮助了。
本来 M-x grep-find 可以实现这个功能了, 但是有一点 不好,就是每次过滤文件名称都很麻烦。
我的解决办法就是配置 wcy-find-grep-file-class 这个变量了, 他是一个 list ,其中的每一个元素表示一组文件 ,例如下面的例 子中表明了两组文件,一组是 C 和 C++ 的源程序,一组是 elisp 的源程序。
M-x wcy-find-grep ;; 这个功能我发现我极少使用。
提示输入一个 regexp ,和目录名称。
如果当前文件名称符合某一个组,那么就查找所有目录中 的和当前文件名称同组的文件。如果当前buffer 没有文 件名称,例如 dired-mode 的 buffer ,那么就会提示用 户输入过滤文件名称的regexp 。
还有一段代码是在tool bar 上增加了一个图标的快捷方 式。需要在 load-path 之一的目录中放一个 search-in-file.xpm 的文件。
查找结果中会显示文件的绝对路径名称,C-l 可以切换显 示相对路径名称和绝对路径名称。
和其他的 Compile 方式一样,C-x ` 可以跳转到下一个 发现查找到的地方 。C-u C-x ` 跳转到上一个。
M-x grep 可以在运行外部的 grep 命令,然后把输出结 果显示在一个 buffer 中,可以用 C-x ` 和 C-u C-x ` 在结果中跳转。这个命令是 Emacs 自带的,非常好用。
(defvar wcy-find-grep-file-class '(( ".*\\.h$" ".*\\.c$" ".*\\.cc$" ".*\\.cxx$" ".*\\.cpp$") (".*\\.el$"))) (defvar wcy-find-grep-file-class-history nil) (if (boundp 'tool-bar-map) (tool-bar-add-item "search-in-file" 'wcy-find-grep 'wcy-find-grep :help "search in files")) (defun wcy-find-grep-internal ( regexp dir-name regexp-for-filter-file) (let ((my-grep-command (concat " grep -e '" (mapconcat 'identity regexp-for-filter-file "\\|") "'" ))) (setq dir-name (expand-file-name dir-name)) (grep-find (concat "find " dir-name " -type f -print | " my-grep-command " | xargs -e grep -H -n -e '" regexp "'"))) (with-current-buffer compilation-last-buffer (local-set-key (kbd "C-l") 'wcy-find-grep-hide-dirname) (setq default-directory dir-name) (wcy-find-grep-hide-dirname) )) (defun wcy-find-grep-hide-dirname () (interactive) (if (not (eq major-mode 'compilation-mode)) (error "must run this command under grep-find mode buffer") (save-excursion (goto-char (point-min)) (let* ((dir-name default-directory) (r (re-search-forward (concat "^" (regexp-quote dir-name)) nil t)) begin end)progn (while r (setq begin (match-beginning 0)) (setq end (match-end 0)) (let* ((x (overlays-in begin end)) (e (or (and x (car x)) (make-overlay begin end)))) (overlay-put e 'invisible (not (overlay-get e 'invisible)))) (setq r (re-search-forward (concat "^" (regexp-quote dir-name)) nil t ))))))) (defun wcy-find-grep ( regexp dir-name regexp-for-fileter-file) (interactive (list (read-from-minibuffer "Regexp:" (concat "\\<" (regexp-quote (current-word)) "\\>");; initial content is nil nil ;; key map is nil nil ;; read as lisp expression, false; 'regexp-history nil ;; not default nil ;;inherit-input-method ) (read-file-name (format "Directory(recursively):" ) nil default-directory nil) (if (buffer-file-name (current-buffer)) nil (read-from-minibuffer "File Regexp:" nil nil nil 'wcy-find-grep-file-class-history nil nil)))) (let ((files-filter (if (null regexp-for-fileter-file) (dolist-if (var wcy-find-grep-file-class) (string-match (mapconcat 'identity var "\\|") (buffer-file-name (current-buffer))) var) (list (list regexp-for-fileter-file))))) (wcy-find-grep-internal regexp dir-name (apply 'append files-filter))))