mirror of
https://github.com/protesilaos/denote.git
synced 2026-09-10 07:16:20 -04:00
Honor unapplied dir-local denote-directory in denote-directories
Directory-local variables are applied only after the major mode body
has run: 'run-mode-hooks' calls 'hack-local-variables' after the mode
hooks. Anything that resolves Denote paths while the mode is still
initializing therefore sees the global 'denote-directory' instead of
the silo's dir-local value. Org's startup link previews
('org-startup-with-link-previews') are one such case: previews of
'denote:' links inside a silo resolve against the wrong directory.
Make 'denote-directories' read the dir-local value directly from the
directory-local variables data in that window. A buffer-local value
or an explicit dynamic binding of 'denote-directory' still takes
precedence, preserving the documented let-binding override.
The read uses 'hack-dir-local--get-variables', which is available in
Emacs 30 or higher; older versions behave as before. The value is
read without the safe-local-variable filter, which is equivalent for
this variable because its 'safe-local-variable' predicate accepts any
string or list value.
This commit is contained in:
parent
1004f735b7
commit
2fe3bcdf68
47
denote.el
47
denote.el
|
|
@ -961,25 +961,50 @@ Make any parent directories as well."
|
|||
(mapcar get-dir directory-or-directories)
|
||||
(list (funcall get-dir directory-or-directories)))))
|
||||
|
||||
(declare-function hack-dir-local--get-variables "files" (&optional predicate))
|
||||
|
||||
(defun denote-directories--dir-local-value ()
|
||||
"Return the dir-local value of variable `denote-directory', if any.
|
||||
Read the value directly from the directory-local variables data, so
|
||||
that it is available even before `hack-local-variables' has applied it.
|
||||
Major mode bodies run before directory-local variables are applied to
|
||||
the buffer, so anything that resolves Denote paths during mode setup,
|
||||
such as Org link previews at startup, would otherwise see the wrong
|
||||
value inside a silo.
|
||||
|
||||
Return nil if the variable `denote-directory' is buffer-local or
|
||||
dynamically bound, if directory-local variables are disabled, or if
|
||||
they do not specify a value for the variable `denote-directory'."
|
||||
(when (and (not (local-variable-p 'denote-directory))
|
||||
(eq denote-directory (default-toplevel-value 'denote-directory))
|
||||
(fboundp 'hack-dir-local--get-variables))
|
||||
(cdr (assq 'denote-directory
|
||||
(cdr (hack-dir-local--get-variables))))))
|
||||
|
||||
(defun denote-directories ()
|
||||
"Return path of variable `denote-directory' as a proper directory.
|
||||
If the variable `denote-directory' is set to a list of file paths,
|
||||
return the list with each element expanded to be a directory. Create
|
||||
any directories and their parents, if needed.
|
||||
|
||||
A directory-local value of the variable `denote-directory' is honored
|
||||
even when it has not yet been applied to the buffer, as is the case
|
||||
while the major mode is still initializing.
|
||||
|
||||
Custom Lisp code can `let' bind the variable `denote-directory'
|
||||
to override what this function returns."
|
||||
(if-let* (((or (eq denote-directory 'default-directory) (eq denote-directory 'local)))
|
||||
(silo-dir (denote--default-directory-is-silo-p)))
|
||||
(progn
|
||||
(display-warning
|
||||
'denote
|
||||
"Silo value must be a string; `local' or `default-directory' are obsolete"
|
||||
:error)
|
||||
(list silo-dir))
|
||||
(let ((denote-directories (denote-directories--get-paths denote-directory)))
|
||||
(denote-directories--make-paths denote-directories)
|
||||
denote-directories)))
|
||||
(let ((denote-directory (or (denote-directories--dir-local-value) denote-directory)))
|
||||
(if-let* (((or (eq denote-directory 'default-directory) (eq denote-directory 'local)))
|
||||
(silo-dir (denote--default-directory-is-silo-p)))
|
||||
(progn
|
||||
(display-warning
|
||||
'denote
|
||||
"Silo value must be a string; `local' or `default-directory' are obsolete"
|
||||
:error)
|
||||
(list silo-dir))
|
||||
(let ((denote-directories (denote-directories--get-paths denote-directory)))
|
||||
(denote-directories--make-paths denote-directories)
|
||||
denote-directories))))
|
||||
|
||||
(defun denote-has-single-denote-directory-p ()
|
||||
"Return non-nil if the variable `denote-directory' is a single item."
|
||||
|
|
|
|||
|
|
@ -95,6 +95,32 @@ Also see `denote-test--denote--make-denote-directory',
|
|||
(should (and (seq-every-p #'file-directory-p denote-directory)
|
||||
(seq-every-p #'file-name-absolute-p denote-directory)))))
|
||||
|
||||
(ert-deftest dt-denote-directories--dir-local-value ()
|
||||
"Test that an unapplied dir-local `denote-directory' is honored.
|
||||
Directory-local variables are applied only after the major mode is
|
||||
initialized, so `denote-directories' reads the dir-local value directly
|
||||
in that window. A dynamic binding or a buffer-local value of the
|
||||
variable `denote-directory' still takes precedence."
|
||||
(skip-unless (fboundp 'hack-dir-local--get-variables))
|
||||
(let* ((directory (file-name-as-directory
|
||||
(expand-file-name "denote-test-silo" temporary-file-directory)))
|
||||
(silo (file-name-as-directory (expand-file-name "notes" directory))))
|
||||
(unwind-protect
|
||||
(progn
|
||||
(make-directory directory :parents)
|
||||
(with-temp-file (expand-file-name ".dir-locals.el" directory)
|
||||
(insert (format "((nil . ((denote-directory . %S))))" silo)))
|
||||
(with-temp-buffer
|
||||
(setq default-directory directory)
|
||||
(should (equal (denote-directories) (list silo)))
|
||||
(let ((denote-directory "/tmp/denote-test-notes"))
|
||||
(should (equal (denote-directories)
|
||||
(denote-directories--get-paths denote-directory))))
|
||||
(setq-local denote-directory "/tmp/denote-test-notes")
|
||||
(should (equal (denote-directories)
|
||||
(denote-directories--get-paths denote-directory)))))
|
||||
(delete-directory directory :recursive))))
|
||||
|
||||
(ert-deftest dt-denote-sluggify-title ()
|
||||
"Test that `denote-sluggify-title' removes punctuation from the string.
|
||||
Concretely, remove anything specified in `denote-sluggify-title'."
|
||||
|
|
|
|||
Loading…
Reference in a new issue