zetteldeft icon indicating copy to clipboard operation
zetteldeft copied to clipboard

Can I set it up to follow The Archive style links? [[202012290540]]

Open patmaddox opened this issue 3 years ago • 29 comments

I am starting to use emacs in conjunction with the archive, and am trying to get emacs to have similar behavior to the archive in that it will pull up a matching file when clicking a link such as [[202012290540]]. I'm using org and md files.

I read this and this, hoping they would point the way - but they seem to be doing something different.

Any ideas on how I can get emacs to follow those sorts of links? I would still want [[#internal]] links to work.

patmaddox avatar Dec 29 '20 13:12 patmaddox

Here's a config that worked - the missing piece was the zetteldeft-id-regex to find candidates.

(setq zetteldeft-link-indicator "[[")
(setq zetteldeft-link-suffix "]]")
(setq zetteldeft-id-format "%Y%m%d%H%M")
(setq zetteldeft-id-regex "20[0-9]\\{10\\}")

Any idea how to hook zetteldeft-follow-link into org-return / org-open-at-point? That would be the final touch.

patmaddox avatar Dec 29 '20 21:12 patmaddox

Here's a config that will try org-mode's search first, then fall back to zetteldeft-follow-link:

(setq org-return-follows-link t)
(setq org-link-search-must-match-exact-headline nil)

(defun zetteldeft-try-follow-link (orig-org-open-at-point &optional arg)
  (condition-case nil
      (apply orig-org-open-at-point arg)
    (error (zetteldeft-follow-link))))

(advice-add 'org-open-at-point :around #'zetteldeft-try-follow-link)

I do notice some weird behavior where zetteldeft-follow-link changes the text and downcases a character, if it's in one of the first two characters, or there is no match:

image

image

It still doesn't work with the first two characters (I guess it has to do with the regex), but I managed to stop the weird behavior not running the avy file prompt:

(defun zetteldeft-follow-link ()
  "Follows zetteldeft link to a file if point is on a link.
Prompts for a link to follow with `zetteldeft-avy-file-search' if it isn't."
  (interactive)
  (if (thing-at-point-looking-at (zetteldeft--link-regex))
      (zetteldeft--search-filename
       (zetteldeft--lift-id (zetteldeft--get-thing-at-point)))
    (message "Not a zetteldeft link!")))

patmaddox avatar Dec 30 '20 01:12 patmaddox

I've never tried integration with The Archive -- although I do hope to achieve some compatibility with Zetteldeft. I think the extra challenge that you have is that you mix .md and .org files, as the use of [[ ]] as Zetteldeft link delimiters overlaps with the markup Org uses for links. Anyway, glad you've found a way to combine the two -- that's a nice solution.

With regards to the zetteldeft-follow-link hick-up, I think it indeed has to do with the zetteldeft-id-regex you've set up. Not sure what the issue is exactly, though.

The easiest way to prevent all of this is to make a choice between .md and .org for your files, but that might not be a real option.

Also, you might not really need to call zetteldeft-follow-link in your zetteldeft-try-follow-link function, as that would involve the Avy-style functions where you really don't need them.

Maybe try:

(defun zetteldeft-try-follow-link (orig-org-open-at-point &optional arg)
  (condition-case nil
      (apply orig-org-open-at-point arg)
    (error (zetteldeft--search-filename (zetteldeft--lift-id (zetteldeft--get-thing-at-point))))))

EFLS avatar Dec 30 '20 21:12 EFLS

As a reference: over on forum.zettelkasten.de someone shared a configuration to make Zetteldeft work like The Archive, see https://forum.zettelkasten.de/discussion/1640/making-zetteldeft-work-like-the-archive

EFLS avatar Jan 29 '21 10:01 EFLS

Thanks both @patmaddox and @EFLS, this thread helped me fix some things that I had been trying to figure out for a long time.

I would like to be greedy here and ask for the next step for me- how would I take the zetteldeft-try-follow-link that @EFLS posted there and add a third fallback, so that if neither an org link nor a zetteldeft link worked, it would instead call zetteldeft-search-at-point ? I am trying, but my lisp is not up to the task.

I thank you for your potential indulgence.

mediapathic avatar Feb 12 '21 08:02 mediapathic

Not really sure about that. You could look at zetteldeft--search-filename and try to write a similar function that launches a search when there are no files found (i.e., replace the when in that function with an if).

EFLS avatar Feb 14 '21 11:02 EFLS

(setq zetteldeft-link-indicator "[[")
(setq zetteldeft-link-suffix "]]")
(setq zetteldeft-id-format "%Y%m%d%H%M")
(setq zetteldeft-id-regex "20[0-9]\\{10\\}")

Is this a viable formatting for links in zetteldeft that wouldn't clash with orgmode?

AtomicNess123 avatar Mar 06 '22 08:03 AtomicNess123

Have you tried it? My guess is it will clash with Org, as it also uses [[ ]] style links.

EFLS avatar Mar 06 '22 09:03 EFLS

Yes, just tried. I noticed some discussion around this topic. I suppose there is no way to have it then! :)

AtomicNess123 avatar Mar 06 '22 09:03 AtomicNess123

You need to be more clear about what you are trying to achieve if you want help. It is possible to use The Archive style links, but if you do that in .org files, you run into trouble. So the best way to go is to not use .org file extensions if you want to use The Archive links (but simply use .md, as The Archive does AFAIK).

EFLS avatar Mar 06 '22 09:03 EFLS

Thanks for this. I wanted to know whether I should open a new issue for this quick question, relevant here: How to customize the link format? AT the moment it looks like [[ID]]. So whenever Izetteldeft-copy-ID-current-fileand paste it on another note, I just paste an ID, and would like to have [[ID]]: title of note if it's possible. Thanks for your help!

AtomicNess123 avatar Apr 16 '22 16:04 AtomicNess123

To insert that, you should use zetteldeft-find-file-full-title-insert. Does that do what you want?

EFLS avatar Apr 16 '22 18:04 EFLS

Thanks for this. I just tried and it prompts to find the file. The scenario I have in mind is the following:

  1. I work on a file and copy its ID with zetteldeft-copy-ID-current-file
  2. I paste it on a different file.

If I use zetteldeft-find-file-full-title-insert I have to search for the current note I am on. It would feel like an extra step. Maybe there could be a simple function (I wish I could code it myself) that just pastes an "extended" ID with full title, something like zetteldeft-paste-ID-with-full-title (I'm not good with function naming) :)

AtomicNess123 avatar Apr 16 '22 19:04 AtomicNess123

Haven’t tested this, but try:

(defun zetteldeft-copy-id-title-current-file ()
  "Copy current ID and title.
Add the id and title from the filename the buffer is currently visiting to the
kill ring."
  (interactive)
  (zetteldeft--check)
  (let* ((ID (concat zetteldeft-link-indicator
                    (zetteldeft--lift-id (file-name-base (buffer-file-name)))
                    zetteldeft-link-suffix))
(title (zetteldeft--id-to-title ID)))
    (kill-new (format “%s: %s” ID title))))

localauthor avatar Apr 16 '22 19:04 localauthor

Thanks! It's not working, and giving me this error:

Debugger entered--Lisp error: (wrong-type-argument stringp nil)

AtomicNess123 avatar Apr 16 '22 20:04 AtomicNess123

It was a bit more complicated than I expected.

The functions zetteldeft--lift-file-title and zetteldeft--id-to-title return a title in the form "id title", so it's necessary to extract the actual title manually with the regexp. :/

Try this:

(defun zetteldeft-copy-id-title-current-file ()
  "Copy current ID and title.
Add the id and title from the filename the buffer is currently visiting to the
kill ring."
  (interactive)
  (zetteldeft--check)
  (let* ((file (buffer-file-name))
         (id (zetteldeft--lift-id file))
         (full-title (zetteldeft--lift-file-title file))
         (title (progn
                  (string-match (concat "\\(?1:"
                                        zetteldeft-id-regex
                                        "\\).\\(?2:.*\\)")
                                full-title)
                  (match-string 2 full-title)))
         (link (concat zetteldeft-link-indicator
                       id
                       zetteldeft-link-suffix))
         (return (format "%s: %s" link title)))
    (kill-new return)
    (message return)))

localauthor avatar Apr 17 '22 05:04 localauthor

Thanks. Now it won't spit out any error message. For some reason it's returning: [2022-03-03-1911-16]]: nil

AtomicNess123 avatar Apr 17 '22 10:04 AtomicNess123

That will be caused by the regex argument passed to string-match in the function above. I guess it’s not general enough, but it could be changed to match the title portion of your own notes’ file names.

localauthor avatar Apr 20 '22 08:04 localauthor

Thanks. So in the lines

concat "\\(?1:"
                                        zetteldeft-id-regex
                                        "\\).\\(?2:.*\\)")

I should replace \\).\\(?2:.*\\) by my zetteldeft-id-regex expression?

AtomicNess123 avatar Apr 20 '22 08:04 AtomicNess123

The functions zetteldeft--lift-file-title and zetteldeft--id-to-title return a title in the form "id title", so it's necessary to extract the actual title manually with the regexp. :/

Not sure what you mean? zetteldeft–id-to-title should really just retunr the title.

Anyway, this is what I came up with. Does this work for you @AtomicNess123?

    (defun efls/zd-copy-id-and-title ()
      (interactive)
      (zetteldeft--check)
      (let* ((id (zetteldeft--lift-id (file-name-base (buffer-file-name))))
             (link (concat zetteldeft-link-indicator
                           id
                           zetteldeft-link-suffix))
             (title (zetteldeft--id-to-title id)))
        (kill-new (concat link
                          " "
                          title))))

EFLS avatar Apr 20 '22 18:04 EFLS

Sorry, I see my misunderstanding. I didn't realize that deft-parse-title takes the title from the first line of the file itself, not from the file name. My mistake!

localauthor avatar Apr 20 '22 19:04 localauthor

The functions zetteldeft--lift-file-title and zetteldeft--id-to-title return a title in the form "id title", so it's necessary to extract the actual title manually with the regexp. :/

Not sure what you mean? zetteldeft–id-to-title should really just retunr the title.

Anyway, this is what I came up with. Does this work for you @AtomicNess123?

    (defun efls/zd-copy-id-and-title ()
      (interactive)
      (zetteldeft--check)
      (let* ((id (zetteldeft--lift-id (file-name-base (buffer-file-name))))
             (link (concat zetteldeft-link-indicator
                           id
                           zetteldeft-link-suffix))
             (title (zetteldeft--id-to-title id)))
        (kill-new (concat link
                          " "
                          title))))

Actually it doesn't. It returns this (I tried with several notes):

helm-M-x-execute-command: ID Error. Multiple zetteldeft files found with ID 2021-09-09-2119-26

AtomicNess123 avatar Apr 21 '22 10:04 AtomicNess123

Seems like you have multiple notes with the same ID. Make sure the IDs are unique. Open your notes folder, look for the note with that ID in the filename, and change it so it's unique.

EFLS avatar Apr 21 '22 11:04 EFLS

Yes, I had a bak dirctory with some duplicates for some reason. After deleting them, it works:

[[2021-09-09-2119-26]] title of the note

However, how to change the function to include the title of the note as part of the clickable link? Like this:

[[2022-04-21-1328-22][title of the note]]

This would look nicer on the note.

AtomicNess123 avatar Apr 21 '22 12:04 AtomicNess123

Not sure how that would work. Are you using Markdown or Org-mode? In Org, the [ formatting would interfere with Org-links. Unless you use some kind of custom link.

EFLS avatar Apr 21 '22 13:04 EFLS

Thing is, I have a function that makes org try to follow link, and if it fails, then uses zetteldeft. I copied it from somewhere, and it works fine. So I would like to have the links with that formatting, as if I just have text beside a link, I may have to wrap it with brackets of something not to be confused with the text if inserted in a paragraph.

AtomicNess123 avatar Apr 21 '22 15:04 AtomicNess123

I copied it from somewhere, and it works fine.

Ah yes, I remember that discussion somewhere around here.

With such heavy customization, it might be worth it to learn some basic emacs lisp.

You could replace the (concat ...) part in the previous function with something like this:

(concat "[["
        id
        "]["          
        title
        "]]")

EFLS avatar Apr 22 '22 12:04 EFLS

Thank you!

AtomicNess123 avatar Apr 25 '22 08:04 AtomicNess123

Hi, and coming back to this, this function is great to have orgmode follow the links using zetteldeft when using two brackets:


;  from: https://github.com/localauthor/zk#using-org-mode-and-org-links
  (defun zk-org-try-to-follow-link (fn &optional arg)
    "When 'org-open-at-point' FN fails, try 'zk-follow-link-at-point'.
  Optional ARG."
    (let ((org-link-search-must-match-exact-headline t))
      (condition-case nil
          (apply fn arg)
        (error (zetteldeft-follow-link)))))

  (advice-add 'org-open-at-point :around #'zk-org-try-to-follow-link)

But in my case, it does not work when the follow link has the format:

[[2022-10-23-1720-41][2022-10-23-1720-41 title of the note]]

Any way to tweak the function to make this work? It would be nice to have the title inside the clickable link rather than only the numerical code (less informative).

This would be of use to many users.

Thanks!

AtomicNess123 avatar Oct 23 '22 14:10 AtomicNess123