------------------------------------------------------------------------------- -- 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() 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 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 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 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 return TaskViews