]> git.r.bdr.sh - rbdr/nota.nvim/blob - lua/tasks.lua
66dbc48d4422845cd5a6bd152f04ed9fc0281949
[rbdr/nota.nvim] / lua / tasks.lua
1 -------------------------------------------------------------------------------
2 -- Tools to deal with tasks
3 -------------------------------------------------------------------------------
4 local Tasks = {}
5 local Configuration = require('configuration')
6 local Notes = require('notes')
7 local Util = require('util')
8 local api = vim.api
9 -------------------------------------------------------------------------------
10 -- Internal Functions
11 -------------------------------------------------------------------------------
12 local unchecked_pattern = '^(%s*)%- %[ %]'
13 local unchecked_important_pattern = '^(%s*)%* %[ %]'
14 local checked_pattern = '^(%s*)%- %[x%]'
15 local checked_important_pattern = '^(%s*)%* %[x%]'
16
17 local function open(path)
18 local parent = Util.directory_name(path)
19 Util.ensure_directory_exists(parent)
20 vim.cmd('edit ' .. path)
21 end
22
23 local function open_inbox()
24 local path = Configuration.path_for(Configuration.configuration.tasks.inbox)
25 open(path)
26 end
27 local function open_someday()
28 local path = Configuration.path_for(Configuration.configuration.tasks.someday)
29 open(path)
30 end
31 -------------------------------------------------------------------------------
32 -- Public Interface
33 -------------------------------------------------------------------------------
34
35 --- Toggles a task completion status
36 function Tasks.toggle()
37 local line_number = api.nvim_win_get_cursor(0)[1]
38 local line = api.nvim_get_current_line()
39
40 if line:match(unchecked_pattern) then
41 line = line:gsub(unchecked_pattern, '%1- [x]', 1)
42 elseif line:match(unchecked_important_pattern) then
43 line = line:gsub(unchecked_important_pattern, '%1* [x]', 1)
44 elseif line:match(checked_pattern) then
45 line = line:gsub(checked_pattern, '%1- [ ]', 1)
46 elseif line:match(checked_important_pattern) then
47 line = line:gsub(checked_important_pattern, '%1* [ ]', 1)
48 end
49
50 api.nvim_buf_set_lines(0, line_number - 1, line_number, false, {line})
51 end
52
53 --- Toggles a task completion status
54 function Tasks.toggle_importance()
55 local line_number = api.nvim_win_get_cursor(0)[1]
56 local line = api.nvim_get_current_line()
57
58 if line:match(unchecked_pattern) then
59 line = line:gsub(unchecked_pattern, '%1* [ ]', 1)
60 elseif line:match(unchecked_important_pattern) then
61 line = line:gsub(unchecked_important_pattern, '%1- [ ]', 1)
62 elseif line:match(checked_pattern) then
63 line = line:gsub(checked_pattern, '%1* [x]', 1)
64 elseif line:match(checked_important_pattern) then
65 line = line:gsub(checked_important_pattern, '%1- [x]', 1)
66 end
67
68 api.nvim_buf_set_lines(0, line_number - 1, line_number, false, {line})
69 end
70
71 --- Inserts a new task at the cursor location
72 function Tasks.insert()
73 vim.cmd('normal! o- [ ] ')
74 vim.cmd('startinsert!')
75 end
76
77 --- Captures a new task into the inbox
78 function Tasks.capture()
79 local prefix = '- [ ] '
80 open_inbox()
81 vim.cmd('normal! Go'..prefix)
82 vim.cmd('startinsert!')
83 end
84
85 --- Tag a task
86 function Tasks.tag()
87 error('Not yet implemented')
88 end
89
90 --- Reschedule a task for today
91 function Tasks.reschedule_for_today()
92 local today = os.date('%Y-%m-%d')
93 Tasks.reschedule(today)
94 end
95
96 --- Reschedule a task for tomorrow
97 function Tasks.reschedule_for_tomorrow()
98 local tomorrow = os.date('%Y-%m-%d', os.time() + 24*60*60)
99 Tasks.reschedule(tomorrow)
100 end
101
102 --- Reschedule a task for someday
103 function Tasks.reschedule_for_someday()
104 Tasks.reschedule('someday')
105 end
106
107 --- Reschedule a task for an arbitrary date
108 function Tasks.reschedule(new_date)
109
110 if not new_date or new_date == '' then
111 new_date = vim.fn.input('Reschedule for which date (YYYY-mm-dd): ')
112 end
113
114 if not Util.is_valid_date(new_date) and new_date ~= 'someday' then
115 api.nvim_err_writeln(new_date .. ' is not a valid date in the format YYYY-mm-dd')
116 return
117 end
118
119 local line_number = api.nvim_win_get_cursor(0)[1]
120 local buffer = api.nvim_get_current_buf()
121 local line = api.nvim_get_current_line()
122 local filename = vim.fn.expand('%:t:r')
123
124 if line:match(unchecked_pattern) or line:match(unchecked_important_pattern) then
125 if Util.is_before_today(filename) and line:match(unchecked_pattern) then
126 local rescheduled_line = line:gsub(unchecked_pattern, '%1- [>' .. new_date .. ']', 1)
127 api.nvim_buf_set_lines(0, line_number - 1, line_number, false, {rescheduled_line})
128 elseif Util.is_before_today(filename) and line:match(unchecked_important_pattern) then
129 local rescheduled_line = line:gsub(unchecked_important_pattern, '%1* [>' .. new_date .. ']', 1)
130 api.nvim_buf_set_lines(0, line_number - 1, line_number, false, {rescheduled_line})
131 else
132 api.nvim_buf_set_lines(buffer, line_number - 1, line_number, false, {})
133 end
134
135 vim.cmd('write')
136
137 if new_date == 'someday' then
138 open_someday()
139 else
140 Notes.open_daily(new_date)
141 end
142
143 local line_count = api.nvim_buf_line_count(0)
144 api.nvim_buf_set_lines(0, line_count, line_count, false, {line})
145 api.nvim_win_set_cursor(0, {line_count, 0})
146 else
147 api.nvim_err_writeln('Reschedule only works on open tasks')
148 end
149 end
150
151 return Tasks