aboutsummaryrefslogtreecommitdiff
path: root/lua
diff options
context:
space:
mode:
Diffstat (limited to 'lua')
-rw-r--r--lua/muwiki/config.lua58
-rw-r--r--lua/muwiki/external.lua30
-rw-r--r--lua/muwiki/health.lua33
-rw-r--r--lua/muwiki/init.lua45
-rw-r--r--lua/muwiki/links.lua146
-rw-r--r--lua/muwiki/paths.lua43
-rw-r--r--lua/muwiki/utils.lua73
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