Max Nikulin <maniku...@gmail.com> writes:
> On 12/03/2022 02:59, Tim Cross wrote: >> Ignacio Casso writes: > >>> (let ((org-capture-templates >>> '(("d" "default" entry >>> (file+headline org-default-notes-file "Tasks") >>> "* %?")))) >>> (org-capture nil "d"))) >>> >>> I put an autoload cookie myself and it doesn't fix it, so it's probably >>> not that. It's the first time I manage autoload cookies though, so I may >>> have done something wrong. I only tested that the autoload cookie worked >>> by checking that before loading org-capture, org-capture-templates >>> appears in the completion list for C-h v, and I can evaluate it. >> While I don't know if this is a bug, it certainly doesn't seem to be >> doing the right thing from an 'intuitive' point of view. I would expect >> when a variable is bound to a value inside a let and a function is then >> called which uses that variable, the initial let bound value should be >> used and the result be the same regardless of whether org-capture has or >> has not been loaded. It means there is a hidden side-effect here, which >> isn't good and probably needs more analysis. If you had set the value >> using setq rather than as a let form, it wouldn't be overridden when >> org-capture is loaded, so why does it when it is a let binding? > > For `defcustom' autoload generates no more than > > (defvar org-capture-templates nil "...") > > It seems, behavior depends on whether `org-capture-templates' has the :set > attribute. The setter receives nil instead of the let-bound value. I can not > say > I understand the tricks with bypassing lexical binding in `defcustom' and some > checks in `custom-declare-variable'. Since emacs-26 something has changed: > > https://git.savannah.gnu.org/cgit/emacs.git/commit/?id=6309131349 >> - ;; Use defvar to set the docstring as well as the special-variable-p flag. >> - ;; FIXME: We should reproduce more of `defvar's behavior, such as the >> warning >> - ;; when the var is currently let-bound. >> - (if (not (default-boundp symbol)) > > I am unsure that the setter of `defcustom' should get let-bound value in the > case of autoloading since it might lead to fragile behavior. > > I still think that explicit templates argument for `org-capture' is better > than > relying on autoloading. > Yes, it would seem that something has changed and I suspect it may be related to the introduction of lexical bindings. Explicit template arguments for org-capture may or may not be better, I don't know. However, this behaviour seems like it may be the tip of a much bigger issue outside of org-mode and potential source of bugs for Emacs. Bottom line is I don't think any function should behave differently depending on when autoload runs. It could be because the setter used in the defcustom is incorrect since the change a while back to use lexical-binding by default or something else. It looks like the setter on org-capture-template is used to do some form of conversion on the template specification to force a new format. Not sure how long that has been there or whether it is actually still required. Could be that this setter was added to aid in transition to a new template format which could/should be removed at some point. Personally, I've never liked custom setters. I typically avoid the custom interface. However, exotic custom variable setters can mean that using setq won't work correctly and you need to use custom-set-variable etc. In fact, I'm seeing a lot more use of custom-set-variable* in init code recently - something which was almost never seen 20 years ago. Regardless, I don't think having the situation where the programmer must know (guess) whether autoload will/could execute during the evaluation of code they write is tenable and am beginning to suspect it may be an Emacs bug OR a subtle bug in org-mode as a result to the transition to lexical binding as the default. My recommendation would be to come up with a non-org specific example which reproduces the behaviour and then ask on emacs-devel, using the example to demonstrate the issue. > Reading the code I noticed `org-capture-templates-contexts' so I wonder if it > might help for the original use case. I thought about that as well. However, from re-reading the OP's posts, I suspect not. org-capture-templates-contexts seems to be useful when you want to restrict access to some templates based on context. However, from reading the OP's posts, I get the impression that what they want is for templates to be different based on context i.e. they still want the template associated with 'd', but want its definition to be different. It is possible org-capture-template-contexts might provide an alternative solution where you don't need to dynamically modify/add templates in this manner. For example, you could have all your templates defined, but only offer those relevant based on context. However, I guess this would mean having to have different template keys, which might be an issue.