dotfiles/symlinks/config/nvim/lua/vimwiki_reviews.lua

301 lines
8.5 KiB
Lua

-------------------------------------------------------------------------------
-- - Vimwiki reviews extension library -
-------------------------------------------------------------------------------
local Path = require('plenary.path')
local scandir = require('plenary.scandir')
-- Gets path to reviews dir of provided vimwiki (by index)
local function get_reviews_dir(vimwiki_index)
local vimwiki = {}
if (vimwiki_index == 0)
then
local current_index = vim.fn['vimwiki#vars#get_bufferlocal']('wiki_nr')
if (current_index < 0)
then
current_index = 0
end
vimwiki = vim.g.vimwiki_list[current_index + 1]
else
vimwiki = vim.g.vimwiki_list[vimwiki_index]
end
return vimwiki.path .. 'reviews/'
end
-- Finds review template path for provided review type
local function get_review_template_path(vimwiki_reviews_path, review_type)
return vimwiki_reviews_path .. 'template-' .. review_type .. '.md'
end
-- Reads template for provided review type into current buffer
-- Uses overrides in form of files in reviews directory
-- Looks for file named template-{review_type}.md:
-- - template-week.md
-- - template-month.md
-- - template-year.md
-- Templates can use variables using %variable% syntax
-- Currently supported variables are:
-- - %date% (Puts different date based on review type)
local function read_review_template_into_buffer(vimwiki_reviews_path, review_type)
local template_path = get_review_template_path(vimwiki_reviews_path, review_type)
if (vim.fn.filereadable(vim.fn.glob(template_path)) ~= 0)
then
vim.cmd('read ' .. template_path)
vim.cmd('0d')
else
if (review_type == 'week')
then
vim.fn.setline(1, '# %date% Weekly Review')
elseif (review_type == 'month')
then
vim.fn.setline(1, '# %date% Monthly Review')
elseif (review_type == 'year')
then
vim.fn.setline(1, '# %date% Yearly Review')
end
end
end
local function file_exists_or_open(file_name)
local exists = Path:new(Path:new(file_name):expand()):exists()
local open = vim.fn.bufwinnr(file_name) > 0
return exists or open
end
local function get_filename_from_path(path)
local _, filename, _ = string.match(path, "(.-)([^\\/]-%.?([^%.\\/]*))$")
return filename
end
-------------------------------------------------------------------------------
-- - Public API -
-------------------------------------------------------------------------------
local M = {}
-- Edits weekly review template
function M.open_review_weekly_template(vimwiki_index)
local reviews_dir = get_reviews_dir(vimwiki_index)
vim.cmd('edit ' .. get_review_template_path(reviews_dir, 'week'))
end
-- Edits monthly review template
function M.open_review_monthly_template(vimwiki_index)
local reviews_dir = get_reviews_dir(vimwiki_index)
vim.cmd('edit ' .. get_review_template_path(reviews_dir, 'month'))
end
-- Edits yearly review template
function M.open_review_yearly_template(vimwiki_index)
local reviews_dir = get_reviews_dir(vimwiki_index)
vim.cmd('edit ' .. get_review_template_path(reviews_dir, 'year'))
end
-- Open current week weekly review file
-- Created buffer is dated to Sunday of current week
-- Opens current week because Sunday is good time to do this review
function M.vimwiki_weekly_review(vimwiki_index)
local reviews_dir = get_reviews_dir(vimwiki_index)
local days_to_sunday = 7 - tonumber(os.date('%u'))
local week_date = os.date('%Y-%m-%d', os.time() + days_to_sunday * 24 * 60 * 60)
local file_name = reviews_dir .. week_date .. '-week.md'
local exists = file_exists_or_open(file_name)
vim.cmd('edit ' .. file_name)
if (exists == false)
then
read_review_template_into_buffer(reviews_dir, 'week')
vim.cmd('%substitute/%date%/' .. week_date)
end
end
-- Open past month monthly review file
-- Created buffer is dated to previous month
-- Previous month is calculated in an erroneous way
-- 28 days are subtracted from current time to get previous month
function M.vimwiki_monthly_review(vimwiki_index)
local reviews_dir = get_reviews_dir(vimwiki_index)
local month_time = os.time() - 28 * 24 * 60 * 60
local month_date = os.date('%Y-%m', month_time)
local file_name = reviews_dir .. month_date .. '-month.md'
local exists = file_exists_or_open(file_name)
vim.cmd('edit ' .. file_name)
if (exists == false)
then
read_review_template_into_buffer(reviews_dir, 'month')
vim.cmd('%substitute/%date%/' .. os.date('%Y %B', month_time))
end
end
-- Open past year yearly review file
-- Created buffer is dated to previous year
function M.vimwiki_yearly_review(vimwiki_index)
local reviews_dir = get_reviews_dir(vimwiki_index)
local year_date = (tonumber(os.date('%Y')) - 1)
local file_name = reviews_dir .. year_date .. '-year.md'
local exists = file_exists_or_open(file_name)
vim.cmd('edit ' .. file_name)
if (exists == false)
then
read_review_template_into_buffer(reviews_dir, 'year')
vim.cmd('%substitute/%date%/' .. year_date)
end
end
-- Generates review index table
-- Takes arguments similar to all vimwiki calls
-- (no args, or 1 arg representing vimwiki index)
function M.get_review_index(vimwiki_index)
local reviews_dir = get_reviews_dir(vimwiki_index)
local reviews_path = Path:new(reviews_dir):expand()
local entries = scandir.scan_dir(
reviews_path,
{
hidden = false,
add_dirs = false,
respect_gitignore = true,
depth = 1
})
local index = {}
-- TODO better default values handling
for _,entry in pairs(entries) do
local filename = get_filename_from_path(entry)
if (string.match(filename, '^%d*-year.md$'))
then
local year = string.match(filename, '(%d*)-year')
if (index[year] == nil)
then
index[year] = {
months = {}
}
end
index[year].year = filename
elseif (string.match(filename, '^%d*-%d*-month.md$'))
then
local year = string.match(filename, '(%d*)-%d*-month')
local month = string.match(filename, '(%d*)-month')
if (index[year] == nil)
then
index[year] = {
months = {}
}
end
if (index[year].months[month] == nil)
then
index[year].months[month] = {
weeks = {}
}
end
index[year].months[month].month = filename
elseif (string.match(filename, '^%d*-%d*-%d*-week.md$'))
then
local year = string.match(filename, '(%d*)-%d*-%d*-week')
local month = string.match(filename, '(%d*)-%d*-week')
local week = string.match(filename, '(%d*)-week')
if (index[year] == nil)
then
index[year] = {
months = {}
}
end
if (index[year].months[month] == nil)
then
index[year].months[month] = {
weeks = {}
}
end
index[year].months[month].weeks[week] = filename
end
end
return index
end
-- Open reviews index file
function M.vimwiki_review_index(vimwiki_index)
local reviews_dir = get_reviews_dir(vimwiki_index)
vim.cmd('edit ' .. reviews_dir .. 'reviews.md')
local index = M.get_review_index(vimwiki_index)
local lines = {
'# Reviews',
'',
}
local month_names = {
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December'
}
-- Sort index by year
local years = {}
for k in pairs(index) do table.insert(years, k) end
table.sort(years, function(a, b) return a > b end)
local tablelength = function(T)
local count = 0
for _ in pairs(T) do count = count + 1 end
return count
end
-- Add years
for _, year in pairs(years) do
table.insert(lines, '## ' .. year)
table.insert(lines, '')
if (index[year].year)
then
table.insert(lines, '- [Yearly review](' .. index[year].year .. ')')
table.insert(lines, '')
end
-- Sort months
local months = {}
for k in pairs(index[year].months) do table.insert(months, k) end
table.sort(months, function(a, b) return a > b end)
-- Add months
for _, month in pairs(months) do
table.insert(lines, '### ' .. month_names[tonumber(month)])
table.insert(lines, '')
if (index[year].months[month].month)
then
table.insert(lines, '- [Monthly review](' .. index[year].months[month].month .. ')')
end
-- Sort weeks
local weeks = index[year].months[month].weeks
local sorted = {}
for k in pairs(weeks) do table.insert(sorted, k) end
table.sort(sorted, function(a, b) return a > b end)
-- Add weeks
local count = tablelength(sorted)
for _, week in pairs(sorted) do
table.insert(lines, '- [Week #' .. count .. ' Review](' .. weeks[week] .. ')')
count = count - 1
end
table.insert(lines, '')
end
end
local buf = vim.api.nvim_get_current_buf()
vim.api.nvim_buf_set_lines(buf, 0, -1, false, {}) -- Clear out
vim.api.nvim_buf_set_lines(buf, 0, 0, false, lines) -- Put new contents
end
return M