aboutsummaryrefslogtreecommitdiffhomepage
path: root/.config/nvim/lua/leaf/init.lua
blob: c389ffdd44eb06983ebc600113ce69abf79a4b24 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
local M = {}


local A = vim.api
local F = vim.fn

local TASK_STATUS_PATTERN = [=[\[[ x-]\] ]=]
local TASK_STATUS_PATTERN_EXCEPT_DONE = [=[\[[ -]\] ]=]
local TASK_STATUS_PATTERN_EXCEPT_CANCELED = [=[\[[ x]\] ]=]
-- op = T
--    T => T
--    D => T
--    C => T
-- op = D
--    T => D
--    D => D
--    C => C
-- op = C
--    T => C
--    D => D
--    C => C


local function vim_match(s, pattern)
   return vim.regex(pattern):match_str(s)
end

local function switch_task_status_internal(line_num, op, is_subtask)
   local line = F.getline(line_num)
   local pattern
   if is_subtask then
      if op == ' ' then
         pattern = TASK_STATUS_PATTERN
      elseif op == 'x' then
         pattern = TASK_STATUS_PATTERN_EXCEPT_CANCELED
      elseif op == '-' then
         pattern = TASK_STATUS_PATTERN_EXCEPT_DONE
      else
         assert('unexpected op: ' .. tostring(op))
      end
   else
      pattern = TASK_STATUS_PATTERN
   end
   if vim_match(line, pattern) then
      local replacement = ('[%s] '):format(op)
      F.setline(line_num, F.substitute(line, pattern, replacement, ''))
      return true
   else
      return false
   end
end


function M.checkbox(check, char)
   local line = F.getline('.')
   if vim_match(line, [[^\s*$]]) and #line % F.shiftwidth() == 0 then
      return check and '[x] ' or '[ ] '
   else
      return char
   end
end

function M.switch_task_status(op)
   switch_task_status_internal(F.line('.'), op)
end

function M.switch_task_status_rec(op)
   local current_line_num = F.line('.')
   local replaced = switch_task_status_internal(current_line_num, op)
   if not replaced then
      return
   end
   local last_line_num = F.line('$')
   if current_line_num == last_line_num then
      return
   end

   local base_indent_level = F.indent('.')
   for l = current_line_num + 1, last_line_num do
      if F.indent(l) <= base_indent_level then
         break
      end
      switch_task_status_internal(l, op, true)
   end
end


return M