]> git.r.bdr.sh - rbdr/nota.nvim/blob - lua/task_views.lua
9309ad3277c276fab28233937f913652346f7867
[rbdr/nota.nvim] / lua / task_views.lua
1 -------------------------------------------------------------------------------
2 -- Tools to deal with task views
3 -------------------------------------------------------------------------------
4 local TaskViews = {}
5 local Util = require('util')
6 local Configuration = require('configuration')
7 local api = vim.api
8 -------------------------------------------------------------------------------
9 -- Internal Functions
10 -------------------------------------------------------------------------------
11 local function get_this_weeks_files()
12 local today = os.time()
13 local day_of_week = os.date('*t', today).wday
14 local week_start = today - (day_of_week - 2) * 86400
15 local filenames = {}
16
17 for i = 0, 6 do
18 local date = os.date('*t', week_start + i * 86400)
19 table.insert(filenames, string.format('%04d-%02d-%02d.md', date.year, date.month, date.day))
20 end
21
22 return filenames
23 end
24
25 local function find_tasks(completed, important)
26 local file_directory_path = Configuration.path_for()
27
28 local completed_fragment = '(\\s|x)'
29 if completed == 1 then
30 completed_fragment = 'x'
31 elseif completed == 0 then
32 completed_fragment = '\\s'
33 end
34
35 local important_fragment = '(\\-|\\*)'
36 if important == 1 then
37 important_fragment = '\\*'
38 elseif important == 0 then
39 important_fragment = '\\-'
40 end
41
42
43 local pattern = '^\\s*' .. important_fragment .. '\\s\\[' .. completed_fragment .. ']'
44
45 local command = string.format('rg --vimgrep \'%s\' \'%s\'', pattern, file_directory_path)
46 local results = vim.fn.systemlist(command)
47
48 if vim.v.shell_error == 0 then
49 local items = {}
50 for _, line in ipairs(results) do
51 local filename, lnum, col, text = line:match('([^:]+):(%d+):(%d+):(.*)')
52 table.insert(items, {
53 filename = filename,
54 lnum = tonumber(lnum),
55 col = tonumber(col),
56 text = text,
57 })
58 end
59
60 -- Set location list for the current window and open it
61 vim.fn.setloclist(0, items)
62 vim.cmd('lopen')
63 end
64 end
65
66 local function populate_quicklist_with_files(filenames)
67 local uv = vim.loop
68 local items = {}
69 local task_pattern = '^%s*%- %[[ ]?x?%]'
70 local important_task_pattern = '^%s*%* %[[ ]?x?%]'
71
72 local file_directory_path = Configuration.path_for(Configuration.configuration.periodic_locations.daily)
73 Util.ensure_directory_exists(file_directory_path)
74
75 for _, filename in ipairs(filenames) do
76 local daily_note = Util.join(file_directory_path, filename)
77 local stat = uv.fs_stat(daily_note)
78
79 if stat then -- File exists
80 local file, err = io.open(daily_note, 'r')
81 if file then
82 local set_header = 0
83 local line_number = 0
84 for line in file:lines() do
85 line_number = line_number + 1
86 if line:match(task_pattern) or line:match(important_task_pattern) then
87 if set_header == 0 then
88 local header = string.sub(filename:match('([^/\\]+)$'), 1, -4)
89 table.insert(items, {filename = '', lnum = 0, text = header})
90 set_header = 1
91 end
92 table.insert(items, {filename = daily_note, text = line, lnum = line_number})
93 end
94 end
95 file:close()
96 end
97 end
98 end
99 vim.fn.setloclist(0, {}, ' ', {title = 'Weekly Tasks', items = items})
100 vim.cmd('lopen')
101 end
102
103 -------------------------------------------------------------------------------
104 -- Public Interface
105 -------------------------------------------------------------------------------
106
107 --- Opens the agenda view to show tasks
108 function TaskViews.open_agenda()
109 local week_filenames = get_this_weeks_files()
110 populate_quicklist_with_files(week_filenames)
111 end
112
113 --- Opens the view to show open tasks
114 function TaskViews.open_open()
115 find_tasks(0)
116 end
117
118 --- Opens the view to show open important tasks
119 function TaskViews.open_open_important()
120 find_tasks(0, 1)
121 end
122
123 --- Opens the view to search the journal
124 function TaskViews.open_journal()
125 local pattern = '^\\s*(\\*|\\-)\\s\\[x]'
126 -- local pattern = 'hell'
127 local success, module = pcall(require, 'fzf-lua')
128 if success then
129 local notes_path = Configuration.path_for()
130 Util.ensure_directory_exists(notes_path)
131 module.files({ cwd = notes_path, cmd = 'rg --line-number --no-heading -- \'' .. pattern ..'\''})
132 else
133 api.nvim_err_writeln('This feature requires optional dependency fzf-lua')
134 end
135 end
136
137 return TaskViews