aboutsummaryrefslogtreecommitdiffstats
path: root/lua/nvim-lsp-installer/ui/display.lua
diff options
context:
space:
mode:
authorWilliam Boman <william@redwill.se>2021-10-10 19:20:16 +0200
committerGitHub <noreply@github.com>2021-10-10 19:20:16 +0200
commit5f54148153a878cc9cbe370adccda0f706251d89 (patch)
tree28ae0436232486323dfce3444e1d25657c34d75e /lua/nvim-lsp-installer/ui/display.lua
parentjdtls: fix jar argument (diff)
downloadmason-5f54148153a878cc9cbe370adccda0f706251d89.tar
mason-5f54148153a878cc9cbe370adccda0f706251d89.tar.gz
mason-5f54148153a878cc9cbe370adccda0f706251d89.tar.bz2
mason-5f54148153a878cc9cbe370adccda0f706251d89.tar.lz
mason-5f54148153a878cc9cbe370adccda0f706251d89.tar.xz
mason-5f54148153a878cc9cbe370adccda0f706251d89.tar.zst
mason-5f54148153a878cc9cbe370adccda0f706251d89.zip
add keybindings to UI window (#140)
- Allows for expanding servers to view more information about it. - Allows for installing/reinstalling/uninstalling servers. The default keybindings is an attempt to mimic vim-fugitive's :Git maps, and these can be overriden. The keybinding implementation in display.lua is a bit hacky, but it works and the "public" API is at least manageable. This will also open up for adding more metadata in the future, such as filetype information, currently installed version, latest available version, etc. Also there's Cowth Vader.
Diffstat (limited to 'lua/nvim-lsp-installer/ui/display.lua')
-rw-r--r--lua/nvim-lsp-installer/ui/display.lua133
1 files changed, 113 insertions, 20 deletions
diff --git a/lua/nvim-lsp-installer/ui/display.lua b/lua/nvim-lsp-installer/ui/display.lua
index 27aca167..e675d715 100644
--- a/lua/nvim-lsp-installer/ui/display.lua
+++ b/lua/nvim-lsp-installer/ui/display.lua
@@ -3,6 +3,20 @@ local log = require "nvim-lsp-installer.log"
local process = require "nvim-lsp-installer.process"
local state = require "nvim-lsp-installer.ui.state"
+local M = {}
+
+local function from_hex(str)
+ return (str:gsub("..", function(cc)
+ return string.char(tonumber(cc, 16))
+ end))
+end
+
+local function to_hex(str)
+ return (str:gsub(".", function(c)
+ return string.format("%02X", string.byte(c))
+ end))
+end
+
local function get_styles(line, render_context)
local indentation = 0
@@ -29,11 +43,13 @@ local function render_node(context, node, _render_context, _output)
context = context,
applied_block_styles = {},
}
- local output = _output or {
- lines = {},
- virt_texts = {},
- highlights = {},
- }
+ local output = _output
+ or {
+ lines = {},
+ virt_texts = {},
+ highlights = {},
+ keybinds = {},
+ }
if node.type == Ui.NodeType.VIRTUAL_TEXT then
output.virt_texts[#output.virt_texts + 1] = {
@@ -81,6 +97,13 @@ local function render_node(context, node, _render_context, _output)
if node.type == Ui.NodeType.CASCADING_STYLE then
render_context.applied_block_styles[#render_context.applied_block_styles] = nil
end
+ elseif node.type == Ui.NodeType.KEYBIND_HANDLER then
+ output.keybinds[#output.keybinds + 1] = {
+ line = node.is_global and -1 or #output.lines,
+ key = node.key,
+ effect = node.effect,
+ payload = node.payload,
+ }
end
return output
@@ -102,10 +125,35 @@ local function create_popup_window_opts()
return popup_layout
end
-local M = {}
-
+local registered_effect_handlers_by_bufnr = {}
+local active_keybinds_by_bufnr = {}
+local registered_keymaps_by_bufnr = {}
local redraw_by_win_id = {}
+local function call_effect_handler(bufnr, line, key)
+ local line_keybinds = active_keybinds_by_bufnr[bufnr][line]
+ if line_keybinds then
+ local keybind = line_keybinds[key]
+ if keybind then
+ local effect_handler = registered_effect_handlers_by_bufnr[bufnr][keybind.effect]
+ if effect_handler then
+ log.fmt_trace("Calling handler for effect %s on line %d for key %s", keybind.effect, line, key)
+ effect_handler { payload = keybind.payload }
+ return true
+ end
+ end
+ end
+ return false
+end
+
+M.dispatch_effect = vim.schedule_wrap(function(bufnr, hex_key)
+ local key = from_hex(hex_key)
+ local line = vim.api.nvim_win_get_cursor(0)[1]
+ log.fmt_trace("Dispatching effect on line %d, key %s, bufnr %s", line, key, bufnr)
+ call_effect_handler(bufnr, line, key) -- line keybinds
+ call_effect_handler(bufnr, -1, key) -- global keybinds
+end)
+
function M.redraw_win(win_id)
local fn = redraw_by_win_id[win_id]
if fn then
@@ -129,6 +177,15 @@ function M.delete_win_buf(win_id, bufnr)
if redraw_by_win_id[win_id] then
redraw_by_win_id[win_id] = nil
end
+ if active_keybinds_by_bufnr[bufnr] then
+ active_keybinds_by_bufnr[bufnr] = nil
+ end
+ if registered_effect_handlers_by_bufnr[bufnr] then
+ registered_effect_handlers_by_bufnr[bufnr] = nil
+ end
+ if registered_keymaps_by_bufnr[bufnr] then
+ registered_keymaps_by_bufnr[bufnr] = nil
+ end
end)
end
@@ -143,6 +200,10 @@ function M.new_view_only_win(name)
bufnr = vim.api.nvim_create_buf(false, true)
win_id = vim.api.nvim_open_win(bufnr, true, create_popup_window_opts())
+ registered_effect_handlers_by_bufnr[bufnr] = {}
+ active_keybinds_by_bufnr[bufnr] = {}
+ registered_keymaps_by_bufnr[bufnr] = {}
+
local buf_opts = {
modifiable = false,
swapfile = false,
@@ -185,8 +246,6 @@ function M.new_view_only_win(name)
):format(win_id, bufnr)
)
- vim.api.nvim_buf_set_keymap(bufnr, "n", "<esc>", "<cmd>bd<CR>", { noremap = true })
-
if highlight_groups then
for i = 1, #highlight_groups do
vim.cmd(highlight_groups[i])
@@ -214,8 +273,10 @@ function M.new_view_only_win(name)
win_width = win_width,
}
local output = render_node(context, view)
- local lines, virt_texts, highlights = output.lines, output.virt_texts, output.highlights
+ local lines, virt_texts, highlights, keybinds =
+ output.lines, output.virt_texts, output.highlights, output.keybinds
+ -- set line contents
vim.api.nvim_buf_clear_namespace(0, namespace, 0, -1)
vim.api.nvim_buf_set_option(bufnr, "modifiable", true)
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, lines)
@@ -227,6 +288,8 @@ function M.new_view_only_win(name)
virt_text = virt_text.content,
})
end
+
+ -- set highlights
for i = 1, #highlights do
local highlight = highlights[i]
vim.api.nvim_buf_add_highlight(
@@ -238,6 +301,32 @@ function M.new_view_only_win(name)
highlight.col_end
)
end
+
+ -- set keybinds
+ local buf_keybinds = {}
+ active_keybinds_by_bufnr[bufnr] = buf_keybinds
+ for i = 1, #keybinds do
+ local keybind = keybinds[i]
+ if not buf_keybinds[keybind.line] then
+ buf_keybinds[keybind.line] = {}
+ end
+ buf_keybinds[keybind.line][keybind.key] = keybind
+ if not registered_keymaps_by_bufnr[bufnr][keybind.key] then
+ vim.api.nvim_buf_set_keymap(
+ bufnr,
+ "n",
+ keybind.key,
+ ("<cmd>lua require('nvim-lsp-installer.ui.display').dispatch_effect(%d, %q)<cr>"):format(
+ bufnr,
+ -- We transfer the keybinding as hex to avoid issues with (neo)vim interpreting the key as a
+ -- literal input to the command. For example, "<CR>" would cause vim to issue an actual carriage
+ -- return - even if it's quoted as a string.
+ to_hex(keybind.key)
+ ),
+ { nowait = true, silent = true, noremap = true }
+ )
+ end
+ end
end)
return {
@@ -267,6 +356,7 @@ function M.new_view_only_win(name)
unsubscribe(false)
local opened_win_id = open(opts)
draw(renderer(get_state()))
+ registered_effect_handlers_by_bufnr[bufnr] = opts.effects
redraw_by_win_id[opened_win_id] = function()
if vim.api.nvim_win_is_valid(opened_win_id) then
draw(renderer(get_state()))
@@ -274,16 +364,19 @@ function M.new_view_only_win(name)
end
end
end),
- -- This is probably not needed.
- -- destroy = vim.schedule_wrap(function()
- -- assert(has_initiated, "Display has not been initiated, cannot destroy.")
- -- TODO: what happens with the state container, etc?
- -- unsubscribe(true)
- -- redraw_by_winnr[win_id] = nil
- -- if win_id then
- -- vim.api.nvim_win_close(win_id, true)
- -- end
- -- end),
+ close = vim.schedule_wrap(function()
+ assert(has_initiated, "Display has not been initiated, cannot close.")
+ unsubscribe(true)
+ M.delete_win_buf(win_id, bufnr)
+ end),
+ set_cursor = function(pos)
+ assert(win_id ~= nil, "Window has not been opened, cannot set cursor.")
+ return vim.api.nvim_win_set_cursor(win_id, pos)
+ end,
+ get_cursor = function()
+ assert(win_id ~= nil, "Window has not been opened, cannot get cursor.")
+ return vim.api.nvim_win_get_cursor(win_id)
+ end,
}
end