diff --git a/symlinks/config/nvim/lua/esensar/common/async_ui.lua b/symlinks/config/nvim/lua/esensar/common/async_ui.lua new file mode 100644 index 0000000..a5d3995 --- /dev/null +++ b/symlinks/config/nvim/lua/esensar/common/async_ui.lua @@ -0,0 +1,9 @@ +-- UI extensions +local plenary_async = require("plenary.async.async") + +local M = {} + +M.input = plenary_async.wrap(vim.ui.input, 2) +M.select = plenary_async.wrap(vim.ui.select, 3) + +return M diff --git a/symlinks/config/nvim/lua/esensar/init/plugins.lua b/symlinks/config/nvim/lua/esensar/init/plugins.lua index 351f6a3..8c141da 100644 --- a/symlinks/config/nvim/lua/esensar/init/plugins.lua +++ b/symlinks/config/nvim/lua/esensar/init/plugins.lua @@ -33,6 +33,8 @@ return require("packer").startup({ use("romainl/vim-devdocs") -- Quick DevDocs.io search using :DD use("gpanders/editorconfig.nvim") -- .editorconfig support use("lewis6991/impatient.nvim") -- Caching lua modules for faster startup + use("rcarriga/nvim-notify") -- notifications UI + use("MunifTanjim/nui.nvim") -- General UI -- Tools use("direnv/direnv.vim") -- Integration with Direnv diff --git a/symlinks/config/nvim/plugin/telescope.lua b/symlinks/config/nvim/plugin/telescope.lua index 577c16c..170db2e 100644 --- a/symlinks/config/nvim/plugin/telescope.lua +++ b/symlinks/config/nvim/plugin/telescope.lua @@ -21,6 +21,7 @@ require("telescope").setup({ }) require("telescope").load_extension("dap") +require("telescope").load_extension("notify") vim.keymap.set("n", "", function() require("telescope.builtin").find_files() diff --git a/symlinks/config/nvim/plugin/ui.lua b/symlinks/config/nvim/plugin/ui.lua new file mode 100644 index 0000000..aa874f2 --- /dev/null +++ b/symlinks/config/nvim/plugin/ui.lua @@ -0,0 +1,81 @@ +-- UI setup +local input = require("nui.input") +local event = require("nui.utils.autocmd").event + +-- Notifications +local notify = require("notify") +notify.setup({ + render = "minimal", + stages = "static", +}) +vim.notify = notify + +-- Inputs +local input_ui + +vim.ui.input = function(opts, on_confirm) + if input_ui then + -- ensure single ui.input operation + vim.notify("busy: another input is pending!", vim.log.levels.WARN) + return + end + + local function on_done(value) + if input_ui then + -- if it's still mounted, unmount it + input_ui:unmount() + end + -- pass the input value + on_confirm(value) + -- indicate the operation is done + input_ui = nil + end + + local border_top_text = opts.prompt or "[Input]" + local default_value = opts.default + + input_ui = input({ + relative = "cursor", + position = { + row = 1, + col = 0, + }, + size = { + -- minimum width 20 + width = math.max(20, type(default_value) == "string" and #default_value or 0), + }, + border = { + style = "rounded", + highlight = "Normal", + text = { + top = border_top_text, + top_align = "left", + }, + }, + win_options = { + winhighlight = "Normal:Normal", + }, + }, { + default_value = default_value, + on_close = function() + on_done(nil) + end, + on_submit = function(value) + on_done(value) + end, + }) + + input_ui:mount() + + -- cancel operation if cursor leaves input + input_ui:on(event.BufLeave, function() + on_done(nil) + end, { once = true }) + + -- cancel operation if is pressed + input_ui:map("n", "", function() + on_done(nil) + end, { noremap = true, nowait = true }) +end + +-- Selections