]> git.r.bdr.sh - rbdr/nota.nvim/commitdiff
Add tagging
authorRuben Beltran del Rio <redacted>
Sun, 3 Mar 2024 21:30:03 +0000 (22:30 +0100)
committerRuben Beltran del Rio <redacted>
Sun, 3 Mar 2024 21:30:03 +0000 (22:30 +0100)
README.md
lua/keybinds.lua
lua/notes.lua
lua/tasks.lua
plugin/nota.lua

index 2d8acf378c2717e951f08df235ea83cccc6c574b..852032ebc041532b3af43a453cf300609a1ca705 100644 (file)
--- a/README.md
+++ b/README.md
@@ -91,6 +91,7 @@ require('lazy').setup({
 - `<leader>it`, `:NotaInsertTask`, Inserts a task at cursor location.
 - `<leader>ct`, `:NotaCaptureTask`, Captures a new task into the inbox.
 - `<leader>Tt`, `:NotaTagTask`, Adds a tag to the current task.
 - `<leader>it`, `:NotaInsertTask`, Inserts a task at cursor location.
 - `<leader>ct`, `:NotaCaptureTask`, Captures a new task into the inbox.
 - `<leader>Tt`, `:NotaTagTask`, Adds a tag to the current task.
+- `<leader>Rt`, `:NotaRemoveTagTask`, Removes a tag from the current task.
 - `<leader>rt`, `:NotaRescheduleTaskToday`, Reschedules the task under the cursor to today.
 - `<leader>rT`, `:NotaRescheduleTaskTomorrow`, Reschedules the task under the cursor to tomorrow.
 - `<leader>rs`, `:NotaRescheduleTaskSomeday`, Reschedules the task under the cursor to someday.
 - `<leader>rt`, `:NotaRescheduleTaskToday`, Reschedules the task under the cursor to today.
 - `<leader>rT`, `:NotaRescheduleTaskTomorrow`, Reschedules the task under the cursor to tomorrow.
 - `<leader>rs`, `:NotaRescheduleTaskSomeday`, Reschedules the task under the cursor to someday.
index bbf160b34f84f3a7249ebff06ceab381ed5194a6..1b661acc31d37f1781f51a30d77bdab6da0587af 100644 (file)
@@ -28,6 +28,7 @@ function Keybinds.bind()
   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>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 })
   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 })
index f5a4b00f25c1c92d1759fb08950d749b1f97e5fb..b23d6df9002d09fc992c401668cd81bbdb49aa7b 100644 (file)
@@ -37,7 +37,9 @@ end
 
 --- Opens the daily note
 function Notes.open_daily(date)
 
 --- 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
   local filename =  date .. '.md'
   open_periodic_note('daily', filename)
 end
index 66dbc48d4422845cd5a6bd152f04ed9fc0281949..33fce8f23717eaab87d9b20f83622f0e5dd338a3 100644 (file)
@@ -14,6 +14,18 @@ local unchecked_important_pattern = '^(%s*)%* %[ %]'
 local checked_pattern = '^(%s*)%- %[x%]'
 local checked_important_pattern = '^(%s*)%* %[x%]'
 
 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 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 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 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
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 -- 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)
         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})
     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)
         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
 
     api.nvim_buf_set_lines(0, line_number - 1, line_number, false, {line})
@@ -83,8 +126,63 @@ function Tasks.capture()
 end
 
 --- Tag a task
 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
 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')
 
   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})
     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})
index d34a7be124cd786a7a16bd41fe24226bcdc15a48..9e09d61e0d44f6e4443a547efb6e333477144c52 100644 (file)
@@ -53,7 +53,7 @@ if configuration.default_keybinds then
 end
 
 -- Note Handling Commands
 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('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('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 })
 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 })