aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBozhidar Batsov <bozhidar@toptal.com>2026-04-25 18:55:30 +0100
committerBozhidar Batsov <bozhidar@toptal.com>2026-04-25 18:55:30 +0100
commit930564202e350d5d6c73d6fc765b1cc29cb48f38 (patch)
tree2e87e2a34cf1cf80a0e438597e3d5bcf39bc4e25
parentf8be23b266aec7108fb4b80410623cd50ba8ded9 (diff)
Skip leading whitespace in dirconfig prefix dispatch
A user accidentally typing " -path/" or " # comment" in .projectile would have the line silently routed to the ignore bucket with the prefix character left intact, because the parser dispatched on the first character of the line without trimming. Skip leading spaces and tabs before the pcase so the +/-/! and comment-prefix markers are matched regardless of indentation. Reported in #1508.
-rw-r--r--CHANGELOG.md1
-rw-r--r--projectile.el4
-rw-r--r--test/projectile-test.el25
3 files changed, 29 insertions, 1 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 654862e..f9e3843 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@
### Bugs fixed
+* [#1508](https://github.com/bbatsov/projectile/issues/1508): Fix dirconfig parser silently treating lines as ignore patterns when the `+`/`-`/`!` prefix or the comment character is preceded by whitespace; leading spaces and tabs are now skipped before prefix dispatch.
* Fix `projectile-files-via-ext-command` executing empty string as shell command for non-git VCS sub-projects.
* Fix `projectile-select-files` crashing on filenames with regexp metacharacters by using `string-search` instead of `string-match`.
* Fix `projectile-find-references` using internal `xref--show-xrefs` API whose signature changed across Emacs versions.
diff --git a/projectile.el b/projectile.el
index 0584f66..2d87bb3 100644
--- a/projectile.el
+++ b/projectile.el
@@ -2170,6 +2170,10 @@ Returns a list of (KEEP IGNORE ENSURE) or nil if the file doesn't exist."
(with-temp-buffer
(insert-file-contents dirconfig)
(while (not (eobp))
+ ;; Skip leading whitespace so prefix dispatch isn't defeated by
+ ;; an accidental space or tab before the +/-/! marker or the
+ ;; configured comment character.
+ (skip-chars-forward " \t")
(pcase (char-after)
;; ignore comment lines if prefix char has been set
((pred (lambda (leading-char)
diff --git a/test/projectile-test.el b/test/projectile-test.el
index 3b67734..4a20e92 100644
--- a/test/projectile-test.el
+++ b/test/projectile-test.el
@@ -549,7 +549,30 @@ Just delegates OPERATION and ARGS for all operations except for`shell-command`'.
"left-wspace"
"right-wspace")
nil)))
- ))
+ )
+ (it "skips leading whitespace before dispatching on the prefix"
+ (spy-on 'file-exists-p :and-return-value t)
+ (spy-on 'insert-file-contents :and-call-fake
+ (lambda (_filename)
+ (save-excursion
+ (insert " -indented-exclude\n"
+ "\t+indented-include\n"
+ " !indented-ensure\n"
+ " no-prefix-indented\n"))))
+ (expect (projectile-parse-dirconfig-file)
+ :to-equal '(("indented-include/")
+ ("indented-exclude" "no-prefix-indented")
+ ("indented-ensure"))))
+ (it "treats indented comment-prefix lines as comments"
+ (spy-on 'file-exists-p :and-return-value t)
+ (spy-on 'insert-file-contents :and-call-fake
+ (lambda (_filename)
+ (save-excursion
+ (insert " # indented comment\n"
+ "-keep-this\n"))))
+ (let ((projectile-dirconfig-comment-prefix ?#))
+ (expect (projectile-parse-dirconfig-file)
+ :to-equal '(nil ("keep-this") nil)))))
(describe "projectile-get-project-directories"
(it "gets the list of project directories"