遍历所有子目录查找文件内容

这个方法现在只有在 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))))