]> git.r.bdr.sh - rbdr/nota.nvim/commitdiff
Allow next and previous
authorRuben Beltran del Rio <redacted>
Wed, 6 Mar 2024 13:51:14 +0000 (14:51 +0100)
committerRuben Beltran del Rio <redacted>
Wed, 6 Mar 2024 13:51:14 +0000 (14:51 +0100)
README.md
lua/keybinds.lua
lua/notes.lua
plugin/nota.lua

index 852032ebc041532b3af43a453cf300609a1ca705..87238ad1cdb8d4c887554452cae544b4dcdda4e6 100644 (file)
--- a/README.md
+++ b/README.md
@@ -78,6 +78,8 @@ require('lazy').setup({
 - `<leader>os`, `:NotaOpenSeasonalNote`, Opens this season's seasonal note.
 - `<leader>oy`, `:NotaOpenYearlyNote`, Opens this year's yearly note.
 - `<leader>on`, `:NotaOpenNote`, Opens an arbitrary note. (Requires [fzf-lua][fzf-lua])
+- `<leader>N`, `:NotaOpenNextNote`, Opens the next periodic note. (eg. tomorrow or next year)
+- `<leader>P`, `:NotaOpenPreviousNote`, Opens the previous periodic note. (eg. yesterday or last week)
 
 ### Task Views
 - `<leader>oa`, `:NotaOpenAgenda`, Opens the agenda window with this week's tasks.
index 1b661acc31d37f1781f51a30d77bdab6da0587af..88324f07dd327cd2c55a63fd05d17c810cd22c14 100644 (file)
@@ -17,6 +17,8 @@ function Keybinds.bind()
   api.nvim_set_keymap('n', '<leader>os', '<cmd>NotaOpenSeasonalNote<CR>', { noremap = true, silent = true })
   api.nvim_set_keymap('n', '<leader>oy', '<cmd>NotaOpenYearlyNote<CR>', { noremap = true, silent = true })
   api.nvim_set_keymap('n', '<leader>on', '<cmd>NotaOpenNote<CR>', { noremap = true, silent = true })
+  api.nvim_set_keymap('n', '<leader>N', '<cmd>NotaOpenNextNote<CR>', { noremap = true, silent = true })
+  api.nvim_set_keymap('n', '<leader>P', '<cmd>NotaOpenPreviousNote<CR>', { noremap = true, silent = true })
 
   api.nvim_set_keymap('n', '<leader>oa', '<cmd>NotaOpenAgenda<CR>', { noremap = true, silent = true })
   api.nvim_set_keymap('n', '<leader>oo', '<cmd>NotaOpenOpen<CR>', { noremap = true, silent = true })
index b23d6df9002d09fc992c401668cd81bbdb49aa7b..ca61735ab7fefec17ae625c6fd8fd641b82c120d 100644 (file)
@@ -9,6 +9,21 @@ local api = vim.api
 -------------------------------------------------------------------------------
 -- Internal Functions
 -------------------------------------------------------------------------------
+local templates = {
+  daily = '%Y-%m-%d',
+  weekly = '%Y-w%V',
+  monthly = '%Y-%m',
+  yearly = '%Y'
+}
+
+local patterns = {
+  daily = '^(%d+)-(%d+)-(%d+).md$',
+  weekly = '^(%d+)-w(%d+).md$',
+  monthly = '^(%d+)-(%d+).md$',
+  seasonal = '^(%d+)-s(%d+).md$',
+  yearly = '^(%d+).md$'
+}
+
 local function open_or_create_from_template(type, file_path)
 
   local journal_file = io.open(file_path, 'r')
@@ -31,6 +46,72 @@ local function open_periodic_note(type, filename)
   open_or_create_from_template(type, file_path)
 end
 
+local function find_next(type, filename, go_back_in_time)
+  local multiplier = 1
+  if go_back_in_time then
+    multiplier = -1
+  end
+
+  local pattern = patterns[type]
+  local year, second_match, day = filename:match(pattern)
+  year = tonumber(year)
+
+  -- Depending on context, second_match is either month, week, or season.
+  if second_match then
+    second_match = tonumber(second_match)
+  end
+
+  if day then
+    day = tonumber(day)
+  end
+
+  local next = nil
+
+  if type == 'daily' and year and second_match and day then
+    next = os.date(templates.daily, os.time({
+      year = year,
+      month = second_match,
+      day = day
+    }) + multiplier * 24 * 60 * 60)
+  elseif type == 'weekly' and year and second_match then
+    -- According to ISO, the first week is the one that contains january 4
+    local first_day_of_the_week = os.time({year = year, month = 1, day = 4})
+    if multiplier < 0 then
+      second_match = second_match - 2
+    end
+    next = os.date(templates.weekly, first_day_of_the_week + second_match * 7 * 24 * 60 * 60)
+  elseif type == 'monthly' and year and second_match then
+    next = os.date(templates.monthly, os.time({
+      year = year,
+      month = second_match + multiplier,
+      day = 1
+    }))
+  elseif type == 'seasonal' and year and second_match then
+    if multiplier > 0 and second_match == 4 then
+      year = year + 1
+    end
+    if multiplier < 0 and second_match == 1 then
+      year = year - 1
+    end
+    if multiplier > 0 then
+      second_match = (second_match % 4) + 1
+    else
+      second_match = (second_match + 2) % 4 + 1
+    end
+    next = year .. '-s' .. second_match
+  elseif type == 'yearly' and year then
+    next = os.date(templates.yearly, os.time({
+      year = year + multiplier,
+      month = 1,
+      day = 1
+    }))
+  end
+
+  if next then
+    Notes['open_' .. type](next)
+  end
+end
+
 -------------------------------------------------------------------------------
 -- Public Interface
 -------------------------------------------------------------------------------
@@ -38,40 +119,74 @@ end
 --- Opens the daily note
 function Notes.open_daily(date)
   if not date or date == '' then
-    date = os.date('%Y-%m-%d')
+    date = os.date(templates.daily)
   end
   local filename =  date .. '.md'
   open_periodic_note('daily', filename)
 end
 
 --- Opens the weekly note
-function Notes.open_weekly()
-  local filename = os.date('%Y-w%V')
+function Notes.open_weekly(date)
+  if not date or date == '' then
+    date = os.date(templates.weekly)
+  end
+  local filename = date .. '.md'
   open_periodic_note('weekly', filename)
 end
 
 --- Opens the monthly note
-function Notes.open_monthly()
-  local filename = os.date('%Y-%m') .. '.md'
+function Notes.open_monthly(date)
+  if not date or date == '' then
+    date = os.date(templates.monthly)
+  end
+  local filename = date .. '.md'
   open_periodic_note('monthly', filename)
 end
 
 --- Opens the seasonal note
-function Notes.open_seasonal()
-  local year = os.date('%Y')
-  local month = tonumber(os.date('%m'))
-  local season = math.ceil(month / 3)
+function Notes.open_seasonal(date)
+  if not date or date == '' then
+    local year = os.date('%Y')
+    local month = tonumber(os.date('%m'))
+    local season = math.ceil(month / 3)
+    date = year .. '-s' .. season
+  end
 
-  local filename = year .. '-s' .. season .. '.md'
+  local filename = date .. '.md'
   open_periodic_note('seasonal', filename)
 end
 
 --- Opens the yearly note
-function Notes.open_yearly()
-  local filename = os.date('%Y') .. '.md'
+function Notes.open_yearly(date)
+  if not date or date == '' then
+    date = os.date(templates.yearly)
+  end
+  local filename = date .. '.md'
   open_periodic_note('yearly', filename)
 end
 
+--- Opens the next note
+function Notes.open_next()
+  local filename = vim.fn.expand('%:t')
+  for type, pattern in pairs(patterns) do
+    if filename:match(pattern) ~= nil then
+      return find_next(type, filename)
+    end
+  end
+  api.nvim_err_writeln('Opening next only works on periodic notes.')
+end
+
+--- Opens the previous note
+function Notes.open_previous()
+  local filename = vim.fn.expand('%:t')
+  for type, pattern in pairs(patterns) do
+    if filename:match(pattern) ~= nil then
+      return find_next(type, filename, true)
+    end
+  end
+  api.nvim_err_writeln('Opening previous only works on periodic notes.')
+end
+
 --- Opens an arbitrary note
 function Notes.open()
   local success, module = pcall(require, 'fzf-lua')
index 9e09d61e0d44f6e4443a547efb6e333477144c52..180c84d761d994d32bd445da86c7b17064b004aa 100644 (file)
@@ -59,6 +59,8 @@ command('NotaOpenMonthlyNote', function() require('notes').open_monthly() end, {
 command('NotaOpenSeasonalNote', function() require('notes').open_seasonal() end, { nargs = 0 })
 command('NotaOpenYearlyNote', function() require('notes').open_yearly() end, { nargs = 0 })
 command('NotaOpenNote', function() require('notes').open() end, { nargs = 0 })
+command('NotaOpenNextNote', function() require('notes').open_next() end, { nargs = 0 })
+command('NotaOpenPreviousNote', function() require('notes').open_previous() end, { nargs = 0 })
 
 -- Task View Handling Commands
 command('NotaOpenAgenda', function() require('task_views').open_agenda() end, { nargs = 0 })