diff --git a/.github/workflows/.luarc.json b/.github/workflows/.luarc.json index 199a752b0..6f07d9660 100644 --- a/.github/workflows/.luarc.json +++ b/.github/workflows/.luarc.json @@ -6,6 +6,7 @@ "lua/?/init.lua" ], "Lua.workspace.library": [ + "/home/runner/work/neorg/neorg/lua_modules/share/lua/5.1", "/home/runner/work/neorg/neorg/deps/neovim/runtime/lua", "/home/runner/work/neorg/neorg/deps/neodev.nvim/types/stable" ], diff --git a/.github/workflows/luarocks.yml b/.github/workflows/luarocks.yml index 6379e5740..d2b464523 100644 --- a/.github/workflows/luarocks.yml +++ b/.github/workflows/luarocks.yml @@ -30,3 +30,4 @@ jobs: lua-utils.nvim == 1.0.2 plenary.nvim == 0.1.4 nui.nvim == 0.3.0 + pathlib.nvim ~> 2 diff --git a/.github/workflows/typecheck.yml b/.github/workflows/typecheck.yml index 1ea820e19..791152380 100644 --- a/.github/workflows/typecheck.yml +++ b/.github/workflows/typecheck.yml @@ -14,18 +14,26 @@ jobs: - name: Checkout Code uses: actions/checkout@v3 - - name: Checkout dependency neodev + - name: Checkout dependency neodev # get neodev and neovim/runtime for builtin types uses: actions/checkout@v3 with: repository: "folke/neodev.nvim" path: "deps/neodev.nvim" - - name: Checkout neovim for type annotations uses: actions/checkout@v3 with: repository: "neovim/neovim" path: "deps/neovim" + - uses: leafo/gh-actions-lua@v9 # get luarocks dependencies for their types (eg `PathlibPath`) + with: + luaVersion: "5.1" + - uses: leafo/gh-actions-luarocks@v4 + - name: install dependencies + run: | + luarocks init + luarocks install --only-deps ./*.rockspec + - name: Type Check Code Base uses: mrcjkb/lua-typecheck-action@v0.2.1 with: diff --git a/.gitignore b/.gitignore index 58cc961e8..684095308 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ wiki/ test.norg +/luarocks +/lua_modules +/.luarocks diff --git a/.luarc.json b/.luarc.json index 7f3845742..25605166d 100644 --- a/.luarc.json +++ b/.luarc.json @@ -5,5 +5,6 @@ "_neorg_module_autocommand_triggered", "vim" ], - "workspace.checkThirdParty": false + "Lua.diagnostics.libraryFiles": "Disable", + "Lua.workspace.checkThirdParty": false } diff --git a/build.lua b/build.lua index 0021d411a..551888826 100644 --- a/build.lua +++ b/build.lua @@ -16,6 +16,7 @@ vim.schedule(function() "lua-utils.nvim == 1.0.2", "plenary.nvim == 0.1.4", "nui.nvim == 0.3.0", + "pathlib.nvim ~> 2", }) package.loaded["neorg"] = nil diff --git a/lua/neorg/core/modules.lua b/lua/neorg/core/modules.lua index 764ebb2f5..15cfa68ee 100644 --- a/lua/neorg/core/modules.lua +++ b/lua/neorg/core/modules.lua @@ -512,8 +512,9 @@ function modules.load_module_as_dependency(module_name, parent_module, cfg) end --- Retrieves the public API exposed by the module. ---- @param module_name string The name of the module to retrieve. ---- @return neorg.module.public? +--- @generic T +--- @param module_name `T` The name of the module to retrieve. +--- @return T? function modules.get_module(module_name) if not modules.is_module_loaded(module_name) then log.trace("Attempt to get module with name", module_name, "failed - module is not loaded.") diff --git a/lua/neorg/core/utils.lua b/lua/neorg/core/utils.lua index 9589d0c37..0cf6efd0b 100644 --- a/lua/neorg/core/utils.lua +++ b/lua/neorg/core/utils.lua @@ -178,10 +178,11 @@ function utils.notify(msg, log_level) end --- Opens up an array of files and runs a callback for each opened file. ---- @param files string[] An array of files to open. +--- @param files (string|PathlibPath)[] An array of files to open. --- @param callback fun(buffer: integer, filename: string) The callback to invoke for each file. function utils.read_files(files, callback) for _, file in ipairs(files) do + file = tostring(file) local bufnr = vim.uri_to_bufnr(vim.uri_from_fname(file)) local should_delete = not vim.api.nvim_buf_is_loaded(bufnr) diff --git a/lua/neorg/modules/core/completion/module.lua b/lua/neorg/modules/core/completion/module.lua index dabae894a..42a9c6733 100644 --- a/lua/neorg/modules/core/completion/module.lua +++ b/lua/neorg/modules/core/completion/module.lua @@ -50,8 +50,9 @@ module.private = { engine = nil, --- Get a list of all norg files in current workspace. Returns { workspace_path, norg_files } - --- @return table? + --- @return { [1]: PathlibPath, [2]: PathlibPath[]|nil }|nil get_norg_files = function() + ---@type core.dirman local dirman = neorg.modules.get_module("core.dirman") if not dirman then return nil @@ -89,6 +90,7 @@ module.private = { --- @param file string file path, norg syntax accepted --- @return table get_lines = function(file) + ---@type core.dirman.utils local dirutils = neorg.modules.get_module("core.dirman.utils") if not dirutils then return {} @@ -168,6 +170,7 @@ module.private = { generate_file_links = function(context, _prev, _saved, _match) local res = {} + ---@type core.dirman local dirman = neorg.modules.get_module("core.dirman") if not dirman then return {} @@ -179,14 +182,16 @@ module.private = { end local closing_chars = module.private.get_closing_chars(context, true) - for _, file in pairs(files[2]) do - assert(type(file) == "string") + for _, filepath in pairs(files[2]) do + local file = tostring(filepath) local bufnr = dirman.get_file_bufnr(file) if vim.api.nvim_get_current_buf() ~= bufnr then - -- using -6 to go to the end (-1) and remove '.norg' 5 more chars - local link = "{:$" .. file:sub(#files[1] + 1, -6) .. closing_chars - table.insert(res, link) + local rel = filepath:relative_to(files[1], false) + if rel and rel:len() > 0 then + local link = "{:$/" .. rel:with_suffix(""):tostring() .. closing_chars + table.insert(res, link) + end end end @@ -219,7 +224,7 @@ module.private = { end, --- The node context for normal norg (ie. not in a code block) - normal_norg = function(current, previous) + normal_norg = function(current, previous, _, _) -- If no previous node exists then try verifying the current node instead if not previous then return current and (current:type() ~= "translation_unit" or current:type() == "document") or false @@ -251,7 +256,7 @@ module.load = function() end -- Set a special function in the integration module to allow it to communicate with us - module.private.engine.invoke_completion_engine = function(context) + module.private.engine.invoke_completion_engine = function(context) ---@diagnostic disable-line return module.public.complete(context) ---@diagnostic disable-line -- TODO: type error workaround end @@ -526,8 +531,8 @@ module.public = { --- Parses the public completion table and attempts to find all valid matches ---@param context table #The context provided by the integration engine - ---@param prev table #The previous table of completions - used for descent - ---@param saved string #The saved regex in the form of a string, used to concatenate children nodes with parent nodes' regexes + ---@param prev table? #The previous table of completions - used for descent + ---@param saved string? #The saved regex in the form of a string, used to concatenate children nodes with parent nodes' regexes complete = function(context, prev, saved) -- If the save variable wasn't passed then set it to an empty string saved = saved or "" @@ -560,7 +565,7 @@ module.public = { -- If the type of completion data we're dealing with is a string then attempt to parse it if type(completion_data.node) == "string" then -- Split the completion node string down every pipe character - local split = vim.split(completion_data.node, "|") + local split = vim.split(completion_data.node --[[@as string]], "|") -- Check whether the first character of the string is an exclamation mark -- If this is present then it means we're looking for a node that *isn't* the one we specify local negate = split[1]:sub(0, 1) == "!" diff --git a/lua/neorg/modules/core/dirman/module.lua b/lua/neorg/modules/core/dirman/module.lua index a09b65c20..0de3cbd28 100644 --- a/lua/neorg/modules/core/dirman/module.lua +++ b/lua/neorg/modules/core/dirman/module.lua @@ -49,8 +49,10 @@ dirman.create_file("my_file", "my_ws", { ``` --]] +local Path = require("pathlib") + local neorg = require("neorg.core") -local config, log, modules, utils = neorg.config, neorg.log, neorg.modules, neorg.utils +local log, modules, utils = neorg.log, neorg.modules, neorg.utils local module = modules.create("core.dirman") @@ -64,7 +66,8 @@ end module.load = function() -- Go through every workspace and expand special symbols like ~ for name, workspace_location in pairs(module.config.public.workspaces) do - module.config.public.workspaces[name] = vim.fn.expand(vim.fn.fnameescape(workspace_location)) ---@diagnostic disable-line -- TODO: type error workaround + -- module.config.public.workspaces[name] = vim.fn.expand(vim.fn.fnameescape(workspace_location)) ---@diagnostic disable-line -- TODO: type error workaround + module.config.public.workspaces[name] = Path(workspace_location):resolve():to_absolute() end modules.await("core.keybinds", function(keybinds) @@ -110,8 +113,9 @@ module.config.public = { -- -- There is always an inbuilt workspace called `default`, whose location is -- set to the Neovim current working directory on boot. + ---@type table workspaces = { - default = vim.fn.getcwd(), + default = Path.cwd(), }, -- The name for the index file. -- @@ -131,7 +135,8 @@ module.config.public = { } module.private = { - current_workspace = { "default", vim.fn.getcwd() }, + ---@type { [1]: string, [2]: PathlibPath } + current_workspace = { "default", Path.cwd() }, } ---@class core.dirman @@ -139,6 +144,7 @@ module.public = { get_workspaces = function() return module.config.public.workspaces end, + ---@return string[] get_workspace_names = function() return vim.tbl_keys(module.config.public.workspaces) end, @@ -167,7 +173,7 @@ module.public = { end -- Create the workspace directory if not already present - vim.fn.mkdir(workspace, "p") + workspace:mkdir(Path.const.o755, true) -- Cache the current workspace local current_ws = vim.deepcopy(module.private.current_workspace) @@ -195,13 +201,14 @@ module.public = { --- Dynamically defines a new workspace if the name isn't already occupied and broadcasts the workspace_added event ---@return boolean True if the workspace is added successfully, false otherwise ---@param workspace_name string #The unique name of the new workspace - ---@param workspace_path string #A full path to the workspace root + ---@param workspace_path string|PathlibPath #A full path to the workspace root add_workspace = function(workspace_name, workspace_path) -- If the module already exists then bail if module.config.public.workspaces[workspace_name] then return false end + workspace_path = Path(workspace_path):resolve():to_absolute() -- Set the new workspace and its path accordingly module.config.public.workspaces[workspace_name] = workspace_path -- Broadcast the workspace_added event with the newly added workspace as the content @@ -219,38 +226,27 @@ module.public = { --- If the file we opened is within a workspace directory, returns the name of the workspace, else returns nil get_workspace_match = function() -- Cache the current working directory - module.config.public.workspaces.default = vim.fn.getcwd() + module.config.public.workspaces.default = Path.cwd() - -- Grab the working directory of the current open file - local realcwd = vim.fn.expand("%:p:h") + local file = Path(vim.fn.expand("%:p")) - -- Store the length of the last match - local last_length = 0 + -- Name of matching workspace. Falls back to "default" + local ws_name = "default" - -- The final result - local result = "" + -- Store the depth of the longest match + local longest_match = 0 -- Find a matching workspace for workspace, location in pairs(module.config.public.workspaces) do if workspace ~= "default" then - -- Expand all special symbols like ~ etc. and escape special characters - local expanded = string.gsub(vim.pesc(vim.fn.expand(location)), "%p", "%%%1") ---@diagnostic disable-line -- TODO: type error workaround - - -- If the workspace location is a parent directory of our current realcwd - -- or if the ws location is the same then set it as the real workspace - -- We check this last_length here because if a match is longer - -- than the previous one then we can say it is a much more precise - -- match and hence should be prioritized - if realcwd:find(expanded) and #expanded > last_length then ---@diagnostic disable-line -- TODO: type error workaround - -- Set the result to the workspace name - result = workspace - -- Set the last_length variable to the new length - last_length = #expanded + if file:is_relative_to(location) and location:depth() > longest_match then + ws_name = workspace + longest_match = location:depth() end end end - return result:len() ~= 0 and result or "default" + return ws_name end, --- Uses the `get_workspace_match()` function to determine the root of the workspace based on the --- current working directory, then changes into that workspace @@ -289,7 +285,7 @@ module.public = { ---@field metadata? core.esupports.metagen.metadata metadata fields, if provided inserts metadata - an empty table uses default values --- Takes in a path (can include directories) and creates a .norg file from that path - ---@param path string a path to place the .norg file in + ---@param path string|PathlibPath a path to place the .norg file in ---@param workspace? string workspace name ---@param opts? core.dirman.create_file_opts additional options create_file = function(path, workspace, opts) @@ -309,46 +305,29 @@ module.public = { return end - -- Split the path at every / - local split = vim.split(vim.trim(path), config.pathsep, true) ---@diagnostic disable-line -- TODO: type error workaround + local destination = (fullpath / path):with_suffix(".norg") - -- If the last element is empty (i.e. if the string provided ends with '/') then trim it - if split[#split]:len() == 0 then - split = vim.list_slice(split, 0, #split - 1) - end + -- Generate parents just in case + destination:parent_assert():mkdir(Path.const.o755 + 4 * math.pow(8, 4), true) -- 40755(oct) - -- Go through each directory (excluding the actual file name) and create each directory individually - for _, element in ipairs(vim.list_slice(split, 0, #split - 1)) do - vim.loop.fs_mkdir(fullpath .. config.pathsep .. element, 16877) - fullpath = fullpath .. config.pathsep .. element - end - - -- If the provided filepath ends in .norg then don't append the filetype automatically - local fname = fullpath .. config.pathsep .. split[#split] - if not vim.endswith(path, ".norg") then - fname = fname .. ".norg" - end + -- Touch file + destination:touch(Path.permission("rw-rw-rw-"), false) - -- Create the file - local fd = vim.loop.fs_open(fname, opts.force and "w" or "a", 438) - if fd then - vim.loop.fs_close(fd) - end - - local bufnr = module.public.get_file_bufnr(fname) + -- Broadcast file creation event + local bufnr = module.public.get_file_bufnr(destination:tostring()) modules.broadcast_event( assert(modules.create_event(module, "core.dirman.events.file_created", { buffer = bufnr, opts = opts })) ) if not opts.no_open then -- Begin editing that newly created file - vim.cmd("e " .. fname .. "| w") + vim.cmd("e " .. destination:cmd_string() .. "| w") end end, --- Takes in a workspace name and a path for a file and opens it ---@param workspace_name string #The name of the workspace to use - ---@param path string #A path to open the file (e.g directory/filename.norg) + ---@param path string|PathlibPath #A path to open the file (e.g directory/filename.norg) open_file = function(workspace_name, path) local workspace = module.public.get_workspace(workspace_name) @@ -356,7 +335,7 @@ module.public = { return end - vim.cmd("e " .. workspace .. config.pathsep .. path .. " | w") + vim.cmd("e " .. (workspace / path):cmd_string() .. " | w") end, --- Reads the neorg_last_workspace.txt file and loads the cached workspace from there set_last_workspace = function() @@ -382,34 +361,27 @@ module.public = { -- If we were successful in switching to that workspace then begin editing that workspace's index file if module.public.set_workspace(last_workspace) then - vim.cmd("e " .. workspace_path .. config.pathsep .. module.config.public.index) + vim.cmd("e " .. (workspace_path / module.public.get_index()):cmd_string()) utils.notify("Last Workspace -> " .. workspace_path) end end, --- Checks for file existence by supplying a full path in `filepath` - ---@param filepath string + ---@param filepath string|PathlibPath file_exists = function(filepath) - local f = io.open(filepath, "r") - - if f ~= nil then - f:close() - return true - else - return false - end + return Path(filepath):exists() end, --- Get the bufnr for a `filepath` (full path) - ---@param filepath string + ---@param filepath string|PathlibPath get_file_bufnr = function(filepath) if module.public.file_exists(filepath) then - local uri = vim.uri_from_fname(filepath) + local uri = vim.uri_from_fname(tostring(filepath)) return vim.uri_to_bufnr(uri) end end, --- Returns a list of all files relative path from a `workspace_name` ---@param workspace_name string - ---@return table? + ---@return PathlibPath[]|nil get_norg_files = function(workspace_name) local res = {} local workspace = module.public.get_workspace(workspace_name) @@ -418,11 +390,9 @@ module.public = { return end - local scanned_dir = vim.fs.dir(workspace, { depth = 20 }) - - for name, type in scanned_dir do - if type == "file" and vim.endswith(name, ".norg") then - table.insert(res, workspace .. config.pathsep .. name) + for path in workspace:fs_iterdir(true, 20) do + if path:is_file(true) and path:suffix() == ".norg" then + table.insert(res, path) end end @@ -445,16 +415,15 @@ module.public = { -- If we're switching to a workspace that isn't the default workspace then enter the index file if workspace ~= "default" then - vim.cmd("e " .. ws_match .. config.pathsep .. module.config.public.index) + vim.cmd("e " .. (ws_match / module.public.get_index()):cmd_string()) end end, --- Touches a file in workspace - --- TODO: make the touch file recursive - ---@param path string + ---@param path string|PathlibPath ---@param workspace string touch_file = function(path, workspace) vim.validate({ - path = { path, "string" }, + path = { path, "string", "table" }, workspace = { workspace, "string" }, }) @@ -464,15 +433,7 @@ module.public = { return false end - local file = io.open(ws_match .. config.pathsep .. path, "w") - - if not file then - return false - end - - file:write("") - file:close() - return true + return (ws_match / path):touch(Path.const.o644, true) end, get_index = function() return module.config.public.index @@ -510,9 +471,9 @@ module.on_event = function(event) if event.type == "core.neorgcmd.events.dirman.index" then local current_ws = module.public.get_current_workspace() - local index_path = table.concat({ current_ws[2], "/", module.config.public.index }) + local index_path = current_ws[2] / module.public.get_index() - if vim.fn.filereadable(index_path) == 0 then + if vim.fn.filereadable(index_path:tostring("/")) == 0 then if current_ws[1] == "default" then utils.notify(table.concat({ "Index file cannot be created in 'default' workspace to avoid confusion.", @@ -520,11 +481,11 @@ module.on_event = function(event) }, " ")) return end - if not module.public.touch_file(module.config.public.index, module.public.get_current_workspace()[1]) then + if not index_path:touch(Path.const.o644, true) then utils.notify( table.concat({ "Unable to create '", - module.config.public.index, + module.public.get_index(), "' in the current workspace - are your filesystem permissions set correctly?", }), vim.log.levels.WARN @@ -533,7 +494,7 @@ module.on_event = function(event) end end - vim.cmd.edit(index_path) + vim.cmd.edit(index_path:cmd_string()) return end diff --git a/lua/neorg/modules/core/dirman/utils/module.lua b/lua/neorg/modules/core/dirman/utils/module.lua index 772f733de..2749a0313 100644 --- a/lua/neorg/modules/core/dirman/utils/module.lua +++ b/lua/neorg/modules/core/dirman/utils/module.lua @@ -8,50 +8,76 @@ Currently the only exposed API function is `expand_path`, which takes a path lik converts `$name` into the full path of the workspace called `name`. --]] +local Path = require("pathlib") + local neorg = require("neorg.core") local log, modules = neorg.log, neorg.modules local module = neorg.modules.create("core.dirman.utils") +---@class core.dirman.utils module.public = { ---Resolve `$/path/to/file` and return the real path - ---@param path string # path - ---@param raw_path boolean? # If true, returns resolved path, else, return with appended ".norg" - ---@return string? # Resolved path. If path does not start with `$` or not absolute, adds relative from current file. - expand_path = function(path, raw_path) + ---@param path string|PathlibPath # path + ---@param raw_path boolean? # If true, returns resolved path, otherwise, returns resolved path and append ".norg" + ---@return PathlibPath? # Resolved path. If path does not start with `$` or not absolute, adds relative from current file. + expand_pathlib = function(path, raw_path) + local filepath = Path(path) -- Expand special chars like `$` - local custom_workspace_path = path:match("^%$([^/\\]*)[/\\]") - + local custom_workspace_path = filepath:match("^%$([^/\\]*)[/\\]") if custom_workspace_path then + ---@type core.dirman local dirman = modules.get_module("core.dirman") - if not dirman then - log.error( - "Unable to jump to link with custom workspace: `core.dirman` is not loaded. Please load the module in order to get workspace support." - ) + log.error(table.concat({ + "Unable to jump to link with custom workspace: `core.dirman` is not loaded.", + "Please load the module in order to get workspace support.", + }, " ")) return end - -- If the user has given an empty workspace name (i.e. `$/myfile`) if custom_workspace_path:len() == 0 then - path = dirman.get_current_workspace()[2] .. "/" .. path:sub(3) + filepath = dirman.get_current_workspace()[2] / filepath:relative_to(Path("$")) else -- If the user provided a workspace name (i.e. `$my-workspace/myfile`) - local workspace_path = dirman.get_workspace(custom_workspace_path) - - if not workspace_path then - log.warn("Unable to expand path: workspace does not exist") + local workspace = dirman.get_workspace(custom_workspace_path) + if not workspace then + local msg = "Unable to expand path: workspace '%s' does not exist" + log.warn(string.format(msg, custom_workspace_path)) return end - - path = workspace_path .. "/" .. path:sub(custom_workspace_path:len() + 3) + filepath = workspace / filepath:relative_to(Path("$" .. custom_workspace_path)) end + elseif filepath:is_relative() then + local this_file = Path(vim.fn.expand("%:p")):absolute() + filepath = this_file:parent_assert() / filepath else - -- If the path isn't absolute (doesn't begin with `/` nor `~`) then prepend the current file's - -- filehead in front of the path - path = (vim.tbl_contains({ "/", "~" }, path:sub(1, 1)) and "" or (vim.fn.expand("%:p:h") .. "/")) .. path + filepath = filepath:absolute() end - - return path .. (raw_path and "" or ".norg") + -- requested to expand norg file + if not raw_path then + if type(path) == "string" and (path:sub(#path) == "/" or path:sub(#path) == "\\") then + -- if path ends with `/`, it is an invalid request! + log.error(table.concat({ + "Norg file location cannot point to a directory.", + string.format("Current link points to '%s'", path), + "which ends with a `/`.", + }, " ")) + return + end + filepath = filepath:with_suffix(".norg") + end + return filepath + end, + ---Resolve `$/path/to/file` and return the real path + -- NOTE: Use `expand_pathlib` which returns a PathlibPath object instead. + --- + ---\@deprecate Use `expand_pathlib` which returns a PathlibPath object instead. TODO: deprecate this <2024-03-27> + ---@param path string|PathlibPath # path + ---@param raw_path boolean? # If true, returns resolved path, otherwise, returns resolved path and append ".norg" + ---@return string? # Resolved path. If path does not start with `$` or not absolute, adds relative from current file. + expand_path = function(path, raw_path) + local res = module.public.expand_pathlib(path, raw_path) + return res and res:tostring() or nil end, } diff --git a/lua/neorg/modules/core/esupports/indent/module.lua b/lua/neorg/modules/core/esupports/indent/module.lua index 795e9b599..dc11a4686 100644 --- a/lua/neorg/modules/core/esupports/indent/module.lua +++ b/lua/neorg/modules/core/esupports/indent/module.lua @@ -29,6 +29,7 @@ module.setup = function() } end +---@class core.esupports.indent module.public = { indentexpr = function(buf, line, node) line = line or (vim.v.lnum - 1) diff --git a/lua/neorg/modules/core/integrations/nvim-cmp/module.lua b/lua/neorg/modules/core/integrations/nvim-cmp/module.lua index f84e8295b..68be54085 100644 --- a/lua/neorg/modules/core/integrations/nvim-cmp/module.lua +++ b/lua/neorg/modules/core/integrations/nvim-cmp/module.lua @@ -61,7 +61,7 @@ module.public = { function module.private.source.complete(_, request, callback) local abstracted_context = module.public.create_abstracted_context(request) - local completion_cache = module.public.invoke_completion_engine(abstracted_context) ---@diagnostic disable-line -- TODO: type error workaround + local completion_cache = module.public.invoke_completion_engine(abstracted_context) if completion_cache.options.pre then completion_cache.options.pre(abstracted_context) @@ -114,6 +114,12 @@ module.public = { full_line = request.context.cursor_line, } end, + + invoke_completion_engine = function(context) + error("`invoke_completion_engine` must be set from outside.") + assert(context) + return {} + end, } return module diff --git a/lua/neorg/modules/core/integrations/nvim-compe/module.lua b/lua/neorg/modules/core/integrations/nvim-compe/module.lua index 11b24b554..d0e7c6a27 100644 --- a/lua/neorg/modules/core/integrations/nvim-compe/module.lua +++ b/lua/neorg/modules/core/integrations/nvim-compe/module.lua @@ -184,6 +184,12 @@ module.public = { full_line = context.line, } end, + + invoke_completion_engine = function(context) + error("`invoke_completion_engine` must be set from outside.") + assert(context) + return {} + end, } return module diff --git a/lua/neorg/modules/core/latex/renderer/module.lua b/lua/neorg/modules/core/latex/renderer/module.lua index 9cf37b098..e075552dc 100644 --- a/lua/neorg/modules/core/latex/renderer/module.lua +++ b/lua/neorg/modules/core/latex/renderer/module.lua @@ -54,6 +54,7 @@ module.load = function() end) end +---@class core.latex.renderer module.public = { latex_renderer = function() module.private.ranges = {} diff --git a/lua/neorg/modules/core/promo/module.lua b/lua/neorg/modules/core/promo/module.lua index 2bab77dfb..537de757f 100644 --- a/lua/neorg/modules/core/promo/module.lua +++ b/lua/neorg/modules/core/promo/module.lua @@ -81,6 +81,7 @@ module.private = { }, } +---@class core.promo module.public = { get_promotable_node_prefix = function(node) for _, data in pairs(module.private.types) do diff --git a/lua/neorg/modules/core/summary/module.lua b/lua/neorg/modules/core/summary/module.lua index 307ce8929..793f14b4f 100644 --- a/lua/neorg/modules/core/summary/module.lua +++ b/lua/neorg/modules/core/summary/module.lua @@ -150,7 +150,7 @@ module.load = function() if not norgname then norgname = filename end - norgname = string.sub(norgname, string.len(ws_root) + 1) + norgname = string.sub(norgname, ws_root:len() + 1) -- normalise categories into a list. Could be vim.NIL, a number, a string or a list ... if not metadata.categories or metadata.categories == vim.NIL then @@ -237,7 +237,7 @@ module.load = function() local category = path_tokens[#path_tokens - 1] or "Uncategorised" local norgname = filename:match("(.+)%.norg$") or filename -- strip extension for link destinations - norgname = string.sub(norgname, string.len(ws_root) + 1) + norgname = string.sub(norgname, ws_root:len() + 1) if not metadata.title then metadata.title = get_first_heading_title(bufnr) or vim.fs.basename(norgname) @@ -290,7 +290,7 @@ module.config.public = { -- - "default" - read the metadata to categorize and annotate files. Files -- without metadata will use the top level heading as the title. If no headings are present, the filename will be used. -- - "by_path" - Similar to "default" but uses the capitalized name of the folder containing a *.norg file as category. - -- ---@type string|fun(files: string[], ws_root: string, heading_level: number?, include_categories: string[]?): string[]? + ---@type string|fun(files: PathlibPath[], ws_root: PathlibPath, heading_level: number?, include_categories: string[]?): string[]? strategy = "default", } diff --git a/lua/neorg/modules/core/tempus/module.lua b/lua/neorg/modules/core/tempus/module.lua index 46ae0b8ff..bf9147b39 100644 --- a/lua/neorg/modules/core/tempus/module.lua +++ b/lua/neorg/modules/core/tempus/module.lua @@ -217,6 +217,7 @@ local timezone_list = { ---@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?}?} +---@class core.tempus module.public = { --- Converts a parsed date with `parse_date` to a lua date. ---@param parsed_date Date #The date to convert diff --git a/lua/neorg/modules/core/ui/calendar/module.lua b/lua/neorg/modules/core/ui/calendar/module.lua index 5932de1fb..323b76574 100644 --- a/lua/neorg/modules/core/ui/calendar/module.lua +++ b/lua/neorg/modules/core/ui/calendar/module.lua @@ -86,6 +86,7 @@ module.private = { end, } +---@class core.ui.calendar module.public = { add_mode = function(name, factory) module.private.modes[name] = factory diff --git a/neorg-scm-1.rockspec b/neorg-scm-1.rockspec index 1eb0de1a4..154acec40 100644 --- a/neorg-scm-1.rockspec +++ b/neorg-scm-1.rockspec @@ -16,6 +16,7 @@ dependencies = { -- "norgopolis-client.lua >= 0.2.0", -- "norgopolis-server.lua >= 1.3.1", "lua-utils.nvim", + "pathlib.nvim ~> 2", } source = {