branch: elpa/projectile commit 99b7ff27d1b9b328914bdfcb5caac6fb08c0e184 Author: lWarne <laurencewa...@gmail.com> Commit: Bozhidar Batsov <bozhi...@batsov.dev>
Allow changing of project type precendence Allow changing of project type precendence in projectile-update-project-type. --- projectile.el | 30 ++++++++++++++++++--------- test/projectile-test.el | 54 +++++++++++++++++++++++++++++++++---------------- 2 files changed, 57 insertions(+), 27 deletions(-) diff --git a/projectile.el b/projectile.el index a3399db58f..1e987c9b56 100644 --- a/projectile.el +++ b/projectile.el @@ -2729,7 +2729,8 @@ test/impl/other files as below: (cl-defun projectile-update-project-type (project-type - &key (marker-files nil marker-files-specified) + &key precedence + (marker-files nil marker-files-specified) (project-file nil project-file-specified) (compilation-dir nil compilation-dir-specified) (configure nil configure-specified) @@ -2745,10 +2746,14 @@ test/impl/other files as below: (related-files-fn nil related-files-fn-specified)) "Update an existing projectile project type. -Non-nil passed items will override existing values for the project type given -by PROJECT-TYPE. Raise an error if PROJECT-TYPE is not already registered -with projectile. The arguments to this function are as for -projectile-register-project-type: +Passed items will override existing values for the project type given +by PROJECT-TYPE. nil can be used to remove a project type attribute. Raise +an error if PROJECT-TYPE is not already registered with projectile. This +function may also take the keyword argument PRECEDENCE which when set to ‘high’ +will make projectile prioritise this project type over other clashing project +types, and a value of ‘low’ will make projectile prefer (all) other project +types by default. Otherwise, the arguments to this function are as for +`projectile-register-project-type': A project type is defined by PROJECT-TYPE, a set of MARKER-FILES, and optional keyword arguments: @@ -2800,11 +2805,16 @@ test/impl/other files as below: (cl-flet* ((project-filter (p) (eq project-type (car p))) (project-map (p) (if (project-filter p) project-type-elt p))) (setq projectile-project-types - (mapcar (lambda (p) (if (eq project-type (car p)) - project-type-elt - p)) - projectile-project-types)) - (error "No existing project found for: %s" project-type))) + (if precedence + (let ((filtered-types + (cl-remove-if #'project-filter projectile-project-types))) + (setq projectile-project-type-cache (make-hash-table)) + (cond ((eq precedence 'high) + (cons project-type-elt filtered-types)) + ((eq precedence 'low) + (append filtered-types (list project-type-elt))) + (t (error "Precendence must be one of '(high low)")))) + (mapcar #'project-map projectile-project-types)))))) (defun projectile-cabal-project-p () "Check if a project contains *.cabal files but no stack.yaml file." diff --git a/test/projectile-test.el b/test/projectile-test.el index c3e544e86d..bd86763e55 100644 --- a/test/projectile-test.el +++ b/test/projectile-test.el @@ -185,23 +185,23 @@ Just delegates OPERATION and ARGS for all operations except for`shell-command`'. (describe "projectile-update-project-type" :var ((mock-projectile-project-types - '((foo marker-files "marker-file" - project-file "project-file" - compilation-dir "compilation-dir" - configure-command "configure" - compile-command "compile" - test-command "test" - install-command "install" - package-command "package" - run-command "run")))) + '((foo marker-files ("marker-file") + project-file "project-file" + compilation-dir "compilation-dir" + configure-command "configure" + compile-command "compile" + test-command "test" + install-command "install" + package-command "package" + run-command "run")))) (it "Updates existing project type in projectile-project-types" (let ((projectile-project-types mock-projectile-project-types)) (projectile-update-project-type 'foo - :marker-files "marker-file2" + :marker-files '("marker-file2") :test-suffix "suffix") (expect projectile-project-types :to-equal - '((foo marker-files "marker-file2" + '((foo marker-files ("marker-file2") project-file "project-file" compilation-dir "compilation-dir" configure-command "configure" @@ -215,10 +215,10 @@ Just delegates OPERATION and ARGS for all operations except for`shell-command`'. (let ((projectile-project-types mock-projectile-project-types)) (projectile-update-project-type 'foo - :marker-files "marker-file2" + :marker-files '("marker-file2") :test-suffix nil) (expect projectile-project-types :to-equal - '((foo marker-files "marker-file2" + '((foo marker-files ("marker-file2") project-file "project-file" compilation-dir "compilation-dir" configure-command "configure" @@ -233,7 +233,7 @@ Just delegates OPERATION and ARGS for all operations except for`shell-command`'. (dummy-val "foo")) (projectile-update-project-type 'foo - :marker-files dummy-val + :marker-files (list dummy-val) :project-file dummy-val :compilation-dir dummy-val :configure dummy-val @@ -248,7 +248,7 @@ Just delegates OPERATION and ARGS for all operations except for`shell-command`'. :test-dir dummy-val :related-files-fn dummy-val) (expect projectile-project-types :to-equal - `((foo marker-files ,dummy-val + `((foo marker-files (,dummy-val) project-file ,dummy-val compilation-dir ,dummy-val configure-command ,dummy-val @@ -266,9 +266,29 @@ Just delegates OPERATION and ARGS for all operations except for`shell-command`'. (let ((projectile-project-types mock-projectile-project-types)) (expect (projectile-update-project-type 'bar - :marker-files "marker-file" + :marker-files '("marker-file") :test-suffix "suffix") - :to-throw)))) + :to-throw))) + (it "changes project type precendence" + (let ((projectile-project-types + '((foo marker-files ("foo")) + (bar marker-files ("foo"))))) + (projectile-test-with-sandbox + (projectile-test-with-files + ("projectA/" "projectA/foo") + (spy-on 'projectile-project-root + :and-return-value + (file-truename (expand-file-name "projectA"))) + (expect (projectile-project-type) :to-equal 'foo) + (projectile-update-project-type 'bar :precedence 'high) + (expect (projectile-project-type) :to-equal 'bar) + (projectile-update-project-type 'bar :precedence 'low) + (expect (projectile-project-type) :to-equal 'foo))))) + (it "errors if :precendence not valid" + (let ((projectile-project-types '((bar marker-files ("foo"))))) + (expect + (projectile-update-project-type 'bar :precedence 'invalid-symbol) + :to-throw)))) (describe "projectile-project-type" (it "detects the type of Projectile's project"