Tools for grepping in Emacs
Karl Fogel
karl.fogel at canonical.com
Sun Apr 12 20:52:17 BST 2009
Jonathan Lange <jml at mumak.net> writes:
> My elisp-fu is very weak, and I needed a lot of help even to get this
> much done. I'd love some feedback on how the code could be nicer, or
> suggestions on how this should best be maintained / shared with the
> rest of the Bazaar / Emacs community.
Your elisp is excellent, for someone who says his elisp-fu is weak!
A few comments below.
> (provide 'bzr-tools)
>
> (defun search-upwards (filename starting-path)
> "Search for `filename' in every directory from `starting-path' up."
> (defun parent-dir (path)
> (file-name-directory (directory-file-name path)))
>
> (let ((path (file-name-as-directory starting-path)))
> (if (file-exists-p (concat path filename))
> path
> (let ((parent (parent-dir path)))
> (if (string= parent path)
> nil
> (search-upwards filename parent))))))
It's unusual to have a defun within a defun; more common, I think, is to
use 'lambda' and 'funcall', e.g.:
(let ((parent-dir (lambda (path)
(file-name-directory (directory-file-name path)))))
(funcall parent-dir "/foo/bar/"))
However, I'm not sure the extra readability of a named function is even
worth it. You could just do
(let ((parent (file-name-directory (directory-file-name path))))
...)
and the meaning would be obvious anyway.
> ;; Run 'code' in directory 'dirname'.
> ;; Copied from twisted-dev.el
> (defmacro with-cd (dirname &rest code)
> `(let ((old-dirname default-directory)
> (start-buffer (current-buffer)))
> (cd ,dirname)
> (unwind-protect (progn , at code)
> (let ((end-buffer (current-buffer)))
> (set-buffer start-buffer)
> (cd old-dirname)
> (set-buffer end-buffer)))))
>
>
> ;; Run 'code' at the root of the branch which dirname is in.
> (defmacro at-branch-root (dirname &rest code)
> `(with-cd (search-upwards ".bzr" (expand-file-name ,dirname)) , at code))
>
>
> (defun bzr-grep (expression dirname)
> (interactive "MSearch for: \nDSearch for %s in: ")
> (with-cd
> (search-upwards ".bzr" (expand-file-name dirname))
> (grep-find (format "bzr ls -V --null | xargs -0 grep -In %s" expression))))
Alexander's point about using 'bzr root' means you could avoid the whole
searching-upwards thing anyway, I guess.
(Why not using 'at-branch-root' in 'bzr-grep', by the way?)
> (defun grep-branch (expression)
> (interactive "MSearch for: ")
> (at-branch-root "."
> (grep-find (format "bzr ls -V --null | xargs -0 grep -In %s" expression))))
>
> (defun branch-todo ()
> (interactive)
> (with-cd (search-upwards ".bzr" (expand-file-name "."))
> (compile "bzr todo" t)))
The only other thing I'd suggest is giving a common prefix to all the
symbols, something beginning with 'bzr-...', if you want to distribute
the code. Prefixes are Emacs's module system, believe it or not :-).
-Karl
More information about the bazaar
mailing list