emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Looking for interactive `locate-file'


From: Stuart D. Herring
Subject: Re: Looking for interactive `locate-file'
Date: Tue, 6 Mar 2007 08:23:07 -0800 (PST)
User-agent: SquirrelMail/1.4.8-2.el3.7lanl

> Dear list-
>
> I would like to be able to interactive find a file inside a list of
> paths, interactively, and in a way that supports some basic pattern
> matching. (For reference, the reason I want this is that Eclipse has
> it, and I find it quite useful.) Currently, I have a first
> approximation [1], but, it sucks. All it does is ask for a (possibly
> non-existent) filename, then look for that in a default list of paths.

What I have written is an improvement on this approximation: it does
recursive searches and automatically figures out where GCC keeps its
include files.

;; Should these be organized by extension or so?
(defvar common-file-locations
  (eval-when-compile
    (nconc
     (let ((str (shell-command-to-string "g++ -v -xc++ /dev/null")))
       (and
        (string-match "^#include <...> search starts
here:\n\\(\\(?:.*\n\\)*?\\)End of search list." str)
        (split-string (match-string 1 str) " *\n *\\|^ *")))
     '("/etc" "~")))
  "Directories in which to find common files.")

(defun locate-common-file (name &optional noisy)
  "Return full file name ending in NAME, or nil if not found.
NAME is a relative file name.
Looks in `common-file-locations', then looks in all directories they contain.
The current directory is considered to be the first element of the list.
If called interactively (NOISY is numeric), print the name.
If NOISY is otherwise non-nil, print messages during search."
  (interactive "sCommon file: \np")
  (let* ((places (cons default-directory common-file-locations))
         (ret (save-match-data
                (catch 'file
                  (dolist (dir places)
                    (let ((full (expand-file-name name dir)))
                      (if (file-regular-p full) (throw 'file full))))
                  (dolist (dir places)
                    (if noisy (message "Searching %s..." dir))
                    (locate-common-file-0 name dir)) nil))))
    (if (numberp noisy) (if ret (message "%s is %s" name ret)
                          (message "%s not found" name)))
    ret))

(defun locate-common-file-0 (name dir)
  "Throw full name of file in DIR ending in NAME to `file'.
Return normally if not found."
  (setq dir (file-name-as-directory dir))
  (let ((full (expand-file-name name dir)))
    (if (file-regular-p full) (throw 'file full)))
  (dolist (entry (directory-files dir t))
    (or (file-symlink-p entry)
        (string-match "\\.\\.?" (file-name-nondirectory entry))
        (and (file-directory-p entry) (file-readable-p entry)
             (locate-common-file-0 name entry)))))

Then I have this command to call it, whose utility is in its default value:

(defvar common-file-characters "a-zA-Z0-9-_+./"
  "Characters composing common file names, for use with `find-common-file'.
The default is chosen to be useful with #include directives.")

(defun find-common-file (name)
  "Visit common file NAME.
See `locate-common-file'."
  (interactive
   (list
    (let ((def (buffer-substring
                (point-after (skip-chars-backward common-file-characters))
                (point-after (skip-chars-forward common-file-characters))))
          val)
      (if (zerop (length def)) (setq def nil))
      (setq val (read-string
                 (if def (format "Common file: (default %s) " def)
                   "Common file: ") nil def))
      (if (zerop (length val)) def val))))
  (find-file (or (locate-common-file name t)
                 (error "Cannot find common file: %s" name))))

Together it makes header files (my original application) a cinch, but it
works on lots of other things too.  Obviously it doesn't deal with file
name patterns, but I've found it useful.  (If others do, too, I'll
probably post it at the EmacsWiki page Drew mentioned.)

Davis

-- 
This product is sold by volume, not by mass.  If it appears too dense or
too sparse, it is because mass-energy conversion has occurred during
shipping.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]