Coder Social home page Coder Social logo

protesilaos / denote Goto Github PK

View Code? Open in Web Editor NEW
453.0 453.0 49.0 3.44 MB

Simple notes for Emacs with an efficient file-naming scheme

Home Page: https://protesilaos.com/emacs/denote

License: GNU General Public License v3.0

Emacs Lisp 100.00%
emacs notes

denote's Introduction

denote: Simple notes with an efficient file-naming scheme

Denote is a simple note-taking tool for Emacs. It is based on the idea that notes should follow a predictable and descriptive file-naming scheme. The file name must offer a clear indication of what the note is about, without reference to any other metadata. Denote basically streamlines the creation of such files while providing facilities to link between them.

Denote's file-naming scheme is not limited to "notes". It can be used for all types of file, including those that are not editable in Emacs, such as videos. Naming files in a consistent way makes their filtering and retrieval considerably easier. Denote provides relevant facilities to rename files, regardless of file type.

denote's People

Contributors

alternateved avatar bitspook avatar brabalan avatar damiencassou avatar eeljen avatar eshelyaron avatar fintelkai avatar jackbaty avatar jeanphilippegg avatar jhou1 avatar josephmturner avatar juergenhoetzel avatar kandread avatar kaushalmodi avatar kyleam avatar mattyonweb avatar maxbrieiev avatar meain avatar mgmarlow avatar nbehrnd avatar nobiot avatar phikal avatar pprevos avatar protesilaos avatar sirikid avatar sthesing avatar taoufik07 avatar thibautbenjamin avatar vedang avatar wlharvey4 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

denote's Issues

Date format needs to be in RFC3339 format if setting front-matter to YAML

If I create a note after setting:

  1. denote-front-matter-date-format to org-timestamp
  2. denote-file-type to markdown-yaml

, I get this:

---
title:      zyx
date:       [2022-06-10 Fri 11:25]
tags:       tag1
identifier: 20220610T112538
---

The date format is illegal in YAML. It will need to be converted to RFC3339 format.

Corrected date format:

date = 2022-06-10T11:25:38-04:00

I use this to convert Org date/time to RFC3339:

(defun org-hugo--org-date-time-to-rfc3339 (date-time info)
  "Convert DATE-TIME to RFC 3339 format.

DATE-TIME can be either Emacs format time list (example: return
value of `current-time'), or an Org date/time string.

INFO is a plist used as a communication channel."
  (let* ((date-time (if (stringp date-time)
                        (apply #'encode-time (org-parse-time-string date-time))
                      date-time))
         (date-nocolon (format-time-string
                        (plist-get info :hugo-date-format)
                        date-time)))
    ;; Hugo expects the date stamp in this format (RFC3339 -- See
    ;; `org-hugo--date-time-regexp'.) i.e. if the date contains the
    ;; time-zone, a colon is required to separate the hours and
    ;; minutes in the time-zone section.  2017-07-06T14:59:45-04:00

    ;; But by default the "%z" placeholder for time-zone (see
    ;; `format-time-string') produces the zone time-string as "-0400"
    ;; (Note the missing colon).  Below simply adds a colon between
    ;; "04" and "00" in that example.
    (and (stringp date-nocolon)
         (replace-regexp-in-string
          "\\([0-9]\\{2\\}\\)\\([0-9]\\{2\\}\\)\\'" "\\1:\\2"
          date-nocolon))))
  • Above, (plist-get info :hugo-date-format) will retrieve this by default: "%Y-%m-%dT%T%z".
  • We don't have a date/time format available in Emacs-Lisp that provides the exact RFC3339 format (with colon between hour:min in the zone offset), so I have a workaround in the last part of the code above to fix that.

(reference)

References

RFC3339 date/time examples from the standard

More

The same RFC3339 format date/time will work for TOML too: https://toml.io/en/v1.0.0#offset-date-time

Is it possible to not replace tags when renaming from dired?

I have a number of notes that I have migrated from evernote and have reformatted the yaml header to be as close as possible to the denote format. However, I do not want to change the existing tags in the yaml. Can I skip over them without changing or manually selecting them from the minibuffer?

Ideally, I would want these tags to persist… Is this possible?

Suggestion to rename a `denote-file-type` value

Hello,

From https://protesilaos.com/codelog/2022-06-07-denote-introduction/, I see:

image

May I suggest that that denote-file-type be changed to something like markdown-yaml?

If a user is using a static site generator like Hugo and few others, they can specify the front-matter in YAML, TOML, or even JSON.

For example, in TOML format, the same will look like this:

+++
title = "This is a sample note"
date = 2022-06-10
tags = ["denote", "testing"]
identifier = "20220610T134640"
+++

If this data is organized internally as a plist, it can be easily exported to TOML using tomelr [Disclaimer: I am maintaining that library and it's available on GNU ELPA too.]

Here's an example of using tomelr-encode from that library, which will generate the above TOML.

(tomelr-encode '(:title "This is a sample note"
                 :date "2022-06-10"
                 :tags ("denote" "testing")
                 :identifier "20220610T134640"))

Summary

  • Suggestion is to only rename the markdown value to markdown-yaml for now.
  • If there is motivation to add TOML front-matter export in future, something like above using tomelr can be done if denote-file-type is set to markdown-toml.

Full support for orgmode links (`denote:` type)

Hi,

Denote, within orgmode files, uses the denote: link type internally. denote-link inserts such links.

One may expect such links to work on any orgmode files, for example on your org-agenda-files. Which works, because:

          (org-link-set-parameters
           "denote"
           :follow #'denote-link-ol-follow
           :face #'denote-link-ol-face
           :complete #'denote-link-ol-complete
           :export #'denote-link-ol-export)

But there is someone missing there, :store. This means you cannot save a denote: links to a note using standard orgmode tooling (org-store-link). For example:

  • if you want to get a link to the current note to insert it somewhere.
  • you want to use org-capture from a note, for example to add a task on your agenda linking to that note.

This is unrelated to #8 / #20 / denote-link-use-org-id though mixed with org-id-extra-files might enable some workflows (only to orgmode format notes).

So:

  1. you can, now, follow denote: links from any org file anywhere to your denote notes in any format.
  2. you can, now, insert (org-insert-link) links to denote: notes in any orgmode file.
  3. you can NOT, use org-store-link to get a link to the current note; which prevents using %a in org-capture

The fix is easy though, implement :store; This is my current take on it:

;; only add :store, all else is already set by denote.
(org-link-set-parameters
 "denote"
 :store #'denote-link-ol-store)


(defun denote-link-ol-store()
  "Store an org-link to a denote note using denote: link."
  (when (denote--current-file-is-note-p)
    ;; this let* comes from `denote-link--format-link'
    (let* ((file (buffer-file-name))
           (file-type (denote--filetype-heuristics file))
           (file-id (denote--retrieve-filename-identifier file))
           (file-title (denote--retrieve-title-or-filename file file-type)))
      
      (org-link-store-props
       :type "denote"
       :description file-title
       :link (concat "denote:" file-id)))
    org-store-link-plist))

This should work with notes in any format, now org-capture works and org-store-link too.

Did I miss anything? Is there any particular reason this is not yet in denote? (seems odd that all other org-link-set-parameters are there but this).

If the code looks good I can open a PR (or try to submit it via the mailing list as an exercise!!), maybe in time for 1.0 !!

Denote insert immediately

This is inspired by https://systemcrafters.net/build-a-second-brain-in-emacs/5-org-roam-hacks/#fast-note-insertion-for-a-smoother-writing-flow

Imagine you are writing a note, and there are some terms which are candidate for new notes (and/or linking).
So far, we need to create the node if it does not exist, and then call denote-link.

This is time consuming, so here's a snippet to be able to create the link without loosing focus.
If this is a thing you'd like to integrate as another function into denote, I'd be super happy to prepare a PR for it.

(I don't like the fact that I am relying in the global variable denote-last-path, but org-capture returns either t or nil, so this was the most straight-forward way of getting the target for denote-link -- any ideas on how to make this more solid?).

(defun denote-insert-immediate ()
  (interactive)
  (let (
        (org-capture-templates '(("d" "New note (with Denote)" plain
                 (file denote-last-path)
                 #'denote-org-capture
                 :no-save t
                 :immediate-finish t
                 :kill-buffer t
                 :jump-to-captured nil))))
    (org-capture nil "d")
    (denote-link denote-last-path)))

Re-Naming/Re-writing front matter is missing closing bracket

Hi Prot! I just realized that when renaming a file and chosing the re-write the front-matter the date is missing the closing "]" bracket in the updated front matter. I haven tested this on all file types, but it happens at the least with org-files and *org timestamp". I thought you might want to know.

Create a new note with denote-date without a specific time

Hi Prot,

The manual states that:

"This is where the denote-date command comes in. It creates a note while prompting for a date. The date can be in YEAR-MONTH-DAY notation like 2022-06-30 or that plus the time: 2022-06-16 14:30."

But this function does not accept only a date. I am moving old notes from years ago into denote and like to keep the original date, but I have not record of the original creation time. Could this function be written so that it uses current time, when only a date is added?

P:)

Multiword keyword and fontification issue

Hi Prot!
The latest change with the keywords is nice and certainly adds clarity, but somehow the fontification in Dired doesn't correctly work, or at the least it doesn't on my end:

Screenshot from 2022-06-11 16-43-35

Entries with multiple keywords work as expected.

Of course I might have messed up something myself. Always a possibility :-)

Canonical (probably?) way to set file ID in Org

I have seen this in the Property Syntax section of the Org manual:

Properties can be inserted on buffer level. That means they apply before the first headline and can be inherited by all entries in a file. Property blocks defined before first headline needs to be located at the top of the buffer, allowing only comments above.

Org Roam is probably the only primary Org-related application that uses this feature tremendously, to set the Org Roam "note"s ID.
(PS: I don't use Org Roam myself, but I have seen quite a few examples.)

So an Org Roam file might look like:

:PROPERTIES:
:ID:       1e8ccec9-735d-41d0-b0cf-143d9c3e965d
:END:
#+title: Some Title

I believe that Org Roam sets ID this way because the Org built-in library org-id supports this. If you require org-id and eval (org-id-get) in the above file, it will return "1e8ccec9-735d-41d0-b0cf-143d9c3e965d".


So I couldn't help but draw a parallel between the #+identifier property created by denote (when denote-file-type is nil or Org) and the :ID: property used by Org Roam.

Here's an example file created by denote:

#+title:      idtest2
#+date:       [2022-06-10 Fri 13:44]
#+filetags:   org-id
#+identifier: 20220610T134422
  • #+title: ✔️ Canonical style of setting a file's title
  • #+date: ✔️ Canonical style of setting a file's date
  • #+filetags: ✔️ Canonical style of setting a file's tags
  • #+identifier: ❌ Canonical style of setting a file's unique ID

But the good thing is that the #+identifier value is indeed a unique ID. So that value doesn't need to be changed; it only needs to be presented in a different format.

Suggested Org format

:PROPERTIES:
:ID: 20220610T134422
:END:
#+title:      idtest2
#+date:       [2022-06-10 Fri 13:44]
#+filetags:   org-id

Now if you eval (org-id-get) in this file, it will return "20220610T134422"!

Another benefit: Enables linking of files using Org ID

Example file 1

:PROPERTIES:
:ID: 20220610T134323
:END:
#+title:      idtest1
#+date:       [2022-06-10 Fri 13:43]
#+filetags:   org-id

Example file 2

:PROPERTIES:
:ID: 20220610T134422
:END:
#+title:      idtest2
#+date:       [2022-06-10 Fri 13:44]
#+filetags:   org-id

[[id:20220610T134323]]

If your org ID extra files cache is updated (by evaluating (setq org-id-extra-files (directory-files-recursively default-directory "\.org$"))), and if you put the cursor on that id: link in idtest2 file and hit C-c C-o, it will jump to the idtest1 file.

Suggestion: Searching the contents of the notes

I'm trying (the very impressive) zk program ( https://github.com/localauthor/zk ).
Maybe you already know localauthor (Grant Rosson)?

Among the basic functions, zk offers a search on the contents of the notes ( zk-find-file-by-full-text-search ).
Could be a good addition in Denote.

Small videos ( https://www.youtube.com/channel/UCirnOrHNy7N_CIA_dS7XWug/videos )
present some functionalities of zk. They are all instructive.

In addition, the "philosophy" of zk is the same as denote. No dependency on external packages and heavy use of embark, consult, vertico, orderless ...

Make denote more compatible with non-ascii charactors

Currently denote-faces--file-name-regexp only recognize ascii title and keywords, can we change it to make it recognize non-ascii charactors?

Some thing like:

(defvar denote-faces--file-name-regexp
  (concat "\\(?1:[0-9]\\{8\\}\\)\\(?2:T[0-9]\\{6\\}\\)"
          "\\(?:\\(?3:--\\)\\(?4:[[:word:]_-]*\\)\\)?"
          "\\(?:\\(?5:__\\)\\(?6:[[:word:]_-]*\\)\\)?"
          "\\(?7:\\..*\\)?$"))

can match non-ascii charactors except punctuations.

And maybe also set the value of denote--punctuation-regexp to [[:punct:]] to make denote aware of non-ascii punctuations?

denote--only-note-p and related functions

I am opening this issue to discuss the state of denote--only-note-p. There is this comment in the code:

;; TODO 2022-08-11: In light of `denote--writable-and-supported-p', we
;; should either harden `denote--only-note-p' to also check for a
;; `denote-directory' or decide how to merge the two functions.  I think
;; hardening this one is more appropriate.

What do you mean? Should we check if the file is inside the denote-directory?

Also, there is this comment in denote--retrieve-title-value:

;; NOTE 2022-08-11: The `or' is superfluous, but I am keeping it as a
;; reminder.  See TODO comment above `denote--only-note-p'

I think that when we are calling denote--retrieve-title-value we should be able to assume that the file is valid for this call. The check should be done elsewhere.

`denote-file-type` value get lost and always the Org meta data is inserted

Hello,

I believe this is a recent regression

I am unable to make this work:

(defun denote-md ()
  (interactive)
  (let ((denote-directory (file-name-directory (buffer-file-name)))
        (denote-file-type 'markdown-toml))
    (call-interactively #'denote)))
  • The .md file gets created, but then the inserted meta data is in Org format.

When I did a quick debug using this:

(defun denote--prepare-note (title keywords &optional path)
  "Use TITLE and KEYWORDS to prepare new note file.
Use optional PATH, else create it with `denote--path'."
  (message "denote-file-type: %S" denote-file-type)
  (let* ((p (or path (denote--path title keywords)))
         (default-directory denote-directory)
         (buffer (unless path (find-file p)))
         (header (denote--file-meta-header
                  title (denote--date) keywords
                  (format-time-string denote--id))))
    (unless path
      (with-current-buffer buffer (insert header))
      (setq denote-last-buffer buffer))
    (setq denote-last-front-matter header)))

I noticed that the denote-file-type is back to nil there even when I am setting it to markdown-toml in that let. I need to further debug this, but I won't have time to do that until tomorrow.

I am opening this issue just in case someone else lands up on the same issue.

id: links not working when denote has not been used before

This issue is actually unrelated to the subdir branch, so I created a new issue to keep things separate.

How to reproduce:

  • Open Emacs and never call a denote function.
  • Open a note containing an id: link and click on it.
  • I am prompted with "No match - create this as a new heading?".

Cause: org-id-extra-files is not set yet, because we set it in the function denote-directory which has not been called yet.

I don't know how we should fix this. Is there a clean way to make sure that org-id-extra-files is set when a note is opened?
Maybe the user should add this in their init file if they want id: links:

(setq org-id-extra-files (directory-files-recursively (denote-directory) "\.org"))

But maybe this is too much for a user. Alternatively, we could set this directly in the top-level of denote.el.

(In any case, we should append to that variable instead of overwriting it.)

UPDATE: Actually, I get the same behavior by default using id: links in org files outside of denote: they do not work as-is. I suppose the user is expected to manually set org-id-extra-files.

Idea/Adding "past" notes

Hi Prot,
I was just wondering if it would be useful to have an option to add notes/journal entries from the past, ie creating/renaming files with a past date.

Idea here would be for example if I were to enter for a journal entry from the 1st of January, but do it today, the title would be the "right" day, but the time-stamp/identifier would be today's. Of course this can be changed after the fact, but I wonder wether it would make sense to have such an option during the creation of the note.

Symbol’s function definition is void: `org-link-set-parameters`

I personally don't use org-mode and so does not load it by default. But with org-mode not loaded, loading denote I run into this.

byte-code: Symbol’s function definition is void: org-link-set-parameters

Commenting this out seems to fix it:

denote/denote-link.el

Lines 493 to 497 in 08fa8b2

(org-link-set-parameters
"denote"
:follow #'denote-link-ol-follow
:complete #'denote-link-ol-complete
:export #'denote-link-ol-export)

Use mdfind on macos

Hello and thanks for the very interesting package. I use macos and I've noticed a process-lines-handling-status: find exited with status 1 error when I use denote-link-backlinks. I suspect this is because macos uses mdfind rather than find. As far as I can tell the relevant function here is

(defun denote-retrieve--proces-grep (identifier)
  "Process lines matching IDENTIFIER and return list of files."
  (let* ((default-directory (denote-directory))
         (file (file-name-nondirectory (buffer-file-name))))
    (denote-retrieve--files-in-output
     (sort
      (process-lines
       "find"
       default-directory
       "-maxdepth" "1"
       "-type" "f"
       "!" "-name" file
       "-exec"
       grep-program
       "--color=never"
       "-m"
       "1"
       "-e"
       identifier
       "{}"
       ";"
       "-print")
      #'string-lessp))))

Would it be possible to allow for customization of this function? For example, consult-locate allows the user to specify arguments (like mdfind) using consult-locate-args. Perhaps something similar could be done here. This is all just speculation though, because I haven't yet gotten the function to work appropriately using mdfind and grep.

Add utility for `denote-find-file`

Hi Prot,

I spent a little time with denote and felt the need for a denote-find-file so I could easily visit a note without having to first visit the relevant dired buffer.

I came up with the following two utilities:

(defun fb/denote-title-and-file (file)
  "Given a denote FILE, produce a cons cell containing the file's
     title and the FILE path."
  (interactive)
  (cons (denote--retrieve-title-value file 'org) file))

(defun fb/denote-find-file ()
  "A utility to find a note using `completing-read'."
  (interactive)
  (let* ((files (denote--directory-files))
         (title-file-alist (mapcar #'fb/denote-title-and-file files))
         (titles (mapcar #'car title-file-alist)))
    (find-file (cdr (assoc (completing-read "Find Note: " titles) title-file-alist)))))

Perhaps there's some interest in integrating something like this as part of denote. What are your thoughts?

Command denote-dired-rename-file-and-add-front-matter does not add front matter

The command denote-dired-rename-file-and-add-front-matter does not seem to work correctly.

Steps to reproduce

  1. Assuming, I have a file test.org with content 'test'. in my denote folder.
  2. dired opens the folder.
  3. put point on test.org
  4. M-x denote-dired-rename-file-and-add-front-matter

Effect

  • the file gets renamed on filesystem as requrested
  • the follwoing error is shown in *Messages* buffer:
    denote-dired--rename-buffer: Invalid function: (buffer (find-buffer-visiting old-name))
  • the renamed files does not contain the frontmatter (i.e. file content is still 'test'

Versions

(version) yields: "GNU Emacs 28.1 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.33, cairo version 1.17.6)
Denote Version (GitHub): d3fae65 main origin/main Update the manual's Acknowledgements for 5d245df

Links to notes in subdirectories

Hello,
Thanks a lot for this awesome package. This is not an issue with denote, but my lack of elisp knowledge and I would appreciate if one could shine a bit of light in my path.

I needed to organize my notes into subdirectories as opposed to the default notes path. So I came up with following functions:

(require 'f)
(require 'denote)

(defun mynote--get-note-subdirs ()
  "Lists only names of subdirectories"
  (let ((subdir-names)
        (subdirs (f-directories denote-directory)))
    (dolist (item subdirs)
      (add-to-list 'subdir-names (file-name-nondirectory item)))
    subdir-names))

(defun mynote--set-denote-keywords ()
  "Sets `denote-keywords' based on subfolder structure"
  (setq denote-known-keywords (mynote--get-note-subdirs)))

(defun +mynote/new-subdir ()
  "Creates sub directory in the `denote-directory' for better organization"
  (interactive)
  (if-let (keyword (read-string "Subdir name: " nil))
      (let ((subdir (file-name-concat denote-directory keyword)))
        (let ((loc-file (file-name-concat subdir ".dir-locals.el")))
          (if (f-dir? subdir)
              (message (concat "directory " subdir " already exists!"))
            (progn
              (make-directory subdir)
              (if (f-file? loc-file)
                  (message (concat "file " loc-file " already exists!"))
                (progn
                  (make-empty-file loc-file)
                  (write-region "((nil . ((denote-directory . local))))" nil loc-file)))))
          (mynote--set-denote-keywords)))))

(defun +mynote/new-in-subdir ()
  "Call this function instead of `denote' to create note in a subfolder and set keywords"
  (interactive)
  (let* ((keyword (denote--keywords-prompt))
         (denote-directory (file-name-concat denote-directory keyword)))
    (denote
     (denote--title-prompt)
     keyword)))

(defun +mynote/new-in-subdir-with-date ()
  "Call this function instead of `denote-date' to create notes in subfolder with date"
  (interactive)
  (let* ((keyword (denote--keywords-prompt))
         (denote-directory (file-name-concat denote-directory keyword)))
    (denote-date
     (denote--date-prompt)
     (denote--title-prompt)
     keyword)))

(defun +mynote/browse-notes ()
  "Browse files from `denote-directory'"
  (interactive)
  (unless (bound-and-true-p denote-directory)
    (message "denote-directoy not defined"))
  (doom-project-browse (concat denote-directory "/")))

This allows me to create subdirectories and at the same time populate denote-known-keywords. Everything works as expected. However, when I link a note from any subdirectories, the link would not include the path and fails to open. Also backlinks are nil if links are from subdirectories.

FYI, I use doom emacs and this is the link to my full configuration.

Thanks again.

Convert plain file to Denote

Based on the denote-dired-rename-file function, I came up with this function to convert an existing non-Denote file into a Denote one.

The idea is not to try to convert org-roam files to Denote, though it can probably be useful for that use case. Check the docstring of the function to know the details.

I am sharing it here because I don't know if it should be integrated to the code or where to integrate it.

What do you think?

(defun denote-dired-convert-file-to-denote (file title keywords)
  "Convert a file to Denote format.

This function adds a front matter unconditionally at the start of
the file. It does not check if one is already present. If a front
matter is already present, you will end up with two. Consider
using `denote-dired-rename-file' in that case.

It prompts for a FILE, a TITLE and KEYWORDS.

The identifier is retrieved from the filename if there is one,
else the last modification time is used.

The default title is retrieved from a line starting with
\"#+title:\" if such a line exists (and depending on the file
type). Else, the file name is used."
  (interactive
   (let ((file (denote-dired--rename-file-is-regular (denote-dired--rename-dired-file-or-prompt))))
     (list
      file
      (denote--title-prompt (or (denote-retrieve--value-title file)
                                (file-name-sans-extension (file-name-nondirectory file))))
      (denote--keywords-prompt))))
  (let* ((dir (file-name-directory file))
         (old-name (file-name-nondirectory file))
         (id (denote-dired--file-name-id file))
         (extension (file-name-extension file t))
         (new-name (denote--format-file
                    dir
                    (denote-dired--file-name-id file)
                    keywords
                    (denote--sluggify title)
                    extension))
         (max-mini-window-height 0.33)) ; allow minibuffer to be resized
    (unless (string= old-name (file-name-nondirectory new-name))
      (when (y-or-n-p
             (format "Rename %s to %s?"
                     (propertize old-name 'face 'error)
                     (propertize (file-name-nondirectory new-name) 'face 'success)))
        (rename-file old-name new-name nil)
        (denote-dired--rename-buffer old-name new-name)
        (denote-dired-update-dired-buffers)))
    (when-let* ((filetype (denote-dired--filetype-heuristics file))
                (date (denote--date (date-to-time id)))
                (new-front-matter (denote--file-meta-header title date keywords id filetype)))
      (with-current-buffer (find-file-noselect new-name)
        (goto-char (point-min))
        (insert new-front-matter)))))

Denote links are not unique

Hi Prot,

I have just (finally) completed my conversion from org-roam to denote. In order to do that, I have heavily relied on denote-dired-rename-marked-files, then for each note I've manually corrected +filetags and called denote-rename-file to update the tags on the file name.

To my surprise, denote ended up using current timestamp instead of reusing the original one from org-roam. That's not really a big problem, anyway, as git history can give me some idea of when the file was originally created. That being said, upon trying to use any of the denote-link-insert* functions and looking at the generated link, I noticed that only the timestamp is part of the link, which means that, all of my original notes now evaluate to the same exact denote link.

Is there anything that can be done to improve the situation here?

Of course, I can go through my git history and manually correct time stamps, but I was thinking if this is something that denote should provide a more robust behavior in this situation.

Best regards

Just an idea: denote for attachments

If you think this is something you might use, but disagree with some of its decisions, now is the best time to act.

Just in case this idea could be useful:
I use attached or linked local files for adding multimedia (jpg, pdf, etc) or references (saved html, podcasts, etc) to my org notes.
These multimedia files are in a folder almost kaotically.
To sort those files in the way you've described could give to them a new dimension.

Thanks for elisping!

Is there a way to add link title for none-denote-type files

Hello Protesilaos, and anyone who loves denote. This may be a bit long-winded question, but please allow me to express the origin of the problem.

One of the features I like about denote is that as long as I add a link, such as “b”, to another file in a note file, such as “a”, and as long as “b” is in denote-dir, no matter how I move the “b” file to any subfolder, “b” would always be found and open accurately and quickly.

I love the convenience and wonder if there is a way to manage other files with the denote solution.

I first used denote-rename to rename a xxx.pdf file, (denote-rename is a very useful method) and got, “20220820T211207--test-pdf__test.pdf”. But when I use denote-link to insert this pdf into a note file, I can only get the name [[denote:20220820T211207]], then I click this link, denote quickly finds and opens the pdf, even after the file has been moved to another subdir

My question here is whether I can make this link add a reasonable description and a file identifier,such as "[[denote:xxxx][pdf:test]]" in org mode so that I can fully rely on denote to efficiently manage all my files.

Have a good day

Org mode dates

The default for org mode headers is now:

#+date: 2022-06-10

The Org mode data format is that the numbers are between square brackets. Formatting dates this way provides entry to other Org functionality.

#+date: [2022-06-10]

Is that possible to implement?

Creation of new notes in subdirectories.

As @protesilaos suggested in this closed pull request, I am opening this issue to start a discussion on the creation of notes in subdirectories.

As of now, new notes are created at the root of the denote-directory. @protesilaos suggested a few alternatives:

  • Have a new user option, which will be off by default, that makes all our file-creating commands use the current directory if it is a subdir of denote-directory.

I am adding another possibility to the list:

  • Prompt the user for a directory where to create the note. The default would be the current directory if it is inside denote-directory.

Review of file types

Ping @jeanphilippegg.

I noticed that denote--filetype-heuristics returns org as a fallback value. This has the unintended side-effect of potentially mistreating a non-note file while renaming it (e.g. mp3).

I will put some code in a new branch, so we can continue testing there.

denote-retrieve--files-in-xrefs does not return correct file names.

Hi, I was testing out denote and I found the backlink does not work, it always says "No links to the current note",
it appears to work in your demo video so I tried to debug the code, long story short I found this piece of code:

denote/denote-retrieve.el

Lines 114 to 115 in 0683a19

(delete file (denote-retrieve--files-in-xrefs
(denote-retrieve--xrefs identifier))))))

seems to return wrong path of notes.

To test it, I create 2 notes in a empty directory ~/test by invoke M-x denote, note2.org have a denote link to note1.org,
then I M-x eval-expression the following codes in the note1.org buffer that should have a backlink to it:

(delete (denote--file-name-relative-to-denote-directory (buffer-file-name))
(denote-retrieve--files-in-xrefs
 (denote-retrieve--xrefs (denote-retrieve--filename-identifier (buffer-file-name)))))

It returns something like ("test/20220710T200942--note1__random.org" "test/20220710T201012--note2__random.org"),
when function denote-retrieve--files-in-output receive those as arguments, it returns nil, so no backlinks...

I run the same test with emacs28.1 and emacs29 from a recent commit after emacs -Q, both shows the same results.

"Identifier" search regexp fails for TOML front-matter

Hello,

I am afraid that this fails when using TOML front-matter:

denote/denote-link.el

Lines 103 to 104 in f91d247

(defconst denote-link--identifier-regexp "^\\(#\\+\\)?\\(identifier:\\)[\s\t]+\\(.*\\)"
"Regular expression for filename key and value.")

We will need to look for : or =, with optional space before =.

Sample TOML format output

+++
title      = "testtoml"
date       = 2022-06-11T11:49:10-04:00
tags       = ["test"]
identifier = "20220611T114910"
+++

I was actually looking into it to see if I can live with just the ID property when using Org front-matter (Ref #8).

Do you think this is the only thing we'll need to tweak if I want to have Org front-matter without the identifier keyword?

:PROPERTIES:
:ID: 20220611T114436
:END:
#+title:    test
#+date:     [2022-06-11 Sat 11:44]
#+filetags: test

Or do you plan to deeply bake in the reliance on #+identifier / identifier: / identifier = matches?

Refining the renaming mechanism

I am posting this here since it is where @jeanphilippegg is active with changes to the code.

cc @hpgisler

  1. @jeanphilippegg consolidated the renaming commands to just denote-rename-file and denote-dired-rename-marked-files. I just tested everything and updated the relevant docs. This addresses the issue we had before with ergonomics, namely, that we had distinct commands for rewriting and for adding front matter in addition to the renaming operation.

  2. We now are ready for the function that completes the front matter, as we discussed on the mailing list. In short: add missing entries to the front matter block.

  3. The "reverse rename" operation, which would read the front matter and rename the file accordingly.

I feel that 2 is the trickiest one because we do not define such entries one-by-one but only as a block (e.g. denote-org-front-matter). I would thus leave this for last.

Unless @jeanphilippegg already has some code in the works, I will now start working on 3.


Mailing list thread for the sake of completeness (I wish they were not split like that, but here we are):

Clarification on multi-word keywords

Hello,

This is just for clarification. In the README, it's mentioned:

Keywords that need to be more than one-word-long must be written with an underscore.

That means if that some needs a "multiple word keyword", they will need to write multiple_word_keyword when entering it through M-x denote interactively. Is that right?

To put it a different way, spaces are not allowed in keywords. If that's the case, then printing out those keywords in any front-matter format (Org, YAML) will be easier to manage.

About renaming files and maintaining note links

I haven't yet tried the renaming using dired, but just I reading about it, I feel like it will break all the inter-linked notes, as the links are made using file names.

I don't have a solution except a vague idea that when the files are renamed in dired, there should be a search/replace operation as well that would rename all link references in all the notes in denote-directory as well.

a thought on filetypes

Hi Prot,

I recently came across your youtube channel through other intermediary hops (iosevka-comfy) and saw the package denote and wanted to ask you if you see any value integrating source code files as notes? You know at times someone might just want to collect various bits of information on stack sites for reviewing later (and usually never does because it gets lost in a combined org or markdown file).

All languages have a comment structure and the adhoc nature of denote might be useful for quickly aggregating and later searching. I understand there is a fine line between this and code snippets but snippets are usually something you use frequently and not for research.

I know we can use org code blocks too, but having the notes in their native format can be useful too when you do something on the shell and help possibly use the note in another editor. Just wanted to ask what you think, thank you for your efforts. I will use denote in the next few weeks.

Discussion: Use org-read-date for date prompts?

Sorry, I don't want to overwhelm you with issues and pull requests. This is the last feature I have in mind... for now.

Question: I think that selecting a date with org-read-date (what is done in org-agenda I suppose) is a better interface than writing it by hand. This would add a dependency on org. Is this desirable?

denote-link-backlinks will not list backlinks if denote-directory is a folder within git repo

To reproduce:

Set denote-directory to be a folder within any git repo. In the example below, the denote-directory is subdenotes.

../project-X
└── subdenotes
├── 20220703T135705--another-test-org-note-in-new-denote-directory__denoting_test.org
├── 20220703T142139--lolcat-for-testing-3__denote_test.org
└── subsubdenotes
└── 20220703T135625--note-1-for-testing__denoting_test.org

If the parent project-X folder is initialized as a git repo, denote-link-backlinks will return 'No links to the current note'. The moment the .git directory is deleted, backlinks are populated as expected.

I do not think it makes a difference, but in case it is relevant - I use projectile. Removing the project from the list of known projects or the cache does not seem to make a difference.

Using denote as journal or diary

The online manual provides an example of how to use denote as a journal... Is there a way to make it function my similar to org-journal, whereby a new note can be created for a day, week, etc., and then each entry is appended to the bottom with the time stamp as a sub-header? I've tried to hack something together, by my elisp is not very good... I thought it might be combination of the stuff below, but couldn't get it working…

;; from the manual
(defun my-denote-journal ()
  "Create an entry tagged 'journal' with the date as its title."
  (interactive)
  (denote
   (format-time-string "%A %e %B %Y") ; format like Tuesday 14 June 2022
   '("journal"))) ; multiple keywords are a list of strings: '("one" "two")

(with-eval-after-load 'org-capture
  (add-to-list 'org-capture-templates
               '("J" "New Journal (with Denote)" plain
                 (file+headline denote-last-path (format-time-string "%A %e %B %Y"))
                 #'denote-org-capture
                 :no-save t
                 :immediate-finish nil
                 :kill-buffer t
                 :jump-to-captured t
                 :prepend t)))

Line highlighting and alt-syntax effects lost after `modus-themes-toggle`

Hi @protesilaos,

After configuring modus themes to my liking, I noticed that the effects of modus-themes-hl-line and modus-themes-syntax are, apparently, lost after a call to modus-themes-toggle.

Here's what a piece of source code looks as soon as modus-operandi loads during emacs initialization:

before

And after calling modus-themes-toggle twice:

after

Note that the effect of intense was lost in modus-themes-hl-line and, similarly, the effect of alt-syntax is gone from source code comments. I'm happy to test anything you want me to test, however when running the same configuration (quoted at the end of this report) on top of clean emacs (with emacs -Q), then alt-syntax and intense don't even have any effect at all.

Full configuration:

(use-package modus-themes
  :custom
  (modus-themes-bold-constructs t)
  (modus-themes-fringes 'subtle)
  (modus-themes-hl-line '(accented intense))
  (modus-themes-italic-constructs t)
  (modus-themes-mixed-fonts t)
  (modus-themes-mode-line '(borderless))
  (modus-themes-org-blocks 'tinted-background)
  (modus-themes-paren-match '(intense bold))
  (modus-themes-prompts '(bold intense))
  (modus-themes-region '(bg-only accented))
  (modus-themes-scale-headings t)
  (modus-themes-syntax '(alt-syntax))
  (modus-themes-subtle-line-numbers t)
  (modus-themes-tabs-accented t)

  (modus-themes-completions
   '((matches . (extrabold background intense))
     (selection . (semibold accented intense))
     (popup . (accented))))

  (modus-themes-headings
   '((1 . (rainbow overline background 1.4))
     (2 . (rainbow background 1.3))
     (3 . (rainbow bold 1.2))
     (t . (semilight 1.1))))

   :config
   (load-theme 'modus-operandi t)

   :bind ("<f5>" . modus-themes-toggle))

UPDATE: I just noticed that pretty much every color changes. It looks like alt-syntax is lost. I'll confirm the colors being used later today and post a new comment

Links and Custom Folders

Hi Prot!
I'm sure I'm missing something somewhere, but I get some funny results creating links.

When I'm in my default notes folder, linking to and opening links works as expected. I do however get duplicates when using denote-link-add-links and searching only for date, say 20220617. I guess this is because the regex searches both filename and title, hence creates duplicates.

When I'm though in another folder, say Docs/journal and do the same search it searches the /notes folder and respectively adds files matching the same files with the difference that I can't seem to open them. Adding a link via denote-link-insert-link adds the right link, but I'm unable to open it.

I tried to add a local-variables file, but that rather broke stuff :-)

Org mode front matter is overwritten by Denote

Several of my notes have an enhanced front matter, Org mode allows a lot more entry types than described in Denote, for example #+startup: and #+properties:, #+options:. It also allows using bespoke keywords.

When using the denote-dired-rename-file function, these additional lines vanish.

Can this function be rewritten to replace the content, instead of replacing the complete front matter?

Fontification in dired buffer fails if name contains non [0-9A-Za-z-] character

A file with name:
20220702T230825--intervention-des-simulations-schöpfers-macht-diesen-erkennbar__phantasy_philosophy.org

(note the German character ö in the word Schöpfer),
fontification fails in ```denote-dired-mode'.

I.e. the regexp should be modified (negated) to include basically all characters, but '_', to support non ASCII letters as well.

Unexpected behavior of command denote-dired-rename-file

Situation

I have a file with name 20220724T171924--test__psychology_work.org and content:

#+title: Align the psychology  works
#+date: [2022-06-30 Do]
#+filetags: motivation


  1. If I open dired, set point to said file and call denote-dired-rename-file and
  2. enter a new name, like Align the motivations of
  3. and select eg. 2 keywords, say work,psychology
  4. I get asked whether this is ok (which I answer with y
  5. I get to correct diff (red/green) with new title and new keywords, (which I answer with y)
  6. After that, I get 3 files after updating my dired buffer (with g)
  • #20220724T171924--align-the-motivations-of__psychology_work.org#
  • .#20220724T171924--align-the-motivations-of__psychology_work.org -> [email protected]:1658053153
  • 20220724T171924--align-the-motivations-of__psychology_work.org
  1. when I then do ```org-save-all-org-buffers and again buffer update (g), I've one file left:
  • 20220724T171924--align-the-motivations-of__psychology_work.org
  1. opening this files yields:
#+title: Align the psychology  works of
#+date: [2022-06-30 Do]
#+filetags: motivation

i.e. the file remains unchanged.

Expected behavior

#+title: Align the motivations of
#+date: [2022-06-30 Do]
#+filetags: work psychology

Note

I seem to be unable to reproduce this strange behavior with a simpler file...

Versions

(version) yields: "GNU Emacs 28.1 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.33, cairo version 1.17.6)
Denote Version (GitHub): 61e672f main origin/main Replace needless 'when-let*' with 'when-let'

consider some kind of interoperability with Karl Voits tools

Hi!

I find myself intrigued with denote and wanted to mention the suite of tools that Karl Voit has put together that seem to have a very similar philosophy about file naming, dates, and tags. He describes it here: https://github.com/novoid/filetags#why

I'm not sure what exactly I am suggesting you do here, but wanted to point out the tools in case you are not familiar. It seems like denote and his tools are almost, but not quite compatible (e.g. he separates his tags with spaces).

Merge `refactor-denote-prompts` and delete `denote--prompts`

I am creating this issue following my comment in pull request #33 . I don't have any new code beside what is already in the existing refactor-denote-prompts branch.

I would like to have a discussion about the function denote--prompts (the one that normalizes the values of denote-prompts).

  • Case (iii): This is just to ignore unrecognized values from denote-prompts. It does not seem useful, since the denote command already ignores unrecognized symbols.
  • Case (ii): If denote-prompts is nil, I think we should do as the user probably wanted by setting it to nil, which is no prompts. denote--prompts arranges for the title and the keywords to be prompted in that case.
  • Case (i): This case checks that the value of denote-prompts is a list. I am not sure this is necessary. In denote, dolist over anything that is not a list will throw an error. Maybe this is sufficient?

What do you think?

README feedback

Consider the case where the alternative notes in the blog have no use for the identifier field inside the front matter. Let’s omit it

Is it safe to suggest that? Some user might do that and then wonder whey denote-link doesn't work.

Additionally, if there is no identifier match, denote-link throws an error with backtrace i.e. it's not an elegant user-error.

Dired refresh after renaming in secondary folder

Hi Prot!
I just realized that after re-naming a file in a secondary folder the Dired view doesn't refresh as it does in the primary folder. It's no big deal I think, but I thought you'd like to know.

Is it possible to add a new file type and modify the associated front matter

Thanks for a useful and powerful package.

I am wondering if it is possible to add a new file type? Specifically, .rmd and / or .qmd, which use polymode. These file types are based on markdown but have embedded code-blocks that are executed by, in my main case, R. These file types use the markdown-yaml style front matter, but I might want to add another field, such as `bibliography.

Is this something I can add in my own config? Please let me know if you need any more information about this.

Potentially useful info:

roductName:	macOS
ProductVersion:	11.6.8
BuildVersion:	20G730
GNU Emacs 28.1
Doom core     v3.0.0-dev       HEAD -> master, origin/master d3f2b4d9c 2022-08-01 22:36:33 +0200
Doom modules  v22.07.0-dev     HEAD -> master, origin/master d3f2b4d9c 2022-08-01 22:36:33 +0200

I have installed denote directly from this repo.

Thanks in advance.

`+` char used to separate multiple tags remains in the front-matter too

Recipe to reproduce the issue:

  1. M-x denote
  2. abc (entering title)
  3. tag1+tag2 (entering 2 tags for this note)

Generated file:

#+title:      abc
#+date:       2022-06-10
#+filetags:   tag1+tag2
#+identifier: 20220610T101714

Expected file:

#+title:      abc
#+date:       2022-06-10
#+filetags:   :tag1:tag2:
#+identifier: 20220610T101714

Example #+FILETAGS value in the Org manual: https://orgmode.org/manual/Tag-Inheritance.html.

  • Note: This will work too: #+filetags: tag1 tag2. But that is not documented in the Org manual.

Summary

The + used to separate multiple tags when entering them using M-x denote should not make it way to the front-matter.

Migrating from org-roam (code snippet)

Hey!
I've been using org-roam for taking notes, but I've always wanted something more lightweight and simple, so I'm quite excited to try denote.

For those that are in the same boat, I'd like to share the hack that I wrote for migrating my notes from org-roam to denote (mark files that you want to convert in Dired and do M-x org-roam-convert-to-denote):

(defun org-roam-convert-to-denote (files dir)
  "Convert org-roam notes to denote format and insert them into
`denote-directory'. Works in Dired."
  (interactive
   (list (dired-get-marked-files t current-prefix-arg nil nil t)
         (read-directory-name "Denote directory: " (denote-directory))))
  (unless (file-exists-p dir) (error "Directory does not exist: %s" dir))

  (dolist (file files)
    (let* ((filename (file-name-base file))
           (org-roam-filename-regex
             (rx
              ;; date: YYYY-MM-DD
              (group (= 4 digit) "-" (= 2 digit) "-" (= 2 digit))
              "_"
              ;; time: HH:MM
              (group (= 2 digit) ":" (= 2 digit))
              "-"
              ;; title
              (group (* any))))
           (match? (string-match org-roam-filename-regex filename)))
      (unless match?
        (warn "Filename doesn't match org-roam-filename-regex: %s" filename))

      (let* ((date (match-string 1 filename))
             (time (match-string 2 filename))
             (title (or ;; Try to get title with spaces.
                        (denote-retrieve--value-title file)
                        (replace-regexp-in-string "_" " " (match-string 3 filename))))
             (decoded-time (date-to-time (concat date "T" time)))
             (id (format-time-string denote--id-format decoded-time))
             ;; Code from `org-roam-tag-add'.
             (keywords (with-temp-buffer (insert-file-contents file nil 0 1024)
                         (split-string (or (cadr (assoc "FILETAGS"
                                                        (org-collect-keywords '("filetags"))))
                                           "")
                                       ":" 'omit-nulls)))
             (keywords (denote--sluggify-keywords
                        (if (cdr keywords) keywords (car keywords))))
             (new-name (denote--format-file
                        (denote-directory)
                        id
                        keywords
                        (denote--sluggify title)
                        (denote--file-extension))))
        ;; Ask for confirmation when overwriting, but don't throw an error if
        ;; the user declines.
        (ignore-errors (copy-file file new-name 1))

        (with-current-buffer (find-file-noselect new-name t)
          (save-excursion
           (goto-char (point-min))
           (org-set-property "ID" id)
           ;; Fix keywords: org-roam uses default org :tag1:tag2: format, denote
           ;; uses space-separated format.
           ;; Code from `org-roam-set-keyword'.
           (org-roam-set-keyword "filetags" (string-join (ensure-list keywords) " "))
           (org-roam-set-keyword "date" (denote--date decoded-time))

           ;; Ensure newline before first heading as this is how denote looks
           ;; for front matter ending.
           (goto-char (point-min))
           (outline-next-visible-heading 1)
           (unless (looking-back "\n\n")
             (insert "\n"))

           (let ((inhibit-message t))
             (save-buffer))))
        (message "Converted %s -> %s" file new-name))))
  (denote-dired-update-dired-buffers))

Possible note name collision if denote is called in fast succession

With a simple test such as below:

(defun test ()
  (denote "Test")
  (denote "Test"))

(test)

We can force denote to add the preamble twice to the same file resulting in the following org:

#+title:      Test
#+date:       [2022-07-17 Sun 19:42]
#+filetags:   
#+identifier: 20220717T194217

#+title:      Test
#+date:       [2022-07-17 Sun 19:42]
#+filetags:   
#+identifier: 20220717T194217

This can be solved by append %N to denote--id-format, would that be an acceptable change? It would probably require a "migration" utility to automatically rename all existing notes to append the nanoseconds field.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.