From 53062963b1c2558b188ad3285cd1057f33fece4b Mon Sep 17 00:00:00 2001 From: Chris Pecunies Date: Sun, 29 Dec 2024 13:36:59 -0800 Subject: [PATCH] refactoring, event parsing --- book/lua/module/examples/barebones.lua | 2 +- book/lua/module/examples/basic.lua | 2 +- book/src/modules/examples.md | 4 +- book/src/modules/index.md | 2 +- lua/down.lua | 3 +- lua/down/config.lua | 11 +- lua/down/event/init.lua | 113 ++-- lua/down/mod.lua | 289 +++++--- lua/down/mod/cmd/init.lua | 89 +-- lua/down/mod/cmd/mod/init.lua | 134 ++-- lua/down/mod/code/init.lua | 21 +- lua/down/mod/code/snippet/init.lua | 2 +- lua/down/mod/data/bookmark/init.lua | 80 +-- lua/down/mod/data/date/init.lua | 2 +- lua/down/mod/data/encrypt/init.lua | 10 +- lua/down/mod/data/export/init.lua | 8 +- lua/down/mod/data/history/init.lua | 46 +- lua/down/mod/data/init.lua | 57 +- lua/down/mod/data/store/init.lua | 15 +- lua/down/mod/data/time/init.lua | 136 ++-- lua/down/mod/edit/cursor/init.lua | 2 +- lua/down/mod/edit/indent/init.lua | 139 ++-- lua/down/mod/edit/init.lua | 14 +- lua/down/mod/edit/toc/init.lua | 639 ------------------ lua/down/mod/edit/toc/util.lua | 3 - lua/down/mod/{data => }/link/README.md | 0 lua/down/mod/{data => }/link/init.lua | 191 ++++-- lua/down/mod/log/cmd.lua | 47 ++ lua/down/mod/log/init.lua | 300 ++++---- lua/down/mod/lsp/cmd.lua | 101 +++ lua/down/mod/lsp/init.lua | 97 ++- lua/down/mod/note/capture/init.lua | 12 +- .../mod/{edit/toc/README.md => note/cmd.lua} | 0 lua/down/mod/note/init.lua | 537 +++++++-------- lua/down/mod/parse/init.lua | 2 +- lua/down/mod/tag/init.lua | 54 +- lua/down/mod/task/agenda/init.lua | 2 +- lua/down/mod/task/init.lua | 59 +- lua/down/mod/template/init.lua | 353 ++-------- lua/down/mod/tool/blink/source/init.lua | 2 +- lua/down/mod/tool/init.lua | 4 +- lua/down/mod/tool/telescope/init.lua | 57 +- lua/down/mod/tool/treesitter/init.lua | 112 +-- lua/down/mod/ui/calendar/day/init.lua | 2 +- lua/down/mod/ui/calendar/init.lua | 33 +- lua/down/mod/ui/calendar/month/init.lua | 128 ++-- lua/down/mod/ui/conceal/init.lua | 2 +- lua/down/mod/ui/dashboard/init.lua | 2 +- lua/down/mod/ui/hl/init.lua | 2 +- lua/down/mod/ui/icon/init.lua | 12 +- lua/down/mod/ui/init.lua | 77 +-- lua/down/mod/ui/prompt/init.lua | 2 +- lua/down/mod/ui/win/init.lua | 2 +- lua/down/mod/workspace/init.lua | 331 ++++----- lua/down/types/config.lua | 2 +- lua/down/types/context.lua | 2 +- lua/down/types/date.lua | 2 +- lua/down/types/entity.lua | 2 +- lua/down/types/enum.lua | 2 +- lua/down/types/event.lua | 5 +- lua/down/types/file.lua | 2 +- lua/down/types/init.lua | 4 +- lua/down/types/mod.lua | 132 ++-- lua/down/types/store.lua | 4 +- lua/down/types/util.lua | 4 +- lua/down/types/workspace.lua | 2 +- lua/down/util/lib.lua | 2 +- lua/down/util/log/init.lua | 91 ++- lua/down/util/parse/init.lua | 2 +- lua/down/util/string.lua | 22 +- 70 files changed, 1988 insertions(+), 2638 deletions(-) delete mode 100644 lua/down/mod/edit/toc/init.lua delete mode 100644 lua/down/mod/edit/toc/util.lua rename lua/down/mod/{data => }/link/README.md (100%) rename lua/down/mod/{data => }/link/init.lua (57%) create mode 100644 lua/down/mod/log/cmd.lua create mode 100644 lua/down/mod/lsp/cmd.lua rename lua/down/mod/{edit/toc/README.md => note/cmd.lua} (100%) diff --git a/book/lua/module/examples/barebones.lua b/book/lua/module/examples/barebones.lua index 54c36a8..3d4e480 100644 --- a/book/lua/module/examples/barebones.lua +++ b/book/lua/module/examples/barebones.lua @@ -84,7 +84,7 @@ J.data = { J.config = { ---@brief The default directory you might want to specify for Jupyter notebooks to be stored in. - ---@brief You may also wish to leverage the required "workspace" module to allow users to specify both + ---@brief You may also wish to leverage the dep "workspace" module to allow users to specify both ---@brief a specific workspace tey would like to associate with Jupyter notebooks, as well as a default ---@brief relative directory within that workspace. --- diff --git a/book/lua/module/examples/basic.lua b/book/lua/module/examples/basic.lua index 8939778..2bdfed3 100644 --- a/book/lua/module/examples/basic.lua +++ b/book/lua/module/examples/basic.lua @@ -21,7 +21,7 @@ local M = mod.create("user.mod", { M.setup = function() return { requires = { - ---@brief required modules + ---@brief dep modules --- modules from builtin or custom --- modules that can be loaded in (same as --- if calling `require 'module'`) as a dependency diff --git a/book/src/modules/examples.md b/book/src/modules/examples.md index 92bcdbd..57f3e12 100644 --- a/book/src/modules/examples.md +++ b/book/src/modules/examples.md @@ -90,7 +90,7 @@ J.data = { J.config = { ---@brief The default directory you might want to specify for Jupyter notebooks to be stored in. - ---@brief You may also wish to leverage the required "workspace" module to allow users to specify both + ---@brief You may also wish to leverage the dep "workspace" module to allow users to specify both ---@brief a specific workspace tey would like to associate with Jupyter notebooks, as well as a default ---@brief relative directory within that workspace. --- @@ -153,7 +153,7 @@ local M = mod.create("user.example", { M.setup = function() return { requires = { - ---@brief required modules + ---@brief dep modules --- modules from builtin or custom --- modules that can be loaded in (same as --- if calling `require 'module'`) as a dependency diff --git a/book/src/modules/index.md b/book/src/modules/index.md index 6a0b326..652825b 100644 --- a/book/src/modules/index.md +++ b/book/src/modules/index.md @@ -20,7 +20,7 @@ local M = mod.create("user.example", { M.setup = function() return { requires = { - ---@brief required modules + ---@brief dep modules --- modules from builtin or custom --- modules that can be loaded in (same as --- if calling `require 'module'`) as a dependency diff --git a/lua/down.lua b/lua/down.lua index a93f6c8..2f1f397 100644 --- a/lua/down.lua +++ b/lua/down.lua @@ -17,7 +17,7 @@ Down.default = { -- ['data.log'] = {}, ['lsp'] = {}, ['cmd'] = {}, - ['data.link'] = {}, + ['link'] = {}, -- ['cmd.back'] = {}, -- ['data.history'] = {}, ['tool.telescope'] = {}, @@ -59,6 +59,7 @@ end function Down:post_load() for _, l in pairs(self.mod.mods) do + self.event.load_cb(l) l.post_load() end end diff --git a/lua/down/config.lua b/lua/down/config.lua index 6061a21..fafed8c 100644 --- a/lua/down/config.lua +++ b/lua/down/config.lua @@ -21,12 +21,8 @@ end local Config = { --- Start in dev mode dev = false, - log = {}, - log_config = { - level = 'trace', - lvl = 0, - }, - + ---@type down.log.Config + log = require 'down.util.log'.config, workspace = { default = vim.fn.getcwd(0), }, @@ -100,7 +96,8 @@ function Config.setup(self, user, default, ...) if self.started or not user or vim.tbl_isempty(user) then return false end - self.log = log.new(self.log_config, true) + log.new(self.log, false) + log.info("Config.setup: Log started") user = vim.tbl_deep_extend('force', user, default) self.user = vim.tbl_deep_extend('force', self.user, user) if self.user.hook then diff --git a/lua/down/event/init.lua b/lua/down/event/init.lua index 966da9f..d7edd16 100644 --- a/lua/down/event/init.lua +++ b/lua/down/event/init.lua @@ -1,9 +1,8 @@ local log = require 'down.util.log' ----@type down.Event +---@class down.Event local Event = { - topic = '', - type = '', + id = '', ref = '', split = {}, body = nil, @@ -29,7 +28,7 @@ local Event = { buf = vim.api.nvim_get_current_buf(), win = vim.api.nvim_get_current_win(), dir = vim.fn.getcwd(), - scope = "global" + scope = 'global', }, } @@ -38,13 +37,15 @@ local Event = { local Cb = { ---@type table cb = {}, -} + ---@type table + events = {}, +} --- @param ty? string --- @return { [1]: fun(event: down.Event, content: table|any)> } function Event:get_cb(ty) - return Cb.cb[ty or self.type] + return Cb.cb[ty or self.id] end --- Triggers a new callback to execute whenever an event of the requested type is executed. @@ -52,21 +53,22 @@ end --- @param cb fun(event: down.Event, content: table|any) The function to call whenever our event gets triggered. --- @param filt? fun(event: down.Event): boolean # A filtering function to test if a certain event meets our expectations. function Event.callback(self, cb, filt) - local ty = (self and self.type) or self + local ty = (self and self.id) or self Cb.cb[ty] = Cb.cb[ty] or {} table.insert(Cb.cb[ty], { cb, filt }) end --- @param cb? fun(event: down.Event, content: table|any) -function Event:set_callback(cb) - Cb.cb[self.type] = Cb.cb[self.type] or {} - Cb.cb[self.type]:insert(cb) +function Event.set_callback(self, cb) + Cb.cb[self.id] = Cb.cb[self.id] or {} + table.insert(Cb.cb[self.id], cb) end --- Used internally by down to call all C with an event. --- @param self down.Event function Event.handle(self) - local cbentry = Cb.cb[self.type] + log.trace("Event.handle: Handling ", self.id) + local cbentry = Cb.cb[self.id] if cbentry then for _, cb in ipairs(cbentry) do if not cb[2] or cb[2](self) then @@ -76,22 +78,31 @@ function Event.handle(self) end end ----@type fun(module: down.Mod.Mod, name: string): down.Event +function Event.load_cb(m) + for hk, ht in pairs(m.handle) do + for ck, ct in pairs(ht) do + if type(ct) == 'function' then + Event.callback(Event.define(m, ck), ct) + end + end + end +end + +---@type fun(module: down.Mod.Mod, name: string, body?: any): down.Event ---@return down.Event -Event.define = function(module, name) - local mn = "" +Event.define = function(module, name, body) + local mn = '' if type(module) == 'table' then - mn = module.name + mn = module.id elseif type(module) == 'string' then mn = module end - local type = mn .. '.events.' .. name + local id = mn .. '.events.' .. name return { ---@type down.Event - topic = type, - type = type, + id = id, ref = mn, - split = Event.split_type(type) or {}, - body = module, + split = Event.split_id(id) or {}, + body = body or module, broadcast = true, position = vim.api.nvim_win_get_cursor(0), file = vim.fn.expand('%:p'), @@ -104,51 +115,49 @@ Event.define = function(module, name) } end ---- @param type string The full path of a init event +--- @param id string The full path of a init event --- @return string[]? -function Event.split_type(type) - local start_str, end_str = type:find('%.events%.') - local split_event_type = { type:sub(0, start_str - 1), type:sub(end_str + 1) } - if #split_event_type ~= 2 then - log.warn('Invalid type name:' .. type) +function Event.split_id(id) + local sa, sb = id:find('%.events%.') + local sp_id = { id:sub(0, sa - 1), id:sub(sb + 1) } + if #sp_id ~= 2 then + log.warn('Invalid type name:' .. id) return end - return split_event_type + return sp_id end --- Returns an event template defined in `init.events`. --- @param m down.Mod.Mod A reference to the init invoking the function ---- @param type string A full path to a valid event type (e.g. `init.events.some_event`) +--- @param id string A full path to a valid event type (e.g. `init.events.some_event`) --- @return down.Event? -function Event.get_template(m, type) - local split = Event.split_type(type) +function Event.get_event(m, id) + local split = Event.split_id(id) if not split then - log.warn('Unable to get event template for event' .. type .. 'and init' .. m.name) + log.warn('Unable to get event template for event' .. id .. 'and init' .. m.id) return end - log.trace('Returning' .. split[2] .. 'for init' .. split[1]) return m.events[split[2]] end --- Returns a copy of the event template provided by a init. --- @param m down.Mod.Mod A reference to the init invoking the function ---- @param type string A full path to a valid .vent type (e.g. `init.events.some_event`) +--- @param id string A full path to a valid .vent type (e.g. `init.events.some_event`) --- @param body table|any? The body of the event, can be anything from a string to a table to whatever you please. --- @param ev? table The original event data. --- @return down.Event? # New event. -function Event.new(m, type, body, ev) - local split = Event.split_type(type) - local event_template = Event.get_template(m or { name = '' }, type) +function Event.new(m, id, body, ev) + local event_template = Event.get_event(m or { id = m.id }, id) if not event_template then - log.warn('Unable to create event of type' .. type .. '. Returning nil...') + log.warn('Unable to create event of type' .. id .. '. Returning nil...') return end local mn = vim.deepcopy(event_template) - mn.type = type + mn.id = id mn.body = body - mn.ref = m.name - mn.split = assert(split) + mn.ref = m.id + mn.split = assert(Event.split_id(id)) mn.file = vim.fn.expand('%:t') --[[@as string]] mn.dir = vim.fn.expand('%:p:h') --[[@as string]] mn.buf = ev and ev.buf or vim.api.nvim_get_current_buf() @@ -156,7 +165,6 @@ function Event.new(m, type, body, ev) mn.position = vim.api.nvim_win_get_cursor(mn.win) mn.mode = vim.api.nvim_get_mode() mn.line = vim.api.nvim_buf_get_lines(mn.buf, mn.position[1] - 1, mn.position[1], true)[1] - mn.ref = m.name mn.broadcast = true return mn end @@ -166,17 +174,20 @@ end --- @param self down.Event function Event.broadcast_to(self, mods) if not self.split then - log.error('Unable to broadcast event of type' .. self.type .. '- invalid event name') + log.error('Unable to broadcast event of type' .. self.id .. '- invalid event name') return end Event.handle(self) - for _, cm in pairs(mods or {}) do - if cm.subscribed and cm.subscribed[self.split[1]] then - local evt = cm.subscribed[self.split[1]][self.split[2]] - if evt ~= nil and evt == true then - cm.handle(self) + for mid, cm in pairs(mods or {}) do + if cm.handle and cm.handle[self.split[1]] then + local evt = cm.handle[self.split[1]][self.split[2]] + if evt == nil or type(evt) == 'nil' then + goto broadcastcontinue + elseif type(evt) == 'function' then + evt(self) end end + ::broadcastcontinue:: end end @@ -186,10 +197,10 @@ end function Event.send(self, recv) self.broadcast = false Event.handle(self) - if recv.subscribed and recv.subscribed[self.split[1]] then - local evt = recv.subscribed[self.split[1]][self.split[2]] - if evt ~= nil and evt == true then - recv.handle(self) + if recv.handle and recv.handle[self.split[1]] then + local evt = recv.handle[self.split[1]][self.split[2]] + if evt ~= nil and type(evt) == 'function' then + evt(self) end end end diff --git a/lua/down/mod.lua b/lua/down/mod.lua index ecaca92..303071f 100644 --- a/lua/down/mod.lua +++ b/lua/down/mod.lua @@ -19,7 +19,7 @@ local Mod = { loaded = true, replaces = {}, merge = false, - requires = {}, + dependencies = {}, } end, load = function() @@ -31,34 +31,63 @@ local Mod = { opts = {}, maps = {}, commands = {}, - handle = function(e) - -- print('load' .. e) - end, - name = '', - namespace = '', + handle = {}, + id = '', + namespace = vim.api.nvim_create_namespace('down.mod'), data = {}, config = {}, events = {}, - subscribed = {}, - required = {}, + dep = {}, import = {}, tests = {}, } ----@type metatable Mod.data.metatable = { - __index = function(self, k) - return self.required[k] - end, - __newindex = function(self, k, v) - self.data[k] = v - end, - __eq = function(m1, m2) - return m1.name == m2.name - end, - __call = function(self, fun, ...) - return self.data[fun](...) - end, + ---@type metatable + handle = { + __index = function(self, k) + if type(k) == 'table' then + if k.split then + return self[k.split[1]][k.split[2]] + end + return self[k[1]][k[2]] + elseif type(k) == 'string' then + local ks = string.split(k, '%.') + if #ks == 1 then + return self[ks[1]] + end + return self[ks[1]][ks[2]] + end + return self[k] + end, + __newindex = function(self, k, v) + self[k] = v + end, + __call = function(self, e, ...) + if e then + if self[e] and type(self[e]) == 'function' then + return self[e](e) + end + return self[e](e) + end + return self(e) + end, + }, + ---@type metatable + mod = { + __index = function(self, k) + return self.dep[k] + end, + __newindex = function(self, k, v) + self.data[k] = v + end, + __eq = function(m1, m2) + return m1.id == m2.id + end, + __call = function(self, fun, ...) + return self.data[fun](...) + end, + }, } Mod.mods = {} @@ -78,7 +107,7 @@ Mod.default = { loaded = true, replaces = {}, merge = false, - requires = {}, + dependencies = {}, } end, ---@return down.Mod @@ -95,16 +124,14 @@ Mod.default = { end, opts = {}, maps = {}, - handle = function(e) - -- print('load' .. e) - end, - name = n, + -- handle = setmetatable({}, Mod.data.metatable.handle), + handle = {}, + id = n, namespace = vim.api.nvim_create_namespace('down.mod.' .. n), data = {}, config = {}, events = {}, - subscribed = {}, - required = {}, + dep = {}, import = {}, tests = {}, }, Mod.data.metatable) @@ -135,11 +162,11 @@ Mod.delete = function(mod) return nil end ---- @param m down.Mod.Mod The actual init to load. ---- @return down.Mod|nil # Whether the init successfully loaded. +--- @param m down.Mod.Mod The actual mod to load. +--- @return down.Mod|nil # Whether the mod successfully loaded. Mod.load_mod_from_table = function(m, cfg) - if Mod.mods[m.name] ~= nil then - return Mod.mods[m.name] + if Mod.mods[m.id] ~= nil then + return Mod.mods[m.id] end local mod_load = m.setup and m.setup() or Mod.default.setup() ---@type down.Mod @@ -147,23 +174,21 @@ Mod.load_mod_from_table = function(m, cfg) if mod_load.replaces and mod_load.replaces ~= '' then mod_to_replace = vim.deepcopy(Mod.mods[mod_load.replaces]) end - Mod.mods[m.name] = m - if mod_load.requires and vim.tbl_count(mod_load.requires) then - for _, req in pairs(mod_load.requires) do + Mod.mods[m.id] = m + if mod_load.dependencies and vim.tbl_count(mod_load.dependencies) then + for _, req in pairs(mod_load.dependencies) do if not Mod.is_loaded(req) then if not Mod.load_mod(req) then - return Mod.delete(m.name) + return Mod.delete(m.id) end - else - log.trace('already loaded ' .. m.name) end - m.required[req] = Mod.mods[req].data + m.dep[req] = Mod.mods[req].data end end if mod_to_replace then - m.name = mod_to_replace.name + m.id = mod_to_replace.id if mod_to_replace.replaced then - return Mod.delete(m.name) + return Mod.delete(m.id) end if mod_load.merge then m = vim.tbl_deep_extend('force', m, mod_to_replace) @@ -171,7 +196,7 @@ Mod.load_mod_from_table = function(m, cfg) m.replaced = true end Mod.mod_load(m) - return Mod.mods[m.name] + return Mod.mods[m.id] end --- @param modn string @@ -189,9 +214,9 @@ function Mod.check_mod(modn) return modl end ---- @param modn string A path to a init on disk. A path in down is '.', not '/'. ---- @param cfg table? A config that reflects the structure of `down.config.user.setup["init.name"].config`. ---- @return down.Mod|nil # Whether the init was successfully loaded. +--- @param modn string A path to a mod on disk. A path in down is '.', not '/'. +--- @param cfg table? A config that reflects the structure of `down.config.user.setup["mod.id"].config`. +--- @return down.Mod|nil # Whether the mod was successfully loaded. function Mod.load_mod(modn, cfg) if Mod.mods[modn] then if cfg ~= nil then @@ -209,54 +234,54 @@ function Mod.load_mod(modn, cfg) return Mod.load_mod_from_table(modl) end ---- Has the same principle of operation as load_mod_from_table(), except it then sets up the parent init's "required" table, allowing the parent to access the child as if it were a dependency. +--- Has the same principle of operation as load_mod_from_table(), except it then sets up the parent mod's "dep" table, allowing the parent to access the child as if it were a dependency. --- @param md down.Mod A valid table as returned by mod.new() ---- @param parent_mod string|down.Mod If a string, then the parent is searched for in the loaded mod. If a table, then the init is treated as a valid init as returned by mod.new() +--- @param parent_mod string|down.Mod If a string, then the parent is searched for in the loaded mod. If a table, then the mod is treated as a valid mod as returned by mod.new() function Mod.load_mod_as_dependency_from_table(md, parent_mod) if Mod.load_mod_from_table(md) then if type(parent_mod) == 'string' then - Mod.mods[parent_mod].required[md.name] = md.data + Mod.mods[parent_mod].dep[md.id] = md.data elseif type(parent_mod) == 'table' then - parent_mod.required[md.name] = md.data + parent_mod.dep[md.id] = md.data end end end ---- Normally loads a init, but then sets up the parent init's "required" table, allowing the parent init to access the child as if it were a dependency. ---- @param modn string A path to a init on disk. A path in down is '.', not '/' ---- @param parent_mod string The name of the parent init. This is the init which the dependency will be attached to. ---- @param cfg? table A config that reflects the structure of down.config.user.setup["init.name"].config +--- Normally loads a mod, but then sets up the parent mod's "dep" table, allowing the parent mod to access the child as if it were a dependency. +--- @param modn string A path to a mod on disk. A path in down is '.', not '/' +--- @param parent_mod string The name of the parent mod. This is the mod which the dependency will be attached to. +--- @param cfg? table A config that reflects the structure of down.config.user.setup["mod.id"].config function Mod.load_mod_as_dependency(modn, parent_mod, cfg) if Mod.load_mod(modn, cfg) and Mod.is_loaded(parent_mod) then - Mod.mods[parent_mod].required[modn] = Mod.mod_config(modn) + Mod.mods[parent_mod].dep[modn] = Mod.mod_config(modn) end end ---- Returns the init.config table if the init is loaded ---- @param modn string The name of the init to retrieve (init must be loaded) +--- Returns the mod.config table if the mod is loaded +--- @param modn string The name of the mod to retrieve (mod must be loaded) --- @return table? function Mod.mod_config(modn) if not Mod.is_loaded(modn) then - log.trace('Attempt to get init config with name' .. modn .. 'failed - init is not loaded.') + log.trace('Attempt to get mod config with name' .. modn .. 'failed - mod is not loaded.') return end return Mod.mods[modn].config end ---- Retrieves the public API exposed by the init. +--- Retrieves the public API exposed by the mod. --- @generic T ---- @param modn `T` The name of the init to retrieve. +--- @param modn `T` The name of the mod to retrieve. --- @return T? function Mod.get_mod(modn) if not Mod.is_loaded(modn) then - log.trace('Attempt to get init with name' .. modn .. 'failed - init is not loaded.') + log.trace('Attempt to get mod with name' .. modn .. 'failed - mod is not loaded.') return end return Mod.mods[modn].data end ---- Returns true if init with name modn is loaded, false otherwise ---- @param modn string The name of an arbitrary init +--- Returns true if mod with name modn is loaded, false otherwise +--- @param modn string The name of an arbitrary mod --- @return down.Mod|nil function Mod.is_loaded(modn) if Mod.mods[modn] ~= nil then @@ -265,8 +290,8 @@ function Mod.is_loaded(modn) return nil end ---- Executes `callback` once `init` is a valid and loaded init, else the callback gets instantly executed. ---- @param modn string The name of the init to listen for. +--- Executes `callback` once `mod` is a valid and loaded mod, else the callback gets instantly executed. +--- @param modn string The name of the mod to listen for. --- @param callback fun(mod_public_table: table) function Mod.await(modn, cb) if Mod.is_loaded(modn) then @@ -277,14 +302,15 @@ function Mod.await(modn, cb) Event.callback('mod_loaded', function(_, m) cb(m.data) end, function(event) - return event.body.name == modn + return event.body.id == modn end) end ---@param m down.Mod function Mod.load_opts(m) if m.opts then - for i, k in ipairs(m.opts) do + for i, k in pairs(m.opts) do + vim.bo[i] = k end end end @@ -311,6 +337,7 @@ end function Mod.mod_load(m) Mod.load_maps(m) Mod.load_opts(m) + Event.load_cb(m) if m.load then m.load() end @@ -321,7 +348,7 @@ Mod.get = function(m) if ok then return pc else - log.error('U.load_mod: could not load mod ' .. 'down.mod.' .. m) + log.error('Mod.get: could not load mod ' .. 'down.mod.' .. m) return nil end end @@ -337,59 +364,119 @@ end ---@param m down.Mod Mod.test = function(m) + log.info("Mod.test: Performing tests for ", m.id, ": ") if m.tests then for tn, test in m.tests do - log.info('Running test ', tn, ' for ', m.name, ':') - test(m) + log.info('Mod.test: Running test ', tn, ' for ', m.id, ': ', test(m)) end end end -Mod.handle_event = function(e) - for m, mod in pairs(Mod.mods) do - if mod.subscribed[e.type] then - mod.subscribed[e.type]() +---@param cmds down.Commands +---@return boolean +Mod.handle_cmd = function(self, e, cmd, cmds, ...) + log.trace("Mod.handle_cmd: Handling cmd ", cmd, " for mod ", self.id) + if not cmds or type(cmds) ~= 'table' or not cmds[cmd] then + return false + end + local cc = cmds[cmd] + if cc.name and cc.name == cmd and cc.callback then + if not self.handle then + self.handle = {} end + if not self.handle['cmd'] then + self.handle['cmd'] = {} + end + if not self.handle['cmd'][cmd] then + self.handle['cmd'][cmd] = cc.callback + end + cc.callback(e) + return true + elseif cc.subcommands then + return Mod.handle_cmd(self, e, cmd, cc.subcommands, ...) end + return false +end + +--- @param e down.Event +--- @param self down.Mod +--- @param ... any +--- @return boolean +Mod.handle_event = function(self, e, ...) + log.trace("Mod.handle_event: Handling event ", e.id, " for mod ", self.id) + if self.handle and self.handle[e.split[1]] and self.handle[e.split[1]][e.split[2]] then + self.handle[e.split[1]][e.split[2]](e) + return true + elseif e.split[1] == 'cmd' then + return Mod.handle_cmd(self, e, e.split[2], self.commands, ...) + end + return false end --- @param m down.Mod.Mod ---- @param name string +--- @param id string --- @param body table --- @param ev? table --- @return down.Event? -function Mod.new_event(m, type, body, ev) - return Event.new(m, type, body, ev) +function Mod.new_event(m, id, body, ev) + return Event.new(m, id, body, ev) end ----@type fun(module: down.Mod.Mod, name: string): down.Event +---@type fun(module: down.Mod.Mod, id: string): down.Event ---@return down.Event -function Mod.define_event(module, name) - return Event.define(module, name) +function Mod.define_event(module, nid) + return Event.define(module, nid) end +---@param e down.Event function Mod.broadcast(e) - Event.broadcast_to(e, Mod.mods) + Event.handle(e) + log.trace("Mod.broadcast: Broadcasting event", e.id) + for mn, m in pairs(Mod.mods) do + if Mod.handle_event(m, e) then + log.trace('Mod.broadcast: Broadcast success: ', e.id, ' to mod ', mn) + end + end end -return setmetatable(Mod, { - ---@param self down.mod.base.Base - ---@param modname string - __call = function(self, modname, ...) - return self.new(modname, ...) - end, - -- --- @param self down.mod.base.Base - -- --- @param modname string A path to a init on disk. A path in down is '.', not '/'. - -- --- @param modcfg table? A config that reflects the structure of `down.config.user.setup["init.name"].config`. - -- --- @return boolean # Whether the init was successfully loaded. - -- __index = function(self, modname) - -- return self.load_mod(modname) - -- end, - -- --- @param self down.Mod - -- --- @param modn string A path to a init on disk. A path in down is '.', not '/'. - -- --- @param cfg table? A config that reflects the structure of `down.config.user.setup["init.name"].config`. - -- --- @return boolean # Whether the init was successfully loaded. - -- __newindex = function(self, modn, value) - -- return self.load_mod(modn, value) - -- end, -}) +--- Returns an event template defined in `mod.events`. +--- @param m down.Mod.Mod A reference to the mod invoking the function +--- @param id string A full path to a valid event type (e.g. `mod.events.some_event`) +--- @return down.Event? +function Mod.get_event(self, id) + local split = Event.split_id(id) + if not split then + log.warn('Unable to get event template for event' .. tid .. 'and mod' .. self.id) + return + end + log.trace('Returning' .. split[2] .. 'for mod' .. split[1]) + return self.events[split[2]] +end + +return Mod +-- ---@param self down.mod.base.Base +-- ---@param modname string +-- __call = function(self, modname, sub) +-- return self.new(modname, sub or {}) +-- end, +-- __index = function(self, k) +-- return self.mods[k] +-- end, +-- __newindex = function(self, k, v) +-- self.mods[k] = v +-- end, +-- --- @param self down.mod.base.Base +-- --- @param modname string A path to a mod on disk. A path in down is '.', not '/'. +-- --- @param modcfg table? A config that reflects the structure of `down.config.user.setup["mod.id"].config`. +-- --- @return boolean # Whether the mod was successfully loaded. +-- __index = function(self, modname) +-- return self.load_mod(modname) +-- end, +-- --- @param self down.Mod +-- --- @param modn string A path to a mod on disk. A path in down is '.', not '/'. +-- --- @param cfg table? A config that reflects the structure of `down.config.user.setup["mod.id"].config`. +-- --- @return boolean # Whether the mod was successfully loaded. +-- __newindex = function(self, modn, value) +-- return self.load_mod(modn, value) +-- end, +-- }) diff --git a/lua/down/mod/cmd/init.lua b/lua/down/mod/cmd/init.lua index b58eb27..5cb3eea 100644 --- a/lua/down/mod/cmd/init.lua +++ b/lua/down/mod/cmd/init.lua @@ -6,25 +6,11 @@ local mod = require 'down.mod' local lib = require 'down.util.lib' local util = require 'down.util' ---- @class (exact) down.Command ---- @field name? string ---- @field args? number ---- @field max_args? number ---- @field condition? string ---- @field complete? table ---- @field callback? fun(any) ---- @field min_args? number ---- @field subcommands? down.Commands - ---- @class (exact) down.Commands: { ---- [string]?: down.Command ---- } ---- ---@class down.mod.Cmd: down.Mod -local M = mod.new('cmd') +local M = mod.new 'cmd' M.setup = function() - return { loaded = true, requires = {} } + return { loaded = true, dependencies = {} } end M.commands = {} @@ -34,8 +20,10 @@ M.data = { --- Handles the calling of the appropriate function based on the command the user entered cb = function(data) + -- vim.print(data) local args = data.fargs + local current_buf = vim.api.nvim_get_current_buf() local is_down = vim.bo[current_buf].filetype == 'markdown' @@ -76,7 +64,8 @@ M.data = { return elseif not check_condition(ref.condition) then log.error( - ('Error when executing `:Down %s` - the command is currently disabled. Some commands will only become available under certain conditions, e.g. being within a `.down` file!'):format( + ('Error when executing `:Down %s` - the command is currently disabled. Some commands will only become available under certain conditions, e.g. being within a `.down` file!') + :format( table.concat(vim.list_slice(args, 1, i), ' ') ) ) @@ -99,7 +88,7 @@ M.data = { end if #args == 0 or argument_count < ref.min_args then - local completions = M.data.generate_completions(_, table.concat({ 'Down ', data.args, ' ' })) + local completions = M.data.generate_completions(_, table.concat { 'Down ', data.args, ' ' }) M.data.select_next_cmd_arg(data.args, completions) return elseif argument_count > ref.max_args then @@ -115,26 +104,34 @@ M.data = { if not ref.name then log.error( - ("Error when executing `:down %s` - the ending command didn't have a `name` variable associated with it! This is an implementation error on the developer's side, so file a report to the author of the mod."):format( + ("Error when executing `:down %s` - the ending command didn't have a `name` variable associated with it! This is an implementation error on the developer's side, so file a report to the author of the mod.") + :format( data.args ) ) return end - if not M.events[ref.name] then M.events[ref.name] = mod.define_event(M, ref.name) + if ref.callback then + if not M.handle then M.handle = {} end + if not M.handle['cmd'] then M.handle['cmd'] = {} end + M.handle['cmd'][ref.name] = ref.callback + end end - mod.broadcast( - assert( - mod.new_event( - M, - table.concat({ 'cmd.events.', ref.name }), - vim.list_slice(args, argument_index + 1) - ) - ) + local e = mod.new_event( + M, + table.concat { 'cmd.events.', ref.name }, + vim.list_slice(args, argument_index + 1) ) + if ref.callback then + log.trace("Cmd.data.cb: Running ", ref.name, " callback") + ref.callback(e) + else + log.trace("Cmd.data.cb: Running ", ref.name, " broadcast") + mod.broadcast(e) + end end, check_condition = function(condition, buf, is_down) @@ -143,15 +140,12 @@ M.data = { if condition == nil then return true end - if condition == 'markdown' and not is_down then return false end - if type(condition) == 'function' then return condition(buf, is_down) end - return condition end, } @@ -221,13 +215,12 @@ M.data.generate_completions = function(_, command) -- TODO: Fix `:down m ` giving invalid completions local keys = ref and vim.tbl_keys(ref.subcommands or {}) - or ( - vim.tbl_filter(function(key) - return key:find(splitcmd[#splitcmd]) - end, vim.tbl_keys(last_valid_ref.subcommands or {})) - ) + or ( + vim.tbl_filter(function(key) + return key:find(splitcmd[#splitcmd]) + end, vim.tbl_keys(last_valid_ref.subcommands or {})) + ) table.sort(keys) - do local subcommands = (ref and ref.subcommands or last_valid_ref.subcommands) or {} @@ -241,7 +234,7 @@ end ---@param qargs table #A string of arguments previously supplied to the down command ---@param choices table #all possible choices for the next argument M.data.select_next_cmd_arg = function(qargs, choices) - local current = table.concat({ 'Down ', qargs }) + local current = table.concat { 'Down ', qargs } local query @@ -259,7 +252,7 @@ M.data.select_next_cmd_arg = function(qargs, choices) prompt = current, }, function(choice) if choice ~= nil then - vim.cmd(string.format('%s %s', current, choice)) + vim.cmd(('%s %s'):format(current, choice)) end end) end @@ -293,34 +286,30 @@ M.data.add_commands_from_file = function(name) if not err then log.warn( 'Could not load command' - .. name - .. 'for init base.cmd - the corresponding mod.lua file does not exist.' + .. name + .. 'for init base.cmd - the corresponding mod.lua file does not exist.' ) return end - - -- Load the init from table mod.load_mod_from_table(ret) end --- Rereads data from all mod and rebuild the list of available autocompletiinitinitons and commands M.data.sync = function() - -- Loop through every loaded init and set up all their commands for _, lm in pairs(mod.mods) do - if lm.data.commands then - M.data.add_commands_from_table(lm.data.commands) + if lm.commands then + M.data.add_commands_from_table(lm.commands) end end end --- Defines a custom completion function to use for `base.cmd`. ----@param callback function The same function format as you would receive by being called by `:command -completion=customlist,v:lua.callback down`. +---@param callback function M.data.set_completion = function(callback) M.data.generate_completions = callback end M.load = function() - -- If the user passes no arguments or too few, we'll query them for the remainder using select_next_cmd_arg. vim.api.nvim_create_user_command('Down', M.data.cb, { desc = 'The down command', range = 2, @@ -329,8 +318,6 @@ M.load = function() nargs = '*', complete = M.data.generate_completions, }) - - -- Loop through all the command mod we want to load and load them for _, command in ipairs(M.config.load) do if command == 'default' then for _, basecmd in ipairs(M.config.base) do @@ -342,8 +329,6 @@ end ---@class down.mod.cmd.Config M.config = { - -- A list of cmd mod to load automatically. - -- This feature will soon be deprecated, so it is not recommended to touch it. load = { 'default', }, diff --git a/lua/down/mod/cmd/mod/init.lua b/lua/down/mod/cmd/mod/init.lua index 2d2d810..20af8f5 100644 --- a/lua/down/mod/cmd/mod/init.lua +++ b/lua/down/mod/cmd/mod/init.lua @@ -1,9 +1,9 @@ -local down = require('down') -local map = require('down.util.maps') +local map = require 'down.util.maps' local mod = require 'down.mod' +local log = require 'down.util.log' ---@class down.mod.cmd.Mod: down.Mod -local M = mod.new('cmd.mod') +local M = mod.new 'cmd.mod' ---@class down.mod.cmd.mod.Data M.data = { @@ -14,102 +14,86 @@ M.commands = { mod = { name = 'mod', args = 1, + callback = function(e) + log.trace 'Mod.commands.mod: Callback' + end, subcommands = { new = { args = 1, name = 'mod.new', + callback = function() + log.trace 'Mod.commands.new: Callback' + end }, load = { name = 'mod.load', args = 1, + callback = function(e) + local ok = pcall(mod.load_mod, e.body[1]) + if not ok then + vim.notify(('mod `%s` does not exist!'):format(e.body[1]), vim.log.levels.ERROR, {}) + end + vim.print(ok) + end, }, unload = { name = 'mod.unload', args = 1, + callback = function(e) + log.trace "Mod.commands.unload: Callback" + end }, list = { args = 0, name = 'mod.list', + callback = function(e) + local mods_popup = require 'nui.popup' { + position = '50%', + size = { width = '50%', height = '80%' }, + enter = true, + buf_options = { + filetype = 'markdown', + modifiable = true, + readonly = false, + }, + win_options = { + conceallevel = 3, + concealcursor = 'nvic', + }, + } + mods_popup:on('VimResized', function() + mods_popup:update_layout() + end) + + local function close() + mods_popup:unmount() + end + + mods_popup:map('n', '', close, {}) + mods_popup:map('n', 'q', close, {}) + local lines = {} + table.insert(lines, '# Mods loaded') + table.insert(lines, ''); table.insert(lines, '') + table.insert(lines, '## Mods:') + table.insert(lines, ''); table.insert(lines, '') + for name, _ in pairs(mod.mods) do + table.insert(lines, '1. `' .. name .. '`') + end + vim.api.nvim_buf_set_lines(mods_popup.bufnr, 0, -1, true, lines) + vim.bo[mods_popup.bufnr].modifiable = false + mods_popup:mount() + end }, }, }, } M.maps = { - { 'n', ',dml', 'Down mod list', 'List mods' }, - { 'n', ',dmL', 'Down mod load', 'Load mod' }, + { 'n', ',dml', 'Down mod list', 'List mods' }, + { 'n', ',dmL', 'Down mod load', 'Load mod' }, { 'n', ',dmu', 'Down mod unload', 'Unload mod' }, } M.setup = function() - return { loaded = true, requires = { 'cmd' } } + return { loaded = true, dependencies = { 'cmd' } } end ----@type down.mod.Handler -M.handle = function(event) - if event.type == 'cmd.events.mod.setup' then - local ok = pcall(mod.load_mod, event.body[1]) - - if not ok then - vim.notify( - string.format('init `%s` does not exist!', event.body[1]), - vim.log.levels.ERROR, - {} - ) - end - end - - if event.type == 'cmd.events.mod.unload' then - end - - if event.type == 'cmd.events.mod.list' then - local Popup = require('nui.popup') - - local mods_popup = Popup({ - position = '50%', - size = { width = '50%', height = '80%' }, - enter = true, - buf_options = { - filetype = 'markdown', - modifiable = true, - readonly = false, - }, - win_options = { - conceallevel = 3, - concealcursor = 'nvic', - }, - }) - - mods_popup:on('VimResized', function() - mods_popup:update_layout() - end) - local function close() - mods_popup:unmount() - end - - mods_popup:map('n', '', close, {}) - mods_popup:map('n', 'q', close, {}) - - local lines = {} - - for name, _ in pairs(mod.mods) do - table.insert(lines, '1. `' .. name .. '`') - end - - vim.api.nvim_buf_set_lines(mods_popup.bufnr, 0, -1, true, lines) - - vim.bo[mods_popup.bufnr].modifiable = false - - mods_popup:mount() - end -end ----@class down.mod.cmd.mod.Subscribed: down.mod.Subscribed -M.subscribed = { - cmd = { - ['mod'] = true, - ['mod.new'] = true, - ['mod.setup'] = true, - ['mod.list'] = true, - ['mod.load'] = true, - ['mod.unload'] = true, - }, -} return M diff --git a/lua/down/mod/code/init.lua b/lua/down/mod/code/init.lua index dd0b48a..3e60563 100644 --- a/lua/down/mod/code/init.lua +++ b/lua/down/mod/code/init.lua @@ -1,4 +1,5 @@ -local mod = require('down.mod') +local mod = require 'down.mod' +local log = require 'down.util.log' --- @class down.mod.Code: down.Mod local Code = mod.new('code', { 'snippet', 'run' }) @@ -21,17 +22,32 @@ Code.commands = { name = "code", condition = "markdown", args = 1, + callback = function(e) + log.trace(('Code.commands.code callback: %s'):format(e.body)) + end, subcommands = { edit = { args = 0, + condition = 'markdown', + callback = function(e) + log.trace(('Code.commands.edit cb: %s'):format(e.body)) + end, name = "code.edit", }, run = { args = 0, + condition = 'markdown', + callback = function(e) + log.trace(('Code.commands.run cb: %s'):format(e.body)) + end, name = "code.run", }, save = { args = 0, + condition = 'markdown', + callback = function(e) + log.trace(('Code.commands.save cb: %s'):format(e.body)) + end, name = "code.save", } } @@ -44,8 +60,9 @@ end Code.setup = function() return { loaded = true, - requires = { + dependencies = { 'cmd', + 'data', 'workspace', }, } diff --git a/lua/down/mod/code/snippet/init.lua b/lua/down/mod/code/snippet/init.lua index fc86b1e..4a159b4 100644 --- a/lua/down/mod/code/snippet/init.lua +++ b/lua/down/mod/code/snippet/init.lua @@ -21,7 +21,7 @@ M.setup = function() -- end) return { loaded = true, - requires = { "workspace", "cmd" }, + dependencies = { "workspace", "cmd" }, } end diff --git a/lua/down/mod/data/bookmark/init.lua b/lua/down/mod/data/bookmark/init.lua index 7b79b4c..dc8f187 100644 --- a/lua/down/mod/data/bookmark/init.lua +++ b/lua/down/mod/data/bookmark/init.lua @@ -3,62 +3,66 @@ local B = {} ---@class down.mod.data.bookmark.Config B.config = { - workspace = "default", + workspace = 'default', - file = "bookmark", + file = 'bookmark', } ---@class down.mod.data.bookmark.Data B.data = { bookmarks = { - default = { - - } - } + default = {}, + }, } ---@return down.mod.Setup B.setup = function() return { loaded = true, - requires = { + dependencies = { 'data', 'workspace', 'cmd', - } + }, } end -B.load = function() - B.required["cmd"].add_commands_from_table({ - bookmark = { - args = 1, - name = "bookmark", - subcommands = { - list = { - name = "bookmark.list", - args = 1, - }, - add = { - name = "bookmark.add", - args = 1, - }, - remove = { - name = "bookmark.remove", - args = 1, - }, - } - } - }) -end +B.commands = { + bookmark = { + args = 1, + name = 'bookmark', + callback = function(e) end, + subcommands = { + list = { + name = 'bookmark.list', + args = 1, + callback = function(e) end, + }, + add = { + name = 'bookmark.add', + args = 1, + callback = function(e) end, + }, + remove = { + name = 'bookmark.remove', + args = 1, + callback = function(e) end, + }, + }, + }, +} -B.handle = function(e) - local es = e.split - if es[2] == "bookmark" then - print("es2") - elseif es[2] == "bookmark.list" then - print('es2 list') - end -end +B.load = function() end + +-- B.handle = { +-- cmd = { +-- bookmark = { +-- __call = B.commands.bookmark.callback, +-- list = B.commands.bookmark.subcommands.list.callback, +-- remove = B.commands.bookmark.subcommands.remove.callback, +-- add = B.commands.bookmark.subcommands.add.callback, +-- }, +-- }, +-- } return B diff --git a/lua/down/mod/data/date/init.lua b/lua/down/mod/data/date/init.lua index c574a1d..3e8feb8 100644 --- a/lua/down/mod/data/date/init.lua +++ b/lua/down/mod/data/date/init.lua @@ -143,7 +143,7 @@ M.config = { M.setup = function() ---@type down.mod.Setup return { - requires = { + dependencies = { }, loaded = true, diff --git a/lua/down/mod/data/encrypt/init.lua b/lua/down/mod/data/encrypt/init.lua index ab0fdb4..ce67c35 100644 --- a/lua/down/mod/data/encrypt/init.lua +++ b/lua/down/mod/data/encrypt/init.lua @@ -20,7 +20,7 @@ E.commands = { E.setup = function() return { loaded = true, - requires = { + dependencies = { 'tool.treesitter', 'cmd', 'workspace', @@ -36,11 +36,11 @@ E.data = {} E.handle = function(e) end -E.subscribed = { +E.handle = { cmd = { - ['data.encrypt'] = true, - ['data.encrypt.insert'] = true, - ['data.encrypt.update'] = true, + ['data.encrypt'] = function(e) end, + ['data.encrypt.insert'] = function(e) end, + ['data.encrypt.update'] = function(e) end, }, } diff --git a/lua/down/mod/data/export/init.lua b/lua/down/mod/data/export/init.lua index f78c247..e640c9a 100644 --- a/lua/down/mod/data/export/init.lua +++ b/lua/down/mod/data/export/init.lua @@ -20,7 +20,7 @@ E.commands = { E.setup = function() return { loaded = true, - requires = { + dependencies = { 'tool.treesitter', 'cmd', 'workspace', @@ -36,10 +36,10 @@ E.data = {} E.handle = function(e) end -E.subscribed = { +E.handle = { cmd = { - ['data.export.insert'] = true, - ['data.export.update'] = true, + ['data.export.insert'] = function(e) end, + ['data.export.update'] = function(e) end, }, } diff --git a/lua/down/mod/data/history/init.lua b/lua/down/mod/data/history/init.lua index 569b852..889cdfb 100644 --- a/lua/down/mod/data/history/init.lua +++ b/lua/down/mod/data/history/init.lua @@ -93,38 +93,40 @@ M.config = { M.setup = function() ---@type down.mod.Setup return { - requires = {}, + dependencies = { + 'cmd', + }, loaded = true, } end M.handle = function(event) - if event.type == 'cmd.events.data.history.back' then + if event.id == 'cmd.events.data.history.back' then -- Get all the buffers - local buffers = vim.api.nvim_list_bufs() - - local to_delete = {} - for buffer in vim.iter(buffers):rev() do - if vim.fn.buflisted(buffer) == 1 then - -- If the listed buffer we're working with has a .down extension then remove it (not forcibly) - if not vim.endswith(vim.api.nvim_buf_get_name(buffer), '.md') then - vim.api.nvim_win_set_buf(0, buffer) - break - else - table.insert(to_delete, buffer) - end - end - end - - for _, buffer in ipairs(to_delete) do - vim.api.nvim_buf_delete(buffer, {}) - end end end -M.subscribed = { +M.handle = { cmd = { - ['data.history.back'] = true, + ['data.history.back'] = function(e) + local buffers = vim.api.nvim_list_bufs() + + local to_delete = {} + for buffer in vim.iter(buffers):rev() do + if vim.fn.buflisted(buffer) == 1 then + if not vim.endswith(vim.api.nvim_buf_get_name(buffer), '.md') then + vim.api.nvim_win_set_buf(0, buffer) + break + else + table.insert(to_delete, buffer) + end + end + end + + for _, buffer in ipairs(to_delete) do + vim.api.nvim_buf_delete(buffer, {}) + end + end, }, } diff --git a/lua/down/mod/data/init.lua b/lua/down/mod/data/init.lua index 23616d3..afed04b 100644 --- a/lua/down/mod/data/init.lua +++ b/lua/down/mod/data/init.lua @@ -1,12 +1,17 @@ -local mod = require('down.mod') -local config = require('down.config') +local mod = require 'down.mod' +local log = require 'down.util.log' +local config = require 'down.config' ---@class down.mod.Data: down.Mod -local M = mod.new('data', {}) +local M = mod.new 'data' ----@type down.Store -M.data.files = { - store = {}, +---@class down.mod.data.Data +M.data = { + data = {}, + ---@type down.Store + file = { + store = {}, + }, } --- @return down.mod.Setup @@ -20,7 +25,7 @@ M.setup = function() ---@type down.mod.Setup return { loaded = true, - requires = {}, + dependencies = {}, } end @@ -28,20 +33,16 @@ M.load = function() end ---@class down.mod.data.Config M.config = { - path = vim.fn.stdpath('data') .. '/down.mpack', + path = vim.fn.stdpath 'data' .. '/down.mpack', dir = { - vim = vim.fs.joinpath(vim.fn.stdpath('data'), 'down/'), - home = vim.fs.joinpath(os.getenv('HOME') or '~/', '.down/'), + vim = vim.fs.joinpath(vim.fn.stdpath 'data', 'down/'), + home = vim.fs.joinpath(os.getenv 'HOME' or '~/', '.down/'), }, file = { - vim = vim.fs.joinpath(vim.fn.stdpath('data'), 'down/', 'down.json'), - home = vim.fs.joinpath(os.getenv('HOME') or '~/', '.down/', 'down.json'), + vim = vim.fs.joinpath(vim.fn.stdpath 'data', 'down/', 'down.json'), + home = vim.fs.joinpath(os.getenv 'HOME' or '~/', '.down/', 'down.json'), }, } ----@class down.mod.data.Data -M.data = { - data = {}, -} M.data.concat = function(p1, p2) return table.concat({ p1, config.pathsep, p2 }) @@ -54,9 +55,9 @@ M.data.files = function(path, cond) local f = {} local dir = path or vim.fs.root(vim.fn.cwd(), '.down/') for name, type in vim.fs.dir(dir) do - if type == 'file' and cond or name:endswith('.md') then + if type == 'file' and cond or name:endswith '.md' then table.insert(f, name) - elseif type == 'directory' and not name:startswith('.') then + elseif type == 'directory' and not name:startswith '.' then local fs = M.data.get_files(M.data.concat(path, name)) for _, v in ipairs(fs) do table.insert(f, v) @@ -91,7 +92,7 @@ M.data.copy_directory = function(old_path, new_path) for name, type in vim.fs.dir(old_path) do if type == 'file' then ok, err = - vim.loop.fs_copyfile(M.data.concat({ old_path, name }), M.data.concat(new_path, name)) + vim.loop.fs_copyfile(M.data.concat(old_path, name), M.data.concat(new_path, name)) if not ok then return ok, err ---@diagnostic disable-line -- TODO: type error workaround @@ -113,29 +114,28 @@ M.data.sync = function() if not file then return end - local content = file:read('*a') - io.close(file) - local c = vim.mpack.decode(content) + local content = file:read '*a' + file:close() M.data.data = vim.mpack.decode and vim.mpack.decode(content) end --- Stores a key-value pair in the store ---@param key string #The key to index in the store ---@param data any #The data to store at the specific key -M.data.store = function(key, data) +M.data.put = function(key, data) M.data.data[key] = data end --- Removes a key from store ---@param key string #The name of the key to remove -M.data.remove = function(key) +M.data.del = function(key) M.data.data[key] = nil end --- Retrieves a key from the store ---@param key string #The name of the key to index ---@return any|table #The data present at the key, or an empty table -M.data.retrieve = function(key) +M.data.get = function(key) return M.data.data[key] or {} end @@ -150,16 +150,13 @@ end --- Flushes the contents in memory to the location specified M.data.flush = function(path) local file = io.open(path or M.config.path, 'w') - if not file then return end - file:write(vim.mpack.encode and vim.mpack.encode(M.data.data) or vim.mpack.pack(M.data.data)) - - io.close(file) + file:close() end -M.subscribed = {} +-- M.handle = {} return M diff --git a/lua/down/mod/data/store/init.lua b/lua/down/mod/data/store/init.lua index 023ab8f..3087f98 100644 --- a/lua/down/mod/data/store/init.lua +++ b/lua/down/mod/data/store/init.lua @@ -6,24 +6,19 @@ local Store = mod.new('data.store') Store.setup = function() return { loaded = true, - requires = { + dependencies = { 'data', - } + }, } end --- @class down.mod.data.store.Config -Store.config = { - -} +Store.config = {} --- @class down.mod.data.store.Data -Store.data = { - -} +Store.data = {} ---@type down.mod.Handler -Store.handle = function(ev) -end +Store.handle = {} return Store diff --git a/lua/down/mod/data/time/init.lua b/lua/down/mod/data/time/init.lua index 354641d..5ac186b 100644 --- a/lua/down/mod/data/time/init.lua +++ b/lua/down/mod/data/time/init.lua @@ -1,14 +1,13 @@ -local down = require("down") -local util = require("down.util") -local mod = require("down.mod") -local lib = require("down.util.lib") -local u = require("down.mod.data.time.util") +local down = require('down') +local util = require('down.util') +local mod = require('down.mod') +local lib = require('down.util.lib') +local u = require('down.mod.data.time.util') -local M = mod.new("data.time") +local M = mod.new('data.time') -- NOTE: Maybe encapsulate whole date parser in a single PEG grammar? -local _, time_regex = - pcall(vim.re.compile, [[{%d%d?} ":" {%d%d} ("." {%d%d?})?]]) +local _, time_regex = pcall(vim.re.compile, [[{%d%d?} ":" {%d%d} ("." {%d%d?})?]]) ---@alias Date {weekday: {name: string, number: number}?, day: number?, month: {name: string, number: number}?, year: number?, timezone: string?, time: {hour: number, minute: number, second: number?}?} @@ -18,16 +17,16 @@ M.data = { return setmetatable(date_table, { __tostring = function() local function d(str) - return str and (tostring(str) .. " ") or "" + return str and (tostring(str) .. ' ') or '' end return vim.trim( - d(date_table.weekday and date_table.weekday.name) - .. d(date_table.day) - .. d(date_table.month and date_table.month.name) - .. d(date_table.year and string.format("%04d", date_table.year)) - .. d(date_table.time and tostring(date_table.time)) - .. d(date_table.timezone) + d(date_table.weekday and date_table.weekday.id) + .. d(date_table.day) + .. d(date_table.month and date_table.month.id) + .. d(date_table.year and string.format('%04d', date_table.year)) + .. d(date_table.time and tostring(date_table.time)) + .. d(date_table.timezone) ) end, }) @@ -36,8 +35,8 @@ M.data = { ---@param parsed_date Date #The date to convert ---@return osdate #A Lua date to_lua_date = function(parsed_date) - local now = os.date("*t") --[[@as osdate]] - local parsed = os.time(vim.tbl_deep_extend("force", now, { + local now = os.date('*t') --[[@as osdate]] + local parsed = os.time(vim.tbl_deep_extend('force', now, { day = parsed_date.day, month = parsed_date.month and parsed_date.month.number or nil, year = parsed_date.year, @@ -45,7 +44,7 @@ M.data = { min = parsed_date.time and parsed_date.time.minute, sec = parsed_date.time and parsed_date.time.second, }) --[[@as osdateparam]]) - return os.date("*t", parsed) --[[@as osdate]] + return os.date('*t', parsed) --[[@as osdate]] end, --- Converts a lua `osdate` to a down date. @@ -56,18 +55,12 @@ M.data = { -- TODO: Extract into a function to get weekdays (have to hot recalculate every time because the user may change locale local weekdays = {} for i = 1, 7 do - table.insert( - weekdays, - os.date("%A", os.time({ year = 2000, month = 5, day = i })):lower() - ) ---@diagnostic disable-line -- TODO: type error workaround + table.insert(weekdays, os.date('%A', os.time({ year = 2000, month = 5, day = i })):lower()) ---@diagnostic disable-line -- TODO: type error workaround end local months = {} for i = 1, 12 do - table.insert( - months, - os.date("%B", os.time({ year = 2000, month = i, day = 1 })):lower() - ) ---@diagnostic disable-line -- TODO: type error workaround + table.insert(months, os.date('%B', os.time({ year = 2000, month = i, day = 1 })):lower()) ---@diagnostic disable-line -- TODO: type error workaround end -- os.date("*t") returns wday with Sunday as 1, needs to be @@ -92,13 +85,13 @@ M.data = { }, { __tostring = function() if not include_time then - return "" + return '' end return tostring(osdate.hour) - .. ":" - .. tostring(string.format("%02d", osdate.min)) - .. (osdate.sec ~= 0 and ("." .. tostring(osdate.sec)) or "") + .. ':' + .. tostring(string.format('%02d', osdate.min)) + .. (osdate.sec ~= 0 and ('.' .. tostring(osdate.sec)) or '') end, }) or nil, }) @@ -110,31 +103,25 @@ M.data = { parse_date = function(input) local weekdays = {} for i = 1, 7 do - table.insert( - weekdays, - os.date("%A", os.time({ year = 2000, month = 5, day = i })):lower() - ) ---@diagnostic disable-line -- TODO: type error workaround + table.insert(weekdays, os.date('%A', os.time({ year = 2000, month = 5, day = i })):lower()) ---@diagnostic disable-line -- TODO: type error workaround end local months = {} for i = 1, 12 do - table.insert( - months, - os.date("%B", os.time({ year = 2000, month = i, day = 1 })):lower() - ) ---@diagnostic disable-line -- TODO: type error workaround + table.insert(months, os.date('%B', os.time({ year = 2000, month = i, day = 1 })):lower()) ---@diagnostic disable-line -- TODO: type error workaround end local output = {} - for down in vim.gsplit(input, "%s+") do + for down in vim.gsplit(input, '%s+') do if down:len() == 0 then goto continue end - if down:match("^-?%d%d%d%d+$") then + if down:match('^-?%d%d%d%d+$') then output.year = tonumber(down) - elseif down:match("^%d+%w*$") then - output.day = tonumber(down:match("%d+")) + elseif down:match('^%d+%w*$') then + output.day = tonumber(down:match('%d+')) elseif vim.list_contains(u.tz, down:upper()) then output.timezone = down:upper() else @@ -168,8 +155,8 @@ M.data = { local count = vim.tbl_count(valid_months) if count > 1 then - return "Ambiguous month name! Possible interpretations: " - .. table.concat(vim.tbl_keys(valid_months), ",") + return 'Ambiguous month name! Possible interpretations: ' + .. table.concat(vim.tbl_keys(valid_months), ',') elseif count == 1 then local valid_month_name, valid_month_number = next(valid_months) @@ -183,7 +170,7 @@ M.data = { end do - down = down:match("^([^,]+),?$") + down = down:match('^([^,]+),?$') local valid_weekdays = {} @@ -196,11 +183,10 @@ M.data = { local count = vim.tbl_count(valid_weekdays) if count > 1 then - return "Ambiguous weekday name! Possible interpretations: " - .. table.concat(vim.tbl_keys(valid_weekdays), ",") + return 'Ambiguous weekday name! Possible interpretations: ' + .. table.concat(vim.tbl_keys(valid_weekdays), ',') elseif count == 1 then - local valid_weekday_name, valid_weekday_number = - next(valid_weekdays) + local valid_weekday_name, valid_weekday_number = next(valid_weekdays) output.weekday = { name = lib.title(valid_weekday_name), @@ -211,9 +197,9 @@ M.data = { end end - return "Unidentified string: `" - .. down - .. "` - make sure your locale and language are set correctly if you are using a language other than English!" + return 'Unidentified string: `' + .. down + .. '` - make sure your locale and language are set correctly if you are using a language other than English!' end ::continue:: @@ -224,22 +210,22 @@ M.data = { insert_date = function(insert_mode) local function callback(input) - if input == "" or not input then + if input == '' or not input then return end local output - if type(input) == "table" then + if type(input) == 'table' then output = tostring(M.data.to_date(input)) else output = M.data.parse_date(input) - if type(output) == "string" then + if type(output) == 'string' then utils.notify(output, vim.log.levels.ERROR) vim.ui.input({ - prompt = "Date: ", + prompt = 'Date: ', default = input, }, callback) @@ -249,41 +235,43 @@ M.data = { output = tostring(output) end - vim.api.nvim_put({ "{@ " .. output .. "}" }, "c", false, true) + vim.api.nvim_put({ '{@ ' .. output .. '}' }, 'c', false, true) if insert_mode then vim.cmd.startinsert() end end - if Mod.is_mod_loaded("ui.calendar") then + if Mod.is_mod_loaded('ui.calendar') then vim.cmd.stopinsert() - Mod.get_mod("ui.calendar") - .select({ callback = vim.schedule_wrap(callback) }) + Mod.get_mod('ui.calendar').select({ callback = vim.schedule_wrap(callback) }) else vim.ui.input({ - prompt = "Date: ", + prompt = 'Date: ', }, callback) end end, } -M.maps = function() - vim.keymap.set( - "", - "(down.time.insert-date)", - lib.wrap(M.data.insert_date, false) - ) - vim.keymap.set( - "i", - "(down.time.insert-date.insert-mode)", - lib.wrap(M.data.insert_date, true) - ) -end +M.maps = { + { + '', + '(down.time.insert-date)', + lib.wrap(M.data.insert_date, true), + 'Insert date', + }, + { + 'i', + '(down.time.insert-date.insert-mode)', + lib.wrap(M.data.insert_date, false), + 'Insert date', + }, +} function M.setup() return { - laoded = true + loaded = true, + dependencies = { 'cmd' }, } end diff --git a/lua/down/mod/edit/cursor/init.lua b/lua/down/mod/edit/cursor/init.lua index c1d04f7..7bc0686 100644 --- a/lua/down/mod/edit/cursor/init.lua +++ b/lua/down/mod/edit/cursor/init.lua @@ -3,7 +3,7 @@ local tu = require('nvim-treesitter.ts_utils') function L.setup() return { - requires = { + dependencies = { 'tool.treesitter', 'workspace', }, diff --git a/lua/down/mod/edit/indent/init.lua b/lua/down/mod/edit/indent/init.lua index 1f28e35..d05f477 100644 --- a/lua/down/mod/edit/indent/init.lua +++ b/lua/down/mod/edit/indent/init.lua @@ -1,83 +1,72 @@ -local mod = require "down.mod" -local M = mod.new("edit.indent") +local mod = require 'down.mod' +local M = mod.new('edit.indent') local ts = vim.treesitter -M.maps = function() - Map.nmap(">>", function() - M.data.head.inc() - end) - Map.nmap("<<", function() - M.data.head.dec() - end) -end +M.maps = { + { + 'n', + '>>', + M.data.head.inc, + 'Incr head', + }, + { + 'n', + '<<', + M.data.head.dec, + 'Decr head', + }, +} -M.cmds = function() +M.load = function() -- NOTE: temporary - vim.api.nvim_create_user_command("DownInc", function() + vim.api.nvim_create_user_command('DownInc', function() M.data.head.inc() end, { - desc = "incs heading level", + desc = 'incs heading level', }) - vim.api.nvim_create_user_command("DownDec", function() + vim.api.nvim_create_user_command('DownDec', function() M.data.head.dec() end, { - desc = "decs heading level", + desc = 'decs heading level', }) end ---@class down.edit.indent.Config -M.config = { -} +M.config = {} ---@class down.edit.indent.Data M.data = { head = { atx = { inc = function(node) - local text = - vim.treesitter.get_node_text(node, vim.api.nvim_get_current_buf()) - local markers = text:match("^([#]+)") + local text = vim.treesitter.get_node_text(node, vim.api.nvim_get_current_buf()) + local markers = text:match('^([#]+)') local range = { node:range() } if #markers >= 6 then return end - text = text:gsub("^" .. markers, markers .. "#") - - vim.api.nvim_buf_set_lines( - vim.api.nvim_get_current_buf(), - range[1], - range[3], - false, - { - text, - } - ) + text = text:gsub('^' .. markers, markers .. '#') + + vim.api.nvim_buf_set_lines(vim.api.nvim_get_current_buf(), range[1], range[3], false, { + text, + }) end, dec = function(node) - local text = - vim.treesitter.get_node_text(node, vim.api.nvim_get_current_buf()) - local markers = text:match("^([#]+)") + local text = vim.treesitter.get_node_text(node, vim.api.nvim_get_current_buf()) + local markers = text:match('^([#]+)') local range = { node:range() } if #markers == 1 then return end - text = text:gsub( - "^" .. markers, - vim.fn.strcharpart(markers, 0, vim.fn.strchars(markers) - 1) - ) - - vim.api.nvim_buf_set_lines( - vim.api.nvim_get_current_buf(), - range[1], - range[3], - false, - { - text, - } - ) + text = + text:gsub('^' .. markers, vim.fn.strcharpart(markers, 0, vim.fn.strchars(markers) - 1)) + + vim.api.nvim_buf_set_lines(vim.api.nvim_get_current_buf(), range[1], range[3], false, { + text, + }) end, }, @@ -89,25 +78,18 @@ M.data = { return end - local text = - vim.treesitter.get_node_text(marker, vim.api.nvim_get_current_buf()) + local text = vim.treesitter.get_node_text(marker, vim.api.nvim_get_current_buf()) local range = { marker:range() } - if text:match("^([-]+)$") then + if text:match('^([-]+)$') then return end - text = text:gsub("%=", "%-") - - vim.api.nvim_buf_set_lines( - vim.api.nvim_get_current_buf(), - range[1], - range[3] + 1, - false, - { - text, - } - ) + text = text:gsub('%=', '%-') + + vim.api.nvim_buf_set_lines(vim.api.nvim_get_current_buf(), range[1], range[3] + 1, false, { + text, + }) end, dec = function(node) local marker = node:named_child(1) @@ -116,25 +98,18 @@ M.data = { return end - local text = - vim.treesitter.get_node_text(marker, vim.api.nvim_get_current_buf()) + local text = vim.treesitter.get_node_text(marker, vim.api.nvim_get_current_buf()) local range = { marker:range() } - if text:match("^([=]+)$") then + if text:match('^([=]+)$') then return end - text = text:gsub("%-", "%=") - - vim.api.nvim_buf_set_lines( - vim.api.nvim_get_current_buf(), - range[1], - range[3] + 1, - false, - { - text, - } - ) + text = text:gsub('%-', '%=') + + vim.api.nvim_buf_set_lines(vim.api.nvim_get_current_buf(), range[1], range[3] + 1, false, { + text, + }) end, }, inc = function() @@ -144,7 +119,7 @@ M.data = { return end - if nodeType == "atx_heading" then + if nodeType == 'atx_heading' then M.data.head.atx.inc(node --[[ @as table ]]) else M.data.head.setext.inc(node --[[ @as table ]]) @@ -157,7 +132,7 @@ M.data = { return end - if nodeType == "atx_heading" then + if nodeType == 'atx_heading' then M.data.head.atx.dec(node --[[ @as table ]]) else M.data.head.setext.dec(node --[[ @as table ]]) @@ -172,10 +147,10 @@ M.data = { while node:parent() do if - vim.list_contains({ - "atx_heading", - "setext_heading", - }, node:type()) + vim.list_contains({ + 'atx_heading', + 'setext_heading', + }, node:type()) then return true, node:type(), node end diff --git a/lua/down/mod/edit/init.lua b/lua/down/mod/edit/init.lua index 91c1ec6..090c7e3 100644 --- a/lua/down/mod/edit/init.lua +++ b/lua/down/mod/edit/init.lua @@ -1,13 +1,13 @@ ---@type down.Mod local M = require('down.mod').new('edit', { - 'toc', + -- 'toc', -- 'task', -- "fold", -- "inline", -- "syntax", 'cursor', 'indent', - 'link', + -- 'link', }) local down = require('down') local config, lib, log, mod = down.cfg, down.lib, down.log, down.mod @@ -15,7 +15,7 @@ local config, lib, log, mod = down.cfg, down.lib, down.log, down.mod M.setup = function() return { loaded = true, - requires = { 'edit.link' }, + dependencies = {}, } end @@ -164,7 +164,7 @@ M.data.go_to_heading = function(anchor_text, reverse) continue = false else -- Format current heading to see if it matches our search term - local heading_as_anchor = M.required['link'].formatLink(line[1], nil, 2) + local heading_as_anchor = M.dep['link'].formatLink(line[1], nil, 2) if anchor_text == heading_as_anchor then -- Set a mark vim.api.nvim_buf_set_mark(0, '`', position[1], position[2], {}) @@ -324,10 +324,10 @@ M.data.yankAsAnchorLink = function(full_path) local line = vim.api.nvim_buf_get_lines(0, row - 1, row, false) -- See if the line starts with a hash local is_heading = string.find(line[1], '^#') - local is_bracketed_span = M.required.link.getBracketedSpanPart() + local is_bracketed_span = M.dep.link.getBracketedSpanPart() if is_heading then -- Format the line as an anchor link - local anchor_link = M.required.link.formatLink(line[1]) + local anchor_link = M.dep.link.formatLink(line[1]) anchor_link = string.gsub(anchor_link[1], '"', '\\"') if full_path then -- Get the full buffer name and insert it before the hash @@ -341,7 +341,7 @@ M.data.yankAsAnchorLink = function(full_path) vim.cmd('let @"="' .. anchor_link .. '"') end elseif is_bracketed_span then - local name = M.required.link.getBracketedSpanPart('text') + local name = M.dep.link.getBracketedSpanPart('text') local attr = is_bracketed_span local anchor_link if name and attr then diff --git a/lua/down/mod/edit/toc/init.lua b/lua/down/mod/edit/toc/init.lua deleted file mode 100644 index b6ff07a..0000000 --- a/lua/down/mod/edit/toc/init.lua +++ /dev/null @@ -1,639 +0,0 @@ -local down = require('down') -local mod, utils, log = down.mod, down.utils, down.log - -local M = mod.new('edit.toc') - -M.setup = function() - -- mod.await("cmd", function(downcmd) - -- downcmd.add_commands_from_table({ - -- toc = { - -- name = "toc", - -- max_args = 1, - -- condition = "markdown", - -- complete = { - -- { "left", "right", "qflist" }, - -- }, - -- }, - -- }) - -- end) - -- - -- if M.config.auto_toc.open then - -- vim.api.nvim_create_autocmd("BufWinEnter", { - -- pattern = "*.md", - -- callback = function() - -- vim.schedule(function() - -- if vim.bo.filetype == "markdown" then - -- next_open_is_auto = true - -- vim.cmd([[down toc]]) - -- end - -- end) - -- end, - -- }) - -- end - return { - requires = { 'tool.treesitter', 'ui', 'cmd' }, - } -end - ----Track if the next TOC open was automatic. Used to determine if we should enter the TOC or not. -local next_open_is_auto = false - ----@class down.edit.toc.Config -M.config = { - -- close the Table of Contents after an entry in the table is picked - close_after_use = false, - - -- width of the Table of Contents window will automatically fit its longest line, up to - -- `max_width` - fit_width = true, - - -- max width of the ToC window when `fit_width = true` (in columns) - max_width = 30, - - -- when set, the ToC window will always be this many cols wide. - -- will override `fit_width` and ignore `max_width` - fixed_width = nil, - - -- enable `cursorline` in the ToC window, and sync the cursor position between ToC and content - -- window - sync_cursorline = true, - - -- Enter a ToC window opened manually (any ToC window not opened by auto_toc) - enter = true, - - -- options for automatically opening/entering the ToC window - auto_toc = { - -- automatically open a ToC window when entering any `down` buffer - open = false, - -- enter an automatically opened ToC window - enter = false, - -- automatically close the ToC window when there is no longer an open down buffer - close = true, - -- will exit nvim if the ToC is the last buffer on the screen, similar to help windows - exit_nvim = true, - }, -} - -local ui_data_of_tabpage = {} -local data_of_down_buf = {} -local toc_namespace - -local function upper_bound(array, v) - -- assume array is sorted - -- find index of first element in array that is > v - local l = 1 - local r = #array - - while l <= r do - local m = math.floor((l + r) / 2) - if v >= array[m] then - l = m + 1 - else - r = m - 1 - end - end - - return l -end - -local toc_query - ----@class down.edit.toc.Data -M.data = { - parse_toc_macro = function(buffer) - local toc, toc_name = false, nil - - local success = M.required['tool.treesitter'].execute_query( - [[ - (infirm_tag - (tag_name) @name - (tag_parameters)? @parameters) - ]], - function(query, id, node) - local capture_name = query.captures[id] - - if - capture_name == 'name' - and M.required['tool.treesitter'].get_node_text(node, buffer):lower() - == 'toc' - then - toc = true - elseif capture_name == 'parameters' and toc then - toc_name = M.required['tool.treesitter'].get_node_text(node, buffer) - return true - end - end, - buffer - ) - - if not success then - return - end - - return toc_name - end, - - generate_qflist = function(original_buffer) - local prefix, title - local qflist_data = {} - - local success = M.required['.treesitter'].execute_query( - [[ - (_ - . - (_) @prefix - . - title: (paragraph_segment) @title) - ]], - function(query, id, node) - local capture = query.captures[id] - - if capture == 'prefix' then - if node:type():match('_prefix$') then - prefix = node - else - prefix = nil - end - title = nil - elseif capture == 'title' then - title = node - end - - if prefix and title then - local prefix_text = M.required['tool.treesitter'].get_node_text(prefix, original_buffer) - local title_text = M.required['tool.treesitter'].get_node_text(title, original_buffer) - - if prefix_text:sub(1, 1) ~= '*' and prefix_text:match('^%W%W') then - prefix_text = table.concat({ prefix_text:sub(1, 1), ' ' }) - end - - table.insert(qflist_data, { - bufnr = original_buffer, - lnum = (prefix:start()) + 1, - text = table.concat({ prefix_text, title_text }), - }) - - prefix, title = nil, nil - end - end, - original_buffer - ) - - if not success then - return - end - - return qflist_data - end, - - -- Update ui cursor according to down cursor - update_cursor = function(ui_data) - local down_window = vim.fn.bufwinid(ui_data.down_buffer) - local down_data = data_of_down_buf[ui_data.down_buffer] - local ui_window = vim.fn.bufwinid(ui_data.buffer) - assert(ui_window ~= -1) - - local current_row_1b = vim.fn.line('.', down_window) - if down_data.last_row == current_row_1b then - return - end - down_data.last_row = current_row_1b - - local start_lines = ui_data.start_lines - assert(start_lines) - - local current_toc_item_idx = upper_bound(start_lines, current_row_1b - 1) - 1 - local current_toc_row = ( - current_toc_item_idx == 0 and math.max(1, start_lines.offset) - or current_toc_item_idx + start_lines.offset - ) - vim.api.nvim_win_set_cursor(ui_window, { current_toc_row, 0 }) - end, - - update_toc = function(toc_title, ui_data, down_buffer) - local ui_buffer = ui_data.buffer - ui_data.down_buffer = down_buffer - - if not vim.api.nvim_buf_is_valid(ui_buffer) then - log.error('update_toc called with invalid ui buffer') - return - end - - vim.bo[ui_buffer].modifiable = true - vim.api.nvim_buf_clear_namespace(down_buffer, toc_namespace, 0, -1) - - table.insert(toc_title, '') - vim.api.nvim_buf_set_lines(ui_buffer, 0, -1, true, toc_title) - - local down_data = {} - data_of_down_buf[down_buffer] = down_data - - local extmarks = {} - down_data.extmarks = extmarks - - local offset = vim.api.nvim_buf_line_count(ui_buffer) - local start_lines = { offset = offset } - ui_data.start_lines = start_lines - - toc_query = toc_query - or utils.ts_parse_query( - 'down', - [[ - ( - [(heading1_prefix)(heading2_prefix)(heading3_prefix)(heading4_prefix)(heading5_prefix)(heading6_prefix)]@prefix - . - state: (detached_modifier_extension (_)@modifier)? - . - title: (paragraph_segment)@title - )]] - ) - - local down_root = M.required['tool.treesitter'].get_document_root(down_buffer) - if not down_root then - return - end - - local current_capture - local heading_nodes = {} - for id, node in toc_query:iter_captures(down_root, down_buffer) do - local type = toc_query.captures[id] - if type == 'prefix' then - current_capture = {} - table.insert(heading_nodes, current_capture) - end - current_capture[type] = node - end - - local heading_texts = {} - for _, capture in ipairs(heading_nodes) do - if capture.modifier and capture.modifier:type() == 'todo_item_cancelled' then - goto continue - end - - local row_start_0b, col_start_0b, _, _ = capture.prefix:range() - local _, _, row_end_0bin, col_end_0bex = capture.title:range() - - table.insert(start_lines, row_start_0b) - table.insert( - extmarks, - vim.api.nvim_buf_set_extmark(down_buffer, toc_namespace, row_start_0b, col_start_0b, {}) - ) - - for _, line in - ipairs( - vim.api.nvim_buf_get_text( - down_buffer, - row_start_0b, - col_start_0b, - row_end_0bin, - col_end_0bex, - {} - ) - ) - do - table.insert(heading_texts, line) - end - - ::continue:: - end - - vim.api.nvim_buf_set_lines(ui_buffer, -1, -1, true, heading_texts) - - vim.bo[ui_buffer].modifiable = false - - vim.api.nvim_buf_set_keymap(ui_buffer, 'n', '', '', { - callback = function() - local location = get_target_location_under_cursor(ui_data) - if not location then - return - end - - local down_window = vim.fn.bufwinid(down_buffer) - if down_window == -1 then - local toc_window = vim.fn.bufwinid(ui_data.buffer) - local buf_width = nil - if toc_window ~= -1 then - buf_width = vim.api.nvim_win_get_width(toc_window) - M.data.data.get_toc_width(ui_data) - if buf_width < 1 then - buf_width = nil - end - end - down_window = vim.api.nvim_open_win( - down_buffer, - true, - { win = 0, vertical = true, width = buf_width } - ) - else - vim.api.nvim_set_current_win(down_window) - vim.api.nvim_set_current_buf(down_buffer) - end - vim.api.nvim_win_set_cursor(down_window, { location[1] + 1, location[2] }) - - if M.config.close_after_use then - vim.api.nvim_buf_delete(ui_buffer, { force = true }) - end - end, - }) - - if M.config.sync_cursorline then - M.data.update_cursor(ui_data) - end - end, -} - -M.data.get_target_location_under_cursor = function(ui_data) - local ui_window = vim.fn.bufwinid(ui_data.buffer) - local curline = vim.api.nvim_win_get_cursor(ui_window)[1] - local offset = ui_data.start_lines.offset - local extmark_lookup = data_of_down_buf[ui_data.down_buffer].extmarks[curline - offset] - - if not extmark_lookup then - return - end - - return vim.api.nvim_buf_get_extmark_by_id(ui_data.down_buffer, toc_namespace, extmark_lookup, {}) -end - -M.data.data = { - ---get the width of the ToC window - ---@param ui_data table - ---@return number - get_toc_width = function(ui_data) - if type(M.config.fixed_width) == 'number' then - return M.config.fixed_width - end - local max_virtcol_1bex = M.data.data.get_max_virtcol(ui_data.window) - local current_winwidth = vim.api.nvim_win_get_width(ui_data.window) - local new_winwidth = math.min(current_winwidth, M.config.max_width, max_virtcol_1bex - 1) - return new_winwidth + 1 - end, - - get_max_virtcol = function(win) - local n_line = vim.fn.line('$', win) - local result = 1 - for i = 1, n_line do - result = math.max(result, vim.fn.virtcol({ i, '$' }, 0, win)) - end - return result - end, -} - -local function get_down_ui(down_buffer) - local tabpage = vim.api.nvim_win_get_tabpage(vim.fn.bufwinid(down_buffer)) - return ui_data_of_tabpage[tabpage] -end - ----Guard an autocommand callback function with a check that the ToC is still open ----@param listener function ----@return function -local function unlisten_if_closed(listener) - return function(ev) - if vim.tbl_isempty(ui_data_of_tabpage) then - return true - end - - local down_buffer = ev.buf - local ui_data = get_down_ui(down_buffer) - if not ui_data or vim.fn.bufwinid(ui_data.buffer) == -1 then - return - end - - return listener(down_buffer, ui_data) - end -end - ----Create a split window and buffer for the table of contents. Set buffer and window options ----accordingly ----@param tabpage number ----@param split_dir "left" | "right" ----@param enter boolean ----@return table -local function create_ui(tabpage, split_dir, enter) - assert(tabpage == vim.api.nvim_get_current_tabpage()) - - toc_namespace = toc_namespace or vim.api.nvim_create_namespace('down/toc') - local ui_buffer, ui_window = M.required['core.ui'].new_vsplit( - ('toc-%d'):format(tabpage), - enter, - { ft = 'down' }, - { split = split_dir, win = 0, style = 'minimal' } - ) - - local ui_wo = vim.wo[ui_window] - ui_wo.scrolloff = 999 - ui_wo.conceallevel = 0 - ui_wo.foldmethod = 'expr' - ui_wo.foldexpr = 'v:lua.vim.treesitter.foldexpr()' - ui_wo.foldlevel = 99 - ui_wo.winfixbuf = true - - if M.config.sync_cursorline then - ui_wo.cursorline = true - end - - local ui_data = { - buffer = ui_buffer, - tabpage = tabpage, - window = ui_window, - } - - ui_data_of_tabpage[tabpage] = ui_data - - return ui_data -end - ---- should we enter the ToC window? -local function enter_toc_win() - local do_enter = M.config.enter - if next_open_is_auto then - do_enter = M.config.auto_toc.enter - end - return do_enter -end - -M.handle = function(event) - if event.split_type[2] ~= M.name then - return - end - - local toc_title = vim.split(M.data.parse_toc_macro(event.buffer) or 'Table of Contents', '\n') - local down_buffer = event.buffer - - if event.content and event.content[1] == 'qflist' then - local qflist = M.data.generate_qflist(event.buffer) - - if not qflist then - utils.notify('An error occurred and the qflist could not be generated', vim.log.levels.WARN) - return - end - - vim.fn.setqflist(qflist, 'r') - vim.fn.setqflist({}, 'a', { title = toc_title[1] }) - vim.cmd.copen() - - return - end - - local tabpage = vim.api.nvim_win_get_tabpage(vim.fn.bufwinid(down_buffer)) - if ui_data_of_tabpage[tabpage] then - if down_buffer == ui_data_of_tabpage[tabpage].buffer then - return - end - M.data.update_toc(toc_title, ui_data_of_tabpage[tabpage], down_buffer) - - if enter_toc_win() then - vim.api.nvim_set_current_win(ui_data_of_tabpage[tabpage].window) - end - return - end - - local ui_data = create_ui(tabpage, event.content[1] or 'left', enter_toc_win()) - next_open_is_auto = false - - M.data.update_toc(toc_title, ui_data_of_tabpage[tabpage], down_buffer) - - if M.config.fit_width then - vim.api.nvim_win_set_width(ui_data.window, M.data.data.get_toc_width(ui_data)) - end - - local close_buffer_callback = function() - -- Check if ui_buffer exists before deleting it - if vim.api.nvim_buf_is_loaded(ui_data.buffer) then - vim.api.nvim_buf_delete(ui_data.buffer, { force = true }) - end - ui_data_of_tabpage[tabpage] = nil - end - - vim.keymap.set('n', 'q', close_buffer_callback, { buffer = ui_data.buffer }) - - --- WinClosed matches against the win number as a string, not the buf number - vim.api.nvim_create_autocmd('WinClosed', { - pattern = tostring(ui_data.window), - callback = close_buffer_callback, - }) - - vim.api.nvim_create_autocmd('BufWritePost', { - pattern = '*.down', - callback = unlisten_if_closed(function(buf, ui) - toc_title = vim.split(M.data.parse_toc_macro(buf) or 'Table of Contents', '\n') - data_of_down_buf[buf].last_row = nil -- invalidate cursor cache - M.data.update_toc(toc_title, ui, buf) - end), - }) - - vim.api.nvim_create_autocmd('BufEnter', { - pattern = '*.down', - callback = unlisten_if_closed(function(buf, ui) - if buf == ui.buffer or buf == ui.down_buffer then - return - end - - toc_title = vim.split(M.data.parse_toc_macro(buf) or 'Table of Contents', '\n') - M.data.update_toc(toc_title, ui, buf) - end), - }) - - -- Sync cursor: ToC -> content - if M.config.sync_cursorline then - -- Ignore the first (fake) CursorMoved coming together with BufEnter of the ToC buffer - vim.api.nvim_create_autocmd('BufEnter', { - buffer = ui_data.buffer, - callback = function(_ev) - ui_data.cursor_start_moving = false - end, - }) - - vim.api.nvim_create_autocmd({ 'CursorMoved', 'CursorMovedI' }, { - buffer = ui_data.buffer, - callback = function(ev) - assert(ev.buf == ui_data.buffer) - - if vim.fn.bufwinid(ui_data.down_buffer) == -1 then - return - end - - -- Ignore the first (fake) CursorMoved coming together with BufEnter of the ToC buffer - if ui_data.cursor_start_moving then - local location = get_target_location_under_cursor(ui_data) - if location then - local down_window = vim.fn.bufwinid(ui_data.down_buffer) - vim.api.nvim_win_set_cursor(down_window, { location[1] + 1, location[2] }) - vim.api.nvim_buf_call(ui_data.down_buffer, function() - vim.cmd('normal! zz') - end) - end - end - ui_data.cursor_start_moving = true - end, - }) - - -- Sync cursor: content -> ToC - vim.api.nvim_create_autocmd({ 'CursorMoved', 'CursorMovedI' }, { - pattern = '*.down', - callback = unlisten_if_closed(function(buf, ui) - if buf ~= ui.down_buffer then - return - end - - if not data_of_down_buf[buf] then - -- toc not yet created because BufEnter is not yet triggered - return - end - - M.data.update_cursor(ui) - end), - }) - - -- When leaving the content buffer, add its last cursor position to jump list - vim.api.nvim_create_autocmd('BufLeave', { - pattern = '*.down', - callback = unlisten_if_closed(function(_down_buffer, _ui_data) - vim.cmd("normal! m'") - end), - }) - end - - if M.config.auto_toc.exit_nvim then - vim.api.nvim_create_autocmd('WinEnter', { - buffer = ui_data.buffer, - callback = unlisten_if_closed(function(_, _) - vim.schedule(function() - local real_windows = vim - .iter(vim.api.nvim_list_wins()) - :filter(function(win) - return vim.api.nvim_win_get_config(win).relative == '' - end) - :totable() - if #real_windows == 1 then - vim.schedule(vim.cmd.q) - end - end) - end), - }) - end - - if M.config.auto_toc.close then - vim.api.nvim_create_autocmd('BufWinLeave', { - pattern = '*.down', - callback = unlisten_if_closed(function(_buf, ui) - vim.schedule(function() - if vim.fn.winnr('$') > 1 then - local win = vim.fn.bufwinid(ui.buffer) - if win ~= -1 then - vim.api.nvim_win_close(win, true) - close_buffer_callback() - end - end - end) - end), - }) - end -end - -M.subscribed = { - ['core.downcmd'] = { - [M.name] = true, - }, -} - -return M diff --git a/lua/down/mod/edit/toc/util.lua b/lua/down/mod/edit/toc/util.lua deleted file mode 100644 index d4a49f8..0000000 --- a/lua/down/mod/edit/toc/util.lua +++ /dev/null @@ -1,3 +0,0 @@ -local U = {} - -return U diff --git a/lua/down/mod/data/link/README.md b/lua/down/mod/link/README.md similarity index 100% rename from lua/down/mod/data/link/README.md rename to lua/down/mod/link/README.md diff --git a/lua/down/mod/data/link/init.lua b/lua/down/mod/link/init.lua similarity index 57% rename from lua/down/mod/data/link/init.lua rename to lua/down/mod/link/init.lua index adac260..958d854 100644 --- a/lua/down/mod/data/link/init.lua +++ b/lua/down/mod/link/init.lua @@ -1,20 +1,24 @@ local config = require 'down.config' +local log = require 'down.util.log' local mod = require 'down.mod' local util = require 'down.util' ---@class down.mod.data.Link: down.Mod -local Link = mod.new('data.link') +local Link = mod.new 'link' -local tsu = require 'nvim-treesitter.ts_utils' +local tsu_ok, tsu = pcall(require, 'nvim-treesitter.ts_utils') local ts = vim.treesitter local tsq = vim.treesitter.query +--- @return down.mod.Setup Link.setup = function() - return { + return { ---@type down.mod.Setup loaded = true, - requires = { + dependencies = { + 'cmd', --- For commands + 'data.history', --- For history storage 'tool.treesitter', --- For treesitter node parsing - 'workspace', --- For checking filetype and index file names of current workspace + 'workspace', --- For checking filetype and index file names of current workspace }, } end @@ -30,21 +34,64 @@ Link.maps = { { 'n', '', - ':lua require("down.mod.data.link").data.follow.link()', + ':lua require("down.mod.link").data.follow.link()', 'Follow link', }, + { + 'n', + '', + ':lua require("down.mod.link").data.goto_prev_link()', + 'Go to previous link', + }, + { + 'n', + '', + ':lua require("down.mod.link").data.goto_next_link()', + 'Go to next link', + }, } -Link.load = function() -end +Link.commands = { + link = { + name = 'link', + args = 1, + condition = 'markdown', + callback = function(e) + log.trace 'Link.commands.link: Callback' + local cmd = e.body[1] + end, + subcommands = { + next = { + name = 'link.next', + args = 0, + condition = 'markdown', + callback = Link.data.goto_next_link, + }, + previous = { + name = 'link.previous', + args = 0, + condition = 'markdown', + callback = Link.data.goto_prev_link, + }, + select = { + name = 'link.select', + args = 0, + condition = 'markdown', + callback = Link.data.select_link, + }, + }, + }, +} + +Link.load = function() end ----@class down.mod.data.link.Data +---@class down.mod.link.Data Link.data = { parser = function() end, mk = {}, follow = {}, - ---@enum down.mod.data.link.Type - ---@alias down.mod.data.link.Tyoe + ---@enum down.mod.link.Type + ---@alias down.mod.link.Tyoe ---| "local" ---| "web" ---| "heading" @@ -56,23 +103,23 @@ Link.data = { } Link.data.dir = function(dir) - return vim.fn.expand('%:p:h') + return vim.fn.expand '%:p:h' end Link.data.cwd = function(path) - return vim.fn.expand('%:p:h') .. config.pathsep .. (path or '') + return vim.fn.expand '%:p:h' .. config.pathsep .. (path or '') end Link.data.mk.dir = function(path) - return vim.fn.mkdir(vim.fn.expand('%:p:h') .. config.pathsep .. path, 'p') + return vim.fn.mkdir(vim.fn.expand '%:p:h' .. config.pathsep .. path, 'p') end Link.data.mk.file = function(path) if path:sub(-3) == '.md' then return Link.data.cwd(path) elseif path:sub(-1) == config.pathsep then - Link.data.mkdir(path) - io.write(path .. 'index' .. '.md', vim.fn.expand('%:p') .. 'index.md') + Link.data.mk.dir(path) + io.write(path .. 'index' .. '.md', vim.fn.expand '%:p' .. 'index.md') else return Link.data.cwd(path .. '.md') end @@ -87,11 +134,11 @@ Link.data.resolve = function(ln) elseif ch == '#' then return ln:sub(2), 'heading' elseif ch == '~' then - return os.getenv('HOME') .. config.pathsep .. ln:sub(2), 'local' + return os.getenv 'HOME' .. config.pathsep .. ln:sub(2), 'local' elseif ln:sub(1, 8) == 'https://' or ln:sub(1, 7) == 'http://' then return ln, 'web' else - return vim.fn.expand('%:p:h') .. config.pathsep .. ln, 'local' + return vim.fn.expand '%:p:h' .. config.pathsep .. ln, 'local' end end @@ -114,6 +161,52 @@ Link.data.next_node = function(node) return next, next:type() end +Link.data.next_link = function(node) + local next = tsu.get_next_node(node) + if not next then + return + end + if Link.data.destination(next) ~= nil then + return next + end + return Link.data.next_link(next) +end + +Link.data.prev_link = function(node) + local prev = tsu.get_prev_node(node) + if not prev then + return + end + if Link.data.destination(prev) ~= nil then + return prev + end + return Link.data.prev_link(prev) +end + +Link.data.goto_next_link = function() + local node, nodety = Link.data.cursor() + local next = Link.data.next_link(node) + if next then + tsu.goto_node(next) + end +end + +Link.data.goto_prev_link = function() + local node, nodety = Link.data.cursor() + local prev = Link.data.prev_link(node) + if prev then + tsu.goto_node(prev) + end +end + +Link.data.select_link = function() + local node, nodety = Link.data.cursor() + local dest = Link.data.destination(node) + if dest then + vim.fn.setreg('*', dest) + end +end + Link.data.text = function(node) return vim.split(ts.get_node_text(node, 0), '\n')[1] end @@ -121,51 +214,45 @@ end Link.data.ref = function(node) local link_label = Link.data.text(node) for _, captures, _ in - Link.required['tool.treesitter'].query([[ + Link.dep['tool.treesitter'].query([[ (link_reference_definition (link_label) @label (#eq? @label "]] .. link_label .. [[") (link_destination) @link_destination - )]], 'markdown') + )]]), + 'markdown' do - local capture = vim.treesitter.get_node_text(captures[2], 0) - return string.gsub(capture, '[<>]', '') + local capture = ts.get_node_text(captures[2], 0) + return capture:gsub('[<>]', '') end end Link.data.query = function(n, lang) - local lt = vim.treesitter.get_parser(0, lang or vim.bo.filetype) - local st = lt:parse()[1] - local sr = st:root() - local pq = vim.treesitter.query.parse(lang or vim.bo.filetype, n) - return pq:iter_matches(sr, 0) + lang = lang or vim.bo.filetype + local lt = ts.get_parser(0, lang):parse()[1]:root() + local pq = tsq.parse(lang, n) + return pq:iter_matches(lt, 0) end --- Checks whether a node is a wikilink, and if not, checks if parent is a wikilink --- If either are, then returns the link destination, otherwise nil --- @return string|nil Link.data.iswikilink = function(node, parent) - if not node and not parent then - return nil + if node and parent then + return ts.get_node_text(parent, 0):iswikilink() elseif node and not parent then - -- print('node and not parent: ', node:type(), Link.data.text(node)) - local wikilink = vim.treesitter.get_node_text(node, 0):iswikilink() - if wikilink then - return wikilink - else - end + return ts.get_node_text(node, 0):iswikilink() else - -- print(node:type(), Link.data.text(node)) - -- print(parent:type(), Link.data.text(parent)) - local wikilink = vim.treesitter.get_node_text(parent, 0):iswikilink() - if wikilink then - return wikilink - end return nil end end -Link.data.destination = function() - local node, nodety = Link.data.cursor() +Link.data.destination = function(nd) + local node, nodety + if not nd then + node, nodety = Link.data.cursor() + else + node, nodety = node, node:type() + end local parent = node:parent() local wikilink = Link.data.iswikilink(node, parent) if wikilink then @@ -208,12 +295,11 @@ Link.data.destination = function() return Link.data.ref(nc) end end - else - return end + return end ----@class down.mod.data.link.Config +---@class down.mod.link.Config Link.config = {} Link.data.follow.loc = function(ln) @@ -223,10 +309,12 @@ Link.data.follow.loc = function(ln) local ix = path .. 'index' .. '.md' path = path:sub(1, -2) if vim.fn.glob(path) == '' then - vim.fn.mkdir(vim.fn.fnameescape(path), 'p') - return vim.cmd(string.format('edit %s', vim.fn.fnameescape(ix))) + local dir, file = vim.fn.fnameescape(path), vim.fn.fnameescape(ix) + vim.fn.mkdir(dir, 'p') + Link.dep['data.history'].push(file) + return vim.cmd(('edit %s'):format(file)) else - return vim.cmd(string.format('edit %s', vim.fn.fnameescape(ix))) + return vim.cmd(('edit %s'):format(vim.fn.fnameescape(ix))) end end if path:sub(-3) ~= '.md' then @@ -238,9 +326,9 @@ Link.data.follow.loc = function(ln) mod_ln = path end if mod_ln and line then - vim.cmd(string.format('silent! %s +%s %s', 'e', line, vim.fn.fnameescape(mod_ln))) + vim.cmd(('silent! %s +%s %s'):format('e', line, vim.fn.fnameescape(mod_ln))) elseif mod_ln and not line then - vim.cmd(string.format('silent! %s %s', 'e', vim.fn.fnameescape(mod_ln))) + vim.cmd(('silent! %s %s'):format('e', vim.fn.fnameescape(mod_ln))) end end Link.data.follow.heading = function(ln) @@ -249,6 +337,7 @@ Link.data.follow.heading = function(ln) vim.fn.search('\\c^#\\+ *' .. ln, 'ew') end Link.data.follow.web = function(ln) + ---TODO: vim.fn.open if config.os == 'linux' then vim.fn.system('xdg-open ' .. vim.fn.shellescape(ln)) elseif config.os == 'mac' then diff --git a/lua/down/mod/log/cmd.lua b/lua/down/mod/log/cmd.lua new file mode 100644 index 0000000..28d6241 --- /dev/null +++ b/lua/down/mod/log/cmd.lua @@ -0,0 +1,47 @@ +return { + log = { + min_args = 1, + max_args = 2, + name = 'log', + callback = function(e) + log.trace 'log' + end, + subcommands = { + index = { + args = 0, + name = 'log.index', + callback = M.data.open_index, + }, + month = { + max_args = 1, + name = 'log.month', + callback = M.data.open_month, + }, + tomorrow = { + args = 0, + name = 'log.tomorrow', + callback = M.data.log_tomorrow, + }, + yesterday = { + args = 0, + callback = M.data.log_yesterday, + name = 'log.yesterday', + }, + new = { + args = 0, + callback = M.data.log_new, + name = 'log.new', + }, + custom = { + callback = M.data.calendar_months, + max_args = 1, + name = 'log.custom', + }, -- format :yyyy-mm-dd + template = { + args = 0, + name = 'log.template', + callback = M.data.create_template, + }, + }, + }, +} diff --git a/lua/down/mod/log/init.lua b/lua/down/mod/log/init.lua index e0548fc..6d2f99d 100644 --- a/lua/down/mod/log/init.lua +++ b/lua/down/mod/log/init.lua @@ -4,41 +4,62 @@ local lib = require 'down.util.lib' local log = require 'down.util.log' local mod = require 'down.mod' -local M = require 'down.mod'.new('log') +local M = mod.new 'log' + +M.load = function() end M.commands = { log = { min_args = 1, max_args = 2, + name = 'log', + callback = function(e) + log.trace(('log %s'):format(e.body)) + end, subcommands = { - index = { args = 0, name = 'log.index' }, - month = { max_args = 1, name = 'log.month' }, - tomorrow = { args = 0, name = 'log.tomorrow' }, - yesterday = { args = 0, name = 'log.yesterday' }, - new = { args = 0, name = 'log.new' }, - custom = { max_args = 1, name = 'log.custom' }, -- format :yyyy-mm-dd - template = { args = 0, name = 'log.template' }, - toc = { - args = 1, - name = 'log.toc', - subcommands = { - open = { args = 0, name = 'log.toc.open' }, - update = { args = 0, name = 'log.toc.update' }, - }, + index = { + args = 0, + name = 'log.index', + callback = M.data.open_index, + }, + month = { + max_args = 1, + name = 'log.month', + callback = M.data.open_month, + }, + tomorrow = { + args = 0, + name = 'log.tomorrow', + callback = M.data.log_tomorrow, + }, + yesterday = { + args = 0, + callback = M.data.log_yesterday, + name = 'log.yesterday', + }, + new = { + args = 0, + callback = M.data.log_new, + name = 'log.new', + }, + custom = { + callback = M.data.calendar_months, + max_args = 1, + name = 'log.custom', + }, -- format :yyyy-mm-dd + template = { + args = 0, + name = 'log.template', + callback = M.data.create_template, }, }, }, } -M.load = function() - if M.config.strategies[M.config.strategy] then - M.config.strategy = M.config.strategies[M.config.strategy] - end -end M.setup = function() return { - loaded = true, - requires = { + loaded = function(e) end, + dependencies = { 'ui.calendar', 'ui.popup', 'edit.inline', @@ -46,12 +67,11 @@ M.setup = function() 'ui.progress', 'workspace', 'tool.treesitter', + 'cmd', }, } end --- M.set = M.data.set - ---@class data.log.Config M.config = { -- Which workspace to use for the log files, the base behaviour @@ -74,13 +94,7 @@ M.config = { template_name = 'template.md', -- Whether to apply the template file to new log entries. - use_template = true, - - -- Formatter function used to generate the toc file. - -- Receives a table that contains tables like { yy, mm, dd, link, title }. - -- - -- The function must return a table of strings. - toc_format = nil, + use_template = function(e) end, } M.config.strategies = { @@ -92,9 +106,31 @@ M.config.strategies = { M.data = { data = {}, logs = {}, - version = '0.1.0', count = 0, + calendar_months = function(e) + if not e.content[1] then + local calendar = mod.get_mod('ui.calendar') + if not calendar then + log.error('[ERROR]: `base.calendar` is not loaded! Said M is dep for this operation.') + return + end + M.dep['ui.calendar'].select({ + callback = vim.schedule_wrap(function(osdate) + M.data.open_log( + nil, + string.format('%04d', osdate.year) + .. '-' + .. string.format('%02d', osdate.month) + .. '-' + .. string.format('%02d', osdate.day) + ) + end), + }) + else + M.data.open_log(nil, e.content[1]) + end + end, get_log = function() end, get_logs = function() end, open_index = function() end, @@ -103,8 +139,8 @@ M.data = { ---@param custom_date? string #A YYYY-mm-dd string that specifies a date to open the log at instead open_log = function(time, custom_date) -- TODO(vhyrro): Change this to use down dates! - local workspace = M.config.workspace or M.required['workspace'].get_current_workspace()[1] - local workspace_path = M.required['workspace'].get_workspace(workspace) + local workspace = M.config.workspace or M.dep['workspace'].get_current_workspace()[1] + local workspace_path = M.dep['workspace'].get_workspace(workspace) local folder_name = M.config.log_folder local template_name = M.config.template_name @@ -125,24 +161,23 @@ M.data = { local path = os.date( type(M.config.strategy) == 'function' and M.config.strategy(os.date('*t', time)) - or M.config.strategy, + or M.config.strategy, time ) - local log_file_exists = M.required['workspace'].file_exists( - workspace_path .. '/' .. folder_name .. config.pathsep .. path - ) + local log_file_exists = + M.dep['workspace'].file_exists(workspace_path .. '/' .. folder_name .. config.pathsep .. path) - M.required['workspace'].new_file(folder_name .. config.pathsep .. path, workspace) + M.dep['workspace'].new_file(folder_name .. config.pathsep .. path, workspace) - M.required['workspace'].new_file(folder_name .. config.pathsep .. path, workspace) + M.dep['workspace'].new_file(folder_name .. config.pathsep .. path, workspace) if - not log_file_exists - and M.config.use_template - and M.required['workspace'].file_exists( - workspace_path .. '/' .. folder_name .. '/' .. template_name - ) + not log_file_exists + and M.config.use_template + and M.dep['workspace'].file_exists( + workspace_path .. '/' .. folder_name .. '/' .. template_name + ) then vim.cmd( '$read ' .. workspace_path .. '/' .. folder_name .. '/' .. template_name .. '| silent! w' @@ -152,13 +187,13 @@ M.data = { --- Opens a log entry for tomorrow's date log_tomorrow = function() - -- M.required['ui.progress'].start() - M.required['ui.win'].new_new() + -- M.dep['ui.progress'].start() + M.dep['ui.win'].new_new() end, --- Opens a log entry for yesterday's date log_yesterday = function() - M.required['ui.win'].win(0) + M.dep['ui.win'].win(0) end, --- Opens a log entry for new's date @@ -180,21 +215,21 @@ M.data = { local folder_name = M.config.log_folder local template_name = M.config.template_name - M.required['workspace'].new_file( + M.dep['workspace'].new_file( folder_name .. config.pathsep .. template_name, - workspace or M.required['workspace'].get_current_workspace()[1] + workspace or M.dep['workspace'].get_current_workspace()[1] ) end, --- Opens the toc file open_toc = function() - local workspace = M.config.workspace or M.required['workspace'].get_current_workspace()[1] + local workspace = M.config.workspace or M.dep['workspace'].get_current_workspace()[1] local index = mod.mod_config('workspace').index local folder_name = M.config.log_folder -- If the toc exists, open it, if not, create it - if M.required['workspace'].file_exists(folder_name .. config.pathsep .. index) then - M.required['workspace'].open_file(workspace, folder_name .. config.pathsep .. index) + if M.dep['workspace'].file_exists(folder_name .. config.pathsep .. index) then + M.dep['workspace'].open_file(workspace, folder_name .. config.pathsep .. index) else M.data.new_toc() end @@ -202,9 +237,9 @@ M.data = { --- Creates or updates the toc file create_toc = function() - local workspace = M.config.workspace or M.required['workspace'].get_current_workspace()[1] + local workspace = M.config.workspace or M.dep['workspace'].get_current_workspace()[1] local index = mod.mod_config('workspace').index - local workspace_path = M.required['workspace'].get_workspace(workspace) + local workspace_path = M.dep['workspace'].get_workspace(workspace) local workspace_name_for_link = M.config.workspace or '' local folder_name = M.config.log_folder @@ -229,8 +264,8 @@ M.data = { -- Gets the title from the metadata of a file, must be called in a vim.schedule local get_title = function(file) local buffer = - vim.fn.bufadd(workspace_path .. config.pathsep .. folder_name .. config.pathsep .. file) - local meta = M.required['workspace'].get_document_metadata(buffer) + vim.fn.bufadd(workspace_path .. config.pathsep .. folder_name .. config.pathsep .. file) + local meta = M.dep['workspace'].get_document_metadata(buffer) return meta.title end @@ -288,16 +323,16 @@ M.data = { tonumber(mname), tonumber(file[1]), '{:$' - .. workspace_name_for_link - .. config.pathsep - .. M.config.log_folder - .. config.pathsep - .. name - .. config.pathsep - .. mname - .. config.pathsep - .. file[1] - .. ':}', + .. workspace_name_for_link + .. config.pathsep + .. M.config.log_folder + .. config.pathsep + .. name + .. config.pathsep + .. mname + .. config.pathsep + .. file[1] + .. ':}', title, }) end) @@ -331,12 +366,12 @@ M.data = { parts[2], parts[3], '{:$' - .. workspace_name_for_link - .. config.pathsep - .. M.config.log_folder - .. config.pathsep - .. file[1] - .. ':}', + .. workspace_name_for_link + .. config.pathsep + .. M.config.log_folder + .. config.pathsep + .. file[1] + .. ':}', title, }) end) @@ -346,34 +381,34 @@ M.data = { vim.schedule(function() -- Gets a base format for the entries local format = M.config.toc_format - or function(entries) - local months_text = M.data.months - -- Convert the entries into a certain format to be written - local output = {} - local current_year - local current_month - for _, entry in ipairs(entries) do - -- Don't print the year and month if they haven't changed - if not current_year or current_year < entry[1] then - current_year = entry[1] - current_month = nil - table.insert(output, '* ' .. current_year) - end - if not current_month or current_month < entry[2] then - current_month = entry[2] - table.insert(output, '** ' .. months_text[current_month]) + or function(entries) + local months_text = require 'down.mod.note.util'.months + -- Convert the entries into a certain format to be written + local output = {} + local current_year + local current_month + for _, entry in ipairs(entries) do + -- Don't print the year and month if they haven't changed + if not current_year or current_year < entry[1] then + current_year = entry[1] + current_month = nil + table.insert(output, '* ' .. current_year) + end + if not current_month or current_month < entry[2] then + current_month = entry[2] + table.insert(output, '** ' .. months_text[current_month]) + end + + -- Prints the file link + table.insert(output, ' ' .. entry[4] .. string.format('[%s]', entry[5])) end - -- Prints the file link - table.insert(output, ' ' .. entry[4] .. string.format('[%s]', entry[5])) + return output end - return output - end - - M.required['workspace'].new_file( + M.dep['workspace'].new_file( folder_name .. config.pathsep .. index, - workspace or M.required['workspace'].get_current_workspace()[1] + workspace or M.dep['workspace'].get_current_workspace()[1] ) -- The current buffer now must be the toc file, so we set our toc entries there @@ -385,67 +420,16 @@ M.data = { end, } -M.handle = function(event) - if event.split_type[1] == 'cmd' then - if event.split_type[2] == 'log.index' then - M.data.open_index() - -- pop.new(()) - elseif event.split_type[2] == 'log.month' then - M.data.open_month() - elseif event.split_type[2] == 'log.tomorrow' then - M.data.log_tomorrow() - elseif event.split_type[2] == 'log.yesterday' then - M.data.log_yesterday() - elseif event.split_type[2] == 'log.custom' then - if not event.content[1] then - local calendar = mod.get_mod('ui.calendar') - - if not calendar then - log.error( - '[ERROR]: `base.calendar` is not loaded! Said M is required for this operation.' - ) - return - end - - M.required['calendar'].select({ - callback = vim.schedule_wrap(function(osdate) - M.data.open_log( - nil, - string.format('%04d', osdate.year) - .. '-' - .. string.format('%02d', osdate.month) - .. '-' - .. string.format('%02d', osdate.day) - ) - end), - }) - else - M.data.open_log(nil, event.content[1]) - end - elseif event.split_type[2] == 'log.new' then - M.data.log_new() - elseif event.split_type[2] == 'log.template' then - M.data.new_template() - elseif event.split_type[2] == 'log.toc.open' then - M.data.open_toc() - elseif event.split_type[2] == 'log.toc.update' then - M.data.new_toc() - end - end -end - -M.subscribed = { - cmd = { - ['log.index'] = true, - ['log.month'] = true, - ['log.yesterday'] = true, - ['log.tomorrow'] = true, - ['log.new'] = true, - ['log.custom'] = true, - ['log.template'] = true, - ['log.toc.update'] = true, - ['log.toc.open'] = true, - }, -} +-- M.handle = { +-- cmd = { +-- ['log.index'] = M.data.open_index, +-- ['log.month'] = M.data.open_month, +-- ['log.yesterday'] = M.data.log_yesterday, +-- ['log.tomorrow'] = M.data.log_tomorrow, +-- ['log.new'] = M.data.log_new, +-- ['log.custom'] = function(e) end, +-- ['log.template'] = M.data.new_template, +-- }, +-- } return M diff --git a/lua/down/mod/lsp/cmd.lua b/lua/down/mod/lsp/cmd.lua new file mode 100644 index 0000000..ac1616d --- /dev/null +++ b/lua/down/mod/lsp/cmd.lua @@ -0,0 +1,101 @@ +return { + lsp = { + name = 'lsp', + condition = 'markdown', + callback = function(e) + log.trace 'lsp' + end, + subcommands = { + restart = { + args = 0, + name = 'lsp.restart', + condition = 'markdown', + callback = function(e) + log.trace 'lsp.restart' + end, + }, + start = { + args = 0, + name = 'lsp.start', + condition = 'markdown', + callback = function(e) + log.trace 'lsp.start' + end, + }, + status = { + args = 0, + name = 'lsp.status', + condition = 'markdown', + callback = function(e) + log.trace 'lsp.status' + end, + }, + stop = { + args = 0, + name = 'lsp.stop', + condition = 'markdown', + callback = function(e) + log.trace 'lsp.stop' + end, + }, + }, + }, + actions = { + args = 1, + name = 'actions', + condition = 'markdown', + callback = function(e) + log.trace 'actions' + end, + subcommands = { + workspace = { + args = 1, + name = 'actions.workspace', + condition = 'markdown', + callback = function(e) + log.trace 'actions.workspce' + end, + }, + }, + }, + rename = { + args = 1, + max_args = 1, + name = 'rename', + condition = 'markdown', + subcommands = { + workspace = { + args = 0, + name = 'rename.workspace', + condition = 'markdown', + callback = function(e) + log.trace 'rename.workspace' + end, + }, + dir = { + args = 0, + name = 'rename.dir', + condition = 'markdown', + callback = function(e) + log.trace 'rename.dir' + end, + }, + section = { + args = 0, + name = 'rename.section', + condition = 'markdown', + callback = function(e) + log.trace 'rename.section' + end, + }, + file = { + args = 0, + name = 'rename.file', + condition = 'markdown', + callback = function(e) + log.trace 'rename.file' + end, + }, + }, + }, +} diff --git a/lua/down/mod/lsp/init.lua b/lua/down/mod/lsp/init.lua index 3256126..fd9ee9f 100644 --- a/lua/down/mod/lsp/init.lua +++ b/lua/down/mod/lsp/init.lua @@ -1,15 +1,16 @@ local mod = require 'down.mod' +local log = require 'down.util.log' local settings = require('down.mod.lsp.settings') ---@class down.mod.Lsp: down.Mod -local Lsp = require('down.mod').new('lsp', {}) +local Lsp = mod.new 'lsp' ---@return down.mod.Setup Lsp.setup = function() ---@type down.mod.Setup return { loaded = true, - requires = { + dependencies = { 'cmd', 'workspace', }, @@ -17,14 +18,62 @@ Lsp.setup = function() end Lsp.commands = { + lsp = { + name = 'lsp', + condition = 'markdown', + callback = function(e) + log.trace 'lsp' + end, + subcommands = { + restart = { + args = 0, + name = 'lsp.restart', + condition = 'markdown', + callback = function(e) + log.trace 'lsp.restart' + end, + }, + start = { + args = 0, + name = 'lsp.start', + condition = 'markdown', + callback = function(e) + log.trace 'lsp.start' + end, + }, + status = { + args = 0, + name = 'lsp.status', + condition = 'markdown', + callback = function(e) + log.trace 'lsp.status' + end, + }, + stop = { + args = 0, + name = 'lsp.stop', + condition = 'markdown', + callback = function(e) + log.trace 'lsp.stop' + end, + }, + }, + }, actions = { args = 1, name = 'actions', condition = 'markdown', + callback = function(e) + log.trace 'actions' + end, subcommands = { workspace = { args = 1, name = 'actions.workspace', + condition = 'markdown', + callback = function(e) + log.trace 'actions.workspce' + end, }, }, }, @@ -37,24 +86,41 @@ Lsp.commands = { workspace = { args = 0, name = 'rename.workspace', + condition = 'markdown', + callback = function(e) + log.trace 'rename.workspace' + end, }, dir = { args = 0, name = 'rename.dir', + condition = 'markdown', + callback = function(e) + log.trace 'rename.dir' + end, + }, + section = { + args = 0, + name = 'rename.section', + condition = 'markdown', + callback = function(e) + log.trace 'rename.section' + end, }, file = { args = 0, name = 'rename.file', + condition = 'markdown', + callback = function(e) + log.trace 'rename.file' + end, }, }, }, } Lsp.load = function() - -- local autocmd = Lsp.data.ft('*.{md,dn,dd}') - local autocmd = Lsp.data.ft('markdown') - -- local autocmd = Lsp.data.ft('*.dd') - -- local autocmd = Lsp.data.ft('*.dn') + local autocmd = Lsp.data.ft 'markdown' end ---@class (exact) down.mod.lsp.Config @@ -70,7 +136,7 @@ Lsp.config = { function Lsp.data.run() local ft = vim.bo.filetype - local ext = vim.fn.expand('%:e') + local ext = vim.fn.expand '%:e' if ext == 'md' or ext == 'dn' or ext == 'dd' or ext == 'down' or ext == 'downrc' then vim.lsp.start(Lsp.config) end @@ -83,12 +149,12 @@ function Lsp.data.augroup() end function Lsp.data.serve() - vim.lsp.start({ + vim.lsp.start { name = 'downls', cmd = { 'down', 'lsp' }, root_dir = vim.fn.getcwd(), settings = Lsp.config.settings, - }) + } end Lsp.data.autocmd = function(ft) @@ -107,10 +173,13 @@ Lsp.data.ft = function(ft) }) end ----@param e down.Event -Lsp.handle = function(e) - print(e) - local es = e.split -end +-- ---@param e down.Event +-- Lsp.handle = { +-- cmd = { +-- ['rename'] = function(e) end, +-- ['action'] = function(e) end, +-- ['lsp'] = function(e) end, +-- }, +-- } return Lsp diff --git a/lua/down/mod/note/capture/init.lua b/lua/down/mod/note/capture/init.lua index a74dc87..3858324 100644 --- a/lua/down/mod/note/capture/init.lua +++ b/lua/down/mod/note/capture/init.lua @@ -1,14 +1,14 @@ ---@type down.Mod -local M = require "down.mod".new("note.capture") +local M = require 'down.mod'.new('note.capture') ---@return down.mod.Setup M.setup = function() ---@type down.mod.Setup return { loaded = true, - requires = { - "cmd", - "workspace", + dependencies = { + 'cmd', + 'workspace', }, } end @@ -23,9 +23,9 @@ M.config = {} M.events = {} ---@class down.mod.note.capture.Subscribed -M.subscribed = { +M.handle = { cmd = { - ["capture"] = true, + ['capture'] = true, }, } diff --git a/lua/down/mod/edit/toc/README.md b/lua/down/mod/note/cmd.lua similarity index 100% rename from lua/down/mod/edit/toc/README.md rename to lua/down/mod/note/cmd.lua diff --git a/lua/down/mod/note/init.lua b/lua/down/mod/note/init.lua index 646fd07..683dd05 100644 --- a/lua/down/mod/note/init.lua +++ b/lua/down/mod/note/init.lua @@ -7,158 +7,149 @@ local util = require('down.util') local mod = require('down.mod') ---@class down.mod.Note: down.Mod -local M = mod.new('note', {}) +local M = mod.new 'note' M.maps = { - { 'n', ',dn', 'Down note today', 'Down today note' }, + { 'n', ',dn', 'Down note today', 'Down today note' }, { 'n', ',dy', 'Down note yesterday', 'Down yesterday note' }, - { 'n', ',dt', 'Down note tomorrow', 'Down tomorrow note' }, - { 'n', ',dc', 'Down note capture', 'Down capture note' }, + { 'n', ',dt', 'Down note tomorrow', 'Down tomorrow note' }, + { 'n', ',dc', 'Down note capture', 'Down capture note' }, } ---@class down.mod.note.Data M.data = { week_index = function() - local wk = os.date('%V') + local wk = os.date '%V' end, year_index = function() - local yr = os.date('%Y') - local ws = M.config.workspace or M.required['workspace'].get_current_workspace()[1] - local ws_path = M.required['workspace'].get_workspace(ws) + local yr = os.date '%Y' + local ws = M.config.workspace or M.dep['workspace'].get_current_workspace()[1] + local ws_path = M.dep['workspace'].get_workspace(ws) local ix = M.config.note_folder .. config.pathsep .. yr .. config.pathsep .. M.config.index local path = ws_path .. config.pathsep .. ix - local index_exists = M.required['workspace'].file_exists(path) - if index_exists then - M.required['workspace'].open_file(ws, ix) - else - M.required['workspace'].new_file(ix, ws) - M.required['workspace'].open_file(ws, ix) + local index_exists = M.dep['workspace'].file_exists(path) + if not index_exists then + M.dep['workspace'].new_file(ix, ws) end + M.dep['workspace'].open_file(ws, ix) end, month_index = function() - local yr = os.date('%Y') - local mo = os.date('%m') - local ws = M.config.workspace or M.required['workspace'].get_current_workspace()[1] - local ws_path = M.required['workspace'].get_workspace(ws) + local yr = os.date '%Y' + local mo = os.date '%m' + local ws = M.config.workspace or M.dep['workspace'].get_current_workspace()[1] + local ws_path = M.dep['workspace'].get_workspace(ws) local ix = M.config.note_folder - .. config.pathsep - .. yr - .. config.pathsep - .. mo - .. config.pathsep - .. M.config.index + .. config.pathsep + .. yr + .. config.pathsep + .. mo + .. config.pathsep + .. M.config.index local path = ws_path .. config.pathsep .. ix - local index_exists = M.required['workspace'].file_exists(path) + local index_exists = M.dep['workspace'].file_exists(path) if index_exists then - M.required['workspace'].open_file(ws, ix) + M.dep['workspace'].open_file(ws, ix) else - M.required['workspace'].new_file(ix, ws) - M.required['workspace'].open_file(ws, ix) + M.dep['workspace'].new_file(ix, ws) + M.dep['workspace'].open_file(ws, ix) end end, select_month = function() end, note_index = function() - local ws = M.config.workspace or M.required['workspace'].get_current_workspace()[1] - local ws_path = M.required['workspace'].get_workspace(ws) + local ws = M.config.workspace or M.dep['workspace'].get_current_workspace()[1] + local ws_path = M.dep['workspace'].get_workspace(ws) local ix = M.config.note_folder .. config.pathsep .. M.config.index local path = ws_path .. config.pathsep .. ix - local index_exists = M.required['workspace'].file_exists(path) + local index_exists = M.dep['workspace'].file_exists(path) if not index_exists then - M.required['workspace'].new_file(ix, ws) + M.dep['workspace'].new_file(ix, ws) end - M.required['workspace'].open_file(ws, ix) + M.dep['workspace'].open_file(ws, ix) end, --- Opens a note entry at the given time ---@param time? number #The time to open the note entry at as returned by `os.time()` ---@param custom_date? string #A YYYY-mm-dd string that specifies a date to open the note at instead open_year = function(time, custom_date) - -- TODO(vhyrro): Change this to use down dates! - local workspace = M.config.workspace or M.required['workspace'].get_current_workspace()[1] - local workspace_path = M.required['workspace'].get_workspace(workspace) + local workspace = M.config.workspace or M.dep['workspace'].get_current_workspace()[1] + local workspace_path = M.dep['workspace'].get_workspace(workspace) local folder_name = M.config.note_folder local tmpl = M.config.template.year - if custom_date then - local year, _month, _day = custom_date:match('^(%d%d%d%d)-(%d%d)-(%d%d)$') - + local year, _month, _day = custom_date:match '^(%d%d%d%d)-(%d%d)-(%d%d)$' if not year then - log.error('Wrong date format: use YYYY-mm-dd') + log.error 'Wrong date format: use YYYY-mm-dd' return end - - time = os.time({ + time = os.time { year = year, month = 1, day = 1, - }) - local y = os.date('%Y') + } end local path = os.date( type(M.config.strategy) == 'function' and M.config.strategy(os.date('*t', time)) - or M.config.strategy, + or M.config.strategy, time ) - local note_file_exists = M.required['workspace'].file_exists( - workspace_path .. '/' .. folder_name .. config.pathsep .. path - ) + local note_file_exists = + M.dep['workspace'].file_exists(workspace_path .. config.pathsep .. folder_name .. config.pathsep .. path) - M.required['workspace'].new_file(folder_name .. config.pathsep .. path, workspace) + M.dep['workspace'].new_file(folder_name .. config.pathsep .. path, workspace) if - not note_file_exists - and M.config.template.enable - and M.required['workspace'].file_exists(workspace_path .. '/' .. folder_name .. '/' .. tmpl) + not note_file_exists + and M.config.template.enable + and M.dep['workspace'].file_exists(workspace_path .. config.pathsep .. folder_name .. config.pathsep .. tmpl) then - vim.cmd('$read ' .. workspace_path .. '/' .. folder_name .. '/' .. tmpl .. '| silent! w') + vim.cmd('$read ' .. workspace_path .. config.pathsep .. folder_name .. config.pathsep .. tmpl .. '| silent! w') end end, ---@param time? number #The time to open the note entry at as returned by `os.time()` ---@param custom_date? string #A YYYY-mm-dd string that specifies a date to open the note at instead open_month = function(time, custom_date) - local workspace = M.config.workspace or M.required['workspace'].get_current_workspace()[1] - local workspace_path = M.required['workspace'].get_workspace(workspace) + local workspace = M.config.workspace or M.dep['workspace'].get_current_workspace()[1] + local workspace_path = M.dep['workspace'].get_workspace(workspace) local folder_name = M.config.note_folder local tmpl = M.config.template.month if custom_date then - local year, month, day = custom_date:match('^(%d%d%d%d)-(%d%d)-(%d%d)$') + local year, month, day = custom_date:match '^(%d%d%d%d)-(%d%d)-(%d%d)$' if not year or not month or not day then - log.error('Wrong date format: use YYYY-mm-dd') + log.error 'Wrong date format: use YYYY-mm-dd' return end - time = os.time({ + time = os.time { year = year, month = month, day = day, - }) + } end local path = os.date( type(M.config.strategy) == 'function' and M.config.strategy(os.date('*t', time)) - or M.config.strategy, + or M.config.strategy, time ) - local note_file_exists = M.required['workspace'].file_exists( - workspace_path .. '/' .. folder_name .. config.pathsep .. path - ) + local note_file_exists = + M.dep['workspace'].file_exists(workspace_path .. config.pathsep .. folder_name .. config.pathsep .. path) - M.required['workspace'].new_file(folder_name .. config.pathsep .. path, workspace) + M.dep['workspace'].new_file(folder_name .. config.pathsep .. path, workspace) if - not note_file_exists - and M.config.template.enable - and M.required['workspace'].file_exists(workspace_path .. '/' .. folder_name .. '/' .. tmpl) + not note_file_exists + and M.config.template.enable + and M.dep['workspace'].file_exists(workspace_path .. config.pathsep .. folder_name .. config.pathsep .. tmpl) then - vim.cmd('$read ' .. workspace_path .. '/' .. folder_name .. '/' .. tmpl .. '| silent! w') + vim.cmd('$read ' .. workspace_path .. config.pathsep .. folder_name .. config.pathsep .. tmpl .. '| silent! w') end end, capture = function() - local b, w = M.required['ui.win'].win('today', 'note', 'Down note today') + local b, w = M.dep['ui.win'].win('today', 'note', 'Down note today') -- vim.cmd -- Mod.get_mod("ui.win").cmd(w, function() @@ -170,46 +161,41 @@ M.data = { ---@param time? number #The time to open the note entry at as returned by `os.time()` ---@param custom_date? string #A YYYY-mm-dd string that specifies a date to open the note at instead open_note = function(time, custom_date) - -- TODO(vhyrro): Change this to use down dates! - local workspace = M.config.workspace or M.required['workspace'].get_current_workspace()[1] - local workspace_path = M.required['workspace'].get_workspace(workspace) + local workspace = M.config.workspace or M.dep['workspace'].get_current_workspace()[1] + local workspace_path = M.dep['workspace'].get_workspace(workspace) local folder_name = M.config.note_folder local tmpl = M.config.template.day if custom_date then - local year, month, day = custom_date:match('^(%d%d%d%d)-(%d%d)-(%d%d)$') + local year, month, day = custom_date:match '^(%d%d%d%d)-(%d%d)-(%d%d)$' if not year or not month or not day then - log.error('Wrong date format: use YYYY-mm-dd') + log.error 'Wrong date format: use YYYY-mm-dd' return end - time = os.time({ + time = os.time { year = year, month = month, day = day, - }) + } end local path = os.date( type(M.config.strategy) == 'function' and M.config.strategy(os.date('*t', time)) - or M.config.strategy, + or M.config.strategy, time ) - local note_file_exists = M.required['workspace'].file_exists( - workspace_path .. '/' .. folder_name .. config.pathsep .. path - ) - - -- M.required['workspace'].new_file(folder_name .. config.pathsep .. path, workspace) - M.required['workspace'].new_file(folder_name .. config.pathsep .. path, workspace) + local note_file_exists = + M.dep['workspace'].file_exists(workspace_path .. '/' .. folder_name .. config.pathsep .. path) - -- M.required["workspace"].new_file(folder_name..config.pathsep..path, workspace) + M.dep['workspace'].new_file(folder_name .. config.pathsep .. path, workspace) if - not note_file_exists - and M.config.template.enable - and M.required['workspace'].file_exists(workspace_path .. '/' .. folder_name .. '/' .. tmpl) + not note_file_exists + and M.config.template.enable + and M.dep['workspace'].file_exists(workspace_path .. '/' .. folder_name .. '/' .. tmpl) then vim.cmd('$read ' .. workspace_path .. '/' .. folder_name .. '/' .. tmpl .. '| silent! w') end @@ -256,9 +242,9 @@ M.data = { local workspace = M.config.workspace local folder_name = M.config.note_folder local tmpl = M.config.template.month - M.required['workspace'].new_file( + M.dep['workspace'].new_file( folder_name .. config.pathsep .. tmpl, - workspace or M.required['workspace'].get_current_workspace()[1] + workspace or M.dep['workspace'].get_current_workspace()[1] ) end, --- Creates a template file @@ -266,9 +252,9 @@ M.data = { local workspace = M.config.workspace local folder_name = M.config.note_folder local tmpl = M.config.template.year - M.required['workspace'].new_file( + M.dep['workspace'].new_file( folder_name .. config.pathsep .. tmpl, - workspace or M.required['workspace'].get_current_workspace()[1] + workspace or M.dep['workspace'].get_current_workspace()[1] ) end, create_day_template = function() @@ -276,31 +262,31 @@ M.data = { local folder_name = M.config.note_folder local tmpl = M.config.template.day - M.required['workspace'].new_file( + M.dep['workspace'].new_file( folder_name .. config.pathsep .. tmpl, - workspace or M.required['workspace'].get_current_workspace()[1] + workspace or M.dep['workspace'].get_current_workspace()[1] ) end, --- Opens the toc file open_toc = function() - local workspace = M.config.workspace or M.required['workspace'].get_current_workspace()[1] - local index = mod.mod_config('workspace').index + local workspace = M.config.workspace or M.dep['workspace'].get_current_workspace()[1] + local index = mod.mod_config 'workspace'.index local folder_name = M.config.note_folder -- If the toc exists, open it, if not, create it - if M.required['workspace'].file_exists(folder_name .. config.pathsep .. index) then - M.required['workspace'].open_file(workspace, folder_name .. config.pathsep .. index) + if M.dep['workspace'].file_exists(folder_name .. config.pathsep .. index) then + M.dep['workspace'].open_file(workspace, folder_name .. config.pathsep .. index) else - M.data.new_toc() + M.data.create_toc() end end, --- Creates or updates the toc file create_toc = function() - local workspace = M.config.workspace or M.required['workspace'].get_current_workspace()[1] + local workspace = M.config.workspace or M.dep['workspace'].get_current_workspace()[1] local index = mod.mod_config('workspace').index - local workspace_path = M.required['workspace'].get_workspace(workspace) + local workspace_path = M.dep['workspace'].get_workspace(workspace) local workspace_name_for_link = M.config.workspace or '' local folder_name = M.config.note_folder @@ -325,8 +311,8 @@ M.data = { -- Gets the title from the metadata of a file, must be called in a vim.schedule local get_title = function(file) local buffer = - vim.fn.bufadd(workspace_path .. config.pathsep .. folder_name .. config.pathsep .. file) - local meta = M.required['workspace'].get_document_metadata(buffer) + vim.fn.bufadd(workspace_path .. config.pathsep .. folder_name .. config.pathsep .. file) + local meta = M.dep['workspace'].get_document_metadata(buffer) return meta.title end @@ -341,18 +327,13 @@ M.data = { while true do -- Name corresponds to either a YYYY-mm-dd.down file, or just the year ("nested" strategy) local name, type = vim.loop.fs_scandir_next(handle) ---@diagnostic disable-line -- TODO: type error workaround - if not name then break end - - -- Handle nested entries if type == 'directory' then local years_handle = get_fs_handle(name) while true do - -- mname is the month local mname, mtype = vim.loop.fs_scandir_next(years_handle) - if not mname then break end @@ -360,15 +341,13 @@ M.data = { if mtype == 'directory' then local months_handle = get_fs_handle(name .. config.pathsep .. mname) while true do - -- dname is the day local dname, dtype = vim.loop.fs_scandir_next(months_handle) - if not dname then break end -- If it's a .down file, also ensure it is a day entry - if dtype == 'file' and string.match(dname, '%d%d%.md') then + if dtype == 'file' and (dname):match('%d%d%.md') then -- Split the file name local file = vim.split(dname, '.', { plain = true }) @@ -384,16 +363,16 @@ M.data = { tonumber(mname), tonumber(file[1]), '{:$' - .. workspace_name_for_link - .. config.pathsep - .. M.config.note_folder - .. config.pathsep - .. name - .. config.pathsep - .. mname - .. config.pathsep - .. file[1] - .. ':}', + .. workspace_name_for_link + .. config.pathsep + .. M.config.note_folder + .. config.pathsep + .. name + .. config.pathsep + .. mname + .. config.pathsep + .. file[1] + .. ':}', title, }) end) @@ -427,12 +406,12 @@ M.data = { parts[2], parts[3], '{:$' - .. workspace_name_for_link - .. config.pathsep - .. M.config.note_folder - .. config.pathsep - .. file[1] - .. ':}', + .. workspace_name_for_link + .. config.pathsep + .. M.config.note_folder + .. config.pathsep + .. file[1] + .. ':}', title, }) end) @@ -440,36 +419,32 @@ M.data = { end vim.schedule(function() - -- Gets a base format for the entries local format = M.config.toc_format - or function(entries) - local months_text = M.months - -- Convert the entries into a certain format to be written - local output = {} - local current_year - local current_month - for _, entry in ipairs(entries) do - -- Don't print the year and month if they haven't changed - if not current_year or current_year < entry[1] then - current_year = entry[1] - current_month = nil - table.insert(output, '* ' .. current_year) - end - if not current_month or current_month < entry[2] then - current_month = entry[2] - table.insert(output, '** ' .. months_text[current_month]) + or function(entries) + local months_text = M.months + local output = {} + local current_year, current_month + for _, entry in ipairs(entries) do + if not current_year or current_year < entry[1] then + current_year = entry[1] + current_month = nil + output:insert('* ' .. current_year) + end + if not current_month or current_month < entry[2] then + current_month = entry[2] + output:insert('** ' .. months_text[current_month]) + end + + -- Prints the file link + output:insert(' ' .. entry[4] .. ('[%s]'):format(entry[5])) end - -- Prints the file link - table.insert(output, ' ' .. entry[4] .. string.format('[%s]', entry[5])) + return output end - return output - end - - M.required['workspace'].new_file( + M.dep['workspace'].new_file( folder_name .. config.pathsep .. index, - workspace or M.required['workspace'].get_current_workspace()[1] + workspace or M.dep['workspace'].get_current_workspace()[1] ) -- The current buffer now must be the toc file, so we set our toc entries there @@ -524,101 +499,27 @@ M.config.strategies = { nested = '%Y' .. config.pathsep .. '%m' .. config.pathsep .. '%d.md', } ----@param event down.Event -M.handle = function(event) - local ty = event.split[1] - local ev = event.split[2] - if ty == 'cmd' then - if ev == 'note' or ev == 'note.index' then - M.data.note_index() - elseif ev == 'note.week' or ev == 'note.week.index' then - M.data.week_index() - elseif event.split[2] == 'note.week.previous' then - M.data.week_prev() - elseif event.split[2] == 'note.week.next' then - M.data.week_next() - elseif event.split[2] == 'note.month.previous' then - print('TODO:month previous') - elseif event.split[2] == 'note.month.next' then - print('TODO:month next') - elseif event.split[2] == 'note.year.previous' then - print('TODO:year prev') - elseif event.split[2] == 'note.year.next' then - print('TODO:year next') - elseif ev == 'note.year' or ev == 'note.year.index' then - M.data.year_index() - elseif ev == 'note.month' or ev == 'note.month.index' then - M.data.month_index() - elseif event.split[2] == 'note.capture' then - M.data.capture() - elseif event.split[2] == 'note.tomorrow' then - M.data.note_tomorrow() - elseif event.split[2] == 'note.yesterday' then - M.data.note_yesterday() - elseif event.split[2] == 'calendar' then - if not event.body[1] then - local cal = M.required['ui.calendar'] - if not cal then - print('[ERROR]: `ui.calendar` is not loaded!') - return - end - cal.select_date({ - callback = vim.schedule_wrap(function(osdate) - M.data.open_note( - nil, - string.format('%04d', osdate.year) - .. '-' - .. string.format('%02d', osdate.month) - .. '-' - .. string.format('%02d', osdate.day) - ) - end), - }) - else - M.data.open_note(nil, event.body[1]) - end - elseif event.split[2] == 'note.calendar' then - if not event.body[1] then - local cal = M.required['ui.calendar'] - if not cal then - print('[ERROR]: `ui.calendar` is not loaded!') - return - end - cal.select_date({ - callback = vim.schedule_wrap(function(osdate) - M.data.open_note( - nil, - string.format('%04d', osdate.year) - .. '-' - .. string.format('%02d', osdate.month) - .. '-' - .. string.format('%02d', osdate.day) - ) - end), - }) - else - M.data.open_note(nil, event.body[1]) - end - elseif ev == 'note.today' then - M.data.note_today() - elseif ev == 'note.template' then - M.data.new_day_template() - elseif ev == 'note.template.day' then - M.data.new_template() - elseif ev == 'note.template.week' then - -- M.data.new_template() - print('TODO note template week index') - elseif ev == 'note.template.month' then - -- M.data.new_template() - print('TODO note template month') - elseif ev == 'note.template.year' then - -- M.data.new_template() - print('TODO note template year') - elseif ev == 'note.toc.open' then - M.data.open_toc() - elseif ev == 'note.toc.update' then - M.data.new_toc() +M.data.open_month_calendar = function(event) + if not event.body[1] then + local cal = M.dep['ui.calendar'] + if not cal then + log.error '[ERROR]: `ui.calendar` is not loaded!' + return end + cal.select_date({ + callback = vim.schedule_wrap(function(osdate) + M.data.open_note( + nil, + ('%04d'):format(osdate.year) + .. '-' + .. ('%02d'):format(osdate.month) + .. '-' + .. ('%02d'):format(osdate.day) + ) + end), + }) + else + M.data.open_note(nil, event.body[1]) end end @@ -626,81 +527,133 @@ M.commands = { calendar = { min_args = 0, max_args = 1, + callback = M.data.open_month_calendar, name = 'calendar', }, -- format :yyyy-mm-dd note = { + name = 'note', + callback = function(e) + log.trace 'note' + end, min_args = 1, max_args = 2, subcommands = { - index = { args = 0, name = 'note.index' }, + index = { + callback = M.data.note_index, + args = 0, + name = 'note.index', + }, month = { max_args = 1, name = 'note.month', + callback = M.data.month_index, subcommands = { - index = { args = 0, name = 'note.month.index' }, + index = { + callback = M.data.month_index, + args = 0, + name = 'note.month.index', + }, previous = { args = 0, + callback = M.data.month_prev, name = 'note.month.previous', }, next = { args = 0, name = 'note.month.next', + callback = M.data.month_next, }, }, }, week = { subcommands = { - index = { args = 0, name = 'note.week.index' }, + index = { + args = 0, + name = 'note.week.index', + callback = M.data.week_index, + }, previous = { args = 0, name = 'note.week.previous', + callback = M.data.week_prev, }, next = { args = 0, name = 'note.week.next', + callback = M.data.week_next, }, }, max_args = 1, name = 'note.week', + callback = M.data.week_index, }, year = { max_args = 1, name = 'note.year', + callback = M.data.year_index, subcommands = { - index = { args = 0, name = 'note.year.index' }, + index = { + args = 0, + callback = M.data.year_index, + name = 'note.year.index', + }, previous = { args = 0, name = 'note.year.previous', + callback = M.data.year_prev, }, next = { args = 0, name = 'note.year.next', + callback = M.data.year_next, }, }, }, - capture = { args = 0, name = 'note.capture' }, - tomorrow = { args = 0, name = 'note.tomorrow' }, - yesterday = { args = 0, name = 'note.yesterday' }, - today = { args = 0, name = 'note.today' }, + capture = { + callback = M.data.capture, + args = 0, + name = 'note.capture', + }, + tomorrow = { + callback = M.data.note_tomorrow, + args = 0, + name = 'note.tomorrow', + }, + yesterday = { + args = 0, + name = 'note.yesterday', + callback = M.data.note_yesterday, + }, + today = { + callback = M.data.note_today, + args = 0, + name = 'note.today', + }, calendar = { + callback = M.data.open_month_calendar, max_args = 1, name = 'note.calendar', }, -- format :yyyy-mm-dd template = { + callback = M.data.create_day_template, subcommands = { year = { + callback = M.data.create_year_template, name = 'notes.template.year', args = 0, }, week = { + callback = M.data.create_year_template, name = 'notes.template.week', args = 0, }, month = { + callback = M.data.create_month_template, name = 'notes.template.month', args = 0, }, day = { + callback = M.data.create_day_template, name = 'notes.template.day', args = 0, }, @@ -711,9 +664,18 @@ M.commands = { toc = { args = 1, name = 'note.toc', + callback = M.data.open_toc, subcommands = { - open = { args = 0, name = 'note.toc.open' }, - update = { args = 0, name = 'note.toc.update' }, + open = { + callback = M.data.open_toc, + args = 0, + name = 'note.toc.open', + }, + update = { + args = 0, + name = 'note.toc.update', + callback = M.data.create_toc, + }, }, }, }, @@ -730,10 +692,11 @@ end M.setup = function() return { loaded = true, - requires = { + dependencies = { 'ui.win', 'ui.calendar', 'data', + 'cmd', 'template', 'workspace', 'tool.treesitter', @@ -741,37 +704,37 @@ M.setup = function() } end ----@class down.mod.note.Subscribed -M.subscribed = { - cmd = { - ['note.index'] = true, - ['note.month'] = true, - ['note.week'] = true, - ['note.year'] = true, - ['note'] = true, - ['note.month.previous'] = true, - ['note.week.previous'] = true, - ['note.year.previous'] = true, - ['note.month.next'] = true, - ['note.week.next'] = true, - ['note.year.next'] = true, - ['note.month.index'] = true, - ['note.week.index'] = true, - ['note.year.index'] = true, - ['note.yesterday'] = true, - ['note.tomorrow'] = true, - ['note.capture'] = true, - ['note.today'] = true, - ['calendar'] = true, - ['note.calendar'] = true, - ['note.template'] = true, - ['note.template.day'] = true, - ['note.template.month'] = true, - ['note.template.week'] = true, - ['note.template.year'] = true, - ['note.toc.update'] = true, - ['note.toc.open'] = true, - }, -} +-- -@class down.mod.note.Subscribed +-- M.handle = { +-- cmd = { +-- ['note.index'] = M.data.note_index, +-- ['note.month'] = M.data.month_index, +-- ['note.week'] = M.data.week_index, +-- ['note.year'] = M.data.year_index, +-- ['note'] = function(e) end, +-- ['note.month.previous'] = M.data.month_prev, +-- ['note.week.previous'] = M.data.week_prev, +-- ['note.year.previous'] = M.data.year_prev, +-- ['note.month.next'] = M.data.month_next, +-- ['note.week.next'] = M.data.week_next, +-- ['note.year.next'] = M.data.year_next, +-- ['note.month.index'] = M.data.month_index, +-- ['note.week.index'] = M.data.week_index, +-- ['note.year.index'] = M.data.year_index, +-- ['note.yesterday'] = M.data.note_yesterday, +-- ['note.tomorrow'] = M.data.note_tomorrow, +-- ['note.capture'] = M.data.capture, +-- ['note.today'] = M.data.note_today, +-- ['calendar'] = M.data.open_note, +-- ['note.calendar'] = M.data.open_note, +-- ['note.template'] = M.data.create_day_template, +-- ['note.template.day'] = M.data.create_day_template, +-- ['note.template.month'] = M.data.create_month_template, +-- ['note.template.year'] = M.data.create_year_template, +-- ['note.toc.update'] = M.data.create_toc, +-- ['note.toc.open'] = M.data.open_toc, +-- ['note.template.week'] = function(e) end, +-- }, +-- } return M diff --git a/lua/down/mod/parse/init.lua b/lua/down/mod/parse/init.lua index 1fd9525..2cbed01 100644 --- a/lua/down/mod/parse/init.lua +++ b/lua/down/mod/parse/init.lua @@ -3,7 +3,7 @@ local P = require 'down.mod'.create('parse') P.setup = function() return { loaded = true, - requires = { + dependencies = { 'tool.treesitter' } } diff --git a/lua/down/mod/tag/init.lua b/lua/down/mod/tag/init.lua index 3bf4981..9591612 100644 --- a/lua/down/mod/tag/init.lua +++ b/lua/down/mod/tag/init.lua @@ -4,28 +4,49 @@ local M = require('down.mod').new('tag') M.commands = { tag = { + name = 'tag', + condition = 'markdown', + args = 0, + max_args = 1, + callback = function(e) + log.trace 'tag.commands.tag: cb ' + end, subcommands = { delete = { - args = 0, name = 'data.tag.delete', + condition = 'markdown', + args = 0, + max_args = 1, + callback = function(e) + log.trace 'tag.commands.tag.delete: cb ' + end, }, new = { args = 0, + max_args = 1, + condition = 'markdown', + callback = function(e) + log.trace 'tag.commands.tag.new: cb ' + end, name = 'data.tag.new', }, list = { name = 'data.tag.list', args = 0, + max_args = 1, + condition = 'markdown', + callback = function(e) + log.trace 'tag.commands.tag.list: cb ' + end, }, }, - name = 'tag', }, } ---@return down.mod.Setup M.setup = function() return { loaded = true, - requires = { 'workspace', 'cmd' }, + dependencies = { 'workspace', 'cmd' }, } end @@ -43,17 +64,16 @@ M.data = { --- @return string[] M.data.parse_ln = function(ln) local tags = {} - for tag in ln:gmatch('#%S+') do - table.insert(tags, tag) + for tag in ln:gmatch '#%S+' do + tags:insert(tag) end - print(tags) return tags end M.data.parse = function(text) M.data.tags.document = {} - for ln in text:gmatch('[^\n]+') do - vim.tbl_deep_extend('force', M.data.parse_ln(ln)) + for ln in text:gmatch '[^\n]+' do + vim.tbl_deep_extend('force', M.data.tags.document, M.data.parse_ln(ln)) end return M.data.tags.document end @@ -61,15 +81,13 @@ end ---@class down.mod.data.tag.Config M.config = {} ----@class down.mod.data.tag.Subscribed -M.subscribed = { - cmd = { - ['data.tag.delete'] = true, - ['data.tag.new'] = true, - ['data.tag.list'] = true, - }, -} - -M.handle = function(e) end +-- ---@class down.mod.data.tag.Subscribed +-- M.handle = { +-- cmd = { +-- ['data.tag.delete'] = function(e) end, +-- ['data.tag.new'] = function(e) end, +-- ['data.tag.list'] = function(e) end, +-- }, +-- } return M diff --git a/lua/down/mod/task/agenda/init.lua b/lua/down/mod/task/agenda/init.lua index e635c46..c1abb3b 100644 --- a/lua/down/mod/task/agenda/init.lua +++ b/lua/down/mod/task/agenda/init.lua @@ -40,7 +40,7 @@ M.config = { M.setup = function() ---@type down.mod.Setup return { - requires = { + dependencies = { }, loaded = true, diff --git a/lua/down/mod/task/init.lua b/lua/down/mod/task/init.lua index 2e6df75..a6a7743 100644 --- a/lua/down/mod/task/init.lua +++ b/lua/down/mod/task/init.lua @@ -1,5 +1,8 @@ ----@type down.Mod -local M = require 'down.mod'.new('task', { +local mod = require 'down.mod' +local log = require 'down.util.log' + +---@class down.mod.Task: down.Mod +local M = mod.new('task', { 'agenda', }) @@ -17,13 +20,13 @@ M.Task = { char = -1, }, } ----@class down.mod.data.task.Data +---@class down.mod.task.Data M.data = {} ----@class table +---@class table M.data.tasks = {} ----@class down.mod.data.task.Config +---@class down.mod.task.Config M.config = { store = { root = 'data/task', @@ -36,36 +39,57 @@ M.commands = { name = 'task', args = 0, max_args = 1, + callback = function(e) + log.trace 'task' + end, subcommands = { list = { args = 0, max_args = 1, name = 'task.list', + callback = function(e) + log.trace 'task.list' + end, subcommands = { today = { name = 'task.list.today', args = 0, max_args = 1, + callback = function(e) + log.trace 'task.list.today' + end, }, recurring = { name = 'task.list.recurring', args = 0, max_args = 1, + callback = function(e) + log.trace 'task.list.recurring' + end, }, todo = { name = 'task.list.todo', args = 0, max_args = 1, + callback = function(e) + log.trace 'task.list.todo' + end, }, done = { name = 'task.list.done', args = 0, max_args = 1, + callback = function(e) + log.trace 'task.list.done' + end, }, }, }, add = { name = 'task.add', + callback = function(e) + log.trace 'task.add' + end, args = 1, min_args = 0, max_args = 2, @@ -80,7 +104,7 @@ M.load = function() end M.setup = function() ---@type down.mod.Setup return { - requires = { + dependencies = { 'workspace', 'cmd', 'ui.calendar', @@ -91,4 +115,27 @@ M.setup = function() } end +-- M.handle = { +-- cmd = { +-- ['task.list'] = function() +-- print('task.list') +-- end, +-- ['task.list.today'] = function() +-- print('task.list.today') +-- end, +-- ['task.list.recurring'] = function() +-- print('task.list.recurring') +-- end, +-- ['task.list.todo'] = function() +-- print('task.list.todo') +-- end, +-- ['task.list.done'] = function() +-- print('task.list.done') +-- end, +-- ['task.add'] = function() +-- print('task.add') +-- end, +-- }, +-- } + return M diff --git a/lua/down/mod/template/init.lua b/lua/down/mod/template/init.lua index 27aa647..986401a 100644 --- a/lua/down/mod/template/init.lua +++ b/lua/down/mod/template/init.lua @@ -5,28 +5,49 @@ local mod = require 'down.mod' local lib = require 'down.util.lib' ---@class down.mod.template: down.Mod -local M = require 'down.mod'.new('template') +local M = mod.new 'template' M.commands = { template = { min_args = 1, max_args = 2, name = 'template', + callback = M.data.create_template, subcommands = { - index = { args = 0, name = 'template.index' }, - month = { max_args = 1, name = 'template.month' }, - tomorrow = { args = 0, name = 'template.tomorrow' }, - yesterday = { args = 0, name = 'template.yesterday' }, - today = { args = 0, name = 'template.today' }, - custom = { max_args = 1, name = 'template.custom' }, -- format :yyyy-mm-dd - template = { args = 0, name = 'template.template' }, - toc = { - args = 1, - name = 'template.toc', - subcommands = { - open = { args = 0, name = 'template.toc.open' }, - update = { args = 0, name = 'template.toc.update' }, - }, + index = { + callback = M.data.open_index, + args = 0, + name = 'template.index', + }, + month = { + max_args = 1, + name = 'template.month', + callback = M.data.open_month, + }, + tomorrow = { + callback = M.data.template_tomorrow, + args = 0, + name = 'template.tomorrow', + }, + yesterday = { + args = 0, + name = 'template.yesterday', + M.data.template_yesterday, + }, + today = { + args = 0, + name = 'template.today', + callback = M.data.template_today, + }, + custom = { + callback = M.data.create_template, + max_args = 1, + name = 'template.custom', + }, -- format :yyyy-mm-dd + template = { + callback = M.data.create_template, + args = 0, + name = 'template.template', }, }, }, @@ -40,7 +61,7 @@ end M.setup = function() return { loaded = true, - requires = { + dependencies = { 'cmd', 'workspace', 'tool.treesitter', @@ -75,12 +96,6 @@ M.config = { -- Whether to apply the template file to new template entries. use_template = true, - - -- Formatter function used to generate the toc file. - -- Receives a table that contains tables like { yy, mm, dd, link, title }. - -- - -- The function must return a table of strings. - toc_format = nil, } ---@class down.mod.template.Data @@ -93,9 +108,8 @@ M.data = { ---@param time? number #The time to open the template entry at as returned by `os.time()` ---@param custom_date? string #A YYYY-mm-dd string that specifies a date to open the template at instead open_template = function(time, custom_date) - -- TODO(vhyrro): Change this to use down dates! - local workspace = M.config.workspace or M.required['workspace'].get_current_workspace()[1] - local workspace_path = M.required['workspace'].get_workspace(workspace) + local workspace = M.config.workspace or M.dep['workspace'].get_current_workspace()[1] + local workspace_path = M.dep['workspace'].get_workspace(workspace) local folder_name = M.config.template_folder local template_name = M.config.template_name @@ -120,18 +134,18 @@ M.data = { time ) - local template_file_exists = M.required['workspace'].file_exists( + local template_file_exists = M.dep['workspace'].file_exists( workspace_path .. '/' .. folder_name .. config.pathsep .. path ) - M.required['workspace'].new_file(folder_name .. config.pathsep .. path, workspace) + M.dep['workspace'].new_file(folder_name .. config.pathsep .. path, workspace) - M.required['workspace'].new_file(folder_name .. config.pathsep .. path, workspace) + M.dep['workspace'].new_file(folder_name .. config.pathsep .. path, workspace) if not template_file_exists and M.config.use_template - and M.required['workspace'].file_exists( + and M.dep['workspace'].file_exists( workspace_path .. '/' .. folder_name .. '/' .. template_name ) then @@ -162,279 +176,24 @@ M.data = { local folder_name = M.config.template_folder local template_name = M.config.template_name - M.required.workspace.new_file( + M.dep.workspace.new_file( folder_name .. config.pathsep .. template_name, - workspace or M.required.workspace.get_current_workspace()[1] - ) - end, - - --- Opens the toc file - open_toc = function() - local workspace = M.config.workspace or M.required['workspace'].get_current_workspace()[1] - local index = mod.mod_config('workspace').index - local folder_name = M.config.template_folder - - -- If the toc exists, open it, if not, create it - if M.required.workspace.file_exists(folder_name .. config.pathsep .. index) then - M.required.workspace.open_file(workspace, folder_name .. config.pathsep .. index) - else - M.data.data.new_toc() - end - end, - - --- Creates or updates the toc file - create_toc = function() - local workspace = M.config.workspace or M.required['workspace'].get_current_workspace()[1] - local index = mod.mod_config('workspace').index - local workspace_path = M.required['workspace'].get_workspace(workspace) - local workspace_name_for_link = M.config.workspace or '' - local folder_name = M.config.template_folder - - -- Each entry is a table that contains tables like { yy, mm, dd, link, title } - local toc_entries = {} - - -- Get a filesystem handle for the files in the template folder - -- path is for each subfolder - local get_fs_handle = function(path) - path = path or '' - local handle = vim.loop.fs_scandir( - workspace_path .. config.pathsep .. folder_name .. config.pathsep .. path - ) - - if type(handle) ~= 'userdata' then - error( - lib.lazy_string_concat("Failed to scan directory '", workspace, path, "': ", handle) - ) - end - - return handle - end - - -- Gets the title from the metadata of a file, must be called in a vim.schedule - local get_title = function(file) - local buffer = - vim.fn.bufadd(workspace_path .. config.pathsep .. folder_name .. config.pathsep .. file) - local meta = M.required['workspace'].get_document_metadata(buffer) - return meta.title - end - - vim.loop.fs_scandir( - workspace_path .. config.pathsep .. folder_name .. config.pathsep, - function(err, handle) - assert( - not err, - lib.lazy_string_concat( - "Unable to generate TOC for directory '", - folder_name, - "' - ", - err - ) - ) - - while true do - -- Name corresponds to either a YYYY-mm-dd.down file, or just the year ("nested" strategy) - local name, type = vim.loop.fs_scandir_next(handle) ---@diagnostic disable-line -- TODO: type error workaround - - if not name then - break - end - - -- Handle nested entries - if type == 'directory' then - local years_handle = get_fs_handle(name) - while true do - -- mname is the month - local mname, mtype = vim.loop.fs_scandir_next(years_handle) - - if not mname then - break - end - - if mtype == 'directory' then - local months_handle = get_fs_handle(name .. config.pathsep .. mname) - while true do - -- dname is the day - local dname, dtype = vim.loop.fs_scandir_next(months_handle) - - if not dname then - break - end - - -- If it's a .down file, also ensure it is a day entry - if dtype == 'file' and string.match(dname, '%d%d%.md') then - -- Split the file name - local file = vim.split(dname, '.', { plain = true }) - - vim.schedule(function() - -- Get the title from the metadata, else, it just base to the name of the file - local title = get_title( - name .. config.pathsep .. mname .. config.pathsep .. dname - ) or file[1] - - -- Insert a new entry - table.insert(toc_entries, { - tonumber(name), - tonumber(mname), - tonumber(file[1]), - '{:$' - .. workspace_name_for_link - .. config.pathsep - .. M.config.template_folder - .. config.pathsep - .. name - .. config.pathsep - .. mname - .. config.pathsep - .. file[1] - .. ':}', - title, - }) - end) - end - end - end - end - end - - -- Handles flat entries - -- If it is a .down file, but it's not any user generated file. - -- The match is here to avoid handling files made by the user, like a template file, or - -- the toc file - if type == 'file' and string.match(name, '%d+-%d+-%d+%.md') then - -- Split yyyy-mm-dd to a table - local file = vim.split(name, '.', { plain = true }) - local parts = vim.split(file[1], '-') - - -- Convert the parts into numbers - for k, v in pairs(parts) do - parts[k] = tonumber(v) ---@diagnostic disable-line -- TODO: type error workaround - end - - vim.schedule(function() - -- Get the title from the metadata, else, it just base to the name of the file - local title = get_title(name) or parts[3] - - -- And insert a new entry that corresponds to the file - table.insert(toc_entries, { - parts[1], - parts[2], - parts[3], - '{:$' - .. workspace_name_for_link - .. config.pathsep - .. M.config.template_folder - .. config.pathsep - .. file[1] - .. ':}', - title, - }) - end) - end - end - - vim.schedule(function() - -- Gets a base format for the entries - local format = M.config.toc_format - or function(entries) - local months_text = require('down.mod.template.util').months - -- Convert the entries into a certain format to be written - local output = {} - local current_year - local current_month - for _, entry in ipairs(entries) do - -- Don't print the year and month if they haven't changed - if not current_year or current_year < entry[1] then - current_year = entry[1] - current_month = nil - table.insert(output, '* ' .. current_year) - end - if not current_month or current_month < entry[2] then - current_month = entry[2] - table.insert(output, '** ' .. months_text[current_month]) - end - - -- Prints the file link - table.insert(output, ' ' .. entry[4] .. string.format('[%s]', entry[5])) - end - - return output - end - - M.required['workspace'].new_file( - folder_name .. config.pathsep .. index, - workspace or M.required['workspace'].get_current_workspace()[1] - ) - - -- The current buffer now must be the toc file, so we set our toc entries there - vim.api.nvim_buf_set_lines(0, 0, -1, false, format(toc_entries)) - vim.cmd('silent! w') - end) - end + workspace or M.dep.workspace.get_current_workspace()[1] ) end, }, } -M.handle = function(event) - if event.split_type[1] == 'cmd' then - if event.split_type[2] == 'template.index' then - M.data.data.open_index() - elseif event.split_type[2] == 'template.month' then - M.data.data.open_month() - elseif event.split_type[2] == 'template.tomorrow' then - M.data.data.oemplate_tomorrow() - elseif event.split_type[2] == 'template.yesterday' then - M.data.data.oemplate_yesterday() - elseif event.split_type[2] == 'template.custom' then - if not event.content[1] then - local calendar = mod.get_mod('ui.calendar') - - if not calendar then - log.error( - '[ERROR]: `base.calendar` is not loaded! Said M is required for this operation.' - ) - return - end - - calendar.select({ - callback = vim.schedule_wrap(function(osdate) - M.data.data.open_template( - nil, - string.format('%04d', osdate.year) - .. '-' - .. string.format('%02d', osdate.month) - .. '-' - .. string.format('%02d', osdate.day) - ) - end), - }) - else - M.data.data.open_template(nil, event.content[1]) - end - elseif event.split_type[2] == 'template.today' then - M.data.data.oemplate_today() - elseif event.split_type[2] == 'template.template' then - M.data.data.new_template() - elseif event.split_type[2] == 'template.toc.open' then - M.data.data.open_toc() - elseif event.split_type[2] == 'template.toc.update' then - M.data.data.new_toc() - end - end -end - -M.subscribed = { - cmd = { - ['template.index'] = true, - ['template.month'] = true, - ['template.yesterday'] = true, - ['template.tomorrow'] = true, - ['template.today'] = true, - ['template.custom'] = true, - ['template.template'] = true, - ['template.toc.update'] = true, - ['template.toc.open'] = true, - }, -} +-- M.handle = { +-- cmd = { +-- ['template.index'] = M.data.open_index, +-- ['template.month'] = M.data.open_month, +-- ['template.tomorrow'] = M.data.template_tomorrow, +-- ['template.yesterday'] = M.data.template_yesterday, +-- ['template.custom'] = M.data.open_template, +-- ['template.today'] = M.data.template_today, +-- ['template.template'] = M.data.create_template, +-- }, +-- } return M diff --git a/lua/down/mod/tool/blink/source/init.lua b/lua/down/mod/tool/blink/source/init.lua index 7c0d1fd..33041b2 100644 --- a/lua/down/mod/tool/blink/source/init.lua +++ b/lua/down/mod/tool/blink/source/init.lua @@ -43,7 +43,7 @@ function Src:get_completiosn(ctx, cb) ---@type blink.cmp.CompletionItem completion = completion local item = { - kind = require("blink.cmp.types").CompletionItemKind.Lsp, + kind = require("blink.cmp.ids").CompletionItemKind.Lsp, -- label = "cmp", label = completion.displayText, insertTextFormat = vim.lsp.protocol.InsertTextFormat.PlainText, diff --git a/lua/down/mod/tool/init.lua b/lua/down/mod/tool/init.lua index 3769b20..ffa3290 100644 --- a/lua/down/mod/tool/init.lua +++ b/lua/down/mod/tool/init.lua @@ -46,7 +46,7 @@ end --- Generic setup function for tool submodules --- @param ext string: the tool to setup ---- @param req table: the modules required by the tool module +--- @param req table: the modules dep by the tool module --- @return down.mod.Setup E.data.setup = function(ext, req) local ok, e = E.data.has(ext) @@ -68,7 +68,7 @@ E.setup = function() } return { loaded = true, - requires = enabled + dependencies = enabled } end diff --git a/lua/down/mod/tool/telescope/init.lua b/lua/down/mod/tool/telescope/init.lua index 909cf5e..283ef7a 100644 --- a/lua/down/mod/tool/telescope/init.lua +++ b/lua/down/mod/tool/telescope/init.lua @@ -7,7 +7,7 @@ M.setup = function() if tok then return { loaded = true, - requires = { 'workspace' }, + dependencies = { 'workspace' }, } else return { @@ -59,33 +59,29 @@ M.data.load_pickers = function() M.data.pickers = r return r end -M.subscribed = { - cmd = { - ['find.files'] = true, - ['find'] = true, - ['find.links'] = true, - ['find.tags'] = true, - ['find.workspace'] = true, - }, -} M.commands = { find = { args = 0, name = 'find', + callback = require 'telescope._extensions.down.picker.files', subcommands = { links = { + callback = require 'telescope._extensions.down.picker.links', name = 'find.links', args = 0, }, tags = { + callback = require 'telescope._extensions.down.picker.tags', name = 'find.tags', args = 0, }, files = { + callback = require 'telescope._extensions.down.picker.files', name = 'find.files', args = 0, }, workspace = { + callback = require 'telescope._extensions.down.picker.workspace', name = 'find.workspace', args = 0, }, @@ -96,7 +92,7 @@ M.load = function() assert(tok) M.data.load_pickers() if tok then - t.load_extension('down') + t.load_extension 'down' for _, pic in ipairs(M.config.enabled) do vim.keymap.set('n', 'down.telescope.' .. pic .. '', M.data.pickers[pic]) end @@ -106,34 +102,21 @@ M.load = function() end M.maps = { - { 'n', ',df', 'Telescope down files', 'Telescope down files' }, - { 'n', ',dt', 'Telescope down tags', 'Telescope down tags' }, - { 'n', ',dk', 'Telescope down links', 'Telescope down links' }, + { 'n', ',df', 'Telescope down files', 'Telescope down files' }, + { 'n', ',dF', 'Telescope down', 'Telescope down' }, + { 'n', ',dt', 'Telescope down tags', 'Telescope down tags' }, + { 'n', ',dk', 'Telescope down links', 'Telescope down links' }, { 'n', ',dW', 'Telescope down workspace', 'Telescope down workspaces' }, } -M.handle = function(event) - if event.split[1] == 'cmd' then - if event.split[2] == 'find' then - require('telescope._extensions.down.picker.files')() - elseif event.split[2] == 'find.files' then - if M.config.enabled['files'] ~= nil then - require('telescope._extensions.down.picker.files')() - end - elseif event.split[2] == 'find.tags' then - if M.config.enabled['tags'] ~= nil then - require('telescope._extensions.down.picker.tags')() - end - elseif event.split[2] == 'find.links' then - if M.config.enabled['links'] ~= nil then - require('telescope._extensions.down.picker.links')() - end - elseif event.split[2] == 'find.workspace' then - if M.config.enabled['workspace'] ~= nil then - require('telescope._extensions.down.picker.workspace')() - end - end - end -end +-- M.handle = { +-- cmd = { +-- ['find'] = +-- ['find.files'] = require('telescope._extensions.down.picker.files'), +-- ['find.tags'] = require('telescope._extensions.down.picker.tags'), +-- ['find.workspace'] = require('telescope._extensions.down.picker.workspace'), +-- ['find.links'] = require('telescope._extensions.down.picker.links'), +-- }, +-- } return M diff --git a/lua/down/mod/tool/treesitter/init.lua b/lua/down/mod/tool/treesitter/init.lua index 0a7eb16..2fc6032 100644 --- a/lua/down/mod/tool/treesitter/init.lua +++ b/lua/down/mod/tool/treesitter/init.lua @@ -1,21 +1,25 @@ -local down = require("down") -local config = require("down.config") +local down = require "down" +local config = require "down.config" local log = require "down.util.log" local mod = require "down.mod" local lib = require "down.util.lib" local util = require "down.util" - +local tsu_ok, tsu = pcall(require, "nvim-treesitter.ts_utils") +local install = require "nvim-treesitter.install" +local shell = require "nvim-treesitter.shell_command_selectors" +local u = require "nvim-treesitter.utils" +local ntp = require "nvim-treesitter.parsers" +local loc = require "nvim-treesitter.locals" + +local ts = vim.treesitter local vt = vim.treesitter local q = vt.query - local hi = vt.highlight -local u = require("nvim-treesitter.utils") -local loc = require("nvim-treesitter.locals") -local tsu = require("nvim-treesitter.ts_utils") -local M = require("down.mod").new("tool.treesitter") +---@class down.mod.tool.Treesitter: down.Mod +local M = mod.new "tool.treesitter" ----@class down.tool.treesitter.Data +---@class down.mod.tool.treesitter.Data M.data = { ts_utils = nil, heading = [[ @@ -82,14 +86,13 @@ M.load = function() -- }, -- }) -- end) - local success, ts_utils = pcall(require, "nvim-treesitter.ts_utils") - assert(success, "Unable to load nvim-treesitter.ts_utils :(") + assert(tsu_ok, "Unable to load nvim-treesitter.ts_utils") if M.config.configure_parsers then -- luacheck: push ignore - local parser_configs = require("nvim-treesitter.parsers").get_parser_configs() + local parser_configs = ntp.get_parser_configs() -- parser_configs.down = { -- install_info = M.config.parser_configs.down, @@ -154,7 +157,7 @@ M.config = { configure_parsers = true, --- If true will automatically install down parsers if they are not present. -- install_parsers = true, - --- Configurations for each parser as required by `nvim-treesitter`. + --- Configurations for each parser as dep by `nvim-treesitter`. -- If you would like to tweak your parser configs you may do so here. -- parser_configs = { -- Configuration for the mainline down parser. @@ -184,7 +187,7 @@ M.data = { parse = function(language, query) local result = M.data.queries[query] if result == nil then - result = vim.treesitter.query.parse(language, query) + result = ts.query.parse(language, query) M.data.queries[query] = result end return result @@ -198,7 +201,7 @@ M.data = { end local query = '' - local files = vim.treesitter.query.get_files(language, 'injections') + local files = ts.query.get_files(language, 'injections') for _, file in ipairs(files) do local f = io.open(file, 'r') if f ~= nil then @@ -207,7 +210,7 @@ M.data = { end end query = query .. injection.query - pcall(vim.treesitter.query.set, language, 'injections', query) + pcall(ts.query.set, language, 'injections', query) end, --- Gives back an instance of `nvim-treesitter.ts_utils` ---@return table #`nvim-treesitter.ts_utils` @@ -300,7 +303,7 @@ M.data = { end -- Do we need to go through each tree? lol - vim.treesitter.get_parser(opts.buf, opts.ft):for_each_tree(function(tree) + ts.get_parser(opts.buf, opts.ft):for_each_tree(function(tree) table.insert(result, M.data.search_tree(tree, node_type)) end) @@ -317,8 +320,8 @@ M.data = { filetype = "markdown" end - local contents = io.open(path, "r"):read("*a") - local tree = vim.treesitter.get_string_parser(contents, filetype):parse()[1] + local contents = io.open(path, "r"):read "*a" + local tree = ts.get_string_parser(contents, filetype):parse()[1] if not (tree or tree.root) then return {} end @@ -331,13 +334,13 @@ M.data = { if text:sub(-1) ~= "\n" then text = text .. "\n" end - for line in text:gmatch("(.-)\n") do + for line in text:gmatch "(.-)\n" do if not leading_spaces then - leading_spaces = line:match("^%s+"); + leading_spaces = line:match "^%s+" end - line = line:gsub("^" .. leading_spaces, ""); - _l = _l .. line .. "\n"; + line = line:gsub("^" .. leading_spaces, "") + _l = _l .. line .. "\n" end _l = _l:gsub("(\n)$", ""); @@ -372,7 +375,7 @@ M.data = { ---@param callback function ---@param ts_tree any #Optional syntax tree ---@diagnostic disable-line -- TODO: type error workaround tree_map = function(callback, ts_tree) - local tree = ts_tree or vim.treesitter.get_parser(0, "markdown"):parse()[1] + local tree = ts_tree or ts.get_parser(0, "markdown"):parse()[1] local root = tree:root() @@ -384,7 +387,7 @@ M.data = { ---@param callback function Executes with each node as parameter, can return false to stop recursion ---@param ts_tree any #Optional syntax tree ---@diagnostic disable-line -- TODO: type error workaround tree_map_rec = function(callback, ts_tree) - local tree = ts_tree or vim.treesitter.get_parser(0, "markdown"):parse()[1] + local tree = ts_tree or ts.get_parser(0, "markdown"):parse()[1] local root = tree:root() @@ -493,7 +496,7 @@ M.data = { if cursor_to_second then -- set jump location - vim.cmd("normal! m'") + vim.cmd "normal! m'" local char_delta = 0 local line_delta = 0 @@ -551,7 +554,7 @@ M.data = { return iterate(parent) end - vim.treesitter.get_parser(buf, "markdown"):for_each_tree(function(tree) + ts.get_parser(buf, "markdown"):for_each_tree(function(tree) -- Iterate over all top-level children and attempt to find a match return iterate(tree:root()) ---@diagnostic disable-line -- TODO: type error workaround end) @@ -573,7 +576,7 @@ M.data = { end -- Do we need to go through each tree? lol - vim.treesitter.get_parser(opts.buf, opts.ft):for_each_tree(function(tree) + ts.get_parser(opts.buf, opts.ft):for_each_tree(function(tree) -- Get the root for that tree local root if opts.parent then @@ -664,7 +667,7 @@ M.data = { return nil end end - content[i] = string.rep(" ", content_start_column - start_column) .. line + content[i] = (" "):rep((content_start_column - start_column) .. line) else content[i] = line:sub(1 + start_column) end @@ -719,9 +722,9 @@ M.data = { local parser if type(src) == "string" then - parser = vim.treesitter.get_string_parser(src, filetype) + parser = ts.get_string_parser(src, filetype) else - parser = vim.treesitter.get_parser(src or 0, filetype) + parser = ts.get_parser(src or 0, filetype) end local tree = parser:parse()[1] @@ -768,7 +771,7 @@ M.data = { return end - local first_char = (vim.api.nvim_buf_get_lines(buf, line, line + 1, true)[1] or ""):match("^(%s+)[^%s]") + local first_char = (vim.api.nvim_buf_get_lines(buf, line, line + 1, true)[1] or ""):match "^(%s+)[^%s]" first_char = first_char and first_char:len() or 0 local descendant = document_root:descendant_for_range(line, first_char, line, first_char + 1) ---@diagnostic disable-line -- TODO: type error workaround @@ -907,7 +910,7 @@ M.data = { local meta_source = M.data.get_node_text(meta_node, iter_src) - local markdown_inline_parser = vim.treesitter.get_string_parser(meta_source, "markdown_inline") + local markdown_inline_parser = ts.get_string_parser(meta_source, "markdown_inline") local markdown_inline_tree = markdown_inline_parser:parse()[1] @@ -974,15 +977,15 @@ M.data = { if vim.fn.bufnr(source) ~= -1 then ---@diagnostic disable-line source = vim.uri_to_bufnr(vim.uri_from_fname(source)) else - iter_src = io.open(source, "r"):read("*a") - down_parser = vim.treesitter.get_string_parser(iter_src, "markdown") + iter_src = io.open(source, "r"):read "*a" + down_parser = ts.get_string_parser(iter_src, "markdown") end end if type(source) == "number" then if source == 0 then source = vim.api.nvim_get_current_buf() end - down_parser = vim.treesitter.get_parser(source, "markdown") + down_parser = ts.get_parser(source, "markdown") iter_src = source end @@ -992,13 +995,10 @@ M.data = { -- this fixes the problem of installing down ts parsers on macOS without resorting to using gcc local function install_down_ts() - local install = require("nvim-treesitter.install") - - if vim.fn.has("macunix") == 1 then + if vim.fn.has "macunix" == 1 then -- https://github.com/nvim-down/tree-sitter-down/issues/7 -- (we have to force clang to c++11 mode on macOS manually) - local shell = require("nvim-treesitter.shell_command_selectors") -- save the original functions local select_executable = shell.select_executable @@ -1016,7 +1016,8 @@ local function install_down_ts() -- install down parsers local ok, err = pcall(function() - install.commands.TSInstallSync["run!"]("markdown") + install.commands.TSInstallSync["run!"] "markdown" + install.commands.TSInstallSync["run!"] "markdown_inline" end) -- no matter what, restore the defaults back @@ -1028,15 +1029,16 @@ local function install_down_ts() error(err) end else - install.commands.TSInstallSync["run!"]("markdown") + install.commands.TSInstallSync["run!"] "markdown" + install.commands.TSInstallSync["run!"] "markdown_inline" end end M.data.query = function(query, lang) - local tsp = vim.treesitter.get_parser(0, lang or vim.bo.filetype) + local tsp = ts.get_parser(0, lang or vim.bo.filetype) local tss = tsp:parse()[1] local tsr = tss:root() - local tpq = vim.treesitter.query.parse(lang or vim.bo.filetype, query) + local tpq = ts.query.parse(lang or vim.bo.filetype, query) return tpq:iter_matches(tsr, 0) end M.data.icon = {} @@ -1048,38 +1050,38 @@ M.data.quote = [[ ]] M.data.icon.quote = "┃" M.data.parser = function() - return vim.treesitter.get_parser(0) + return ts.get_parser(0) end M.data.cursor = function() - return require "nvim-treesitter.ts_utils".get_node_at_cursor() + return tsu.get_node_at_cursor() end M.data.root = function() local lang = vim.bo.filetype - local langtree = vim.treesitter.get_parser(0, lang) + local langtree = ts.get_parser(0, lang) local tree = langtree:parse() local root = tree[1]:root() return tree, root end -M.handle = function(event) +M.handler = function(event) if event.split[2] == "sync" then local ok, err = pcall(install_down_ts) if not ok then - utils.notify(string.format([[Unable to auto-install down parser: %s]], err), vim.log.levels.WARN) + utils.notify(('Unable to auto-install down parser: %s'):format(err), vim.log.levels.WARN) end - - local install = require("nvim-treesitter.install") - install.commands.TSInstallSync["run!"]("markdown") - install.commands.TSInstallSync["run!"]("markdown_inline") + install.commands.TSInstallSync["run!"] "markdown" + install.commands.TSInstallSync["run!"] "markdown_inline" end end -M.subscribed = { +M.handle = { cmd = { - ['tool.treesitter'] = true, + ['tool.treesitter'] = function() + + end }, } diff --git a/lua/down/mod/ui/calendar/day/init.lua b/lua/down/mod/ui/calendar/day/init.lua index c7279e9..ca0d2bf 100644 --- a/lua/down/mod/ui/calendar/day/init.lua +++ b/lua/down/mod/ui/calendar/day/init.lua @@ -5,7 +5,7 @@ local D = require("down.mod").new("ui.calendar.day") D.setup = function() return { ---@type down.mod.Setup loaded = true, - requires = { + dependencies = { } } diff --git a/lua/down/mod/ui/calendar/init.lua b/lua/down/mod/ui/calendar/init.lua index d1e0f56..181b489 100644 --- a/lua/down/mod/ui/calendar/init.lua +++ b/lua/down/mod/ui/calendar/init.lua @@ -1,18 +1,19 @@ -local down = require('down') +local down = require 'down' +local mod = require 'down.mod' local util = require 'down.util' -local mod = down.mod +local log = require 'down.util.log' -local G = require 'down.mod'.new('ui.calendar') - -G.maps = function() - vim.keymap.set('n', ',d.', 'Down calendar') - vim.keymap.set('n', ',do', 'Down calendar') - vim.keymap.set('n',',dl', 'Down calendar') -end +local G = mod.new 'ui.calendar' +G.maps = { + { 'n', ',d.', 'Down calendar', 'Open calendar' }, + { 'n', ',do', 'Down calendar' }, + { 'n', ',dl', 'Down calendar' }, +} G.setup = function() return { - requires = { + loaded = true, + dependencies = { 'ui', 'ui.calendar.day', 'ui.calendar.month', @@ -31,11 +32,11 @@ G.data = { get_mode = function(name, callback) if G.data.modes[name] ~= nil then local cur_mode = G.data.modes[name](callback) - cur_mode.name = name + cur_mode.id = name return cur_mode end - print('Error: mode not set or not available') + log.error 'Error: mode not set or not available' end, } @@ -45,7 +46,7 @@ G.data.get_view = function(name) return G.data.view[name] end - print('Error: view not set or not available') + log.error 'Error: view not set or not available' end G.data.extract_ui_info = function(buffer, window) @@ -68,7 +69,7 @@ end G.data.open_window = function(options) local MIN_HEIGHT = 14 - local buffer, window = G.required['ui'].new_split( + local buffer, window = G.dep['ui'].new_split( 'ui.calendar-' .. tostring(os.clock()):gsub('%.', '-'), {}, options.height or MIN_HEIGHT + (options.padding or 0) @@ -112,7 +113,7 @@ G.data.new_calendar = function(buffer, window, options) local v = G.data.get_view(options.view or 'month') - v.setup(ui_info, mode, options.date or os.date('*t'), options) + v.setup(ui_info, mode, options.date or os.date '*t', options) end G.data.open = function(options) @@ -167,7 +168,7 @@ G.load = function() return true else if os.time(date) <= os.time(self.range_start) then - print('Error: you should choose a date that is after the starting day.') + log.error 'Error: you should choose a date that is after the starting day.' return false end diff --git a/lua/down/mod/ui/calendar/month/init.lua b/lua/down/mod/ui/calendar/month/init.lua index b606bb0..edd30fd 100644 --- a/lua/down/mod/ui/calendar/month/init.lua +++ b/lua/down/mod/ui/calendar/month/init.lua @@ -12,7 +12,7 @@ end M.setup = function() return { - requires = { + dependencies = { 'ui.calendar', 'data.time', }, @@ -26,13 +26,9 @@ M.data = { setup = function(ui_info, mode, date, options) options.distance = options.distance or 4 - local view = M.data.new_view_instance() - view.current_mode = mode - view:render_view(ui_info, date, nil, options) - do vim.keymap.set('n', 'q', function() vim.api.nvim_buf_delete(ui_info.buffer, { force = true }) @@ -40,41 +36,41 @@ M.data = { -- TODO: Make cursor wrapping behaviour rable vim.keymap.set('n', 'l', function() - local new_date = reformat_time({ + local new_date = reformat_time { year = date.year, month = date.month, day = date.day + 1 * vim.v.count1, - }) + } view:render_view(ui_info, new_date, date, options) date = new_date end, { buffer = ui_info.buffer }) vim.keymap.set('n', 'h', function() - local new_date = reformat_time({ + local new_date = reformat_time { year = date.year, month = date.month, day = date.day - 1 * vim.v.count1, - }) + } view:render_view(ui_info, new_date, date, options) date = new_date end, { buffer = ui_info.buffer }) vim.keymap.set('n', 'j', function() - local new_date = reformat_time({ + local new_date = reformat_time { year = date.year, month = date.month, day = date.day + 7 * vim.v.count1, - }) + } view:render_view(ui_info, new_date, date, options) date = new_date end, { buffer = ui_info.buffer }) vim.keymap.set('n', 'k', function() - local new_date = reformat_time({ + local new_date = reformat_time { year = date.year, month = date.month, day = date.day - 7 * vim.v.count1, - }) + } view:render_view(ui_info, new_date, date, options) date = new_date end, { buffer = ui_info.buffer }) @@ -92,31 +88,31 @@ M.data = { end, { buffer = ui_info.buffer }) vim.keymap.set('n', 'L', function() - local new_date = reformat_time({ + local new_date = reformat_time { year = date.year, month = date.month + vim.v.count1, day = date.day, - }) + } view:render_view(ui_info, new_date, date, options) date = new_date end, { buffer = ui_info.buffer }) vim.keymap.set('n', 'H', function() - local new_date = reformat_time({ + local new_date = reformat_time { year = date.year, month = date.month - vim.v.count1, day = date.day, - }) + } view:render_view(ui_info, new_date, date, options) date = new_date end, { buffer = ui_info.buffer }) vim.keymap.set('n', 'm', function() - local new_date = reformat_time({ + local new_date = reformat_time { year = date.year, month = date.month + vim.v.count1, day = 1, - }) + } view:render_view(ui_info, new_date, date, options) date = new_date end, { buffer = ui_info.buffer }) @@ -125,53 +121,53 @@ M.data = { if date.day > 1 then date.month = date.month + 1 end - local new_date = reformat_time({ + local new_date = reformat_time { year = date.year, month = date.month - vim.v.count1, day = 1, - }) + } view:render_view(ui_info, new_date, date, options) date = new_date end, { buffer = ui_info.buffer }) vim.keymap.set('n', 'y', function() - local new_date = reformat_time({ + local new_date = reformat_time { year = date.year + vim.v.count1, month = date.month, day = date.day, - }) + } view:render_view(ui_info, new_date, date, options) date = new_date end, { buffer = ui_info.buffer }) vim.keymap.set('n', 'Y', function() - local new_date = reformat_time({ + local new_date = reformat_time { year = date.year - vim.v.count1, month = date.month, day = date.day, - }) + } view:render_view(ui_info, new_date, date, options) date = new_date end, { buffer = ui_info.buffer }) vim.keymap.set('n', '$', function() local new_day = date.day - (lib.number_wrap(date.wday - 1, 1, 7) - 1) + 6 - local new_date = reformat_time({ + local new_date = reformat_time { year = date.year, month = date.month, day = new_day, - }) + } view:render_view(ui_info, new_date, date, options) date = new_date end, { buffer = ui_info.buffer }) local start_of_week = function() local new_day = date.day - (lib.number_wrap(date.wday - 1, 1, 7) - 1) - local new_date = reformat_time({ + local new_date = reformat_time { year = date.year, month = date.month, day = new_day, - }) + } view:render_view(ui_info, new_date, date, options) date = new_date end @@ -180,7 +176,7 @@ M.data = { vim.keymap.set('n', '_', start_of_week, { buffer = ui_info.buffer }) vim.keymap.set('n', 't', function() - local new_date = os.date('*t') + local new_date = os.date '*t' view:render_view(ui_info, new_date, date, options) date = new_date @@ -191,42 +187,42 @@ M.data = { if end_of_current_month > date.day then date.month = date.month - 1 end - local new_date = reformat_time({ + local new_date = reformat_time { year = date.year, month = date.month + vim.v.count1, day = M.data.get_month_length(date.month + vim.v.count1, date.year), - }) + } view:render_view(ui_info, new_date, date, options) date = new_date end, { buffer = ui_info.buffer }) vim.keymap.set('n', 'E', function() - local new_date = reformat_time({ + local new_date = reformat_time { year = date.year, month = date.month - vim.v.count1, day = M.data.get_month_length(date.month - vim.v.count1, date.year), - }) + } view:render_view(ui_info, new_date, date, options) date = new_date end, { buffer = ui_info.buffer }) vim.keymap.set('n', 'w', function() - local new_date = reformat_time({ + local new_date = reformat_time { year = date.year, month = date.month, day = date.day + 7 * vim.v.count1, - }) + } new_date.day = new_date.day - (lib.number_wrap(new_date.wday - 1, 1, 7) - 1) view:render_view(ui_info, new_date, date, options) date = new_date end, { buffer = ui_info.buffer }) vim.keymap.set('n', 'W', function() - local new_date = reformat_time({ + local new_date = reformat_time { year = date.year, month = date.month, day = date.day - 7 * vim.v.count1, - }) + } new_date.day = new_date.day - (lib.number_wrap(new_date.wday - 1, 1, 7) - 1) view:render_view(ui_info, new_date, date, options) date = new_date @@ -236,7 +232,7 @@ M.data = { for i = 1, 12 do table.insert( months, - (os.date('%B', os.time({ year = 2000, month = i, day = 1 })) --[[@as string]]):lower() + (os.date('%B', os.time { year = 2000, month = i, day = 1 }) --[[@as string]]):lower() ) end @@ -279,11 +275,11 @@ M.data = { skip_next = false end - local new_date = reformat_time({ + local new_date = reformat_time { year = date.year, month = m, day = date.day, - }) + } view:render_view(ui_info, new_date, date, options) date = new_date break @@ -302,11 +298,11 @@ M.data = { else skip_next = false end - local new_date = reformat_time({ + local new_date = reformat_time { year = date.year, month = m, day = date.day, - }) + } view:render_view(ui_info, new_date, date, options) date = new_date break @@ -317,21 +313,21 @@ M.data = { vim.keymap.set('n', 'g', function() local day = math.min(vim.v.count1, M.data.get_month_length(date.month, date.year)) - local new_date = reformat_time({ + local new_date = reformat_time { year = date.year, month = date.month, day = day, - }) + } view:render_view(ui_info, new_date, date, options) date = new_date end, { buffer = ui_info.buffer, nowait = true }) vim.keymap.set('n', 'G', function() - local new_date = reformat_time({ + local new_date = reformat_time { year = date.year, month = date.month, day = M.data.get_month_length(date.month, date.year), - }) + } view:render_view(ui_info, new_date, date, options) date = new_date end, { buffer = ui_info.buffer }) @@ -339,11 +335,11 @@ M.data = { vim.keymap.set('n', 'd', function() local n = vim.v.count1 local weekday = math.min(n, 7) - local new_date = reformat_time({ + local new_date = reformat_time { year = date.year, month = date.month, day = date.day + (weekday - lib.number_wrap(date.wday - 1, 1, 7)), - }) + } view:render_view(ui_info, new_date, date, options) date = new_date end, { buffer = ui_info.buffer, nowait = true }) @@ -576,7 +572,7 @@ M.data = { vim.keymap.set({ 'n', 'i' }, '', function() local line = vim.api.nvim_buf_get_lines(buffer, 0, -1, true)[1] - local parsed_date = M.required['time'].parse_date(line) + local parsed_date = M.dep['time'].parse_date(line) if type(parsed_date) == 'string' then log.error('[ERROR]:', parsed_date) @@ -585,7 +581,7 @@ M.data = { quit() - local lua_date = M.required['time'].to_lua_date(parsed_date) + local lua_date = M.dep['time'].to_lua_date(parsed_date) local should_redraw = false @@ -602,8 +598,8 @@ M.data = { end, namespaces = { - logical = vim.api.nvim_create_namespace('down/calendar/logical'), - decorational = vim.api.nvim_create_namespace('down/calendar/decorational'), + logical = vim.api.nvim_create_namespace 'down.mod.ui.calendar.logical', + decorational = vim.api.nvim_create_namespace 'down.mod.ui.calendar.decorational', }, set_extmark = function(ui_info, namespace, row, col, length, virt_text, alignment, extra) @@ -689,11 +685,11 @@ M.data = { render_month_banner = function(self, ui_info, date, weekday_banner_extmark_id) local month_name = os.date( '%B', - os.time({ + os.time { year = date.year, month = date.month, day = date.day, - }) + } ) ---@cast month_name string local month_length = vim.api.nvim_strwidth(month_name) @@ -732,7 +728,7 @@ M.data = { local weekdays = {} local weekdays_string_length = 0 for i = 1, 7 do - local weekday = os.date('%a', os.time({ year = 2000, month = 5, day = i })) + local weekday = os.date('%a', os.time { year = 2000, month = 5, day = i }) ---@cast weekday string local truncated = util.truncate_by_cell(weekday, 2) local truncated_length = vim.api.nvim_strwidth(truncated) @@ -787,7 +783,7 @@ M.data = { -- [day of month] = , } - local current_date = os.date('*t') + local current_date = os.date '*t' local month, year = target_date.month, target_date.year @@ -796,11 +792,11 @@ M.data = { for i = 1, days_in_current_month do days_of_month[i] = tonumber(os.date( '%u', - os.time({ + os.time { year = year, month = month, day = i, - }) + } )) end @@ -879,22 +875,22 @@ M.data = { for i = 1, months_to_render do weekday_banner = self:render_weekday_banner(ui_info, i, options.distance) - local positive_target_date = reformat_time({ + local positive_target_date = reformat_time { year = date.year, month = date.month + i, day = 1, - }) + } self:render_month_banner(ui_info, positive_target_date, weekday_banner) self:render_month(ui_info, positive_target_date, weekday_banner) weekday_banner = self:render_weekday_banner(ui_info, i * -1, options.distance) - local negative_target_date = reformat_time({ + local negative_target_date = reformat_time { year = date.year, month = date.month - i, day = 1, - }) + } self:render_month_banner(ui_info, negative_target_date, weekday_banner) self:render_month(ui_info, negative_target_date, weekday_banner) @@ -1057,7 +1053,7 @@ M.data = { -- the meaty stuff, but will come in handy for rendering decorational -- elements. local fill = {} - local filler = string.rep(' ', ui_info.width) + local filler = (' '):rep(ui_info.width) for i = 1, ui_info.height do fill[i] = filler @@ -1141,7 +1137,7 @@ M.data = { callback = quit, }) - local namespace = vim.api.nvim_create_namespace('down/calendar-help') + local namespace = vim.api.nvim_create_namespace 'down.mod.ui.calendar.help' vim.api.nvim_buf_set_option(buffer, 'modifiable', false) vim.api.nvim_buf_set_extmark(buffer, namespace, 0, 0, { @@ -1151,7 +1147,7 @@ M.data = { } M.load = function() - M.required['ui.calendar'].add_view(M.data.view_name, M.data) + M.dep['ui.calendar'].add_view(M.data.view_name, M.data) end return M diff --git a/lua/down/mod/ui/conceal/init.lua b/lua/down/mod/ui/conceal/init.lua index 2c0089a..a8fea1d 100644 --- a/lua/down/mod/ui/conceal/init.lua +++ b/lua/down/mod/ui/conceal/init.lua @@ -9,7 +9,7 @@ M.border = require("down.mod.ui.conceal.border") M.setup = function() return { loaded = true, - requires = {}, + dependencies = {}, } end diff --git a/lua/down/mod/ui/dashboard/init.lua b/lua/down/mod/ui/dashboard/init.lua index 069d43a..3dabf94 100644 --- a/lua/down/mod/ui/dashboard/init.lua +++ b/lua/down/mod/ui/dashboard/init.lua @@ -3,7 +3,7 @@ local D = require("down.mod").new("ui.dashboard") D.setup = function() return { loaded = true, - requires = {}, + dependencies = {}, } end diff --git a/lua/down/mod/ui/hl/init.lua b/lua/down/mod/ui/hl/init.lua index 2c55cfb..ed56896 100644 --- a/lua/down/mod/ui/hl/init.lua +++ b/lua/down/mod/ui/hl/init.lua @@ -374,7 +374,7 @@ M.config = { } M.setup = function() - return { loaded = true, requires = {} } + return { loaded = true, dependencies = {} } end M.load = function() diff --git a/lua/down/mod/ui/icon/init.lua b/lua/down/mod/ui/icon/init.lua index 7897bbe..56baa7a 100644 --- a/lua/down/mod/ui/icon/init.lua +++ b/lua/down/mod/ui/icon/init.lua @@ -11,7 +11,7 @@ local M = mod.new("ui.icon", { M.setup = function() return { loaded = true, - requires = { + dependencies = { "tool.treesitter", }, } @@ -1151,7 +1151,7 @@ local function prettify_range(bufid, row_start_0b, row_end_0bex) -- TODO: optimize row_end_0bex = math.min(row_end_0bex + 1, vim.api.nvim_buf_line_count(bufid)) - local tsm = M.required["tool.treesitter"] + local tsm = M.dep["tool.treesitter"] local document_root = tsm.get_document_root(bufid) assert(document_root) @@ -1474,15 +1474,15 @@ local event_handlers = { } M.handle = function(event) - if not M.data.enabled and (event.type ~= "cmd.events.icon.toggle") then + if not M.data.enabled and (event.id ~= "cmd.events.icon.toggle") then return end - return event_handlers[event.type](event) + return event_handlers[event.id](event) end M.load = function() local icon = - M.import[M.name .. "." .. M.config.icon].config["icon_" .. M.config.icon] + M.import[M.id .. "." .. M.config.icon].config["icon_" .. M.config.icon] if not icon then log.error( ("Unable to load icon preset '%s' - such a preset does not exist"):format( @@ -1499,7 +1499,7 @@ M.load = function() M.config.custom or {} ) - -- M.required["core.autocommands"].enable_autocommand("BufNewFile") + -- M.dep["core.autocommands"].enable_autocommand("BufNewFile") mod.await("cmd", function(downcmd) downcmd.add_commands_from_table({ diff --git a/lua/down/mod/ui/init.lua b/lua/down/mod/ui/init.lua index 91d78d5..366bae0 100644 --- a/lua/down/mod/ui/init.lua +++ b/lua/down/mod/ui/init.lua @@ -1,13 +1,9 @@ -local mod = require("down.mod") +local mod = require "down.mod" +local log = require 'down.util.log' + ---@type down.Mod -local M = mod.new('ui', { - -- "icon", - -- "win", - 'win', - 'sidebar', - 'dashboard', - 'popup', -}) +local M = mod.new 'ui' + M.load = function() for _, i in pairs(M.import) do M.data = vim.tbl_extend('force', M.data, i.data) @@ -15,8 +11,8 @@ M.load = function() end M.setup = function() return { - namespace = vim.api.nvim_create_namespace('down.ui'), - requires = {}, + namespace = vim.api.nvim_create_namespace 'down.mod.ui', + dependencies = {}, loaded = true, } end @@ -27,7 +23,7 @@ M.config = { } ---@class down.mod.ui.Data M.data = { - namespace = vim.api.nvim_create_namespace('down.ui'), + namespace = vim.api.nvim_create_namespace 'down.mod.ui', --- Returns a table in the form of { width, height } containing the width and height of the current window ---@param half boolean #If true returns a position that could be considered the center of the window get_window_size = function(half) @@ -61,10 +57,8 @@ M.data = { width = 100, height = 100, }) - -- Get the current window's dimensions except halved local halved_window_size = M.data.get_window_size(true) - -- If we want to center along the x axis then return a configuration that does so if user_options.center_x then config.row = config.row + halved_window_size[2] - math.floor(config.height / 2) @@ -93,25 +87,20 @@ M.data = { ---@param height number? the height of the new split ---@return number?, number? #Both the buffer ID and window ID new_split = function(name, config, height) - vim.validate({ + vim.validate { name = { name, 'string' }, { config, 'table', true }, height = { height, 'number', true }, - }) - + } local bufname = 'down://' .. name - if vim.fn.bufexists(bufname) == 1 then ---@diagnostic disable-line log.error("Buffer '" .. name .. "' already exists") return end - - vim.cmd('below new') - + vim.cmd 'below new' if height then vim.api.nvim_win_set_height(0, height) end - local buf = vim.api.nvim_win_get_buf(0) local base_options = { @@ -121,10 +110,8 @@ M.data = { buflisted = false, filetype = 'markdown', } - vim.api.nvim_buf_set_name(buf, bufname) vim.api.nvim_win_set_buf(0, buf) - vim.api.nvim_win_set_option(0, 'list', false) vim.api.nvim_win_set_option(0, 'colorcolumn', '') vim.api.nvim_win_set_option(0, 'number', false) @@ -156,12 +143,12 @@ M.data = { ---@param win_config table table of