Add denote-subdirectory command

It is like the 'denote' command, but puts the new note in the selected
subdirectory.  This is in response to issue 31 over at the GitHub
mirror: <https://github.com/protesilaos/denote/issues/31>.

Thanks to Jean-Philippe Gagné Guay and Shreyas Ragavan for their
feedback!
This commit is contained in:
Protesilaos Stavrou 2022-07-04 07:17:19 +03:00
parent e669653221
commit d3a54f63db
No known key found for this signature in database
GPG key ID: 99BD6459CD5CA3EA
2 changed files with 79 additions and 9 deletions

View file

@ -254,10 +254,11 @@ insert single words at the relevant prompts.
#+findex: denote-type
#+findex: denote-org-capture
#+findex: denote-date
There are four ways to write a note with Denote: invoke the ~denote~,
~denote-type~, ~denote-date~ commands, or leverage the
~org-capture-templates~ by setting up a template which calls the
function ~denote-org-capture~.
#+findex: denote-subdirectory
There are five ways to write a note with Denote: invoke the ~denote~,
~denote-type~, ~denote-date~, ~denote-subdirectory~ commands, or
leverage the ~org-capture-templates~ by setting up a template which
calls the function ~denote-org-capture~.
In the first case, all that is needed is to run ~denote~. It will
prompt for a title. Once it is supplied, the command will ask for
@ -300,6 +301,13 @@ established (e.g. when you use ~denote-date~ with =2022-06-16= twice, it
will generate the same identifier of =20220616T000000=). The user must
thus call the ~denote-date~ command again and provide a unique value.
[ The ~denote-subdirectory~ is part of {{{development-version}}} ]
The ~denote-subdirectory~ command is the same as ~denote~ except it
prompts for a directory to place the new note in. Candidates are the
value of the user option ~denote-directory~ and any subdirectory inside
of it. Denote does not create subdirectories.
For integration with ~org-capture~, the user must first add the relevant
template. Such as:
@ -347,11 +355,18 @@ the ~denote-org-capture-specifiers~.
#+findex: denote-create-note
#+findex: denote-create-note-using-type
#+findex: denote-create-note-using-date
For convencience, the ~denote~ command has a ~denote-create-note~ alias.
Same for ~denote-type~ which is ~denote-create-note-using-type~ and
~denote-date~ that has ~denote-create-note-using-date~. The purpose of
these aliases is to provide alternative, more descriptive names of
select commands to aid with discoverability.
#+findex: denote-create-note-in-subdirectory
For convenience, we provide these aliases:
| Name | Alias |
|---------------------+------------------------------------|
| denote | denote-create-note |
| denote-type | denote-create-note-using-type |
| denote-date | denote-create-note-using-date |
| denote-subdirectory | denote-create-note-in-subdirectory |
The purpose of these aliases is to provide alternative, more descriptive
names of select commands to aid with discoverability.
* Renaming files
:PROPERTIES:
@ -1358,6 +1373,7 @@ Everything is in place to set up the package.
(define-key map (kbd "C-c n n") #'denote)
(define-key map (kbd "C-c n N") #'denote-type)
(define-key map (kbd "C-c n d") #'denote-date)
(define-key map (kbd "C-c n s") #'denote-subdirectory)
;; If you intend to use Denote with a variety of file types, it is
;; easier to bind the link-related commands to the `global-map', as
;; shown here. Otherwise follow the same pattern for `org-mode-map',

View file

@ -767,5 +767,59 @@ The TITLE and KEYWORDS arguments are the same as with `denote'."
(defalias 'denote-create-note-using-date (symbol-function 'denote-date))
;;;;; The `denote-subdirectory' command
(defvar denote--subdir-history nil
"Minibuffer history of `denote-subdirectory'.")
(defun denote--subdirs ()
"Return list of subdirectories in variable `denote-directory'."
(seq-remove
(lambda (filename)
;; TODO 2022-07-03: Generalise for all VC backends. Which ones?
;;
;; TODO 2022-07-03: Maybe it makes sense to also allow the user to
;; specify a blocklist of directories that should always be
;; excluded?
(or (string-match-p "\\.git" filename)
(not (file-directory-p filename))))
(directory-files-recursively (denote-directory) ".*" t t)))
(defun denote--subdirs-completion-table (dirs)
"Match DIRS as a completion table."
(let* ((def (car denote--subdir-history))
(table (denote--completion-table 'file dirs))
(prompt (if def
(format "Select subdirectory [%s]: " def)
"Select subdirectory: ")))
(completing-read prompt table nil t nil 'denote--subdir-history def)))
(defun denote--subdirs-prompt ()
"Handle user input on choice of subdirectory."
(let* ((root (denote-directory))
(subdirs (denote--subdirs))
(dirs (push root subdirs)))
(denote--subdirs-completion-table dirs)))
;;;###autoload
(defun denote-subdirectory (directory title keywords)
"Like `denote' but ask for DIRECTORY to put the note in.
The DIRECTORY is either the variable `denote-directory' or a
subdirectory of it. The TITLE and KEYWORDS are the same as for
the `denote' command.
Denote does not create subdirectories."
(interactive
(list
(denote--subdirs-prompt)
(denote--title-prompt)
(denote--keywords-prompt)))
(let ((denote-directory directory))
(denote--prepare-note title keywords)
(denote--keywords-add-to-history keywords)))
(defalias 'denote-create-note-in-subdirectory (symbol-function 'denote-subdirectory))
(provide 'denote)
;;; denote.el ends here