Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

### New features

* Add `projectile-uniquify-dirname-transform`, a project-aware value for `uniquify-dirname-transform` that disambiguates same-named buffers using the project name. Mirrors `project.el`'s `project-uniquify-dirname-transform`.
* [#2008](https://github.com/bbatsov/projectile/issues/2008): Add `projectile-remove-project-type` to unregister a project type. This is the supported way to stop Projectile auto-detecting a type; clearing its `marker-files` does not work (see the related bug fix below).
* [#1936](https://github.com/bbatsov/projectile/issues/1936): Add `projectile-discard-root-cache` command to clear `projectile-project-root-cache` without touching other Projectile caches. Useful after creating or removing a project marker, since the existing `projectile-invalidate-cache` either also drops the file list cache or prompts for a project depending on context.
* Warn once per session when `projectile-indexing-method' is `alien' but the project has a non-empty `.projectile' file, so users notice their dirconfig rules are being bypassed. Controlled by the new `projectile-warn-when-dirconfig-is-ignored' option.
Expand Down
15 changes: 15 additions & 0 deletions doc/modules/ROOT/pages/projects.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -1200,6 +1200,21 @@ When you run `projectile-kill-buffers` (kbd:[s-p k]), the variable
You can also set it to a custom predicate function that receives a buffer and
returns non-nil if the buffer should be killed.

=== Uniquifying buffer names by project

When you open same-named files from different projects (say two `README.md`
files), Emacs's `uniquify` library disambiguates the buffer names using parent
directory components. Projectile can make that disambiguation use the project
name instead, via `projectile-uniquify-dirname-transform`:

[source,elisp]
----
(setq uniquify-dirname-transform #'projectile-uniquify-dirname-transform)
----

Outside of a project the directory is left untouched, so this is safe to set
globally. This mirrors `project.el`'s `project-uniquify-dirname-transform`.

== Configure a Project's Lifecycle Commands and Other Attributes

There are a few variables that are intended to be customized via `.dir-locals.el`.
Expand Down
19 changes: 19 additions & 0 deletions projectile.el
Original file line number Diff line number Diff line change
Expand Up @@ -1684,6 +1684,25 @@ If PROJECT is not specified acts on the current project."
"-"))))


(defun projectile-uniquify-dirname-transform (dirname)
"Project-aware transform for `uniquify-dirname-transform'.
When DIRNAME is inside a project, return a path with the project name
spliced in, so buffers visiting same-named files in different projects
get distinct, project-qualified names. Outside a project DIRNAME is
returned unchanged.

To enable, set `uniquify-dirname-transform' to this function:

(setq uniquify-dirname-transform #\\='projectile-uniquify-dirname-transform)"
(if-let* ((root (projectile-project-root dirname)))
(expand-file-name
(file-name-concat
(file-name-directory root)
(projectile-project-name root)
(file-relative-name dirname root)))
dirname))


;;; Project indexing
(defun projectile-get-project-directories (project-dir)
"Get the list of PROJECT-DIR directories that are of interest to the user.
Expand Down
11 changes: 11 additions & 0 deletions test/projectile-test.el
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,17 @@ by `projectile-files-via-ext-command')."
(let ((projectile-project-name-function (lambda (dir) dir)))
(expect (projectile-project-name) :to-equal "current/project"))))

(describe "projectile-uniquify-dirname-transform"
(it "splices the project name into a directory inside a project"
(spy-on 'projectile-project-root :and-return-value "/home/me/work/checkout-42/")
(spy-on 'projectile-project-name :and-return-value "myproject")
(expect (projectile-uniquify-dirname-transform "/home/me/work/checkout-42/src/")
:to-equal "/home/me/work/checkout-42/myproject/src/"))
(it "returns the directory unchanged outside a project"
(spy-on 'projectile-project-root :and-return-value nil)
(expect (projectile-uniquify-dirname-transform "/tmp/not-a-project/")
:to-equal "/tmp/not-a-project/")))

(describe "projectile-prepend-project-name"
(it "prepends the project name to its parameter"
(spy-on 'projectile-project-name :and-return-value "project")
Expand Down