diff options
| author | moxie <moxie@3kgcat.fi> | 2026-03-15 09:54:31 +0200 |
|---|---|---|
| committer | moxie <moxie@3kgcat.fi> | 2026-03-15 10:05:20 +0200 |
| commit | de2df63dcbe44f07dc994e29d7d400c49c811080 (patch) | |
| tree | 10ae2c8eee90c661792e71aa5bd35cd26f5407d4 /lua/muwiki | |
| parent | 49c1e9d1fc3d6bf8748756a8543d8c1b7287940f (diff) | |
refactor: simplify codebase and fix FileType autocommands
Diffstat (limited to 'lua/muwiki')
| -rw-r--r-- | lua/muwiki/config.lua | 58 | ||||
| -rw-r--r-- | lua/muwiki/external.lua | 30 | ||||
| -rw-r--r-- | lua/muwiki/health.lua | 33 | ||||
| -rw-r--r-- | lua/muwiki/init.lua | 45 | ||||
| -rw-r--r-- | lua/muwiki/links.lua | 146 | ||||
| -rw-r--r-- | lua/muwiki/paths.lua | 43 | ||||
| -rw-r--r-- | lua/muwiki/utils.lua | 73 |
7 files changed, 118 insertions, 310 deletions
diff --git a/lua/muwiki/config.lua b/lua/muwiki/config.lua index 1e04d4a..9d668b9 100644 --- a/lua/muwiki/config.lua +++ b/lua/muwiki/config.lua @@ -3,22 +3,8 @@ local M = {} M.options = { dirs = nil, index_file = 'index.md', - text_extensions = { 'md', 'txt' }, - use_external_handlers = false, - external_handlers = { - { - name = 'xdg-open', - cmd = 'xdg-open', - pattern = '.*', - }, - }, } -local function dir_exists(path) - local stat = vim.uv.fs_stat(path) - return stat and stat.type == 'directory' -end - function M.setup(opts) opts = opts or {} @@ -42,51 +28,11 @@ function M.setup(opts) end for _, dir in ipairs(M.options.dirs or {}) do - if not dir_exists(dir.path) then + local stat = vim.uv.fs_stat(dir.path) + if not (stat and stat.type == 'directory') then vim.notify('Wiki directory not found: ' .. dir.path, vim.log.levels.WARN) end end end --- Lookup wiki path by name (e.g., "default" -> "~/wiki/") -function M.wiki_path(name) - if not M.options.dirs or #M.options.dirs == 0 then - vim.notify('MuWiki: No dirs configured. See :help muwiki-configuration', vim.log.levels.ERROR) - return nil - end - - if name then - for _, dir in ipairs(M.options.dirs) do - if dir.name == name then - return dir.path - end - end - vim.notify(string.format('Wiki "%s" not found, using default', name), vim.log.levels.WARN) - end - - return M.options.dirs[1].path -end - --- Find which wiki contains this buffer's file (cached per-buffer) -function M.wiki_root(bufnr) - bufnr = bufnr or 0 - - if vim.b[bufnr].muwiki_root ~= nil then - return vim.b[bufnr].muwiki_root or nil - end - - local filepath = vim.api.nvim_buf_get_name(bufnr) - local normalized = vim.fs.normalize(filepath) - - for _, dir in ipairs(M.options.dirs or {}) do - if vim.startswith(normalized, dir.path) then - vim.b[bufnr].muwiki_root = dir.path - return dir.path - end - end - - vim.b[bufnr].muwiki_root = false - return nil -end - return M diff --git a/lua/muwiki/external.lua b/lua/muwiki/external.lua deleted file mode 100644 index 9ea83b5..0000000 --- a/lua/muwiki/external.lua +++ /dev/null @@ -1,30 +0,0 @@ -local config = require('muwiki.config') -local paths = require('muwiki.paths') - -local M = {} - -function M.open(url) - if type(url) ~= 'string' then - vim.notify('Invalid URL type', vim.log.levels.ERROR) - return false - end - - local valid, err = paths.validate_url_scheme(url) - if not valid then - vim.notify(err, vim.log.levels.ERROR) - return false - end - - vim.system({ 'xdg-open', url }, { detach = true }) - return true -end - -function M.execute(handler, url) - if type(handler.cmd) == 'function' then - handler.cmd(url) - else - vim.system({ handler.cmd, url }, { detach = true }) - end -end - -return M diff --git a/lua/muwiki/health.lua b/lua/muwiki/health.lua index 22c9747..13c5523 100644 --- a/lua/muwiki/health.lua +++ b/lua/muwiki/health.lua @@ -1,15 +1,5 @@ - -local utils = require('muwiki.utils') - local M = {} -local function command_exists(cmd) - if type(cmd) == 'function' then - return true - end - return vim.fn.executable(cmd) == 1 -end - M.check = function() vim.health.start('Wiki Setup') @@ -26,7 +16,8 @@ M.check = function() vim.health.info('Add to your config: dirs = {{name = "default", path = "~/wiki"}}') else for _, dir in ipairs(cfg.dirs) do - if utils.dir_exists(dir.path) then + local stat = vim.uv.fs_stat(dir.path) + if stat and stat.type == 'directory' then vim.health.ok(string.format("Wiki '%s': %s", dir.name, dir.path)) else vim.health.warn(string.format("Wiki '%s': %s (not found)", dir.name, dir.path)) @@ -34,26 +25,6 @@ M.check = function() end end - vim.health.start('External Handlers') - - if cfg.use_external_handlers then - vim.health.ok('External handlers are enabled') - - for _, handler in ipairs(cfg.external_handlers) do - if type(handler.cmd) == 'function' then - vim.health.ok(string.format("Handler '%s': <Lua function>", handler.name)) - elseif command_exists(handler.cmd) then - vim.health.ok(string.format("Handler '%s': %s", handler.name, handler.cmd)) - else - vim.health.error( - string.format("Handler '%s': command not found (%s)", handler.name, handler.cmd) - ) - end - end - else - vim.health.info('External handlers are disabled') - end - vim.health.start('Treesitter (Required)') local has_ts_parser = pcall(vim.treesitter.get_parser, 0, 'markdown') diff --git a/lua/muwiki/init.lua b/lua/muwiki/init.lua index a6997a7..f9d8f23 100644 --- a/lua/muwiki/init.lua +++ b/lua/muwiki/init.lua @@ -1,37 +1,16 @@ local M = {} -local config = require('muwiki.config') - -M.setup = function(opts) - config.setup(opts) -end - -function M.open_link() - require('muwiki.links').open_link() -end - -function M.next_link() - require('muwiki.links').next_link() -end - -function M.prev_link() - require('muwiki.links').prev_link() -end - -function M.open_link_with() - require('muwiki.links').open_link_with() -end - -function M.create_link() - require('muwiki.links').create_link() -end - -function M.open_index(name) - require('muwiki.utils').open_index(name) -end - -function M.wiki_root(bufnr) - return config.wiki_root(bufnr) -end +function M.setup(opts) + require('muwiki.config').setup(opts) +end + +M.open_link = function() require('muwiki.links').open_link() end +M.next_link = function() require('muwiki.links').jump_link('next') end +M.prev_link = function() require('muwiki.links').jump_link('prev') end +M.create_link = function() require('muwiki.links').create_link() end +M.get_link = function() return require('muwiki.links').get_link() end +M.open_with_menu = function(handlers, link) require('muwiki.links').open_with_menu(handlers, link) end +M.open_index = function(name) require('muwiki.utils').open_index(name) end +M.wiki_root = function(bufnr) return require('muwiki.utils').wiki_root(bufnr) end return M diff --git a/lua/muwiki/links.lua b/lua/muwiki/links.lua index 55ce692..1a681fa 100644 --- a/lua/muwiki/links.lua +++ b/lua/muwiki/links.lua @@ -1,7 +1,4 @@ -local config = require('muwiki.config') -local paths = require('muwiki.paths') local utils = require('muwiki.utils') -local external = require('muwiki.external') local M = {} @@ -15,6 +12,12 @@ local function get_link_type(target) return 'wiki' end +local function resolve_file_url(url) + local path = url:gsub('^file://', '') + local resolved = utils.resolve(path, nil) + return 'file://' .. resolved +end + function M.get_link() local cursor = vim.api.nvim_win_get_cursor(0) @@ -60,20 +63,8 @@ function M.get_link() } end -local function resolve_file_url(url) - local path = paths.strip_file_protocol(url) - local path_type = paths.get_path_type(path) - - if path_type == 'relative' then - local current_dir = vim.fs.dirname(vim.api.nvim_buf_get_name(0)) - path = vim.fs.joinpath(current_dir, path) - end - - return 'file://' .. vim.fs.normalize(path) -end - local function get_wiki_root_or_notify() - local wiki_root = config.wiki_root(0) + local wiki_root = utils.wiki_root(0) if not wiki_root then vim.notify('Not in a wiki buffer', vim.log.levels.ERROR) return nil @@ -88,10 +79,9 @@ function M.open_link() return end + -- Web links - open with xdg-open if link.type == 'web' then - if config.options.use_external_handlers then - external.open(link.target) - end + vim.system({'xdg-open', link.target}, {detach = true}) return end @@ -100,107 +90,89 @@ function M.open_link() return end + -- File links - use xdg-open if link.type == 'file' then if vim.startswith(link.target, 'file://') then - if config.options.use_external_handlers then - local absolute_url = resolve_file_url(link.target) - external.open(absolute_url) - end + -- file:// URLs - open with xdg-open + vim.system({'xdg-open', resolve_file_url(link.target)}, {detach = true}) else + -- Local file paths - open with xdg-open local ok, file_path = pcall(utils.resolve, link.target, wiki_root) if not ok then vim.notify(string.format('Cannot resolve path: %s', link.target), vim.log.levels.ERROR) return end - if not utils.file_exists(file_path) then - vim.notify(string.format('File not found: %s', file_path), vim.log.levels.ERROR) - return - end - - local ext = file_path:match('%.([^%.]+)$') or '' - if not utils.is_text_file(ext) then - if config.options.use_external_handlers then - external.open(file_path) - end - return - end - - utils.open_in_buffer(file_path) + vim.system({'xdg-open', file_path}, {detach = true}) end return end - -- wiki link + -- Wiki links - open in buffer local file_path = utils.resolve(link.target, wiki_root) - utils.open_wiki_file(file_path) + utils.open_in_buffer(file_path) end -function M.open_link_with() - local link = M.get_link() +function M.open_with_menu(handlers, link) + -- Get link automatically if not provided + link = link or M.get_link() if not link then - vim.notify('No link found under cursor', vim.log.levels.WARN) - return - end - - if link.type == 'wiki' then - vim.notify('Menu not available for wiki links', vim.log.levels.WARN) + vim.notify('No link under cursor', vim.log.levels.WARN) return end - local url = link.target - if link.type == 'file' then - local wiki_root = get_wiki_root_or_notify() - if not wiki_root then - return - end - url = utils.resolve(url, wiki_root) - end - - -- Find matching handlers for URL - local function handler_matches(handler, url) - local pattern = handler.pattern - if pattern == nil then - return true - end - if type(pattern) == 'string' then - return url:match(pattern) ~= nil - end - for _, p in ipairs(pattern) do - if url:match(p) then - return true - end - end - return false - end + -- Get file extension + local ext = link.target:match('%.([^%.]+)$') + ext = ext and ext:lower() or nil + -- Filter handlers by extension local matching_handlers = {} - for _, handler in ipairs(config.options.external_handlers) do - if handler_matches(handler, url) then + for _, handler in ipairs(handlers) do + -- Check if handler matches this extension + if handler.exts then + for _, handler_ext in ipairs(handler.exts) do + if handler_ext:lower() == ext then + table.insert(matching_handlers, handler) + break + end + end + else + -- No exts specified - matches all table.insert(matching_handlers, handler) end end if #matching_handlers == 0 then - vim.notify('No handlers available for this URL', vim.log.levels.WARN) + vim.notify('No handlers for file type: ' .. (ext or 'unknown'), vim.log.levels.WARN) return end - if #matching_handlers == 1 then - external.execute(matching_handlers[1], url) - return + -- Resolve the path + local url = link.target + if link.type == 'file' and not vim.startswith(url, 'file://') then + local wiki_root = get_wiki_root_or_notify() + if wiki_root then + url = utils.resolve(url, wiki_root) + end end + -- Build menu items local handler_names = {} for _, handler in ipairs(matching_handlers) do table.insert(handler_names, handler.name) end + -- Show menu with link text as title vim.ui.select(handler_names, { - prompt = 'Open with:', + prompt = 'Open "' .. link.text .. '" with:', }, function(choice, idx) if choice and idx then - external.execute(matching_handlers[idx], url) + local handler = matching_handlers[idx] + if type(handler.cmd) == 'function' then + handler.cmd(url) + else + vim.system({ handler.cmd, url }, { detach = true }) + end end end) end @@ -254,17 +226,17 @@ function M.create_link() vim.api.nvim_buf_set_text(0, start_row, start_col, end_row, end_col, { link_text }) vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes('<Esc>', true, false, true), 'n', false) - local wiki_root = config.wiki_root(0) + local wiki_root = utils.wiki_root(0) if not wiki_root then vim.notify('Not in a wiki buffer', vim.log.levels.ERROR) return end local target_path = utils.resolve(link_target, wiki_root) - utils.open_wiki_file(target_path) + utils.open_in_buffer(target_path) end -local function jump_link(direction) +function M.jump_link(direction) local flags = direction == 'next' and 'w' or 'bw' local msg = direction == 'next' and 'No more links' or 'No previous links' @@ -273,12 +245,4 @@ local function jump_link(direction) end end -function M.next_link() - jump_link('next') -end - -function M.prev_link() - jump_link('prev') -end - return M diff --git a/lua/muwiki/paths.lua b/lua/muwiki/paths.lua deleted file mode 100644 index c2f8fdb..0000000 --- a/lua/muwiki/paths.lua +++ /dev/null @@ -1,43 +0,0 @@ -local M = {} - -function M.get_path_type(path) - if path:sub(1, 1) == '/' then - return 'absolute' - elseif path:sub(1, 1) == '~' then - return 'home' - else - return 'relative' - end -end - -function M.resolve(filepath, current_file) - local path_type = M.get_path_type(filepath) - - if path_type == 'relative' then - local base = current_file and vim.fs.dirname(current_file) - or vim.fs.dirname(vim.api.nvim_buf_get_name(0)) - filepath = vim.fs.joinpath(base, filepath) - end - - return vim.fs.normalize(filepath) -end - -function M.strip_file_protocol(url) - return url:gsub('^file://', '') -end - -local ALLOWED_SCHEMES = { - http = true, - https = true, - file = true, -} - -function M.validate_url_scheme(url) - local scheme = url:match('^([a-zA-Z]+)://') - if scheme and not ALLOWED_SCHEMES[scheme:lower()] then - return false, string.format('URL scheme not allowed: %s', scheme) - end - return true, nil -end - -return M diff --git a/lua/muwiki/utils.lua b/lua/muwiki/utils.lua index af22c8e..bc6094e 100644 --- a/lua/muwiki/utils.lua +++ b/lua/muwiki/utils.lua @@ -1,25 +1,54 @@ local config = require('muwiki.config') -local paths = require('muwiki.paths') local M = {} -function M.file_exists(path) - local stat = vim.uv.fs_stat(path) - return stat and stat.type == 'file' +function M.open_in_buffer(filepath) + vim.cmd.edit(vim.fn.fnameescape(filepath)) end -function M.dir_exists(path) - local stat = vim.uv.fs_stat(path) - return stat and stat.type == 'directory' +-- Lookup wiki path by name (e.g., "default" -> "~/wiki/") +function M.wiki_path(name) + if not config.options.dirs or #config.options.dirs == 0 then + vim.notify('MuWiki: No dirs configured. See :help muwiki-configuration', vim.log.levels.ERROR) + return nil + end + + if name then + for _, dir in ipairs(config.options.dirs) do + if dir.name == name then + return dir.path + end + end + vim.notify(string.format('Wiki "%s" not found, using default', name), vim.log.levels.WARN) + end + + return config.options.dirs[1].path end -function M.open_in_buffer(filepath) - local bufnr = vim.fn.bufnr(filepath, true) - vim.api.nvim_win_set_buf(0, bufnr) +-- Find which wiki contains this buffer's file (cached per-buffer) +function M.wiki_root(bufnr) + bufnr = bufnr or 0 + + if vim.b[bufnr].muwiki_root ~= nil then + return vim.b[bufnr].muwiki_root or nil + end + + local filepath = vim.api.nvim_buf_get_name(bufnr) + local normalized = vim.fs.normalize(filepath) + + for _, dir in ipairs(config.options.dirs or {}) do + if vim.startswith(normalized, dir.path) then + vim.b[bufnr].muwiki_root = dir.path + return dir.path + end + end + + vim.b[bufnr].muwiki_root = false + return nil end function M.open_index(name) - local wiki_path = config.wiki_path(name) + local wiki_path = M.wiki_path(name) if not wiki_path then return end @@ -29,18 +58,14 @@ function M.open_index(name) end function M.resolve(filepath, wiki_root) - local path = paths.strip_file_protocol(filepath) - return paths.resolve(path, wiki_root) -end - -function M.is_text_file(ext) - local ext_lower = ext:lower() - for _, text_ext in ipairs(config.options.text_extensions) do - if ext_lower == text_ext then - return true - end + local path = filepath:gsub('^file://', '') + local path_type = path:sub(1, 1) + if path_type ~= '/' and path_type ~= '~' then + local base = wiki_root and vim.fs.dirname(wiki_root) + or vim.fs.dirname(vim.api.nvim_buf_get_name(0)) + path = vim.fs.joinpath(base, path) end - return false + return vim.fs.normalize(path) end function M.normalize_filename(text) @@ -50,8 +75,4 @@ function M.normalize_filename(text) return normalized end -function M.open_wiki_file(filepath) - M.open_in_buffer(filepath) -end - return M |
