Browse files

Initial commit.

  • Loading branch information...
0 parents commit 3cce2c01240ac7f1f0a64a81906cd006173d75d6 @wfarr wfarr committed Jan 7, 2009
Showing with 157 additions and 0 deletions.
  1. +3 −0 .gitmodules
  2. +153 −0 find-file-in-project.el
  3. +1 −0 project-el
@@ -0,0 +1,3 @@
+[submodule "project-el"]
+ path = project-el
+ url = git://
@@ -0,0 +1,153 @@
+;;; find-file-in-project.el --- Find files in a project quickly.
+;; Copyright (C) 2006, 2007, 2008 Phil Hagelberg and Doug Alcorn
+;; Author: Phil Hagelberg and Doug Alcorn
+;; URL:
+;; Version: 2.0
+;; Created: 2008-03-18
+;; Keywords: project, convenience
+;; EmacsWiki: FindFileInProject
+;; Package-Requires: ((project-local-variables "0.2"))
+;; This file is NOT part of GNU Emacs.
+;;; License:
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; GNU General Public License for more details.
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+;;; Commentary:
+;; This library depends on GNU find.
+;; This file provides a method for quickly finding any file in a given
+;; project. Projects are defined in two ways. If the
+;; `locate-dominating-file' function is bound, it assumes you are
+;; using Emacs 23, in which case you it will look for a
+;; `.dir-settings.el' file in an ancestor directory of the current
+;; file. Otherwise it uses the `project-local-variables' library,
+;; which looks for a `.emacs-project' file.
+;; By default, it looks only for files whose names match
+;; `ffip-regexp', but it's understood that that variable will be
+;; overridden locally. This can be done either with a mode hook:
+;; (add-hook 'emacs-lisp-mode-hook
+;; (lambda (set (make-local-variable 'ffip-regexp) ".*\\.el")))
+;; or by setting it in your .emacs-project/.dir-settings.el file, in
+;; which case it will get set locally.
+;; You can also be a bit more specific about what files you want to
+;; find. For instance, in a Ruby on Rails project, you may be
+;; interested in all .rb files that don't exist in the "vendor"
+;; directory. In that case you could locally set `ffip-find-options'
+;; to "" from within a hook or your .emacs-project file. The options
+;; accepted in that variable are passed directly to the Unix `find'
+;; command, so any valid arguments for that program are acceptable.
+;; If `ido-mode' is enabled, the menu will use `ido-completing-read'
+;; instead of `completing-read'.
+;; Recommended binding:
+;; (global-set-key (kbd "C-x C-M-f") 'find-file-in-project)
+;;; TODO:
+;; Performance testing with large projects
+;; Switch to using a hash table if it's too slow
+;; Add compatibility with BSD find (PDI; I can't virtualize OS X)
+;;; Code:
+(defvar ffip-patterns
+ '("*.rb" "*.html" "*.el" "*.js" "*.rhtml")
+ "List of patterns to look for with find-file-in-project.")
+(defvar ffip-find-options
+ ""
+ "Extra options to pass to `find' when using find-file-in-project.
+Use this to exclude portions of your project: \"-not -regex \\\".*vendor.*\\\"\"")
+(defvar ffip-project-root nil
+ "If non-nil, overrides the project root directory location.")
+(defun ffip-project-files ()
+ "Return an alist of all filenames in the project and their path.
+Files with duplicate filenames are suffixed with the name of the
+directory they are found in so that they are unique."
+ (let ((file-alist nil))
+ (mapcar (lambda (file)
+ (let ((file-cons (cons (file-name-nondirectory file)
+ (expand-file-name file))))
+ (when (assoc (car file-cons) file-alist)
+ (ffip-uniqueify (assoc (car file-cons) file-alist))
+ (ffip-uniqueify file-cons))
+ (add-to-list 'file-alist file-cons)
+ file-cons))
+ (split-string (shell-command-to-string
+ (format "find %s -type f %s %s"
+ (or ffip-project-root (ffip-project-root))
+ (ffip-join-patterns)
+ ffip-find-options))))))
+;; TODO: Emacs has some built-in uniqueify functions; investigate using those.
+(defun ffip-uniqueify (file-cons)
+ "Set the car of the argument to include the directory name plus the file name."
+ (setcar file-cons
+ (concat (car file-cons) ": "
+ (cadr (reverse (split-string (cdr file-cons) "/"))))))
+(defun ffip-join-patterns ()
+ "Turn `ffip-paterns' into a string that `find' can use."
+ (mapconcat (lambda (pat) (format "-name \"%s\"" pat))
+ ffip-patterns " -or "))
+(defun find-file-in-project ()
+ "Prompt with a completing list of all files in the project to find one.
+The project's scope is defined as the first directory containing
+an `.emacs-project' file. You can override this by locally
+setting the `ffip-project-root' variable."
+ (interactive)
+ (let* ((project-files (ffip-project-files))
+ (file (if (and (boundp 'ido-mode) ido-mode)
+ (ido-completing-read "Find file in project: "
+ (mapcar 'car project-files))
+ (completing-read "Find file in project: "
+ (mapcar 'car project-files)))))
+ (find-file (cdr (assoc file project-files)))))
+(defun ffip-project-root ()
+ "Return the root of the project.
+If `locate-dominating-file' is bound, it will use Emacs' built-in
+functionality; otherwise it will fall back on the definition from
+ (let ((project-root
+ (if (functionp 'locate-dominating-file)
+ (locate-dominating-file default-directory ".dir-settings.el")
+ (require 'project-local-variables)
+ (plv-find-project-file default-directory ""))))
+ (if project-root
+ (file-name-directory project-root)
+ (message "No project was defined for the current file."))))
+(provide 'find-file-in-project)
+;;; find-file-in-project.el ends here
Submodule project-el added at 99ac9b

0 comments on commit 3cce2c0

Please sign in to comment.