Skip to content

Instantly share code, notes, and snippets.

@benevidesh
Last active March 12, 2024 16:10
Show Gist options
  • Star 13 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save benevidesh/d78f7681120a13d5386ea55b39d82c9b to your computer and use it in GitHub Desktop.
Save benevidesh/d78f7681120a13d5386ea55b39d82c9b to your computer and use it in GitHub Desktop.
Zettelkasten Workflow (WIP)
#!/usr/bin/bash
# zn - as zettell
# new export variables EDITOR for your editor and
#+ NOTES for your notes folder.
main () {
note_id=$(date +'%Y%m%d%H%M%S')
$EDITOR $NOTES/"$note_id".md
}
main
#!/usr/bin/bash
#
# zs - is a zettel selector using fzf
# features:
# - it accepts multiple selection (using tab)
# - copy multiple selection to clipboard (mapped to ctrl-y)
# - clear selection (mapped to ctrl-l)
# - populates (n)vim quickfix list with zettel titles (enter)
#
SRC_FOLDER=$(pwd)
main() {
cd "$SRC_FOLDER"
grep --max-count=1 "^#[[:space:]][[:alnum:]]" *.md | sed 's/:#[[:space:]]/ | /g' | fzf --tac --multi \
--layout=reverse \
--preview "echo {} | sed 's/[[:space:]].*//g' | head | xargs bat --style=plain --color=always || xargs cat {}" \
--preview-window=wrap \
--bind '?:toggle-preview' \
--bind 'ctrl-l:clear-selection' \
--bind "ctrl-y:execute(printf '%s\n' {+} | sed 's/.md//g' | xclip -selection clipboard)" \
--bind 'enter:execute(echo {+} | grep -o "[0-9]\+\.md" | xargs $EDITOR -c "silent bufdo grepadd ^\# %")'
}
main
@benevidesh
Copy link
Author

benevidesh commented Jan 13, 2022

This is my attempt to create a workflow for Zettelkasten using fzf + (n)vim. Sadly, the scripts are not self explanatory, so here we go.

the structure of the kasten (box) where notes live

  1. I'm using markdown filetype
  2. files are named using timestamps as the unique ID

So, the box where the zettels are stored looks like

$
.
├── 20220404151016.md
├── 20220404185423.md
├── 20220404191240.md
├── 20220405080857.md

Think of it as a database

the strucure of the zettels

# This is a title for the current note


Lorem ipsum sum dolor...

...

a brief explanation of the zettelselector zs script

A downside of the timestamp convention is that it doesn't help you to find a note. That's why we need a way of accessing the database, and this is the work of zs script.
So, how it works?

1. Define a folder where your notes live. Since I have a bunch of folders with notes, I set it to the current working dir.

SRC_FOLDER=$(pwd)

2. grep the title of your note

grep --max-count=1 "^#[[:space:]][[:alnum:]]" *.md | ...

This assumes that titles are the first occurrence of # followed by an alphanumeric character. So it matches lines such as # This is a note and # 2022-04-06

3. clean up the result of your search a little bit and add format

... | sed 's/:#[[:space:]]/ | /g'

This line uses | as a separator between the filename and the actual title of the note, producing something as

20220404151016.md | This is a title for the current note

4. pass it to fzf

Passing your search to fzf will produce a list with filenames | titles. From this you can use your imagination to do anything you want.

The most interesting options add to fzfwith the script above are:

Preview the zettel with bat for syntax highlighting or with cat (if you don't have it)

 --preview "echo {} | sed 's/[[:space:]].*//g' | xargs  bat --style=plain --color=always || xargs cat {}"

The sed substitution in this pipe removes everything that is not the filename of the zettel.

Copy a list of notes to you clipboard

--bind "ctrl-y:execute(printf '%s\n' {+} | sed 's/.md//g' | xclip -selection clipboard)" 

This might be useful for creating an outline.

Edit a list of notes using vim

--bind 'enter:execute(echo {+} | grep -o "[0-9]\+\.md" | xargs $EDITOR -c "silent bufdo grepadd ^\#  %")'

The nice thing about this line is that it populates vim's quickfix list with the titles of your notes.

@bbelderbos
Copy link

This is amazing, a very quick and simple way to get started with what can be an overwhelming system :)
And it works like a charm, thanks so much!

@bbelderbos
Copy link

On Mac I had to brew install bat (really nice) and "xclip -selection clipboard" did not work so I replaced that by pbcopy. When entering on a file I do get a warning: Vim: Warning: Input is not from a terminal, have you seen that too?

@benevidesh
Copy link
Author

This is amazing, a very quick and simple way to get started with what can be an overwhelming system :)
And it works like a charm, thanks so much!

Thanks for stopping by. Good to know that it migh serve you. I'm still looking forward for an even simpler workflow. Don't be overwhelmed. People like overthinking things. A down to earth reading list about this:

On Mac I had to brew install bat (really nice) and "xclip -selection clipboard" did not work so I replaced that by pbcopy. When entering on a file I do get a warning: Vim: Warning: Input is not from a terminal, have you seen that too?

Yeah, these scripts are biased :) . I get no warning here, but since I'm a nvim user that might interfer. With vim, I guess changing the line

--bind 'enter:execute(echo {+} | grep -o "[0-9]\+\.md" | xargs $EDITOR -c "silent bufdo grepadd ^\#  %")'

with

--bind 'enter:execute(echo {+} | grep -o "[0-9]\+\.md" | xargs -o $EDITOR -c "silent bufdo grepadd ^\#  %")'

might be a good start point for debugging.

Let me know if it works.


{ }'s

@bbelderbos
Copy link

Sweet, the extra -o works on my end.
Also thanks for the resources, looking forward to diving into them.

@buggysolid
Copy link

For anyone reading this I adopted these scripts and have them working for apt based distros including WSL2 on Windows using standard Vim 8.

https://github.com/buggysolid/note-taking-scripts

Setup https://ciaran.dev/2022/09/08/a-vim-zettelkasten-note-taking-system.html

Thank you benevidesh for publishing this.

@benevidesh
Copy link
Author

Hey @buggysolid,

Thanks for spreading the word of Zettelkasten Minimalism. 😅️

@the-intern
Copy link

the-intern commented Oct 20, 2022

Would very much love to use this --- but when calling zn I get the error:
> zn main:2: no such file or directory: /Users/udax/zettel/20221020160540.md

My zn file appears thus:


#!/bin/zsh
main () {
    note_id=$(date +'%Y%m%d%H%M%S')
    $EDITOR $NOTES/"$note_id".md
}

main

My zs file:

#!/bin/zsh

main() {
    cd "$NOTES"
    grep --max-count=1 "^#[[:space:]][[:alnum:]]" *.md | sed 's/:#[[:space:]]/ | /g' |  fzf --tac --multi \
                                --layout=reverse \
                                --preview "echo {} | sed 's/[[:space:]].*//g' | head | xargs bat --style=plain --color=always || xargs cat {}" \
                                --preview-window=wrap \
                                --bind '?:toggle-preview' \
                                --bind 'ctrl-l:clear-selection' \
                                --bind "ctrl-y:execute(printf '%s\n' {+} | sed 's/.md//g' | pbcopy)" \
                                --bind 'enter:execute(echo {+} | grep -o "[0-9]\+\.md" | xargs $EDITOR -c "silent bufdo grepadd ^\#  %")'
}

main

NOTE - I replaced xclip command with pbcopy in the hopes that somehow that was the hold up.

For what it's worth, I am on a Mac 12.6

Any thoughts would be appreciated!

@buggysolid
Copy link

Would very much love to use this --- but when calling zn I get the error: > zn main:2: no such file or directory: /Users/udax/zettel/20221020160540.md

My zn file appears thus: ` #!/bin/zsh main () { note_id=$(date +'%Y%m%d%H%M%S') $EDITOR $NOTES/"$note_id".md }

main ` For what it's worth, I am on a Mac 12.6 Any thoughts would be appreciated!

It looks like the $NOTES variable is not set either in the script or your shell as an environment variable.

What does echo $NOTES output in your terminal?

@the-intern
Copy link

It has been set:

echo $NOTES
/Users/udax/zettel

@the-intern
Copy link

My .zshrc file contains:

export NOTES="/Users/udax/zettel"

@the-intern
Copy link

Well, as is true with almost all of my requests for help, I am embarrassed to say that it was rather obvious:

The EDITOR variable was not set. I simply set it:

export EDITOR=vim

and, as night follows day, it worked.

Sorry.

As an afterthought --- perhaps I'm wrong but I didn't see any discussion of that env variable. (Again, perhaps I am wrong. It has happened on occasion.)

Thanks!

@benevidesh
Copy link
Author

Hey guys!

New scripts: https://github.com/benevidesh/zettelmaking

What is new? A script named zex (for zettelExplorer) that makes interactive real time queries trough your notes. Check it out!

@m-danya
Copy link

m-danya commented Aug 19, 2023

Hi! Thank you for sharing these scripts, they are powerful and minimalistic.

I've dockerized your scripts to freeze nvim/tmux configs and to implement automatic git syncronization: https://github.com/m-danya/dockerized-zk. Maybe one day I will hybreed your fzf-based approach with vimwiki plugin, which have nifty links displaying.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment