reddit / emacs
[ANN] zk: a zettelkasten-style note-taking package, with minimal dependencies
oldjawbone · 2022-01-31 15:09
Located here: [https://github.com/localauthor/zk](https://github.com/localauthor/zk)
And also available on [Melpa](https://melpa.org/#/zk).
Demo of basic features: [https://youtu.be/BixlUK4QTNk](https://youtu.be/BixlUK4QTNk)
​
Also, a few extensions under development:
\- zk-index and zk-desktop - interfaces for browsing, (pre)viewing, and (re)arranging notes: [https://youtu.be/7qNT87dphiA](https://youtu.be/7qNT87dphiA)
\- zk-luhmann - support for an lternative ID scheme: [https://youtu.be/O6iSV4pQQ5g](https://youtu.be/O6iSV4pQQ5g)
​
It's my first time packaging things up, so notes and suggestions welcome!
bdarcus · 2022-01-31 17:08
Nice; congrats!
Thoughts on if and how you might integrate bibliographic notes?
oldjawbone · 2022-01-31 18:24
Thanks!
Yes, definitely. It works great with Citar. :)
I insert citekeys all over the place when I'm making new notes. And I have a function called 'append-bibliography' that finds all the citekeys in a note and appends a formatted bibliography (via citeproc) to the end of the note.
As for my bibliographic notes (or literature notes), they all follow a consistent titling scheme: "UID AuthorYEAR - Title (YEAR).md," so that with the help of a little custom function I can filter in Citar by "has:notes" and get an accurate list.
(All of these functions are in the ['my-lisp' directory](https://github.com/localauthor/.emacs.d/tree/main/my-lisp) of my .emacs.d repo, for the curious.)
bdarcus · 2022-01-31 18:47
>As for my bibliographic notes (or literature notes), they all follow a consistent titling scheme: "UID AuthorYEAR - Title (YEAR).md," so that with the help of a little custom function I can filter in Citar by "has:notes" and get an accurate list.
So zk understands those notes as distinct types of notes?
oldjawbone · 2022-01-31 19:10
Not explicitly, no. But the idea behind zk was to offer really basic low-level functions that would make writing customized functions fairly simple.
For example, the function `zk--directory-files` is a thin wrapper around Emacs's `directory-files`, which matches files in a directory against a regexp.
To find all the lit-notes in my zk-directory, I just write a regexp that will match against the titles of the relevant notes (without worrying about the UID --- that's one thing that `zk--directory-files` takes care of).
If an emacs regexp for an AuthorYEAR string (say, "MacArthur2019") looks like `[a-z]+[0-9]\\{4\\}` then the following function returns a list of all notes with a matching string after the UID:
`(zk--directory-files t "[a-z]+[0-9]\\{4\\}")`
To make this interactive, the following function offers completion on all matching files in the minibuffer:
(defun zk-lit-notes ()
"Find literature note."
(interactive)
(let* ((lit-notes (zk--directory-files t "\[a-z\]+\[0-9\]\\{4\\}")))
(find-file (zk--select-file "Lit notes: " lit-notes))))
Another example: in the above, `zk--select-file` is a convenient wrapper around Emacs's `completing-read` that makes minibuffer selection a bit nicer.
So, if you use zk, you can assemble your own functions to suit whatever naming scheme you want to use, just by writing an appropriate regexp.
EFLS_ · 2022-01-31 19:25
Nice! I like that you got inspired by Zetteldeft – but I guess this means you won't be submitting Zetteldeft PRs anymore? :)
I'll be checking out your videos as well to take some inspiration for new Zetteldeft features.
oldjawbone · 2022-01-31 19:33
Completely inspired by Zetteldeft. It was writing PRs that led me to start putting this together, first as an exercise, then as something I thought others might like to try.
I'd would certainly keep contributing to Zetteldeft, of course! :) There are some PRs there waiting for review, if memory serves. :P
EFLS_ · 2022-01-31 19:53
> There are some PRs there waiting for review, if memory serves. :P
Oh yeah, you are right! Sorry about that, I should take some time to look at those (but my limited elisp skills mean it takes me some time to actually 'get' how the code works).
EDIT: Oh, and the biggest challenge: figuring out which keybindings to use for your added features!
oldjawbone · 2022-02-01 07:43
Definitely feel free to ask, if you have questions about any of it.
And if there are any issues you're working on that you want help with, just ping me on Github. :)
Yeah, and about keybindings, that's a tough one... Not a lot of free space left under the `C-c d` prefix!
simbledress · 2022-02-05 10:21
Looks nice! Btw have you seen [org-brain](https://github.com/Kungsgeten/org-brain/)? It is org-only but also seems minimal in dependencies.
oldjawbone · 2022-02-05 11:45
I'd heard of org-brain, but hadn't checked it out before. It seems pretty cool! Definitely much more complicated than zk :)
ExistingProgram3883 · 2022-02-08 16:21
This is awesome, /u/oldjawbone, thank you very much for providing this package!
After using the package a little and viewing your videos, I would like to ask for an explanation, why you are using Luhmann's numbering scheme "on top" of the system-inherent backlinks?
oldjawbone · 2022-02-09 00:01
Oh boy, that's a can of worms :)
Briefly, I started using them as an experiment, found that I enjoyed using them, and have not found any downsides. Only benefits. If you read no further, I would say, if you're curious, try them out! Only your own experience will tell you if it's useful for you and helps you meet your specific goals.
Ok, a bit of a longer answer:
First, I really (really) like the act of 'placing' a note in the zk by intentionally assigning it a Luhmann style ID number. It feels like roughly a digital equivalent of placing a card in a card-file. It's very satisfying. I've also found that it's really important, for me at least, to make that first very intentional placement of a note. Before using Luhmann IDs, I often found myself making a note and not thinking so intentionally about its relationship(s) with other notes in the zk. I would just make a few connections here and there via standard links, and think that was enough. After a while, though, it felt like I just had a pile of loosely, almost arbitrarily, linked notes. This is probably a failing on my part, because I could certainly have forced myself to make good intentional links with regulars IDs. But using Luhmann IDs almost forces that kind of thought and intentionality implicitly. I find it very handy for that.
It should be said, though, that loose and arbitrary links can be very useful. So I still do make any number of such links. It's just that doing so after I've placed the note solidly in the structure of the zk, via assigning it a Luhmann ID, feels much less chaotic and reckless.
Second (third? fourth?), they help me quickly browse through my notes without having to go into the content of the notes to follow links. Again, it's kind of like dealing with a physical card-file. I can look over the whole thing structure from a 'distance' and find clusters of related notes and (at least roughly) follow threads of thought. (The 'zk-index' package really helps with this kind of browsing.)
For much longer account, see this thread from a few years ago, where I tried to answer the same kind of question. (I'm 'argonsnorts' there. I'm not good at using consistent usernames...)
[https://forum.zettelkasten.de/discussion/comment/4943/#Comment\_4943](https://forum.zettelkasten.de/discussion/comment/4943/#Comment_4943)
ExistingProgram3883 · 2022-02-09 05:59
Thank you very much for your exhaustive answer and the link to the discussion, /u/oldjawbone. This supports me in thinking, that I didn't misunderstood something.
I really like your argument, that it forces the Zettelkasten's maintainer to explicitly think about the connections between Zettels and topics. Personally, I had a comparable feeling, when I used org-roam for some time. Links and backlinks are convenient, but do not support one in structuring one's thoughts and the thinking process like Folgezettels do (probably). So I think that I will try this numbering scheme out.
Do you have considered adding functions like `zk-new-folgezettel`, `zk-new-branched-note` and maybe even `zk-move-branch` to zk-luhmann.el which could save some typing and support note generation and curation?
Furthermore, I have another question: why do you assign the ID with a space before the closing brace like `{2,a,1 }` opposed to `{2,a,1}`?
oldjawbone · 2022-02-09 13:08
The space before the closing brace ensures that the automated sorting works properly. I’m honestly not sure why it works that way, and I didn’t bother to investigate. 😁
Regarding automated numbering, it’s probably technically possible, but I’m inclined to say there’s some value in leaving some interactions not automated. It seems to me that assigning an ID if this type is more than a mechanical act — it takes some thought and consideration. The more involved you are in the process of placing the note in the system, the more the system becomes a structured manifestation of your own thinking. Just my current thoughts.
ExistingProgram3883 · 2022-02-09 17:47
Thanks for getting back to me. I see...the regex `"{\\([0-9a-zA-Z,]*\\)}"` should fix that.
I can relate to your thoughts that the thoughtful process has certain benefits, but at least `zk-new-folgezettel` seems helpful to me. Maybe I'll try to create such a function, if time permits.
What are your plans for working on `zk`? I saw that you removed `zk-luhmann.el` and `zk-desktop.el` from `zk` itself?
oldjawbone · 2022-02-10 12:00
I initially wrote \`zk-luhmann\` for my own idiosyncratic use case, so I didn't consider it general enough to include in the same repo as \`zk\`.
However, work is being done to generalize it, to make it more accessible, customizable, and predictable. After that's done I think I'll move it back to \`zk\`.
ExistingProgram3883 · 2022-02-23 17:13
Can you elaborate how you get `citar` to indicate available notes?
I tried it the way you did (see below) and `citar` opens the notes. However, the indicator for notes is never set.
```
(defun gr/citar-zk-open-note (key entry)
"Custom function for citar-open-note-function."
(let* ((filematch (format "\\`[0-9]\\{12\\}.%s.*\\.\\(?:md\\)\\'"
(regexp-quote key)))
(results-key (seq-mapcat
(lambda (dir)
(if-let ((file (directory-files dir t filematch)))
file))
citar-notes-paths)))
(if results-key
(funcall 'find-file (car results-key))
(if (y-or-n-p "No note associated - create one?")
(let* ((template (citar-get-template 'note))
(title
(when template
(subst-char-in-string ?: ?-
(citar--format-entry-no-widths
entry
template)))))
(zk-new-note title))))))
```
(See https://github.com/localauthor/.emacs.d/blob/2a04192d1156742f1345196f1a7d1f85131bf2cb/init.el#L2972)
Do you, /u/oldjawbone or /u/bdarcus, what to change, so that `citar` displays the existence of notes in the zettelkasten correctly?
Thanks in advance!
oldjawbone · 2022-02-23 19:56
You'll need the function below that, too `gr/citar-file--make-filename-regexp` which you'll need to set to override `citar-file--make-filename-regexp`.
Can't speak to upstreaming this, but it seems not general enough.
EDIT: and don't forget to `citar-refresh`
ExistingProgram3883 · 2022-02-23 20:35
Thanks for the hint. Sorry that I missed that obvious one. Works like a charm of course.
bdarcus · 2022-05-28 17:58
> Can you elaborate how you get citar to indicate available notes?
I recently merged changes that add a new citar-keys-with-notes-functions defcustom. So you write a function to populate a list of citekeys, and citar will use those for the display