www-gem words

Neovim/Taskwarrior interaction

Published on

Edits:
    on 2025-11-23: add the "info" feature [1]
    

cli As someone who uses Neovim as default text/code editor, I’ve always loved its simplicity and flexibility. After a discussion with a group of folks on mastodon, I’ve decided to use this flexibility to allow some interaction between Neovim and Taskwarrior. I use Taskwarrior to track everything from work tasks to personal projects, and while it’s a fantastic tool - when I don’t need something more complete like Taskjuggler - I didn’t want to keep bouncing between Taskwarrior and Neovim just to add, update, or delete tasks. It felt like an unnecessary interruption in my flow. As a bonus, being able to quickly find where my tasks are mentioned in my text files, then why not? :)

So, I decided to build something that would allow me to stay in Neovim while interacting with Taskwarrior. I didn’t want to reinvent Taskwarrior so I went with a simple script limited to my needs. Hopefully, it can help you as well, or maybe give you some inspiration to work on your own version.

In this post, I’ll share how this script works, and also share few additional commands to have Vit interacting with Neovim.

╭── The script inspiration

Like Lavoisier used to say “Nothing is lost, nothing is created, everything is transformed”. That also applies to computer code. This script - while 90% my own - was initially inspired by this one .

The next obvious question is “why a need for another script?”. This online script allows for task creation and addition in Taskwarrior, task update, and task deletion. Mine also offers:

╭── The Neovim script

The script can be found on my codeberg repo and includes comments.

To use it, simply place the script in $HOME/.config/nvim/lua/user_functions/, and add this to your Neovim init.lua:

for _, file in ipairs(vim.fn.readdir(vim.fn.stdpath("config") .. "/lua/user_functions", [[v:val =~ '\.lua$']])) do
	require("user_functions." .. file:gsub("%.lua$", ""))
end

Using the keybindings (that you can change on line 129, 150, and 161), you can:

Create/edit/update a task

Type #TW some text and use the default keybinding <leader>ta to create a task with some text as description, and add a task annotation in the form of “+line filepath” so you can easily access this task’s line from Taskwarrior.
The script will recognize the #TW pattern and ask for a project name, start and due date, and tags for this task. By default, the due date is set to start+1h to fit my specific needs, but you can change that by editing line 90.
All these fields are optional. The task will be added to Taskwarrior, and the task UUID will be appended to the line which will be commented.

If you use the same keybinding on a line with an already existing task, it will ask for all the previously mentioned fields again and update them in Taskwarrior. Note that you can also edit the description to update it as well. If you leave all fields blank, task’ annotations will be updated for all lines below the current in Taskwarrior.

Delete a task

Using the default <leader>td keybinding will delete the current line if it has a valid task UUID and remove the task in Taskwarrior. In the background, it will also add task’ annotations to all tasks below the current line.

Undo actions

You can revert the last delete action with the default <leader>tu keybinding. Again, note that this calls the task undo action from Taskwarrior and will revert any previous action every time you use it, so use it with caution.

Retrieve task info summary

[1] With the default <leader>ti keybinding, you can call a notification window that will show you a summary of the task info.

╭── The Vit commands

I use Vit to interact with my Taskwarrior task. Here are two bash scripts I’ve linked to keybindings in the Vit config.ini file to open the file in Neovim on the line listed in the task’s annotation, and to delete a task and remove it from the text file (and update all annotations for tasks below the deleted task’s line in the text file).

Open the file in Neovim on the task line

#!/usr/bin/env bash
nvim $(task "$1" export | jq '.[].annotations | .[-1].description' | sed "s/[\"']//g")

Delete a task and remove it from the file in Neovmim

#!/usr/bin/env bash
nvim=$(task "$1" export | jq '.[].annotations | .[-1].description' | sed "s/[\"|']//g")
uuid=$(task "$1" export | jq '.[].uuid' | sed "s/\"//g")
line=$(task "$1" export | jq '.[].annotations | .[-1].description' | awk '{print $1}' | sed 's/^..//')
file=$(task "$1" export | jq '.[].annotations | .[-1].description' | awk '{print $2}' | sed "s/['|\"]//g")
uuid_nvim=$(sed -n "$line"p "$file" | sed 's/.*UUID:\ //' | sed 's/\"//g')

# Check if the annotation matches the nvim annotation
if [ ! -z $(echo "nvim" | grep -E '^"+[0-9]{2,}') ]; then
    # Check if the task exists in nvim
    if [ "$uuid" = "$uuid_nvim" ]; then
        task del "$1"
        sed -i "$line"d "$file"
        nvim --headless "$file" -c "lua require('user_functions.tasks').annotation_update(tonumber('"$line"'))" +qa
    else
        notify-send "Can't find a matching task UUID in the file"
    fi
else
    task del "$1"
fi


More food for thoughts? Check other posts about: #Cli #(Neo)vim


Thanks for your read. Hope it's been useful to you.


Interact with this post using Mastodon or

Comment on wwwgem's post

Copy and paste this URL into the search field of your favourite Fediverse app or the web interface of your Mastodon server.

✄ ┈ ┈ ┈ ┈ ┈ ┈ ┈ ┈ ┈ ┈ ┈ ┈ ┈ ┈ ┈ ┈ ┈ ┈ ┈ ┈ ┈ ┈ ┈ ┈ ┈ ┈ ┈