projectile
projectile copied to clipboard
cannot exit projectile-skel-dir-locals while keeping the variables already entered
Expected behavior
When I enter an empty variable name, the template should exit and retain the previous input.
Projectile works well, but there seems to be no detailed documentation on how to properly use edit .dir-locals.el, I tried to use projectile-skel-dir-locals to edit it, but I can't exit the loop of input variables, if I press C-g or esc, my minibuffer will If I press C-g or esc, my minibuffer will close and the variables that have been entered before will disappear. I tried to exit the switch-case skeleton as in sh-mode by typing an empty string, but that doesn't work either.
I use vertico, and when I try to use a minimal configuration with only projectile, I also cannot exit the input loop of the skeleton correctly. This causes me to enter the input loop, press c-g to exit, and only the first input variable is saved, the rest of the variable input disappears.
What is the correct way to use projectile-skel-dir-locals, please help me out and thanks in advance!
The correct behavior should be like this
((nil . ((compile-command . "make -k"))
Actual behavior
((nil . ((compile-command . "make -k")
( .
Steps to reproduce the problem
M-x projectile-skel-dir-locals <cr>
c-file-style <cr>
"llvm.org" <cr>
M-x vertico-exit-input
Environment & Version information
Projectile version information
Projectile 20230317.1101
Emacs version
GNU Emacs 29.0.91 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.38, cairo version 1.17.8) of 2023-05-26
Operating system
E.g. Gentoo Linux 2.13
To add to that projectile-edit-dir-locals
behaves similar, although M-x vertico-exit-input
will also delete the fresh content (projectile 2.8.0
).
Also observing this. I'm not familiar with the Emacs skeleton system, but want to dig into the interaction between it and Projectile's define-skeleton
to discover the root cause.
I found that Emacs 27.2 and before did not have this problem, while Emacs 28.1 and after
- Clears out the whole skeleton on
C-g
at the prompt. - Keeps on looping even with an empty variable name.
Looking at the diff of skeleton.el
between 27.2 and 28.1, the most significant change seems to be this commit that migrates it to lexical binding, but I'm not sure if that's the change that causes the issue.
Missing str
in sub-skeleton?
(define-skeleton projectile-skel-dir-locals
"Insert a .dir-locals.el template."
nil
"((nil . ("
; This sub-skeleton doesn't have a `str`?
("" '(projectile-skel-variable-cons) \n)
resume:
")))")
One thing I noticed is that in the current implementation, the skeleton has a sub-skeleton without a str
. On the Skeleton Language page on the Emacs manual, it's stated that a sub-skeleton must have a str
(emphasis by myself):
skeleton Subskeletons are inserted recursively, not once, but as often as the user enters something at the subskeletons interactor. Thus there must be a str in the subskeleton. They can also be used non-interactively, when prompt is a lisp-expression that returns successive list-elements.
The code of skeleton.el
itself is too difficult for me to fully understand, so I'm not sure if this requirement stated on the manual is still the case.
I came up with a version of projectile-skel-dir-locals
that, unlike the current implementation, has a str
in the sub-skeleton. This version terminates properly on both empty variable name and empty value. It still wipes out the whole skeleton on C-g
[^1], but terminating on empty variable name is good enough for me.
(define-skeleton projectile-skel-dir-locals
"Insert a .dir-locals.el template."
nil
"((nil . ("
- ("" '(projectile-skel-variable-cons) \n)
+ ("Value: "
+ "("
+ (let ((var-name (projectile-read-variable)))
+ (if (string-empty-p var-name)
+ ;; Stop the sub-skeleton iteration on empty variable name.
+ (signal 'quit t)
+ var-name))
+ " . " str ")" \n)
resume:
")))")
[^1]: python-skeleton-if
also wipes out the whole skeleton on C-g
starting from Emacs 28.1.