aboutsummaryrefslogtreecommitdiffhomepage
path: root/.config/nvim/lua/leaf
diff options
context:
space:
mode:
Diffstat (limited to '.config/nvim/lua/leaf')
-rw-r--r--.config/nvim/lua/leaf/calendar.lua43
-rw-r--r--.config/nvim/lua/leaf/fold.lua60
-rw-r--r--.config/nvim/lua/leaf/indent.lua16
-rw-r--r--.config/nvim/lua/leaf/init.lua88
4 files changed, 207 insertions, 0 deletions
diff --git a/.config/nvim/lua/leaf/calendar.lua b/.config/nvim/lua/leaf/calendar.lua
new file mode 100644
index 0000000..f998785
--- /dev/null
+++ b/.config/nvim/lua/leaf/calendar.lua
@@ -0,0 +1,43 @@
+local M = {}
+
+
+local floor = math.floor
+
+
+M.MON = 1
+M.TUE = 2
+M.WED = 3
+M.THU = 4
+M.FRI = 5
+M.SAT = 6
+M.SUN = 7
+
+
+function M.calc_week_of_day(y, m, d)
+ -- Zeller's congruence
+ if m == 1 or m == 2 then
+ m = m + 12
+ y = y - 1
+ end
+ local C = floor(y / 100)
+ local Y = y % 100
+ local G = 5*C + floor(C/4)
+ return 1 + (d + floor(26 * (m+1) / 10) + Y + floor(Y/4) + G + 5) % 7
+end
+
+
+function M.translate_week_of_day(w, locale)
+ -- assert(locale == 'ja_JP')
+ return ({
+ [M.MON] = '月',
+ [M.TUE] = '火',
+ [M.WED] = '水',
+ [M.THU] = '木',
+ [M.FRI] = '金',
+ [M.SAT] = '土',
+ [M.SUN] = '日',
+ })[w]
+end
+
+
+return M
diff --git a/.config/nvim/lua/leaf/fold.lua b/.config/nvim/lua/leaf/fold.lua
new file mode 100644
index 0000000..6f8a0b5
--- /dev/null
+++ b/.config/nvim/lua/leaf/fold.lua
@@ -0,0 +1,60 @@
+local M = {}
+
+
+local F = vim.fn
+local V = vim.v
+
+
+local function find_plain_string(haystack, needle, start)
+ return haystack:find(needle, start or 1, true)
+end
+
+
+function M.foldexpr()
+ local current_line_indent = F.indent(V.lnum)
+ local task_level = math.floor(current_line_indent / F.shiftwidth())
+ if V.lnum == F.line('$') then
+ return task_level
+ end
+ local next_line_indent = F.indent(V.lnum + 1)
+ if current_line_indent < next_line_indent then
+ return ('>%d'):format(task_level + 1)
+ else
+ return task_level
+ end
+end
+
+
+function M.foldtext()
+ local foldstart = V.foldstart
+ local foldend = V.foldend
+ local shiftwidth = F.shiftwidth()
+ local current_line_indent = F.indent(foldstart)
+
+ local todo = 0
+ local done = 0
+ for i = foldstart + 1, foldend do
+ local line = F.getline(i)
+ local line_indent = F.indent(i)
+ if line_indent == current_line_indent + shiftwidth then
+ if find_plain_string(line, '[x] ') then
+ done = done + 1
+ elseif find_plain_string(line, '[ ] ') then
+ todo = todo + 1
+ elseif find_plain_string(line, '[-] ') then
+ done = done + 1
+ end
+ end
+ end
+
+ local progress
+ if done + todo == 0 then
+ progress = '...'
+ else
+ progress = (' [%d/%d]'):format(done, done + todo)
+ end
+ return F.getline(foldstart) .. progress
+end
+
+
+return M
diff --git a/.config/nvim/lua/leaf/indent.lua b/.config/nvim/lua/leaf/indent.lua
new file mode 100644
index 0000000..d1df34a
--- /dev/null
+++ b/.config/nvim/lua/leaf/indent.lua
@@ -0,0 +1,16 @@
+local M = {}
+
+local F = vim.fn
+local V = vim.v
+
+
+function M.indentexpr()
+ local lnum = V.lnum
+ if lnum == 0 then
+ return 0
+ end
+ return F.indent(lnum - 1)
+end
+
+
+return M
diff --git a/.config/nvim/lua/leaf/init.lua b/.config/nvim/lua/leaf/init.lua
new file mode 100644
index 0000000..c389ffd
--- /dev/null
+++ b/.config/nvim/lua/leaf/init.lua
@@ -0,0 +1,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