diff --git a/.stylua.toml b/.stylua.toml index f6b869b..7662e6a 100644 --- a/.stylua.toml +++ b/.stylua.toml @@ -5,4 +5,3 @@ indent_type = "Spaces" indent_width = 2 line_endings = "Unix" quote_style = "AutoPreferDouble" -remove_trailing_separators = false diff --git a/lua/markmap/config.lua b/lua/markmap/config.lua index 05d403a..c14b78d 100644 --- a/lua/markmap/config.lua +++ b/lua/markmap/config.lua @@ -1,8 +1,9 @@ -- Config options to keep init clean. local M = {} -local is_windows = vim.uv.os_uname().sysname == "Windows_NT" -local is_android = vim.fn.isdirectory('/data') == 1 +local uv = vim.uv or vim.loop +local is_windows = uv.os_uname().sysname == "Windows_NT" +local is_android = vim.fn.isdirectory("/data") == 1 ---Parse user options, or set the defaults ---@param opts table A table with options to set. diff --git a/lua/markmap/init.lua b/lua/markmap/init.lua index 3a09ce2..eced275 100644 --- a/lua/markmap/init.lua +++ b/lua/markmap/init.lua @@ -1,4 +1,5 @@ -- This plugin is a wrapper for markmap-cli +local api = vim.api local utils = require("markmap.utils") local jobstart = utils.jobstart local jobstop = vim.fn.jobstop @@ -13,6 +14,7 @@ M.setup = function(opts) local config = vim.g.markmap_config local job = nil local arguments = {} + local lookup_table = {} -- Setup commands ----------------------------------------------------------- cmd("MarkmapOpen", function() @@ -27,48 +29,75 @@ M.setup = function(opts) cmd("MarkmapSave", function() config = vim.g.markmap_config arguments = utils.reset_arguments() - local path = '"' .. vim.fn.expand("%:p") .. '"' -- current buffer path - table.insert(arguments, "--no-open") -- specific to this command - table.insert(arguments, path) - if job ~= nil then jobstop(job) end -- kill jobs + table.insert(arguments, "--no-open") -- specific to this command + table.insert(arguments, vim.fn.expand("%:p")) -- current buffer path + if job ~= nil then jobstop(job) end -- kill jobs job = jobstart(config.markmap_cmd, arguments) end, { desc = "Save the HTML file without opening the mindmap" }) - cmd("MarkmapWatch", function() - config = vim.g.markmap_config - arguments = utils.reset_arguments() - local path = '"' .. vim.fn.expand("%:p") .. '"' -- current buffer path - table.insert(arguments, "--watch") -- spetific to this command - table.insert(arguments, path) - if job ~= nil then jobstop(job) end -- kill jobs - job = jobstart(config.markmap_cmd, arguments) - end, { desc = "Show a mental map of the current file and watch for changes" }) + cmd( + "MarkmapWatch", + function() + local watch_buffer = vim.api.nvim_get_current_buf() + config = vim.g.markmap_config + arguments = utils.reset_arguments() + table.insert(arguments, "--watch") -- spetific to this command + table.insert(arguments, vim.fn.expand("%:p")) -- current buffer path - cmd("MarkmapWatchStop", function() - if job ~= nil then jobstop(job) end -- kill jobs - end, { desc = "Manually stops markmap watch" }) + if lookup_table[watch_buffer] then + vim.notify("You're already watching this buffer.", vim.log.levels.WARN) + else + local kill_on_close = + augroup("markmap_kill_on_close", { clear = false }) - -- Autocmds ----------------------------------------------------------------- - -- Kill jobs after a grace period - local last_execution = vim.uv.now() -- timer for grace period - autocmd("CursorHold", { - desc = "Kill all markmap jobs after a grace period", - group = augroup("markmap_kill_after_grace_period", { clear = true }), - callback = function() - -- If grace_periodd is disabled, remove the autocmd and return - if config.grace_period == 0 then - vim.cmd "autocmd! markmap_kill_after_grace_period" - return - end + job = jobstart(config.markmap_cmd, arguments, { + stderr_buffered = true, -- needed so on_stderr is only called once + on_stderr = function(_, data) + local message = table.concat(data, "\n") + message = message:gsub("\r", "") + vim.notify(message, vim.log.levels.ERROR) + + lookup_table[watch_buffer] = nil + api.nvim_clear_autocmds({ + group = kill_on_close, + buffer = watch_buffer, + }) + end, + }) + + lookup_table[watch_buffer] = job - -- Otherwise, use grace_period - local current_time = vim.uv.now() - if current_time - last_execution >= config.grace_period then -- if grace period exceeded - if job ~= nil then jobstop(job) end -- pkill jobs - last_execution = current_time -- update time + -- Register buffer local autocmd to kill job when buffer closes + autocmd("BufDelete", { + desc = "Kill markmap when watched buffer is closed", + buffer = watch_buffer, + group = kill_on_close, + callback = function() + jobstop(job) + lookup_table[watch_buffer] = nil + api.nvim_clear_autocmds({ + group = kill_on_close, + buffer = watch_buffer, + }) + end, + }) end end, - }) + { desc = "Show a mental map of the current file and watch for changes" } + ) + + cmd("MarkmapWatchStop", function() + local watch_buffer = vim.api.nvim_get_current_buf() + local job = lookup_table[watch_buffer] + if job then + jobstop(job) + lookup_table[watch_buffer] = nil + api.nvim_clear_autocmds({ + group = kill_on_close, + buffer = watch_buffer, + }) + end + end, { desc = "Manually stops markmap watch" }) end return M diff --git a/lua/markmap/utils.lua b/lua/markmap/utils.lua index a720bbe..07bf64b 100644 --- a/lua/markmap/utils.lua +++ b/lua/markmap/utils.lua @@ -12,12 +12,13 @@ local is_windows = vim.uv.os_uname().sysname == "Windows_NT" --- the executables must be added to path in at windows level. ---@param cmd string command to run. ---@param arguments table arguments to pass to the cmd. +---@param opts table vim.fn.jobstart options ---@return number job pid of the job, so we can stop it later. -M.jobstart = function(cmd, arguments) +M.jobstart = function(cmd, arguments, opts) if is_windows then - return vim.fn.jobstart({ cmd, unpack(arguments) }) + return opts and vim.fn.jobstart({ cmd, unpack(arguments) }, opts) or vim.fn.jobstart({ cmd, unpack(arguments) }) else - return vim.fn.jobstart(cmd .. " " .. table.concat(arguments, " ")) + return opts and vim.fn.jobstart(cmd .. " " .. table.concat(arguments, " "), opts) or vim.fn.jobstart(cmd .. " " .. table.concat(arguments, " ")) end end @@ -28,7 +29,7 @@ M.reset_arguments = function() local config = vim.g.markmap_config local arguments = {} - if config.html_output ~= "" then -- if html_output is "", don't pass the parameter + if config.html_output ~= "" then -- if html_output is "", don't pass the parameter table.insert(arguments, "-o") table.insert(arguments, '"' .. config.html_output .. '"') end