From: Ruben Beltran del Rio Date: Sun, 3 Mar 2024 21:30:03 +0000 (+0100) Subject: Add tagging X-Git-Url: https://git.r.bdr.sh/rbdr/nota.nvim/commitdiff_plain/9e9e89d8556ecafa6b11ab21aa9ffab550f7f3ad?ds=inline Add tagging --- diff --git a/README.md b/README.md index 2d8acf3..852032e 100644 --- a/README.md +++ b/README.md @@ -91,6 +91,7 @@ require('lazy').setup({ - `it`, `:NotaInsertTask`, Inserts a task at cursor location. - `ct`, `:NotaCaptureTask`, Captures a new task into the inbox. - `Tt`, `:NotaTagTask`, Adds a tag to the current task. +- `Rt`, `:NotaRemoveTagTask`, Removes a tag from the current task. - `rt`, `:NotaRescheduleTaskToday`, Reschedules the task under the cursor to today. - `rT`, `:NotaRescheduleTaskTomorrow`, Reschedules the task under the cursor to tomorrow. - `rs`, `:NotaRescheduleTaskSomeday`, Reschedules the task under the cursor to someday. diff --git a/lua/keybinds.lua b/lua/keybinds.lua index bbf160b..1b661ac 100644 --- a/lua/keybinds.lua +++ b/lua/keybinds.lua @@ -28,6 +28,7 @@ function Keybinds.bind() api.nvim_set_keymap('n', 'it', 'NotaInsertTask', { noremap = true, silent = true }) api.nvim_set_keymap('n', 'ct', 'NotaCaptureTask', { noremap = true, silent = true }) api.nvim_set_keymap('n', 'Tt', 'NotaTagTask', { noremap = true, silent = true }) + api.nvim_set_keymap('n', 'Rt', 'NotaRemoveTagTask', { noremap = true, silent = true }) api.nvim_set_keymap('n', 'rt', 'NotaRescheduleTaskToday', { noremap = true, silent = true }) api.nvim_set_keymap('n', 'rT', 'NotaRescheduleTaskTomorrow', { noremap = true, silent = true }) api.nvim_set_keymap('n', 'rs', 'NotaRescheduleTaskSomeday', { noremap = true, silent = true }) diff --git a/lua/notes.lua b/lua/notes.lua index f5a4b00..b23d6df 100644 --- a/lua/notes.lua +++ b/lua/notes.lua @@ -37,7 +37,9 @@ end --- Opens the daily note function Notes.open_daily(date) - date = date or os.date('%Y-%m-%d') + if not date or date == '' then + date = os.date('%Y-%m-%d') + end local filename = date .. '.md' open_periodic_note('daily', filename) end diff --git a/lua/tasks.lua b/lua/tasks.lua index 66dbc48..33fce8f 100644 --- a/lua/tasks.lua +++ b/lua/tasks.lua @@ -14,6 +14,18 @@ local unchecked_important_pattern = '^(%s*)%* %[ %]' 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) @@ -24,10 +36,37 @@ local function open_inbox() 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 ------------------------------------------------------------------------------- @@ -45,6 +84,8 @@ function Tasks.toggle() 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}) @@ -63,6 +104,8 @@ function Tasks.toggle_importance() 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}) @@ -83,8 +126,63 @@ function Tasks.capture() 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 @@ -121,7 +219,7 @@ function Tasks.reschedule(new_date) 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}) diff --git a/plugin/nota.lua b/plugin/nota.lua index d34a7be..9e09d61 100644 --- a/plugin/nota.lua +++ b/plugin/nota.lua @@ -53,7 +53,7 @@ if configuration.default_keybinds then 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 }) @@ -71,7 +71,8 @@ command('NotaToggleTask', function() require('tasks').toggle() 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 })