Over the years I have tried a few note systems with various degrees of success. I have tried hnb, zim, google keep, vimwiki and zettlr.

Currently I use vimwiki configured in a way that is compatible with zettlr

task management and notes

zim has a plugin zim task list plugin that collects all the TODO entries and displays the entries that are not done. I understand that emacs org mode allows an even more powerful version of this approach.

Back in the day, when I read getting things done I tried to make the zim task plugin work. At some point around 2012 I thought that it was hard to represent task dependencies if they weren’t in the same zim page.

The next tool I tried was taskwarrior . taskwarrior is a shell program which works like a small DSL to create and query tasks. It can deal with dependencies and time and the querying allows to see the tasks that are actually actionable.

However, using taskwarrior meant that the notes and the tasks were decoupled. The tool taskopen allows to easily open annotations which can be any type of file or url.

vimwiki + taskopen

After observing the task management-note integration in org mode, and with the limitations of zim in mind, I decided to add two scripts to my vimwiki setup so any page could add or read tasks.

I wrote them in lua for neovim neovim:

lua << EOF
function find_tasks()
    local file_path =vim.api.nvim_eval("expand('%:p')")
    file_path = file_path:sub(0,-3) -- remove path
    file_path = file_path:gsub("/", "."):sub(1)
    local command = "!task all /" .. file_path .. "/"
    vim.api.nvim_exec("sp", false)
    vim.api.nvim_exec("enew|pu=execute('"..command.."')| 1,4d_", false)
    vim.api.nvim_exec("setlocal nobuflisted buftype=nofile bufhidden=wipe noswapfile", false)

function add_taskwarrior_task()
    local file_path =vim.api.nvim_eval("expand('%:p')")
    local description = vim.fn.input("description: ", "")
    local command = "!task add " .. description
    local command = "!task +LATEST annotate " .. file_path
    -- vim.api.nvim_exec("execute('"..command.."')", false)

nmap <F5> :lua find_tasks()<CR>
nmap <leader><F5> :lua add_taskwarrior_task()<CR>

The function to read the tasks queries taskwarrior with the current buffer as an argument. I have little experience with lua so it is very likely that this can be done in a better way.

The function to write the tasks create a taskwarrior task and then annotates it using the +LATEST virtual tag.

With this 2 functions and the mappings below I can easily add tasks or query them for each note. To access the tasks via taskwarrior I can simply query the wiki node name task nodename. E.g.:

$ task 2021-02-25

ID  Description                                       
282 make ddd note
      2022-04-23 /full/path/to/wiki/2021-02-25.md

1 task

and then open it again with taskopen 282