~rbdr/nota.nvim

503d09fc95a47c13141d097cf80dd243d1dce342 — Ruben Beltran del Rio 4 months ago 56292c7
Add minimum workable functionality
M README.md => README.md +8 -2
@@ 14,6 14,8 @@ require('lazy').setup({
})
```

This plugin has an optional dependency: [fzf-lua][fzf-lua].

By default, nota adds keybinds that might not suit your style or conflict with other plugins. You can disable them with the `default_keybinds` option.

```lua


@@ 77,15 79,17 @@ If the default directories don't work for you, you can override them as well:
- `<leader>om`, `:NotaOpenMonthlyNote`, Opens this month's monthly note.
- `<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.
- `<leader>on`, `:NotaOpenNote`, Opens an arbitrary note. (Requires [fzf-lua][fzf-lua])

### Task Views
- `<leader>oa`, `:NotaOpenAgenda`, Opens the agenda window with this week's tasks.
- `<leader>oo`, `:NotaOpenOpen`, Opens a window that lets you navigate through all open tasks.
- `<leader>oj`, `:NotaOpenJournal`, Opens a window that lets you search completed tasks to find journal entries.
- `<leader>oO`, `:NotaOpenOpenImportant`, Opens a window that lets you navigate through all open important tasks.
- `<leader>oj`, `:NotaOpenJournal`, Opens a window that lets you search completed tasks to find journal entries. (Requires [fzf-lua][fzf-lua] and ripgrep)

### Task Handling Commands
- `<leader>t`, `:NotaToggleTask`, Toggles completion state of the task under the cursor.
- `<leader>st`, `:NotaToggleTaskImportance`, Toggles importance state of the task under the cursor. (- [ ] is a regular task, * [ ] is an important 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.


@@ 101,3 105,5 @@ If the default directories don't work for you, you can override them as well:
### Plan Handling Commands
- `<leader>op`, `:NotaOpenPlan`, Opens the current plan file.
- `<leader>cp`, `:NotaCapturePlan`, Captures a new plan and archives the current one.

[fzf-lua]: https://github.com/ibhagwan/fzf-lua

M lua/configuration.lua => lua/configuration.lua +48 -4
@@ 1,3 1,14 @@
-------------------------------------------------------------------------------
-- Configuration for nota
-------------------------------------------------------------------------------
local Configuration = {}

local Util = require('util')
-------------------------------------------------------------------------------
-- Internal Functions
-------------------------------------------------------------------------------
local fs = vim.loop

local defaults = {
  nota_home = '~/.local/share/nota',          -- Root location in which to store all notes
  default_keybinds = true,                    -- Whether or not to set the default keybinds


@@ 22,7 33,7 @@ local defaults = {
  },
  learning  = {
      learning_file = 'learning.md',            -- Location of the file in which to store learning entries, relative to nota_home
      prefix = '%Y-%x-%d: '                     -- Prefix to add when capturing learning entries
      prefix = '%Y-%m-%d: '                     -- Prefix to add when capturing learning entries
  },
  plan = {
      archive = 'plans',                        -- Location of the plan archives.


@@ 33,7 44,7 @@ local defaults = {
-- Recursively extends a table with another
local function extend(target, extender)
  for key, value in pairs(extender) do
    if type(target[key]) == "table" and type(value) == "table" then
    if type(target[key]) == 'table' and type(value) == 'table' then
      extend(target[key], value)
    else
      target[key] = value


@@ 41,6 52,39 @@ local function extend(target, extender)
  end
end

function configure(user_configuration)
  return extend(defaults, extender)
-------------------------------------------------------------------------------
-- Public Interface
-------------------------------------------------------------------------------

Configuration.configuration = {}
extend(Configuration.configuration, defaults)

--- Extends configuration with another configuration
function Configuration.configure(configuration)
  configuration = configuration or {}
  extend(Configuration.configuration, configuration)
end

--- Gets expanded paths relative to nota_home
-- @param path string the relative path to expand
function Configuration.path_for(path)
  if not path then
    return vim.fn.expand(Configuration.configuration.nota_home)
  end
  return Util.join(vim.fn.expand(Configuration.configuration.nota_home), path)
end

--- Loads a template by template name
function Configuration.load_template(type)
  local template_path = Configuration.path_for(Configuration.configuration.templates[type])

  local template_file = io.open(template_path, 'r')
  if not template_file then
      return ''
  end
  local content = template_file:read('*a')
  template_file:close()
  return content
end

return Configuration

M lua/keybinds.lua => lua/keybinds.lua +6 -1
@@ 1,13 1,14 @@
-------------------------------------------------------------------------------
-- Sets the default keybinds
-------------------------------------------------------------------------------
local Keybinds = {}
-------------------------------------------------------------------------------
-- Public Interface
-------------------------------------------------------------------------------

--- Sets the default keybinds
-- @param configuration tNotaConfiguration the plugin configuration
function bind()
function Keybinds.bind()
  local api = vim.api

  api.nvim_set_keymap('n', '<leader>od', '<cmd>NotaOpenDailyNote<CR>', { noremap = true, silent = true })


@@ 19,9 20,11 @@ function bind()

  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 })
  api.nvim_set_keymap('n', '<leader>oO', '<cmd>NotaOpenOpenImportant<CR>', { noremap = true, silent = true })
  api.nvim_set_keymap('n', '<leader>oj', '<cmd>NotaOpenJournal<CR>', { noremap = true, silent = true })

  api.nvim_set_keymap('n', '<leader>t', '<cmd>NotaToggleTask<CR>', { noremap = true, silent = true })
  api.nvim_set_keymap('n', '<leader>st', '<cmd>NotaToggleTaskImportance<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 })


@@ 36,3 39,5 @@ function bind()
  api.nvim_set_keymap('n', '<leader>op', '<cmd>NotaOpenPlan<CR>', { noremap = true, silent = true })
  api.nvim_set_keymap('n', '<leader>cp', '<cmd>NotaCapturePlan<CR>', { noremap = true, silent = true })
end

return Keybinds

M lua/learning.lua => lua/learning.lua +18 -9
@@ 1,22 1,31 @@
-------------------------------------------------------------------------------
-- Tools to deal with the learning file
-------------------------------------------------------------------------------
local Learning = {}

local Configuration = require('configuration')
local Util = require('util')
-------------------------------------------------------------------------------
-- Internal Functions
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- Public Interface
-------------------------------------------------------------------------------

--- Opens the learning file
-- @param configuration tNotaConfiguration the plugin configuration
function open_learning(configuration)
  error("Not yet implemented")
function Learning.open()
  local learning_path = Configuration.path_for(Configuration.configuration.learning.learning_file)
  local learning_parent = Util.directory_name(learning_path)
  Util.ensure_directory_exists(learning_parent)
  vim.cmd('edit ' .. learning_path)
end

--- Capture a learning entry
-- @param configuration tNotaConfiguration the plugin configuration
function capture_learning(configuration)
  error("Not yet implemented")
function Learning.capture()
  local prefix = os.date(Configuration.configuration.learning.prefix)
  Learning.open()
  vim.cmd('normal! ggO'..prefix)
  vim.cmd('startinsert!')
end

-------------------------------------------------------------------------------
-- Internal Functions
-------------------------------------------------------------------------------
return Learning

A lua/nota.lua => lua/nota.lua +7 -0
@@ 0,0 1,7 @@
local Nota = {}

function Nota.setup(user_configuration)
  configuration = require('configuration').configure(user_configuration)
end

return Nota

M lua/notes.lua => lua/notes.lua +59 -21
@@ 1,46 1,84 @@
-------------------------------------------------------------------------------
-- Tools to deal with notes
-------------------------------------------------------------------------------
local Notes = {}

local Util = require('util')
local Configuration = require('configuration')
local api = vim.api
-------------------------------------------------------------------------------
-- Internal Functions
-------------------------------------------------------------------------------
local function open_or_create_from_template(type, file_path)

  local journal_file = io.open(file_path, 'r')
  if not journal_file then
    local template_contents = Configuration.load_template(type)

    journal_file = io.open(file_path, 'w')
    journal_file:write(template_contents)
    journal_file:close()
  end
  vim.cmd('edit ' .. file_path)
end

local function open_periodic_note(type, filename)
  local file_directory_path = Configuration.path_for(Configuration.configuration.periodic_locations[type])

  Util.ensure_directory_exists(file_directory_path)
  local file_path = Util.join(file_directory_path, filename)

  open_or_create_from_template(type, file_path)
end

-------------------------------------------------------------------------------
-- Public Interface
-------------------------------------------------------------------------------

--- Opens the daily note
-- @param configuration tNotaConfiguration the plugin configuration
function open_daily(configuration)
  error("Not yet implemented")
function Notes.open_daily()
  local filename = os.date('%Y-%m-%d') .. '.md'
  open_periodic_note('daily', filename)
end

--- Opens the weekly note
-- @param configuration tNotaConfiguration the plugin configuration
function open_weekly(configuration)
  error("Not yet implemented")
function Notes.open_weekly()
  local filename = os.date('%Y-w%V')
  open_periodic_note('weekly', filename)
end

--- Opens the monthly note
-- @param configuration tNotaConfiguration the plugin configuration
function open_monthly(configuration)
  error("Not yet implemented")
function Notes.open_monthly()
  local filename = os.date('%Y-%m') .. '.md'
  open_periodic_note('monthly', filename)
end

--- Opens the seasonal note
-- @param configuration tNotaConfiguration the plugin configuration
function open_seasonal(configuration)
  error("Not yet implemented")
function Notes.open_seasonal()
  local year = os.date('%Y')
  local month = tonumber(os.date('%m'))
  local season = math.ceil(month / 3)

  local filename = year .. '-s' .. season .. '.md'
  open_periodic_note('seasonal', filename)
end

--- Opens the yearly note
-- @param configuration tNotaConfiguration the plugin configuration
function open_yearly(configuration)
  error("Not yet implemented")
function Notes.open_yearly()
  local filename = os.date('%Y') .. '.md'
  open_periodic_note('yearly', filename)
end

--- Opens an arbitrary note
-- @param configuration tNotaConfiguration the plugin configuration
function open_note(configuration)
  error("Not yet implemented")
function Notes.open()
  local success, module = pcall(require, 'fzf-lua')
  if success then
    local notes_path = Configuration.path_for()
    Util.ensure_directory_exists(notes_path)
    module.files({ cwd = notes_path })
  else
    api.nvim_err_writeln('This feature requires optional dependency fzf-lua')
  end
end

-------------------------------------------------------------------------------
-- Internal Functions
-------------------------------------------------------------------------------
return Notes

M lua/plan.lua => lua/plan.lua +54 -10
@@ 1,23 1,67 @@
-------------------------------------------------------------------------------
-- Tools to deal with the plan file
-------------------------------------------------------------------------------
local Plan = {}

local Configuration = require('configuration')
local Util = require('util')
-------------------------------------------------------------------------------
-- Public Interface
-- Internal Functions
-------------------------------------------------------------------------------
local function open_or_create_from_template(file_path, force_template)

--- Opens the active plan file
-- @param configuration tNotaConfiguration the plugin configuration
function open_plan(configuration)
  error("Not yet implemented")
  local plan_file = io.open(file_path, 'r')
  if force_template or not plan_file then
    local template_contents = Configuration.load_template('plan')
    local date = os.date('%Y-%m-%d')

    template_contents = template_contents .. '[' .. date .. ']\n'
    plan_file = io.open(file_path, 'w')
    plan_file:write(template_contents)
    plan_file:close()
  end
  vim.cmd('edit ' .. file_path)
end

--- Capture a new plan file and archive the current one
-- @param configuration tNotaConfiguration the plugin configuration
function capture_plan(configuration)
  error("Not yet implemented")
local function copy(plan_path, archive_path)
  local plan_file = io.open(plan_path, 'r')
  local archive_file = io.open(archive_path, 'wb')
  local plan_content = plan_file:read('*a')
  archive_file:write(plan_content) -- Write the content to the target file

  plan_file:close()
  archive_file:close()
end

-------------------------------------------------------------------------------
-- Internal Functions
-- Public Interface
-------------------------------------------------------------------------------

--- Opens the active plan file
function Plan.open(force_template)
  local plan_path = vim.fn.expand(Configuration.configuration.plan.plan_file)
  local plan_parent = Util.directory_name(plan_path)
  Util.ensure_directory_exists(plan_parent)
  open_or_create_from_template(plan_path, force_template)
end

--- Capture a new plan file and archive the current one
function Plan.capture()
  local fs = vim.loop

  local plan_path = vim.fn.expand(Configuration.configuration.plan.plan_file)
  local plan_parent = Util.directory_name(plan_path)
  Util.ensure_directory_exists(plan_parent)

  local archive_path = Configuration.path_for(Configuration.configuration.plan.archive)
  Util.ensure_directory_exists(archive_path)

  if fs.fs_stat(plan_path) then
    local archive_filename = os.date('%Y-%m-%d') .. '.md'
    copy(plan_path, Util.join(archive_path, archive_filename))
  end

  Plan.open(true)
end

return Plan

M lua/task_views.lua => lua/task_views.lua +121 -12
@@ 1,28 1,137 @@
-------------------------------------------------------------------------------
-- Tools to deal with task views
-------------------------------------------------------------------------------
local TaskViews = {}
local Util = require('util')
local Configuration = require('configuration')
local api = vim.api
-------------------------------------------------------------------------------
-- Internal Functions
-------------------------------------------------------------------------------
local function get_this_weeks_files()
  local today = os.time()
  local day_of_week = os.date('*t', today).wday
  local week_start = today - (day_of_week - 2) * 86400
  local filenames = {}

  for i = 0, 6 do
    local date = os.date('*t', week_start + i * 86400)
    table.insert(filenames, string.format('%04d-%02d-%02d.md', date.year, date.month, date.day))
  end

  return filenames
end

local function find_tasks(completed, important)
  local file_directory_path = Configuration.path_for(Configuration.configuration.periodic_locations.daily)

  local completed_fragment = '(\\s|x)'
  if completed == 1 then
    completed_fragment = 'x'
  elseif completed == 0 then
    completed_fragment = '\\s'
  end

  local important_fragment = '(\\-|\\*)'
  if important == 1 then
    important_fragment = '\\*'
  elseif important == 0 then
    important_fragment = '\\-'
  end


  local pattern = '^\\s*' .. important_fragment .. '\\s\\[' .. completed_fragment .. ']'

  local command = string.format('rg --vimgrep \'%s\' \'%s\'', pattern, file_directory_path)
  local results = vim.fn.systemlist(command)

  if vim.v.shell_error == 0 then
    local items = {}
    for _, line in ipairs(results) do
      local filename, lnum, col, text = line:match('([^:]+):(%d+):(%d+):(.*)')
            table.insert(items, {
                filename = filename,
                lnum = tonumber(lnum),
                col = tonumber(col),
                text = text,
            })
    end

    -- Set location list for the current window and open it
    vim.fn.setloclist(0, items)
    vim.cmd('lopen')
  end
end

local function populate_quicklist_with_files(filenames)
  local uv = vim.loop
  local items = {}
  local task_pattern = '^%s*%- %[[ ]?x?%]'
  local important_task_pattern = '^%s*%* %[[ ]?x?%]'

  local file_directory_path = Configuration.path_for(Configuration.configuration.periodic_locations.daily)
  Util.ensure_directory_exists(file_directory_path)

  for _, filename in ipairs(filenames) do
    local daily_note = Util.join(file_directory_path, filename)
    local stat = uv.fs_stat(daily_note)

    if stat then -- File exists
      local file, err = io.open(daily_note, 'r')
      if file then
        local set_header = 0
        local line_number = 0
        for line in file:lines() do
          line_number = line_number + 1
          if line:match(task_pattern) or line:match(important_task_pattern) then
            if set_header == 0 then
              local header = string.sub(filename:match('([^/\\]+)$'), 1, -4)
              table.insert(items, {filename = '', lnum = 0, text = header})
              set_header = 1
            end
            table.insert(items, {filename = daily_note, text = line, lnum = line_number})
          end
        end
        file:close()
      end
    end
  end
  vim.fn.setloclist(0, {}, ' ', {title = 'Weekly Tasks', items = items})
  vim.cmd('lopen')
end

-------------------------------------------------------------------------------
-- Public Interface
-------------------------------------------------------------------------------

--- Opens the agenda view to show tasks
-- @param configuration tNotaConfiguration the plugin configuration
function open_agenda(configuration)
  error("Not yet implemented")
function TaskViews.open_agenda()
  local week_filenames = get_this_weeks_files()
  populate_quicklist_with_files(week_filenames)
end

--- Opens the view to show open tasks
-- @param configuration tNotaConfiguration the plugin configuration
function open_open(configuration)
  error("Not yet implemented")
function TaskViews.open_open()
  find_tasks(0)
end

--- Opens the view to show open important tasks
function TaskViews.open_open_important()
  find_tasks(0, 1)
end

--- Opens the view to search the journal
-- @param configuration tNotaConfiguration the plugin configuration
function open_journal(configuration)
  error("Not yet implemented")
function TaskViews.open_journal()
  local pattern = '^\\s*(\\*|\\-)\\s\\[x]'
  -- local pattern = 'hell'
  local success, module = pcall(require, 'fzf-lua')
  if success then
    local notes_path = Configuration.path_for()
    Util.ensure_directory_exists(notes_path)
    module.files({ cwd = notes_path, cmd = 'rg --line-number --no-heading -- \'' .. pattern ..'\''})
  else
    api.nvim_err_writeln('This feature requires optional dependency fzf-lua')
  end
end

-------------------------------------------------------------------------------
-- Internal Functions
-------------------------------------------------------------------------------
return TaskViews

M lua/tasks.lua => lua/tasks.lua +65 -28
@@ 1,59 1,96 @@
-------------------------------------------------------------------------------
-- Tools to deal with tasks
-------------------------------------------------------------------------------
local Tasks = {}
local Configuration = require('configuration')
local api = vim.api
-------------------------------------------------------------------------------
-- Internal Functions
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- Public Interface
-------------------------------------------------------------------------------

--- Toggles a task completion status
-- @param configuration tNotaConfiguration the plugin configuration
function toggle(configuration)
  error("Not yet implemented")
function Tasks.toggle()
    local line_number = api.nvim_win_get_cursor(0)[1]
    local line = api.nvim_get_current_line()

    local unchecked_pattern = '^(%s*)%- %[ %]'
    local unchecked_important_pattern = '^(%s*)%* %[ %]'
    local checked_pattern = '^(%s*)%- %[x%]'
    local checked_important_pattern = '^(%s*)%* %[x%]'

    if line:match(unchecked_pattern) then
        line = line:gsub(unchecked_pattern, '%1- [x]', 1)
    elseif line:match(unchecked_important_pattern) then
        line = line:gsub(unchecked_important_pattern, '%1* [x]', 1)
    elseif line:match(checked_pattern) then
        line = line:gsub(checked_pattern, '%1- [ ]', 1)
    elseif line:match(checked_important_pattern) then
        line = line:gsub(checked_important_pattern, '%1* [ ]', 1)
    end

    api.nvim_buf_set_lines(0, line_number - 1, line_number, false, {line})
end

--- Toggles a task completion status
function Tasks.toggle_importance()
    local line_number = api.nvim_win_get_cursor(0)[1]
    local line = api.nvim_get_current_line()

    local unchecked_pattern = '^(%s*)%- %[ %]'
    local unchecked_important_pattern = '^(%s*)%* %[ %]'
    local checked_pattern = '^(%s*)%- %[x%]'
    local checked_important_pattern = '^(%s*)%* %[x%]'

    if line:match(unchecked_pattern) then
        line = line:gsub(unchecked_pattern, '%1* [ ]', 1)
    elseif line:match(unchecked_important_pattern) then
        line = line:gsub(unchecked_important_pattern, '%1- [ ]', 1)
    elseif line:match(checked_pattern) then
        line = line:gsub(checked_pattern, '%1* [x]', 1)
    elseif line:match(checked_important_pattern) then
        line = line:gsub(checked_important_pattern, '%1- [x]', 1)
    end

    api.nvim_buf_set_lines(0, line_number - 1, line_number, false, {line})
end

--- Inserts a new task at the cursor location
-- @param configuration tNotaConfiguration the plugin configuration
function insert(configuration)
  error("Not yet implemented")
function Tasks.insert()
  vim.cmd('normal! o- [ ] ')
  vim.cmd('startinsert!')
end

--- Captures a new task into the inbox
-- @param configuration tNotaConfiguration the plugin configuration
function capture(configuration)
  error("Not yet implemented")
function Tasks.capture()
  error('Not yet implemented')
end

--- Tag a task
-- @param configuration tNotaConfiguration the plugin configuration
function tag(configuration)
  error("Not yet implemented")
function Tasks.tag()
  error('Not yet implemented')
end

--- Reschedule a task for today
-- @param configuration tNotaConfiguration the plugin configuration
function reschedule_for_today(configuration)
  error("Not yet implemented")
function Tasks.reschedule_for_today()
  error('Not yet implemented')
end

--- Reschedule a task for tomorrow
-- @param configuration tNotaConfiguration the plugin configuration
function reschedule_for_tomorrow(configuration)
  error("Not yet implemented")
function Tasks.reschedule_for_tomorrow()
  error('Not yet implemented')
end

--- Reschedule a task for someday
-- @param configuration tNotaConfiguration the plugin someday
function reschedule_for_someday(configuration)
  error("Not yet implemented")
function Tasks.reschedule_for_someday()
  error('Not yet implemented')
end

--- Reschedule a task for an arbitrary date
-- @param configuration tNotaConfiguration the plugin someday
function reschedule(configuration, new_date)
  error("Not yet implemented")
function Tasks.reschedule(new_date)
  error('Not yet implemented')
end

-------------------------------------------------------------------------------
-- Internal Functions
-------------------------------------------------------------------------------

return Tasks

A lua/util.lua => lua/util.lua +48 -0
@@ 0,0 1,48 @@
-------------------------------------------------------------------------------
-- Utilities shared by all modules. Categorize better if > 5 public functions
-------------------------------------------------------------------------------
local Util = {}
-------------------------------------------------------------------------------
-- Internal Functions
-------------------------------------------------------------------------------
local fs = vim.loop

local function create_directory(directory)
  local stat = fs.fs_stat(directory)
  if stat then
    if stat.type == 'directory' then
      return
    else
      error('Expected directory but found file at: ' .. directory)
    end
  else
    local parent = directory:match('(.+)/[^/]*$')
    if parent then
      create_directory(parent)
    end
    local success, error = fs.fs_mkdir(directory, 493)
    if not success then
      error('Could not directory at: ' .. directory .. '. ' .. error)
    end
  end
end
-------------------------------------------------------------------------------
-- Public Interface
-------------------------------------------------------------------------------
function Util.ensure_directory_exists(path)
  local full_path = vim.fn.expand(path)
  create_directory(path)
end

function Util.join(...)
  local separator = '/'
  local paths = {...}
  return table.concat(paths, separator):gsub(separator..'+', separator)
end

function Util.directory_name(file_path)
  local pattern = '(.+)/[^/]+$'
  return file_path:match(pattern)
end

return Util

M plugin/nota.lua => plugin/nota.lua +39 -39
@@ 36,51 36,51 @@

--- Sets up the Nota commands and keybins
-- @param user_configuration tNotaConfiguration the user provided configuration for the plugin
function setup(user_configuration)
  local api = vim.api
  local fs = vim.loop
  local fn = vim.fs
local api = vim.api
local fs = vim.loop
local fn = vim.fs

  if not api.nvim_create_user_command then
    return
  end
if not api.nvim_create_user_command then
  return
end

  local command = api.nvim_create_user_command
local command = api.nvim_create_user_command

  local configuration = require('configuration').configure(user_configuration)
local configuration = require('configuration').configuration

  if configuration.default_keybinds then
    local configuration = require('keybinds').bind()
  end
if configuration.default_keybinds then
  require('keybinds').bind()
end

  -- Note Handling Commands
  command('NotaOpenDailyNote', function() require('notes').open_daily(configuration) end, { nargs = 0 })
  command('NotaOpenWeeklyNote', function() require('notes').open_weekly(configuration) end, { nargs = 0 })
  command('NotaOpenMonthlyNote', function() require('notes').open_monthly(configuration) end, { nargs = 0 })
  command('NotaOpenSeasonalNote', function() require('notes').open_seasonal(configuration) end, { nargs = 0 })
  command('NotaOpenYearlyNote', function() require('notes').open_yearly(configuration) end, { nargs = 0 })
  command('NotaOpenNote', function() require('notes').open(configuration) end, { nargs = 0 })
-- Note Handling Commands
command('NotaOpenDailyNote', function() require('notes').open_daily() 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 })
command('NotaOpenYearlyNote', function() require('notes').open_yearly() end, { nargs = 0 })
command('NotaOpenNote', function() require('notes').open() end, { nargs = 0 })

  -- Task View Handling Commands
  command('NotaOpenAgenda', function() require('task_views').open_agenda(configuration) end, { nargs = 0 })
  command('NotaOpenOpen', function() require('task_views').open_open(configuration) end, { nargs = 0 })
  command('NotaOpenJournal', function() require('task_views').open_journal(configuration) end, { nargs = 0 })
-- Task View Handling Commands
command('NotaOpenAgenda', function() require('task_views').open_agenda() end, { nargs = 0 })
command('NotaOpenOpen', function() require('task_views').open_open() end, { nargs = 0 })
command('NotaOpenOpenImportant', function() require('task_views').open_open_important() end, { nargs = 0 })
command('NotaOpenJournal', function() require('task_views').open_journal() end, { nargs = 0 })

  -- Task Handling Commands
  command('NotaToggleTask', function() require('tasks').toggle(configuration) end, { nargs = 0 })
  command('NotaInsertTask', function() require('tasks').insert(configuration) end, { nargs = 0 })
  command('NotaCaptureTask', function() require('tasks').capture(configuration) end, { nargs = 0 })
  command('NotaTagTask', function() require('tasks').tag(configuration) end, { nargs = 0 })
  command('NotaRescheduleTaskToday', function() require('tasks').reschedule_for_today(configuration) end, { nargs = 0 })
  command('NotaRescheduleTaskTomorrow', function() require('tasks').reschedule_for_tomorrow(configuration) end, { nargs = 0 })
  command('NotaRescheduleTaskSomeday', function() require('tasks').reschedule_for_someday(configuration) end, { nargs = 0 })
  command('NotaRescheduleTask', function(options) require('tasks').reschedule(configuration, options.args) end, { nargs = 1 })
-- Task Handling Commands
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('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('NotaRescheduleTask', function(options) require('tasks').reschedule(options.args) end, { nargs = 1 })

  -- .plan Handling Commands
  command('NotaOpenPlan', function() require('plan').open(configuration) end, { nargs = 0 })
  command('NotaCapturePlan', function() require('plan').capture(configuration) end, { nargs = 0 })
-- .plan Handling Commands
command('NotaOpenPlan', function() require('plan').open() end, { nargs = 0 })
command('NotaCapturePlan', function() require('plan').capture() end, { nargs = 0 })

  -- Learning File Handling Commands
  command('NotaOpenLearning', function() require('learning').open(configuration) end, { nargs = 0 })
  command('NotaCaptureLearning', function() require('learning').capture(configuration) end, { nargs = 0 })
end
-- Learning File Handling Commands
command('NotaOpenLearning', function() require('learning').open() end, { nargs = 0 })
command('NotaCaptureLearning', function() require('learning').capture() end, { nargs = 0 })