]> git.r.bdr.sh - rbdr/dotfiles/blame - config/nvim/lua/brain.lua
Brain
[rbdr/dotfiles] / config / nvim / lua / brain.lua
CommitLineData
7d35a7fc
RBR
1local brain_home = os.getenv('HOME') .. '/brain'
2local templates_path = brain_home .. '/1 periodic/99 templates'
3
fc82060a
RBR
4-------------------------------------------------------------------------------
5-- Private functions for Periodic Tasks
6-------------------------------------------------------------------------------
7
7d35a7fc 8local function load_template(template_name)
fc82060a
RBR
9 local template_path = templates_path .. '/' .. template_name
10
11 print(template_path)
7d35a7fc 12
66b09f6c 13 local template_file = io.open(template_path, 'r')
7d35a7fc 14 if not template_file then
66b09f6c 15 print('Template file not found')
7d35a7fc
RBR
16 return
17 end
66b09f6c 18 local content = template_file:read('*a')
7d35a7fc 19 template_file:close()
fc82060a 20 return content
7d35a7fc
RBR
21end
22
23local function open_or_create_from_template(template_name, file)
66b09f6c 24 local journal_file = io.open(file, 'r')
7d35a7fc
RBR
25 if not journal_file then
26 local template_contents = load_template(template_name)
27
66b09f6c 28 journal_file = io.open(file, 'w')
7d35a7fc
RBR
29 journal_file:write(template_contents)
30 journal_file:close()
31 end
66b09f6c 32 vim.cmd('edit ' .. file)
7d35a7fc
RBR
33end
34
fc82060a
RBR
35local function find_tasks(completed)
36 local journal_path = brain_home .. '/1 periodic/01 journal/'
37
38 local pattern = '^\\s*\\- \\[ \\]'
39 if completed == 1 then
40 pattern = '^\\s*\\- \\[x\\]'
41 end
42
43 local command = string.format('rg --vimgrep \'%s\' \'%s\'', pattern, journal_path)
44 local results = vim.fn.systemlist(command)
45
46 if vim.v.shell_error == 0 then
47 local items = {}
48 for _, line in ipairs(results) do
49 local filename, lnum, col, text = line:match("([^:]+):(%d+):(%d+):(.*)")
50 table.insert(items, {
51 filename = filename,
52 lnum = tonumber(lnum),
53 col = tonumber(col),
54 text = text,
55 })
56 end
57
58 -- Set location list for the current window and open it
59 vim.fn.setloclist(0, items)
60 vim.cmd('lopen')
61 end
62end
63
66b09f6c
RBR
64local function get_this_weeks_files()
65 local today = os.time()
66 local day_of_week = os.date('*t', today).wday
67 local week_start = today - (day_of_week - 2) * 86400
68 local filenames = {}
69
70 for i = 0, 6 do
71 local date = os.date('*t', week_start + i * 86400)
72 table.insert(filenames, string.format('%04d-%02d-%02d.md', date.year, date.month, date.day))
73 end
74
75 return filenames
76end
77
fc82060a
RBR
78local function populate_quicklist_with_files(filenames)
79 local uv = vim.loop
80 local items = {}
81 local pattern = '^%s*%- %[[ ]?x?%]'
82
83 for _, filename in ipairs(filenames) do
84 local daily_note = brain_home .. '/1 periodic/01 journal/' .. filename
85 local stat = uv.fs_stat(daily_note)
86
87 if stat then -- File exists
88 local file, err = io.open(daily_note, 'r')
89 if file then
90 local set_header = 0
91 local line_number = 0
92 for line in file:lines() do
93 line_number = line_number + 1
94 if line:match(pattern) then
95 if set_header == 0 then
96 local header = string.sub(filename:match('([^/\\]+)$'), 1, -4)
97 table.insert(items, {filename = '', lnum = 0, text = header})
98 set_header = 1
99 end
100 table.insert(items, {filename = daily_note, text = line, lnum = line_number})
101 end
102 end
103 file:close()
104 end
105 end
106 end
107 vim.fn.setloclist(0, {}, ' ', {title = 'Weekly Tasks', items = items})
108 vim.cmd('lopen')
109end
110
66b09f6c
RBR
111-------------------------------------------------------------------------------
112-- Periodic Notes
113-------------------------------------------------------------------------------
114
7d35a7fc
RBR
115function open_daily_note()
116 local filename_format = os.date('%Y-%m-%d')
117 local template_name = '001 daily.md'
118
66b09f6c 119 local daily_note = brain_home .. '/1 periodic/01 journal/' .. filename_format .. '.md'
7d35a7fc
RBR
120 open_or_create_from_template(template_name, daily_note)
121end
122
123function open_weekly_note()
124 local filename_format = os.date('%Y-w%V')
125 local template_name = '002 weekly.md'
126
66b09f6c 127 local weekly_note = brain_home .. '/1 periodic/02 weeks/' .. filename_format .. '.md'
7d35a7fc
RBR
128 open_or_create_from_template(template_name, weekly_note)
129end
130
66b09f6c
RBR
131-------------------------------------------------------------------------------
132-- Task Utilities
133-------------------------------------------------------------------------------
134
7d35a7fc
RBR
135function toggle_task()
136 local line_num = vim.api.nvim_win_get_cursor(0)[1]
137 local line = vim.api.nvim_get_current_line()
138
139 local unchecked_pattern = '^%s*%- %[ %]'
140 local checked_pattern = '^%s*%- %[x%]'
141
142 if line:match(unchecked_pattern) then
143 line = line:gsub(unchecked_pattern, '- [x]', 1)
144 elseif line:match(checked_pattern) then
145 line = line:gsub(checked_pattern, '- [ ]', 1)
146 end
147
148 vim.api.nvim_buf_set_lines(0, line_num - 1, line_num, false, {line})
149end
150
66b09f6c 151-------------------------------------------------------------------------------
fc82060a 152-- Task Quicklist Views
66b09f6c
RBR
153-------------------------------------------------------------------------------
154
155function open_agenda()
66b09f6c 156 local week_filenames = get_this_weeks_files()
fc82060a
RBR
157 populate_quicklist_with_files(week_filenames)
158end
66b09f6c 159
fc82060a
RBR
160function open_open()
161 find_tasks(0)
66b09f6c
RBR
162end
163
164-------------------------------------------------------------------------------
165-- Key Bindings
166-------------------------------------------------------------------------------
fc82060a 167-- Periodic Notes
7d35a7fc
RBR
168vim.api.nvim_set_keymap('n', '<leader>od', '<cmd>lua open_daily_note()<CR>', { noremap = true, silent = true })
169vim.api.nvim_set_keymap('n', '<leader>ow', '<cmd>lua open_weekly_note()<CR>', { noremap = true, silent = true })
fc82060a
RBR
170-- Planned: \om to open monthly, \os to open seasonly, and \oy to open yearly
171-- Agenda Views
66b09f6c 172vim.api.nvim_set_keymap('n', '<leader>oa', '<cmd>lua open_agenda()<CR>', { noremap = true, silent = true })
fc82060a
RBR
173vim.api.nvim_set_keymap('n', '<leader>oo', '<cmd>lua open_open()<CR>', { noremap = true, silent = true })
174-- Planned: \oj to open journal
175-- Task Helpers
7d35a7fc 176vim.api.nvim_set_keymap('n', '<leader>t', '<cmd>lua toggle_task()<CR>', { noremap = true, silent = true })
fc82060a
RBR
177-- Planned: \it to insert tasks
178-- Planned: \ct to capture task to an inbox
179-- Planned: \cl to capture a learning
180-- Planned: \cp to capture .plan
181-- Planned: \rt reschedule task to today
182-- Planned: \rT reschedule task for tomorrow
183-- Planned But even later: \rr reschedule task for an arbitrary date.
184-- Planned: \rs reschedule task for someday
185-------------------------------------------------------------------------------
186-- Ideas:
187-- Navigate through the weeks like in org mode?
188-- Labels?