Home

Awesome

Zettelkasten.nvim

A simple Zettelkasten plugin.

Allows you to navigate through a zettelkasten using unique ID anchors, and quickly create links for new zettel.

These anchors, as of now, are simplified time stamps with 10 digits (YYMMDDHHmm), though the intention is to configure the plugin to be configurable for any ID anchor you have. Using ID anchors has the benefit that they are presumably unique, so wherever your zettel is within the directory, or on the file system, will be where you end up. You can even change the file name of everything (zettel, containing directory, etc.) and still end up at the correct note as long as the ID anchor is kept constant.

Currently allows note link creation (automatically appending a time-based anchor to each created note) in markdown and wiki-link style, as well as following links to other notes, wherever they are in the notes directory.

Not much more has been implemented yet, but some options can already be configured by the user.

Lastly, a warning: Though it works, this plugin is in very rough development still, so don't expect too much as of now. It works what I desperately needed it to work for and thus the additional functionalities will only come trickling in, but there's not much here yet.

Usage

All exposed functionality of the plugin can be reached either through lua bindings or through vim <Plug> mappings.

The one mapping you probably want to undertake (replacing the mapping as needed) is the following link mapping:

Linking

nnoremap <cr> :lua require 'zettelkasten'.link_follow()<cr>
vnoremap <cr> :lua require 'zettelkasten'.link_follow(true)<cr>

This will allow you to create new links when over any text, or having text selected; as well as follow links to existing or new notes. It will look through your notes in the zettel directory you set (look for the options below). If you pass in true it will work for visual mode instead of normal mode instead.

The function is also exposed as vim mapping <Plug>zettel_link_follow, so can be set via map <cr> <Plug>zettel_link_follow to get the same result as above.

:lua require 'zettelkasten'.link_open()
:lua require 'zettelkasten'.link_make(visualmode)

allows you to separate the link following and creation set by one function above. Again, you can pass in true for link creation to make it work correctly from visual mode.

The functions are again exposed as <Plug>zettel_link_open and <Plug>zettel_link_make respectively.

Index

nnoremap <leader>w :lua require 'zettelkasten'.index_open()<cr>

allows you to map going to your defined zettel index file. This functions by looking into your zettel directory for a file named 'index' and ending with the extension you set for your zettel. I.e. by default it will open 'index.md' in your zettel root directory.

If you wish to open a different file by default, you can pass it into the lua function as a string, e.g. :lua require 'zettelkasten'.open_index('myfile'), though it will keep adding the zettel extension at the end.

Indexing is also exposed as vim mapping <Plug>zettel_index_open

Listing

You can have a valid zettel anchor returned by using the :lua require 'zettelkasten'.get_anchor() function.

The only other exposed function currently is:

:lua require 'zettelkasten'.get_zettel_list(path, recursive)

to list all existing zettel in a directory. The path in this instance is required. Recursive is an optional boolean variable telling the function if it should recourse into subdirectories on the hunt for zettel and return those as well.

Options

Options can currently be set via lua:

vim.g["zettel_extension"] = ".md"
vim.g["zettel_root"] = "~/documents/notes"

or via vimscript:

let g:zettel_extension = ".wiki"
let g:zettel_root = "~/documents/notes"

The functionality is the same. The plugin will look up options by precedence buffer > global > default.

anchor_separator = vim.b["zettel_anchor_separator"] or vim.g["zettel_anchor_separator"] or "_",
zettel_extension = vim.b["zettel_extension"] or vim.g["zettel_extension"] or ".md",
zettel_root = vim.b["zettel_root"] or vim.g["zettel_root"] or "~/documents/notes",

Since, as long as the api still changes rapidly, a list of options would quickly be outdated, what you can instead is to look into options.lua, where at the top the currently effective options with their defaults and available values are defined.

up next

TODO: needed functionality

TODO: maintenance

Anchor Creation

TODO: nice-to-haves

Developing / Debugging

start neovim with nvim --cmd "set rtp+=$(pwd)" . to automatically load the files in project dir as if they were on path.

Put the following function in the plugin directory as debug.vim or similar and you can instantly reload the plugin during development.

" TODO for DEBUGGING ONLY: reloads the whole lua plugin
fun! ZKReload()
  lua for k in pairs(package.loaded) do if k:match("^zettelkasten")  then package.loaded[k] = nil end end
  lua require 'zettelkasten'
endfun
nnoremap <leader>R :call ZKReload()<cr>