Permalink
Browse files

Toss find-file-in-git-project in favor of find-file-in-project

  • Loading branch information...
1 parent 121842e commit e80c7c928358fda2536e296f8cb782099060510d @candera committed May 15, 2012
Showing with 177 additions and 2 deletions.
  1. +165 −0 find-file-in-project.el
  2. +12 −2 init.el
View
165 find-file-in-project.el
@@ -0,0 +1,165 @@
+
+;;; find-file-in-project.el --- Find files in a project quickly.
+
+;; Copyright (C) 2006-2009, 2011
+;; Phil Hagelberg, Doug Alcorn, and Will Farrington
+
+;; Author: Phil Hagelberg, Doug Alcorn, and Will Farrington
+;; URL: http://www.emacswiki.org/cgi-bin/wiki/FindFileInProject
+;; Git: git://github.com/technomancy/find-file-in-project.git
+;; Version: 3.0
+;; Created: 2008-03-18
+;; Keywords: project, convenience
+;; EmacsWiki: FindFileInProject
+
+;; 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
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; 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 provides a couple methods for quickly finding any file
+;; in a given project. It depends on GNU find.
+
+;; A project is found by searching up the directory tree until a file
+;; is found that matches `ffip-project-file'. (".git" by default.)
+;; You can set `ffip-project-root-function' to provide an alternate
+;; function to search for the project root. By default, it looks only
+;; for files whose names match `ffip-patterns',
+
+;; If you have so many files that it becomes unwieldy, you can set
+;; `ffip-find-options' to a string which will be passed to the `find'
+;; invocation in order to exclude irrelevant subdirectories. 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 set `ffip-find-options' to "-not -regex \".*vendor.*\"".
+
+;; All these variables may be overridden on a per-directory basis in
+;; your .dir-locals.el. See (info "(Emacs) Directory Variables") for
+;; details.
+
+;; Recommended binding: (global-set-key (kbd "C-x f") 'find-file-in-project)
+
+;;; TODO:
+
+;; Add compatibility with BSD find (PDI; I can't virtualize OS X)
+
+;;; Code:
+
+(defvar ffip-project-file ".git"
+ "The file that should be used to define a project root.
+
+May be set using .dir-locals.el.")
+
+(defvar ffip-patterns
+ '("*.html" "*.org" "*.txt" "*.md" "*.el" "*.clj" "*.py" "*.rb" "*.js" "*.pl"
+ "*.sh" "*.erl" "*.hs" "*.ml")
+ "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 \\\".*svn.*\\\"\".")
+
+(defvar ffip-project-root nil
+ "If non-nil, overrides the project root directory location.")
+
+(defvar ffip-project-root-function nil
+ "If non-nil, this function is called to determine the project root.
+
+This overrides variable `ffip-project-root' when set.")
+
+(defvar ffip-limit 512
+ "Limit results to this many files.")
+
+(defun ffip-project-root ()
+ "Return the root of the project."
+ (let ((project-root (or ffip-project-root
+ (if (functionp ffip-project-root-function)
+ (funcall ffip-project-root-function)
+ (locate-dominating-file default-directory
+ ffip-project-file)))))
+ (or project-root
+ (progn (message "No project was defined for the current file.")
+ nil))))
+
+(defun ffip-uniqueify (file-cons)
+ "Set the car of FILE-CONS to include the directory name plus the file name."
+ ;; TODO: see if we can use uniquify.el
+ (setcar file-cons
+ (concat (cadr (reverse (split-string (cdr file-cons) "/"))) "/"
+ (car 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 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 | head -n %s"
+ (or ffip-project-root
+ (ffip-project-root)
+ (error "No project root found"))
+ (ffip-join-patterns)
+ ffip-find-options
+ ffip-limit))))))
+
+;;;###autoload
+(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 variable `ffip-project-root'."
+ (interactive)
+ (let* ((project-files (ffip-project-files))
+ (files (mapcar 'car project-files))
+ (file (if (and (boundp 'ido-mode) ido-mode)
+ (ido-completing-read "Find file in project: " files)
+ (completing-read "Find file in project: " files))))
+ (find-file (cdr (assoc file project-files)))))
+
+;;;###autoload
+(defalias 'ffip 'find-file-in-project)
+
+;; safe locals
+;;;###autoload
+(progn
+ (put 'ffip-patterns 'safe-local-variable 'listp)
+ (put 'ffip-find-options 'safe-local-variable 'stringp)
+ (put 'ffip-project-file 'safe-local-variable 'stringp)
+ (put 'ffip-project-root 'safe-local-variable 'stringp)
+ (put 'ffip-project-root-function 'safe-local-variable 'functionp)
+ (put 'ffip-limit 'safe-local-variable 'integerp))
+
+(provide 'find-file-in-project)
+;;; find-file-in-project.el ends here
View
14 init.el
@@ -908,8 +908,18 @@ if the major mode is one of 'delete-trailing-whitespace-modes'"
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(require 'find-file-in-git-repo)
-(global-set-key (kbd "C-x M-f") 'find-file-in-git-repo)
+;; Deprecating in favor of find-file-in-project
+;; (require 'find-file-in-git-repo)
+;; (global-set-key (kbd "C-x M-f") 'find-file-in-git-repo)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; find-file-in-project
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(require 'find-file-in-project)
+(global-set-key (kbd "C-x M-f") 'find-file-in-project)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;

0 comments on commit e80c7c9

Please sign in to comment.