api.nvim_set_keymap('n', '<leader>it', '<cmd>NotaInsertTask<CR>', { noremap = true, silent = true })
api.nvim_set_keymap('n', '<leader>ct', '<cmd>NotaCaptureTask<CR>', { noremap = true, silent = true })
api.nvim_set_keymap('n', '<leader>Tt', '<cmd>NotaTagTask<CR>', { noremap = true, silent = true })
+ api.nvim_set_keymap('n', '<leader>Rt', '<cmd>NotaRemoveTagTask<CR>', { noremap = true, silent = true })
api.nvim_set_keymap('n', '<leader>rt', '<cmd>NotaRescheduleTaskToday<CR>', { noremap = true, silent = true })
api.nvim_set_keymap('n', '<leader>rT', '<cmd>NotaRescheduleTaskTomorrow<CR>', { noremap = true, silent = true })
api.nvim_set_keymap('n', '<leader>rs', '<cmd>NotaRescheduleTaskSomeday<CR>', { noremap = true, silent = true })
local checked_pattern = '^(%s*)%- %[x%]'
local checked_important_pattern = '^(%s*)%* %[x%]'
+local function is_open_task(line)
+ return line:match(unchecked_pattern) or line:match(unchecked_important_pattern)
+end
+
+local function is_completed_task(line)
+ return line:match(checked_pattern) or line:match(checked_important_pattern)
+end
+
+local function is_task(line)
+ return is_open_task(line) or is_completed_task(line)
+end
+
local function open(path)
local parent = Util.directory_name(path)
Util.ensure_directory_exists(parent)
local path = Configuration.path_for(Configuration.configuration.tasks.inbox)
open(path)
end
+
local function open_someday()
local path = Configuration.path_for(Configuration.configuration.tasks.someday)
open(path)
end
+
+local function parse_tags(tag_string)
+ local tags = {}
+ for tag in tag_string:gmatch('([^,]+)') do
+ table.insert(tags, tag)
+ end
+ return tags
+end
+
+local function table_contains_value(target_table, value)
+ for _, table_value in ipairs(target_table) do
+ if table_value == value then
+ return true
+ end
+ end
+ return false
+end
+
+local function remove_value(target_table, value)
+ for i, table_value in ipairs(target_table) do
+ if table_value == value then
+ table.remove(target_table, i)
+ end
+ end
+end
+
-------------------------------------------------------------------------------
-- Public Interface
-------------------------------------------------------------------------------
line = line:gsub(checked_pattern, '%1- [ ]', 1)
elseif line:match(checked_important_pattern) then
line = line:gsub(checked_important_pattern, '%1* [ ]', 1)
+ else
+ api.nvim_err_writeln('Toggle completion only works on tasks')
end
api.nvim_buf_set_lines(0, line_number - 1, line_number, false, {line})
line = line:gsub(checked_pattern, '%1* [x]', 1)
elseif line:match(checked_important_pattern) then
line = line:gsub(checked_important_pattern, '%1- [x]', 1)
+ else
+ api.nvim_err_writeln('Toggle importance only works on tasks')
end
api.nvim_buf_set_lines(0, line_number - 1, line_number, false, {line})
end
--- Tag a task
-function Tasks.tag()
- error('Not yet implemented')
+function Tasks.tag(tag)
+ local line_number = api.nvim_win_get_cursor(0)[1]
+ local line = api.nvim_get_current_line()
+ if is_task(line) then
+ local pattern = ':(.*):$'
+ local tag_string = line:match(pattern) or ''
+ if not tag or tag == '' then
+ tag = vim.fn.input('Add new tag for task (' .. tag_string .. '): ')
+ if not tag or tag == '' then
+ return
+ end
+ end
+ local tags = parse_tags(tag_string)
+ if not table_contains_value(tags, tag) then
+ table.insert(tags, tag)
+ local new_tags = table.concat(tags, ',')
+ if line:match(pattern) then
+ line = line:gsub(pattern, ':' .. new_tags .. ':', 1)
+ else
+ line = line .. ' :' .. new_tags .. ':'
+ end
+ api.nvim_buf_set_lines(0, line_number - 1, line_number, false, {line})
+ end
+ else
+ api.nvim_err_writeln('Tagging only works on tasks')
+ end
+end
+
+--- Remove tag on a task
+function Tasks.remove_tag(tag)
+ local line_number = api.nvim_win_get_cursor(0)[1]
+ local line = api.nvim_get_current_line()
+ if is_task(line) then
+ local pattern = ':(.*):$'
+ local tag_string = line:match(pattern)
+ if not tag_string then
+ api.nvim_err_writeln('No tags to remove')
+ return
+ end
+
+ if not tag or tag == '' then
+ tag = vim.fn.input('Pick tag to remove (' .. tag_string .. '): ')
+ end
+
+ local tags = parse_tags(tag_string)
+ remove_value(tags, tag)
+ local new_tags = ''
+
+ if #tags > 0 then
+ new_tags = ':' .. table.concat(tags, ',') .. ':'
+ end
+
+ line = line:gsub(pattern, new_tags, 1):gsub('%s+$', '')
+ api.nvim_buf_set_lines(0, line_number - 1, line_number, false, {line})
+ else
+ api.nvim_err_writeln('Tagging only works on tasks')
+ end
end
--- Reschedule a task for today
local line = api.nvim_get_current_line()
local filename = vim.fn.expand('%:t:r')
- if line:match(unchecked_pattern) or line:match(unchecked_important_pattern) then
+ if is_open_task(line) then
if Util.is_before_today(filename) and line:match(unchecked_pattern) then
local rescheduled_line = line:gsub(unchecked_pattern, '%1- [>' .. new_date .. ']', 1)
api.nvim_buf_set_lines(0, line_number - 1, line_number, false, {rescheduled_line})
end
-- Note Handling Commands
-command('NotaOpenDailyNote', function() require('notes').open_daily() end, { nargs = 0 })
+command('NotaOpenDailyNote', function(options) require('notes').open_daily(options.args) end, { nargs = '?' })
command('NotaOpenWeeklyNote', function() require('notes').open_weekly() end, { nargs = 0 })
command('NotaOpenMonthlyNote', function() require('notes').open_monthly() end, { nargs = 0 })
command('NotaOpenSeasonalNote', function() require('notes').open_seasonal() end, { nargs = 0 })
command('NotaToggleTaskImportance', function() require('tasks').toggle_importance() end, { nargs = 0 })
command('NotaInsertTask', function() require('tasks').insert() end, { nargs = 0 })
command('NotaCaptureTask', function() require('tasks').capture() end, { nargs = 0 })
-command('NotaTagTask', function() require('tasks').tag() end, { nargs = 0 })
+command('NotaTagTask', function(options) require('tasks').tag(options.args) end, { nargs = '?' })
+command('NotaRemoveTagTask', function(options) require('tasks').remove_tag(options.args) end, { nargs = '?' })
command('NotaRescheduleTaskToday', function() require('tasks').reschedule_for_today() end, { nargs = 0 })
command('NotaRescheduleTaskTomorrow', function() require('tasks').reschedule_for_tomorrow() end, { nargs = 0 })
command('NotaRescheduleTaskSomeday', function() require('tasks').reschedule_for_someday() end, { nargs = 0 })