summaryrefslogtreecommitdiff
path: root/lua
diff options
context:
space:
mode:
authorMohammad Reza Karimi <m.r.karimi.j@gmail.com>2026-01-22 17:17:43 -0500
committerMohammad Reza Karimi <m.r.karimi.j@gmail.com>2026-01-22 17:17:43 -0500
commitddd2e6b1cce8d6b5ba29df453bb10a6b841df0fa (patch)
treea4058148197ed67f082fc7feb6d2716675db9d9f /lua
parentc6274ae49c9d6c42ab239f23313a5b72b3ba8d5c (diff)
Diffstat (limited to 'lua')
-rw-r--r--lua/mo/org-agenda.lua134
-rw-r--r--lua/mo/org.lua21
2 files changed, 155 insertions, 0 deletions
diff --git a/lua/mo/org-agenda.lua b/lua/mo/org-agenda.lua
new file mode 100644
index 0000000..fd7ed63
--- /dev/null
+++ b/lua/mo/org-agenda.lua
@@ -0,0 +1,134 @@
+local Menu = {}
+
+local default_config = {
+ window = {
+ margin = { 1, 0, 1, 0 },
+ padding = { 1, 1, 1, 1 },
+ title_pos = "center",
+ border = { "", "-", "", "", "", "", "", "" },
+ zindex = 1000,
+ },
+ icons = {
+ separator = "➜",
+ },
+}
+
+function Menu:new(config)
+ config = vim.tbl_deep_extend("force", default_config, config or {})
+
+ local opts = {}
+ opts.window = config.window
+ opts.icons = config.icons
+
+ setmetatable(opts, self)
+ self.__index = self
+ return opts
+end
+
+function Menu:_get_window_margins()
+ local margins = {}
+
+ for i, m in ipairs(self.window.margin) do
+ local _m = m
+ if m > 0 and m < 1 then
+ if i % 2 == 0 then
+ _m = math.floor(vim.o.columns * m)
+ else
+ _m = math.floor(vim.o.lines * m)
+ end
+ end
+ margins[i] = _m
+ end
+
+ return margins
+end
+
+local function add_vertical_padding(content, size)
+ for _ = 1, size do
+ table.insert(content, "")
+ end
+end
+
+function Menu:_process_items(items)
+ local pad_top, pad_right, pad_bot, pad_left = unpack(self.window.padding)
+
+ local content = {}
+ local keys = {}
+
+ add_vertical_padding(content, pad_top)
+
+ for _, item in ipairs(items) do
+ if item.key then
+ keys[item.key] = item
+
+ table.insert(content, string.rep(" ", pad_left) .. vim.fn.join({
+ item.key,
+ self.icons.separator,
+ item.label,
+ }) .. string.rep(" ", pad_right))
+ end
+ end
+
+ add_vertical_padding(content, pad_bot)
+
+ return keys, content
+end
+
+function Menu:_open_window(title, content)
+ local margins = self:_get_window_margins()
+ local wins = vim.tbl_filter(
+ function(w)
+ return vim.api.nvim_win_is_valid(w)
+ and vim.api.nvim_win_get_config(w).relative == ""
+ end,
+ vim.api.nvim_list_wins()
+ )
+
+ local line_lengths = vim.tbl_map(function(s) return #s end, content)
+ line_lengths[#line_lengths + 1] = #title
+ local pref_width = vim.fn.max(line_lengths)
+
+ self.buffer = vim.api.nvim_create_buf(false, true)
+ vim.api.nvim_buf_set_lines(self.buffer, 0, -1, true, content)
+
+ local window = vim.api.nvim_open_win(self.buffer, false, {
+ title = title,
+ title_pos = self.window.title_pos,
+ relative = "editor",
+ width = vim.fn.min({ vim.o.columns, pref_width })
+ - margins[2]
+ - margins[4],
+ height = #content,
+ focusable = false,
+ anchor = "SW",
+ border = self.window.border,
+ row = vim.o.lines
+ - margins[3]
+ + ((vim.o.laststatus == 0 or vim.o.laststatus == 1 and #wins == 1) and 1 or 0)
+ - vim.o.cmdheight,
+ col = margins[4],
+ style = "minimal",
+ noautocmd = true,
+ } --[[@as vim.api.keyset.win_config]])
+ vim.api.nvim__redraw({ win = window, valid = true })
+ return window
+end
+
+function Menu:_close()
+ vim.api.nvim_win_close(self.window, true)
+ vim.api.nvim_buf_delete(self.buffer, { force = true })
+ vim.cmd.redraw()
+end
+
+function Menu:open(data)
+ local keys, content = self:_process_items(data.items)
+ self.window = self:_open_window(data.title, content)
+
+ local char = vim.fn.nr2char(vim.fn.getchar())
+ self:_close()
+
+ local entry = keys[char]
+ if entry and entry.action then return entry.action() end
+end
+
+return Menu
diff --git a/lua/mo/org.lua b/lua/mo/org.lua
new file mode 100644
index 0000000..2218112
--- /dev/null
+++ b/lua/mo/org.lua
@@ -0,0 +1,21 @@
+--- @diagnostic disable: missing-fields
+
+if not package.loaded["fzf-lua"] then
+ vim.cmd([[packadd fzf-lua]])
+end
+
+require("orgmode").setup({
+ org_agenda_files = "~/org/**/*",
+ org_default_notes_file = "~/org/refile.org",
+
+ ui = {
+ input = { use_vim_ui = true },
+ menu = {
+ handler = function(data)
+ require("mo.org-agenda"):new():open(data)
+ end
+ }
+ },
+} --[[@as OrgConfigOpts]])
+
+vim.lsp.enable({ "org" })