Skip to content

Commit

Permalink
Merge branch 'master' of github.com:bbatsov/projectile into avoid_she…
Browse files Browse the repository at this point in the history
…ll_command_to_string
  • Loading branch information
colonelpanic8 committed Aug 16, 2016
2 parents 8490928 + f1a1e74 commit 99e5797
Show file tree
Hide file tree
Showing 6 changed files with 122 additions and 42 deletions.
17 changes: 16 additions & 1 deletion CHANGELOG.md
Expand Up @@ -2,8 +2,21 @@

## master (unreleased)

### Changes

* Ignore backup files in `projectile-get-other-files`.

### Bugs fixed

* [#1024](https://github.com/bbatsov/projectile/issues/1024): Do not cache ignored project files.
* [#1022](https://github.com/bbatsov/projectile/issues/1022): Scan for Fossil's checkout DB, not its config DB.
* [#1007](https://github.com/bbatsov/projectile/issues/1007): Make use of `projectile-go-function`.

## 0.14.0 (2016-07-08)

### New features

* Add [elixir](http://elixir-lang.org) project type.
* Add [emacs-cask](https://github.com/cask/cask) project type.
* Add [boot-clj](https://github.com/boot-clj/boot) project type.
* Add [racket](http://racket-lang.org) project type.
Expand All @@ -24,11 +37,12 @@
* New command `projectile-run-eshell` (<kbd>C-c p x e</kbd>).
* New command `projectile-run-term` (<kbd>C-c p x t</kbd>).
* Let user unignore files in `.projectile` with the ! prefix.
* Add a command to add all projects in a directory to the cache (`projectile-discover-projects-in-directory`).

### Changes

* Prefer ag's internal .gitignore parsing.
* Always use external find-tag implementations.
* Added variable to control use of external find-tag implementations.
* Specify `--with-keep.source` argument when installing R projects

### Bugs fixed
Expand All @@ -41,6 +55,7 @@
* [#957](https://github.com/bbatsov/projectile/pull/957): When opening a specified file from the terminal, do not error inside of `projectile-cache-current-file`.
* [#984](https://github.com/bbatsov/projectile/pull/984): Error when a project is a symlink that changes target.
* [#1044](https://github.com/bbatsov/projectile/issues/1044): Replace `shell-command-to-string` invocations with `call-process` invocations where possible to avoid shell startup cost.
* [#1013](https://github.com/bbatsov/projectile/issues/1013): projectile-project-buffer-p may return incorrect result on Windows.

## 0.13.0 (2015-10-21)

Expand Down
3 changes: 1 addition & 2 deletions Cask
Expand Up @@ -6,5 +6,4 @@
(development
(depends-on "noflet")
(depends-on "helm")
(depends-on "ag")
(depends-on "el-mock"))
(depends-on "ag"))
4 changes: 4 additions & 0 deletions README.md
Expand Up @@ -75,6 +75,9 @@ You can install Projectile with the following command:

<kbd>M-x</kbd> `package-install` <kbd>[RET]</kbd> `projectile` <kbd>[RET]</kbd>

Alternatively, users of Debian 9 or later or Ubuntu 16.04 or later may
simply `apt-get install elpa-projectile`.

### Basic Usage

Enable `projectile-mode`, open a file in one of your projects and type a command such as <kbd>C-c p f</kbd>.
Expand All @@ -85,6 +88,7 @@ See the user manual for more details.

There are a number of packages that built on top of the basic functionality provided by Projectile:

* [counsel-projectile](https://github.com/ericdanan/counsel-projectile) provides Ivy integration
* [helm-projectile](https://github.com/bbatsov/helm-projectile) provides Helm integration
* [persp-projectile](https://github.com/bbatsov/persp-projectile) provides perspective.el integration
* [projectile-rails](https://github.com/asok/projectile-rails) provides extra functionality for Ruby on Rails projects
Expand Down
2 changes: 1 addition & 1 deletion doc/usage.md
Expand Up @@ -2,7 +2,7 @@

### Basic setup

To add a project to Projectile, open a file in the project and enable `projectile-mode` in that buffer.
To add a project to Projectile, open a file in the project and enable `projectile-mode` in that buffer. If you have a projects directory, you can tell Projectile about all of the projects in it with the command `M-x projectile-discover-projects-in-directory`.

To make Projectile automatically remember projects that you access files in, enable Projectile globally:

Expand Down
137 changes: 99 additions & 38 deletions projectile.el
Expand Up @@ -5,7 +5,7 @@
;; Author: Bozhidar Batsov <bozhidar@batsov.com>
;; URL: https://github.com/bbatsov/projectile
;; Keywords: project, convenience
;; Version: 0.14.0-cvs
;; Version: 0.14.0
;; Package-Requires: ((dash "2.11.0") (pkg-info "0.4"))

;; This file is NOT part of GNU Emacs.
Expand Down Expand Up @@ -219,6 +219,26 @@ Otherwise consider the current directory the project root."
:group 'projectile
:type 'string)

(defcustom projectile-tags-backend 'auto
"The tag backend that Projectile should use.
If set to 'auto', `projectile-find-tag' will automatically choose
which backend to use. Preference order is ggtags -> etags-select
-> find-tag. Variable can also be set to specify which backend to
use. If selected backend is unavailable, fall back to `find-tag'.
If this variable is set to 'auto' and ggtags is available, or if
set to 'ggtags', then ggtags will be used for
`projectile-regenerate-tags'. For all other settings
`projectile-tags-command' will be used."
:group 'projectile
:type '(radio
(const :tag "auto" auto)
(const :tag "ggtags" ggtags)
(const :tag "etags" etags-select)
(const :tag "standard" find-tag))
:package-version '(projectile . "0.14.0"))

(defcustom projectile-sort-order 'default
"The sort order used for a project's files."
:group 'projectile
Expand Down Expand Up @@ -703,8 +723,11 @@ The cache is created both in memory and on the hard drive."
;; cache opened files automatically to reduce the need for cache invalidation
(defun projectile-cache-files-find-file-hook ()
"Function for caching files with `find-file-hook'."
(when (and projectile-enable-caching (projectile-project-p))
(projectile-cache-current-file)))
(let ((project-root (projectile-project-p)))
(when (and projectile-enable-caching
project-root
(not (projectile-ignored-project-p project-root)))
(projectile-cache-current-file))))

(defun projectile-cache-projects-find-file-hook ()
"Function for caching projects with `find-file-hook'."
Expand All @@ -722,6 +745,23 @@ The cache is created both in memory and on the hard drive."
projectile-cache-file))
(projectile-invalidate-cache nil)))

;;;###autoload
(defun projectile-discover-projects-in-directory (directory)
"Discover any projects in DIRECTORY and add them to the projectile cache.
This function is not recursive and only adds projects with roots
at the top level of DIRECTORY."
(interactive
(list (read-directory-name "Starting directory: ")))
(let ((subdirs (directory-files directory t)))
(mapcar
(lambda (dir)
(when (and (file-directory-p dir)
(not (member (file-name-nondirectory dir) '(".." "."))))
(let ((default-directory dir))
(when (projectile-project-p)
(projectile-add-known-project (projectile-project-root))))))
subdirs)))


(defadvice delete-file (before purge-from-projectile-cache (filename &optional trash))
(if (and projectile-enable-caching (projectile-project-p))
Expand Down Expand Up @@ -898,7 +938,7 @@ Files are returned as relative paths to the project root."
:type 'string
:package-version '(projectile "0.14.0"))

(defcustom projectile-hg-command "hg locate -0 -I ."
(defcustom projectile-hg-command "hg locate -f -0 -I ."
"Command used by projectile to get the files in a hg project."
:group 'projectile
:type 'string)
Expand Down Expand Up @@ -1134,7 +1174,7 @@ this case unignored files will be absent from FILES."
(string-equal (file-remote-p default-directory)
(file-remote-p project-root))
(not (string-match-p "^http\\(s\\)?://" default-directory))
(string-prefix-p project-root (file-truename default-directory)))))
(string-prefix-p project-root (file-truename default-directory) (eq system-type 'windows-nt)))))

(defun projectile-ignored-buffer-p (buffer)
"Check if BUFFER should be ignored."
Expand Down Expand Up @@ -1588,6 +1628,8 @@ With FLEX-MATCHING, match any file that contains the base name of current file"
(concat "\." (file-name-extension project-file))))))
candidates))
file-list)))
(candidates
(-filter (lambda (file) (not (backup-file-name-p file))) candidates))
(candidates
(-sort (lambda (file _)
(let ((candidate-dirname (file-name-nondirectory (directory-file-name (file-name-directory file)))))
Expand Down Expand Up @@ -1818,6 +1860,22 @@ a COMPILE-CMD, a TEST-CMD, and a RUN-CMD."
'run-command run-cmd)
projectile-project-types))

(defun projectile-cabal ()
"Check if a project contains *.cabal files but no stack.yaml file."
(and (projectile-verify-file "*.cabal")
(not (projectile-verify-file "stack.yaml"))))

(defun projectile-go ()
"Check if a project contains Go source files."
(-any? (lambda (file)
(string= (file-name-extension file) "go"))
(projectile-current-project-files)))

(defcustom projectile-go-function 'projectile-go
"Function to determine if project's type is go."
:group 'projectile
:type 'function)

(projectile-register-project-type 'emacs-cask '("Cask") "cask install")
(projectile-register-project-type 'rails-rspec '("Gemfile" "app" "lib" "db" "config" "spec") "bundle exec rails server" "bundle exec rspec")
(projectile-register-project-type 'rails-test '("Gemfile" "app" "lib" "db" "config" "test") "bundle exec rails server" "bundle exec rake test")
Expand Down Expand Up @@ -1845,24 +1903,9 @@ a COMPILE-CMD, a TEST-CMD, and a RUN-CMD."
(projectile-register-project-type 'haskell-cabal #'projectile-cabal "cabal build" "cabal test")
(projectile-register-project-type 'rust-cargo '("Cargo.toml") "cargo build" "cargo test")
(projectile-register-project-type 'r '("DESCRIPTION") "R CMD INSTALL --with-keep.source ." (concat "R CMD check -o " temporary-file-directory " ."))
(projectile-register-project-type 'go #'projectile-go "go build ./..." "go test ./...")
(projectile-register-project-type 'go projectile-go-function "go build ./..." "go test ./...")
(projectile-register-project-type 'racket '("info.rkt") nil "raco test .")

(defun projectile-cabal ()
"Check if a project contains *.cabal files but no stack.yaml file."
(and (projectile-verify-file "*.cabal")
(not (projectile-verify-file "stack.yaml"))))

(defun projectile-go ()
"Check if a project contains Go source files."
(-any? (lambda (file)
(string= (file-name-extension file) "go"))
(projectile-current-project-files)))

(defcustom projectile-go-function 'projectile-go
"Function to determine if project's type is go."
:group 'projectile
:type 'function)
(projectile-register-project-type 'elixir '("mix.exs") "mix compile" "mix test")

(defvar-local projectile-project-type nil
"Buffer local var for overriding the auto-detected project type.
Expand Down Expand Up @@ -1914,13 +1957,15 @@ PROJECT-ROOT is the targeted directory. If nil, use
(cond
((projectile-file-exists-p (expand-file-name ".git" project-root)) 'git)
((projectile-file-exists-p (expand-file-name ".hg" project-root)) 'hg)
((projectile-file-exists-p (expand-file-name ".fossil" project-root)) 'fossil)
((projectile-file-exists-p (expand-file-name ".fslckout" project-root)) 'fossil)
((projectile-file-exists-p (expand-file-name "_FOSSIL_" project-root)) 'fossil)
((projectile-file-exists-p (expand-file-name ".bzr" project-root)) 'bzr)
((projectile-file-exists-p (expand-file-name "_darcs" project-root)) 'darcs)
((projectile-file-exists-p (expand-file-name ".svn" project-root)) 'svn)
((projectile-locate-dominating-file project-root ".git") 'git)
((projectile-locate-dominating-file project-root ".hg") 'hg)
((projectile-locate-dominating-file project-root ".fossil") 'fossil)
((projectile-locate-dominating-file project-root ".fslckout") 'fossil)
((projectile-locate-dominating-file project-root "_FOSSIL_") 'fossil)
((projectile-locate-dominating-file project-root ".bzr") 'bzr)
((projectile-locate-dominating-file project-root "_darcs") 'darcs)
((projectile-locate-dominating-file project-root ".svn") 'svn)
Expand Down Expand Up @@ -1998,10 +2043,11 @@ It assumes the test/ folder is at the same level as src/."
((member project-type '(rebar)) "_SUITE")
((member project-type '(emacs-cask)) "-test")
((member project-type '(rails-rspec ruby-rspec)) "_spec")
((member project-type '(rails-test ruby-test lein-test boot-clj go)) "_test")
((member project-type '(rails-test ruby-test lein-test boot-clj go elixir)) "_test")
((member project-type '(scons)) "test")
((member project-type '(maven symfony)) "Test")
((member project-type '(gradle gradlew grails)) "Spec")))
((member project-type '(gradle gradlew grails)) "Spec")
((member project-type '(sbt)) "Spec")))

(defun projectile-dirname-matching-count (a b)
"Count matching dirnames ascending file paths."
Expand Down Expand Up @@ -2167,7 +2213,8 @@ regular expression."
(defun projectile-regenerate-tags ()
"Regenerate the project's [e|g]tags."
(interactive)
(if (boundp 'ggtags-mode)
(if (and (boundp 'ggtags-mode)
(memq projectile-tags-backend '(auto ggtags)))
(progn
(let* ((ggtags-project-root (projectile-project-root))
(default-directory ggtags-project-root))
Expand All @@ -2186,7 +2233,8 @@ regular expression."
(buffer-substring (point-min) (point-max)))))
(unless (zerop exit-code)
(error shell-output))
(visit-tags-table tags-file))))
(visit-tags-table tags-file)
(message "Regenerated %s" tags-file))))

(defun projectile-visit-project-tags-table ()
"Visit the current project's tags table."
Expand All @@ -2196,19 +2244,31 @@ regular expression."
(with-demoted-errors "Error loading tags-file: %s"
(visit-tags-table tags-file t))))))

(defun projectile-determine-find-tag-fn ()
"Determine which function to use for a call to `projectile-find-tag'."
(cond
((eq projectile-tags-backend 'auto)
(cond
((fboundp 'ggtags-find-tag-dwim)
'ggtags-find-tag-dwim)
((fboundp 'etags-select-find-tag)
'etags-select-find-tag)
(t 'find-tag)))
((eq projectile-tags-backend 'ggtags)
(if (fboundp 'ggtags-find-tag-dwim)
'ggtags-find-tag-dwim 'find-tag))
((eq projectile-tags-backend 'etags-select)
(if (fboundp 'etags-select-find-tag)
'etags-select-find-tag 'find-tag))
(t 'find-tag)))

;;;###autoload
(defun projectile-find-tag ()
"Find tag in project."
(interactive)
(projectile-visit-project-tags-table)
;; Auto-discover the user's preference for tags
(let ((find-tag-fn (cond
((fboundp 'ggtags-find-tag-dwim)
'ggtags-find-tag-dwim)
((fboundp 'etags-select-find-tag)
'etags-select-find-tag)
(t
'find-tag))))
(let ((find-tag-fn (projectile-determine-find-tag-fn)))
(call-interactively find-tag-fn)))

(defmacro projectile-with-default-dir (dir &rest body)
Expand Down Expand Up @@ -2250,8 +2310,8 @@ regular expression."
"Invoke `eshell' in the project's root."
(interactive)
(let ((eshell-buffer-name (concat "*eshell " (projectile-project-name) "*")))
(projectile-with-default-dir (projectile-project-root)
(eshell))))
(projectile-with-default-dir (projectile-project-root)
(eshell))))

;;;###autoload
(defun projectile-run-term (program)
Expand Down Expand Up @@ -2842,7 +2902,7 @@ overwriting each other's changes."
(projectile-save-known-projects)))

(define-ibuffer-filter projectile-files
"Show Ibuffer with all buffers in the current project."
"Show Ibuffer with all buffers in the current project."
(:reader (read-directory-name "Project root: " (ignore-errors (projectile-project-root)))
:description nil)
(with-current-buffer buf
Expand Down Expand Up @@ -3093,6 +3153,7 @@ is chosen."
["Open project in dired" projectile-dired]
["Switch to project" projectile-switch-project]
["Switch to open project" projectile-switch-open-project]
["Discover projects in directory" projectile-discover-projects-in-directory]
["Search in project (grep)" projectile-grep]
["Search in project (ag)" projectile-ag]
["Replace in project" projectile-replace]
Expand Down
1 change: 1 addition & 0 deletions test/projectile-test.el
Expand Up @@ -594,6 +594,7 @@
"src/some_module/same_name.c"
"include1/same_name.h"
"include1/test1.h"
"include1/test1.h~"
"include1/test2.h"
"include1/test1.hpp"
"include2/some_module/same_name.h"
Expand Down

0 comments on commit 99e5797

Please sign in to comment.