现在的位置: 首页 > 综合 > 正文

一个emacs扩展,从指定目录或文件中搜索指定关键字

2013年09月19日 ⁄ 综合 ⁄ 共 3861字 ⁄ 字号 评论关闭

    这段时间在熟悉一套系统的代码,经常要查找某个变量或函数名在哪些文件中被引用到了 ,虽然在linux下面grep一下就行了,但要查看每处的上下文,还是得打开文件.还好用的是emacs,有什么不爽就自己扩展
    刚用elisp时倒郁闷了一把,elisp貌视不支持尾递归(??还需查证) ,我一上来就用在scheme中惯用的过程自调用的方式来进行递归查找目录中的文件,结果很轻易就会超过elisp的最大求值嵌套深度,改为用elisp中的while则正常.
   实现了search-direct和search-file二个函数,分别是查找指定目录和指定文件,查找结果会加上文件名和行号,内容在结果窗口显示,在结果行上回车则会自动打开相应文件并跳到相应行.不足还有很多,忙过这段时间再扩展了 :-)   保存下面的代码自己本地目录,再在.emacs中添加(require 'file-search) 就可以了
效果图:

file-search.el

;;; file-search.el

(defconst fs-file-search-buffer-name "*file-search*")

(defvar fs-file-list-length 0)
(defvar fs-file-search-str "")
(defvar fs-match-regexp "")
(defvar fs-file-search-keymap (make-sparse-keymap))
(define-key fs-file-search-keymap (kbd "RET") 'fs-result-choose)

(defface fs-file-name-face '((t (:foreground "red" :bold t :underline t)))
  "Face used to highlight the file name")
(defface fs-line-face '((t (:foreground "green" :bold nil :underline nil)))
  "Face used to highlight the line number")

;;查找列表中所有文件
(defun fs-search-list-file (list)
  (while list
    (let ((file-name (car list)))
      (if (not (file-accessible-directory-p file-name))
          (progn
            (message "current file:%s %d in %d"
                     file-name
                     ( + (- fs-file-list-length (length list)) 1)
                     fs-file-list-length)
            (fs-search-file file-name 1))))
    (setq list (cdr list))))

;;查找指定目录
(defun fs-search-directory (dir-name)
  (if (file-accessible-directory-p dir-name)
      (let ((list (cdr (cdr (directory-files dir-name t fs-match-regexp)))))
        (setq fs-file-list-length (length list))
        (fs-search-list-file list))
    (message "%s is a invaild directory name" dir-name)))

;;查找指定文件
(defun fs-search-file (file-name point)
  (let ((buf (get-buffer (file-name-nondirectory file-name)))
        (bpt 0))
    (with-current-buffer (find-file-noselect file-name)
      (if buf
          (setq bpt (point)))
      (while point
        (goto-char point)
        (setq point (search-forward fs-file-search-str nil '(nil)))
        (if point
            (let ((b-pt (line-beginning-position))
                  (e-pt (line-end-position)))
              (fs-insert-result
               (count-lines 1 point)
               file-name
               (buffer-substring b-pt e-pt)))))
      (if buf
          (goto-char bpt)
          (kill-buffer (current-buffer))))))

;;给出结果buffer
(defun fs-get-search-result-buffer()
  (get-buffer-create fs-file-search-buffer-name))
 
;;插入查找结果
(defun fs-insert-result (line file text)
  (with-current-buffer (fs-get-search-result-buffer)
      (setq buffer-read-only nil)
      (goto-char (point-max))
      (let ((bpt (point)))
        (insert (file-name-nondirectory file))
        (set-text-properties bpt (point-max) '(face fs-file-name-face))
        (put-text-property bpt (point-max) 'keymap fs-file-search-keymap)
        (put-text-property bpt (point-max) 'filename file)
        (put-text-property bpt (point-max) 'nline line))
      (goto-char (point-max))
      (let ((bpt (point)))
        (insert "(" (number-to-string line)  "): ")
        (set-text-properties bpt (point-max) '(face fs-line-face)))
      (insert text "/n")
      (setq buffer-read-only t)))

;;显示结果窗口
(defun fs-show-result-window ()
  (with-current-buffer (fs-get-search-result-buffer)
    (let ((w (or (get-buffer-window fs-file-search-buffer-name)
                (split-window-vertically -10))))
      (set-window-buffer w (current-buffer))
      (select-window w)
      (goto-line 1))))

;;在查找结果上按回车的处理函数
(defun fs-result-choose()
  (interactive)
  (let ((bpt (line-beginning-position)))
    (let ((line (get-text-property bpt 'nline))
          (file (get-text-property bpt 'filename)))
      (select-window (next-window))
      (find-file file)
      (goto-line line))))

;;查找目录
;;;###autoload
(defun search-directory(str dir match-regexp)
  (interactive "ssearch string: /nDsearch directory: /nsmatch-regexp:")
  (kill-buffer (fs-get-search-result-buffer))
  (setq fs-file-search-str str)
  (setq fs-match-regexp match-regexp)
  (fs-search-directory dir)
  (fs-show-result-window))

;;查找目录
;;;###autoload
(defun search-file(str file)
  (interactive "ssearch string: /nffile:")
  (kill-buffer (fs-get-search-result-buffer))
  (setq fs-file-search-str str)
  (fs-search-file file 1)
  (fs-show-result-window))

(provide 'file-search)

抱歉!评论已关闭.