A little helper for displaying TaskWarrior's tasks.
For now this plugin offers the following features:
- List of task as list of string to use in the Dashboard
- For current project and others
- Just a few most urgent tasks
You can install little-taskwarrior.nvim
using your favorite package manager.
For example with Lazy
:
{
"praczet/little-taskwarrior.nvim",
config = function()
require("little-taskwarrior").setup({ })
end,
}
- TaskWarrior - it uses standard export command form it
- Dashboard-nvim - if you want to use it in a dashboard
--- Default configuration
M.config = {
--- configuration for the Dashboard
dashboard = {
--- task limit
limit = 5,
--- max number of columns
max_width = 50,
--- if > 0 then additional task (besides current project ones) will be added
non_project_limit = 5,
--- List of columns to be displayed
columns = {
"id",
"project",
"description",
"due",
"urgency",
},
--- List of replacements when getting lines for dashboard
project_replacements = {
["work."] = "w.",
["personal."] = "p.",
},
--- Section separator
sec_sep = ".",
--- Enable or disable section shortening
shorten_sections = true,
},
--- function to reload dashboard config
get_dashboard_config = nil,
--- toggle the logging
debug = true,
--- where information about taskwarrior project can be found
project_info = ".little-taskwarrior.json",
--- above urgency_threshold all task could be highlighted in
--- the different way
urgency_threshold = 9,
--- Highlights
highlight_groups ={
--- for the urgent tasks (above the threshold)
urgent = nil,
--- default style (highlight_groups) for tasks
not_urgnet =nil
}
}
So for example to make the area of task list wider you can do:
{
"praczet/little-taskwarrior.nvim",
config = function()
require("little-taskwarrior").setup({
dashboard = {
max_width = 80
}
})
end,
}
This section sets how the dashboard's part will be displayed.
Those two options are used to display how many tasks will be displayed. Why two?
It is connected to the project_info
option and .little-taskwarrior.json
file.
If in the current folder there is no .little-taskwarrior.json
file only
limit
will be taken. If the .little-taskwarrior.json
is present the limit
will be applied to the number of tasks in for that project and
non_project_limit
will be used for all others tasks.
If in the folder (project folder or current folder) file named
.little-taskwarrior.json
exists. This plugin will try to read project name:
For example:
{
"project": "eos"
}
If it succeeds it will use it as project name therefore the display mode will be switched to project specific mode. Which means the first task will be taken for that specific project. And then (if configuration allows) other tasks will be loaded. You can see this in [Tasks list with a project file](###Tasks list with a project file)
Those two options are use to format project names and they can be used together.
project_replacements
- list of replacements for project namesshorten_sections
- switches shortening of sections
(because I like examples)
Let's assume that we have projects related to work
and several projects
related to personal
.
In the personal
project we have projects like:
personal.dashboard-nvim
personal.little-taskwarrior
So task could look like this:
task add "I need to do something" project:personal.dashboard-nvim
But instead of displaying personal.dashboard-nvim
we want to display
p.dashboard-nvim
Then we can add replacements in the configuration:
project_replacements = {
["work."] = "w.",
["personal."] = "p.",
},
Note
Replacements can by as regular expression
So let's say that your projects hierarchy is much more complex (multi-levels):
- personal.develop.ltw
- personal.develop.nbd
- personal.todos
- personal.health.wo
- personal.health.doc
- personal.health.admin
Of course you can project_replacements
to make it more readable, but this
approach will force you to add each project (subproject) manually.
shorten_sections
will do this job automatically. Before I will try explain how
does it work look how previous list will look like:
- personal.develop.ltw > p.d.ltw
- personal.develop.nbd > p.d.nbd
- personal.todos > p.todos
- personal.health.wo > p.h.wo
- personal.health.doc > p.h.doc
- personal.health.admin > p.h.admin
So, each section but last will be shortened to the first letter, the last section will remain unchanged.
Those two options are used to highlight urgent tasks. The urgency_threshold
set the threshold above which task is themed to be urgent. The task becomes
urgent when urgency >= urgency_threshold
.
highlight_groups
is used to set the style of the tasks. It has two keys:
urgent
- style of urgent tasksnot_urgent
- style of not urgent Tasks
By style I mean vim's highlight. If highlight_groups
is n t set the
default values will be used.
urgent
- based on default@keyword
highlightnot_urgent
- based on defaultComment
highlight
You can see how they are defined in dashboard.lua
in function: get_default_hl_group
Note
For unforeseen 'bug' in the code, you can override single entries. For example:
{
"praczet/little-taskwarrior.nvim",
config = function()
require("little-taskwarrior").setup({
dashboard = {
max_width = 80
}
highlight_groups = {
not_urgent = {
italic=false,
}
}
})
end,
}
This will just 'switch' off italic from default Comment
highlight
Of course you can use it as you want. I mean you can get the list and print it.
lua print(vim.inspect(require("little-taskwarrior").get_dashboard_tasks()))
Important
This method will display Tasks in the Dashboard but it will not allow to refresh
task list after command Task
Based on my dashboard.lua config (I am using LazyVim)
return {
{
"nvimdev/dashboard-nvim",
opts = function()
-- Getting dashboard tasks
local ltw = require("little-taskwarrior")
local tasks = ltw.get_dashboard_tasks()
local logo = [[
...:::...
.. --- ..
. (0 0) .
. \=/ .
.-----------------.
( ©ad.art )
'''''''''''''''''''
]]
local currentDate = os.date("%Y-%m-%d")
local padding = math.floor((10 - #currentDate) / 2)
local centeredDate = string.rep(" ", padding) .. currentDate
logo = logo .. "\n" .. centeredDate .. "\n"
local header = vim.split(logo, "\n")
if tasks ~= nil then
for _, t in ipairs(tasks) do
table.insert(header, t)
end
table.insert(header, "")
end
local opts = {
theme = "doom",
config = {
header = header,
-- ... There is more like center, footer etc.
},
}
return opts
end,
},
}
Important
It will enable refreshing the task list after command Task
, but it requires some
steps
Since dashboard-nvim
does not support refreshing header you can use
config.get_dashboard_config
. Like this:
{
"praczet/little-taskwarrior.nvim",
config = function()
require("little-taskwarrior").setup({
get_dashboard_config = function()
-- here function that will return options for dashboard
-- the same as in dashboard-nvim setup.
local ltw = require("little-taskwarrior")
local tasks = ltw.get_dashboard_tasks()
local logo = [[
...:::...
.. --- ..
. (0 0) .
. \=/ .
.-----------------.
( ©ad.art )
'''''''''''''''''''
]]
local currentDate = os.date("%Y-%m-%d")
local padding = math.floor((10 - #currentDate) / 2)
local centeredDate = string.rep(" ", padding) .. currentDate
logo = logo .. "\n" .. centeredDate .. "\n"
local header = vim.split(logo, "\n")
if tasks ~= nil then
for _, t in ipairs(tasks) do
table.insert(header, t)
end
table.insert(header, "")
end
local opts = {
theme = "doom",
config = {
header = header,
-- ... There is more like center, footer etc.
},
}
return opts
end,
end
})
end,
}
This will enable refreshing after Task
command.
Now you can change configuration of dashboard-nvim
plugin, like this:
return {
{
"nvimdev/dashboard-nvim",
opts = require('little-taskwarrior').get_dashboard_config
}
}
Warning
This mostly works, but sometimes little-taskwarrior
was taking too long to
load and then dashboard-nvim
loaded the default one (in my case LazyVim).
There are many ways to solve it. For example you can put for your dashboard-nvim
config the function as usual, and then the same function in
little-taskwarrior
. I do not like this (in two places the same code). It
forces me to remember to change it in two places.
I suggest this (solution for LazyVim):
-
Add a file
fallback.lua
in~/.config/nvim/lua/
local function fall_back() local next = require("next-birthday") local lines = next.birthdays("now") local ltw = require("little-taskwarrior") local tasks = ltw.get_dashboard_tasks() local logo = [[ ...:::... .. --- .. . (0 0) . . \=/ . .-----------------. ( ©ad.art ) ''''''''''''''''''' ]] local currentDate = os.date("%Y-%m-%d") local padding = math.floor((10 - #currentDate) / 2) local centeredDate = string.rep(" ", padding) .. currentDate logo = logo .. "\n" .. centeredDate .. "\n" local header = vim.split(logo, "\n") if lines ~= nil then for _, l in ipairs(lines) do table.insert(header, l) end end table.insert(header, "") if tasks ~= nil then for _, t in ipairs(tasks) do table.insert(header, t) end table.insert(header, "") end local opts = { theme = "doom", hide = { -- this is taken care of by lualine -- enabling this messes up the actual laststatus setting after loading a file statusline = false, }, config = { header = header, -- stylua: ignore } } return opts end return { fall_back = fall_back, }
-
In the
dashboard-nvim
config use like this:--- this file contains my own Dashboard config local dashboard_config = require("fallback") return { { "nvimdev/dashboard-nvim", opts = dashboard_config.fall_back, }, }
-
In the
little-taskwarrior
config use like this:local dashboard_config = require("fallback") return { { "praczet/little-taskwarrior.nvim", config = function() require("little-taskwarrior").setup({ get_dashboard_config = dashboard_config.fall_back, }) end, }, }
You can see my config files in config
folder of my repository.
- feat: Shortening project names by separator
- feat: Highlight urgent tasks
- feat: Preview task
- feat: Add task from selection or for current line