~rbdr/nota.nvim

ca10d2a36e3e7d8d28f15f36f0812384606c238d — Ruben Beltran del Rio 3 months ago 9e9e89d main
Allow next and previous
4 files changed, 133 insertions(+), 12 deletions(-)

M README.md
M lua/keybinds.lua
M lua/notes.lua
M plugin/nota.lua
M README.md => README.md +2 -0
@@ 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.

M lua/keybinds.lua => lua/keybinds.lua +2 -0
@@ 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 })

M lua/notes.lua => lua/notes.lua +127 -12
@@ 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')

M plugin/nota.lua => plugin/nota.lua +2 -0
@@ 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 })