some optimizations

This commit is contained in:
2026-06-11 18:23:52 +02:00
parent bd6b4722e5
commit d53091f919
4 changed files with 14 additions and 240 deletions
-182
View File
@@ -1,182 +0,0 @@
-- Cycling hover: K shows line diagnostics one at a time, then the LSP hover.
-- Repeated K cycles through them; <CR> enters the floating window.
local M = {}
M.win = nil -- floating window handle
M.buf = nil -- floating buffer handle
M.items = nil -- list of render functions for the current cycle
M.idx = 0 -- current position in the cycle
M.bufnr = nil -- source buffer the cycle was started from
M.lnum = nil -- 0-indexed source line
M.col = nil -- 0-indexed source column
local group = vim.api.nvim_create_augroup("HoverCycle", { clear = true })
local SEVERITY = { "ERROR", "WARN", "INFO", "HINT" }
local function float_open()
return M.win ~= nil and vim.api.nvim_win_is_valid(M.win)
end
local function close_float()
if float_open() then
vim.api.nvim_win_close(M.win, true)
end
M.win = nil
M.buf = nil
end
-- Open (or replace) the float with the given lines.
local function open_float(lines, ft)
close_float()
local buf = vim.api.nvim_create_buf(false, true)
vim.api.nvim_buf_set_lines(buf, 0, -1, false, lines)
vim.bo[buf].bufhidden = "wipe"
local width = 1
for _, l in ipairs(lines) do
width = math.max(width, vim.fn.strdisplaywidth(l))
end
width = math.min(width, math.floor(vim.o.columns * 0.8))
local height = math.min(math.max(#lines, 1), math.floor(vim.o.lines * 0.6))
local win = vim.api.nvim_open_win(buf, false, {
relative = "cursor",
row = 1,
col = 0,
width = width,
height = height,
style = "minimal",
border = "rounded",
focusable = true,
})
vim.wo[win].wrap = true
vim.wo[win].conceallevel = 2
vim.wo[win].concealcursor = "nc"
M.win = win
M.buf = buf
-- Set filetype only now that the buffer is shown in a window, so the
-- FileType autocmds (treesitter + render-markdown) render into it.
if ft then vim.bo[buf].filetype = ft end
vim.bo[buf].modifiable = false
-- Close when the cursor moves in the source buffer. Switching INTO the
-- float (via <CR>) does not move the source cursor, so it survives that.
vim.api.nvim_clear_autocmds({ group = group })
vim.api.nvim_create_autocmd({ "CursorMoved", "CursorMovedI", "InsertEnter" }, {
group = group,
buffer = M.bufnr,
callback = function() close_float() end,
})
vim.keymap.set("n", "q", close_float, { buffer = buf, nowait = true, silent = true })
end
local function with_header(header, body, ft)
local lines = {}
if header then
lines[1] = header
lines[2] = ""
end
vim.list_extend(lines, body)
open_float(lines, ft)
end
local function show_lsp_hover(idx, n)
local header = n > 1 and ("Hover [%d/%d]"):format(idx, n) or nil
local clients = vim.lsp.get_clients({ bufnr = M.bufnr, method = "textDocument/hover" })
if #clients == 0 then
with_header(header, { "No LSP hover available" })
return
end
local params = vim.lsp.util.make_position_params(0, clients[1].offset_encoding)
vim.lsp.buf_request(M.bufnr, "textDocument/hover", params, function(_, result)
if M.idx ~= idx or M.bufnr ~= vim.api.nvim_get_current_buf() then
return -- cycle moved on before the response arrived
end
local body = {}
if result and result.contents then
body = vim.lsp.util.convert_input_to_markdown_lines(result.contents)
end
if vim.tbl_isempty(body) then body = { "No hover information" } end
with_header(header, body, "markdown")
end)
end
-- True if the diagnostic's range covers the (lnum, col) cursor position.
local function under_cursor(d, lnum, col)
local end_lnum = d.end_lnum or d.lnum
local end_col = d.end_col or (d.col + 1)
if lnum < d.lnum or lnum > end_lnum then return false end
if lnum == d.lnum and col < d.col then return false end
if lnum == end_lnum and col >= math.max(end_col, d.col + 1) then return false end
return true
end
-- Diagnostics whose range is under the cursor, sorted by start column.
local function cursor_diags()
local diags = vim.tbl_filter(
function(d) return under_cursor(d, M.lnum, M.col) end,
vim.diagnostic.get(M.bufnr, { lnum = M.lnum }))
table.sort(diags, function(a, b) return a.col < b.col end)
return diags
end
local function build_items()
local items = {}
local diags = cursor_diags()
for _, d in ipairs(diags) do
items[#items + 1] = function(idx, n)
local sev = SEVERITY[d.severity] or "DIAG"
local header = n > 1 and ("Diagnostic [%d/%d] %s"):format(idx, n, sev)
or ("Diagnostic %s"):format(sev)
with_header(header, vim.split(d.message, "\n", { plain = true }))
end
end
items[#items + 1] = show_lsp_hover
return items
end
local function show()
M.items[M.idx](M.idx, #M.items)
end
-- Mapped to K.
function M.hover()
if float_open() then
M.idx = M.idx % #M.items + 1
show()
return
end
M.bufnr = vim.api.nvim_get_current_buf()
local pos = vim.api.nvim_win_get_cursor(0)
M.lnum = pos[1] - 1
M.col = pos[2]
-- No diagnostic under cursor -> a single LSP-hover item (no cycle header),
-- still rendered in our managed float so <CR> can enter it.
M.items = build_items()
M.idx = 1
show()
end
-- Mapped to <CR>: focus the float if open, otherwise default <CR>.
function M.enter()
if float_open() then
vim.api.nvim_set_current_win(M.win)
else
vim.api.nvim_feedkeys(
vim.api.nvim_replace_termcodes("<CR>", true, false, true), "n", false)
end
end
return M
+7 -30
View File
@@ -5,24 +5,22 @@ local silent = { silent = true }
map("n", "<Esc>", "<cmd>nohlsearch<cr>", silent)
-- Visual line navigation
for _, mode in ipairs({ "n", "v" }) do
for _, mode in ipairs({ "n", "x" }) do
map(mode, "j", "gj", silent)
map(mode, "k", "gk", silent)
end
-- Hover: cycle diagnostics on the current line, then LSP hover. <CR> enters.
local hover = require("hover")
map("n", "K", hover.hover, { desc = "Hover (cycle diagnostics / LSP)" })
map("n", "<CR>", hover.enter, { desc = "Enter hover window", silent = true })
-- Hover: native LSP hover (press K again to focus the window).
-- Border comes from the global `winborder` option.
map("n", "K", function() vim.lsp.buf.hover({ max_width = 80 }) end,
{ desc = "LSP hover" })
-- LSP
-- LSP (rename/code-action/references use native gr* defaults on 0.11+)
map("n", "<leader>gf",
function() require("conform").format({ lsp_format = "fallback" }) end,
{ desc = "Format buffer" })
map("n", "<leader>gd", vim.lsp.buf.definition)
map("n", "<leader>gD", vim.lsp.buf.declaration)
map("n", "<leader>ca", vim.lsp.buf.code_action, { desc = "Code Action" })
map("n", "<leader>rn", vim.lsp.buf.rename, { desc = "Rename symbol" })
-- Trouble
map("n", "<leader>xx", "<cmd>Trouble diagnostics toggle focus=true<cr>",
@@ -34,6 +32,7 @@ map("n", "<leader>xt", "<cmd>Trouble todo toggle<cr>", { desc = "Todo (Trouble)"
-- Pickers / files
map("n", "<C-f>", "<cmd>Pick files<cr>")
map("n", "<C-g>", "<cmd>Pick grep_live<cr>")
map("n", "<C-b>", "<cmd>Pick buffers<cr>")
map("n", "<C-h>", "<cmd>Pick help<cr>")
map("n", "<C-e>", "<cmd>Oil<cr>")
map("n", "<C-k>", "<cmd>Pick keymaps<cr>")
@@ -44,28 +43,6 @@ map("n", "<leader>duc", function() require("dapui").close() end)
map("n", "<leader>dbp", function() require("dap").toggle_breakpoint() end)
map("n", "<leader>drc", function() require("dap").run_to_cursor() end)
-- Bufferline
map("n", "<S-h>", "<cmd>BufferLineCyclePrev<cr>", silent)
map("n", "<S-l>", "<cmd>BufferLineCycleNext<cr>", silent)
map("n", "[b", "<cmd>BufferLineCyclePrev<cr>", silent)
map("n", "]b", "<cmd>BufferLineCycleNext<cr>", silent)
map("n", "<", "<cmd>BufferLineMovePrev<cr>", silent)
map("n", ">", "<cmd>BufferLineMoveNext<cr>", silent)
map("n", "<leader>bp", "<cmd>BufferLineTogglePin<cr>", { desc = "Toggle pin" })
map("n", "<leader>bP", "<cmd>BufferLineGroupClose ungrouped<cr>", { desc = "Close non-pinned" })
map("n", "<leader>bo", "<cmd>BufferLineCloseOthers<cr>", { desc = "Close others" })
map("n", "<leader>br", "<cmd>BufferLineCloseRight<cr>", { desc = "Close right" })
map("n", "<leader>bl", "<cmd>BufferLineCloseLeft<cr>", { desc = "Close left" })
map("n", "<leader>bd", "<cmd>bdelete<cr>", { desc = "Delete buffer" })
map("n", "<leader>bb", "<cmd>BufferLinePick<cr>", { desc = "Pick buffer" })
map("n", "<leader>bse", "<cmd>BufferLineSortByExtension<cr>", { desc = "Sort by extension" })
map("n", "<leader>bsd", "<cmd>BufferLineSortByDirectory<cr>", { desc = "Sort by directory" })
map("n", "<leader>bsr", "<cmd>BufferLineSortByRelativeDirectory<cr>", { desc = "Sort by relative dir" })
map("n", "<leader>bst", "<cmd>BufferLineSortByTabs<cr>", { desc = "Sort by tabs" })
for i = 1, 9 do
map("n", ("<leader>%d"):format(i), ("<cmd>BufferLineGoToBuffer %d<cr>"):format(i), silent)
end
-- Spell
map("n", "<leader>sc", function()
vim.wo.spell = not vim.wo.spell
+2 -1
View File
@@ -28,6 +28,7 @@ vim.api.nvim_create_autocmd("FileType", {
})
vim.diagnostic.config({
virtual_text = { prefix = "", spacing = 2, source = "if_many" },
virtual_text = false,
virtual_lines = { current_line = true },
severity_sort = true,
})
+5 -27
View File
@@ -3,6 +3,7 @@ vim.pack.add({
{ src = "https://github.com/stevearc/oil.nvim" },
{ src = "https://github.com/echasnovski/mini.pick" },
{ src = "https://github.com/echasnovski/mini.extra" },
{ src = "https://github.com/echasnovski/mini.icons" },
{ src = "https://github.com/neovim/nvim-lspconfig" },
{ src = "https://github.com/nvim-treesitter/nvim-treesitter", version = "main" },
{ src = "https://github.com/nvim-treesitter/nvim-treesitter-textobjects", version = "main" },
@@ -13,8 +14,6 @@ vim.pack.add({
{ src = "https://codeberg.org/mfussenegger/nvim-jdtls.git" },
{ src = "https://github.com/windwp/nvim-autopairs" },
{ src = "https://codeberg.org/mfussenegger/nvim-dap.git" },
{ src = "https://github.com/akinsho/bufferline.nvim" },
{ src = "https://github.com/nvim-tree/nvim-web-devicons" },
{ src = "https://github.com/echasnovski/mini.ai" },
{ src = "https://github.com/windwp/nvim-ts-autotag" },
{ src = "https://github.com/folke/todo-comments.nvim" },
@@ -35,12 +34,13 @@ vim.api.nvim_set_hl(0, "FlashLabel", { fg = "#1d2021", bg = "#fe8019", bold = tr
-- Simple setup({}) plugins
for _, name in ipairs({
"oil", "mini.pick", "mini.extra", "mason", "typst-preview", "nvim-autopairs",
"trouble", "gitsigns", "nvim-web-devicons",
"mini.ai", "nvim-ts-autotag", "todo-comments", "cssview",
"oil", "mini.pick", "mini.extra", "mini.icons", "mason", "typst-preview",
"nvim-autopairs", "trouble", "gitsigns",
"mini.ai", "nvim-ts-autotag", "todo-comments", "csvview",
}) do
pcall(function() require(name).setup() end)
end
require("mini.icons").mock_nvim_web_devicons()
local prettier = { "prettierd", "prettier", stop_after_first = true }
require("conform").setup({
@@ -191,28 +191,6 @@ vim.keymap.set("x", "<leader>cs", function() silicon_shot(false) end,
require("lualine").setup({ options = { theme = "gruvbox_dark" } })
local bl_bg = "#3c3836" -- lualine statusline bg
local bl_sel_bg = "#504945" -- lualine section_b bg (git branch)
local bl_fg = "#a89984"
local bl_sel_fg = "#ebdbb2"
require("bufferline").setup({
highlights = {
fill = { bg = bl_bg },
background = { bg = bl_bg, fg = bl_fg },
buffer_visible = { bg = bl_bg, fg = bl_fg },
buffer_selected = { bg = bl_sel_bg, fg = bl_sel_fg, bold = true, italic = false },
separator = { bg = bl_bg, fg = bl_bg },
separator_visible = { bg = bl_bg, fg = bl_bg },
separator_selected = { bg = bl_sel_bg, fg = bl_bg },
indicator_selected = { bg = bl_sel_bg, fg = bl_sel_bg },
modified = { bg = bl_bg },
modified_visible = { bg = bl_bg },
modified_selected = { bg = bl_sel_bg },
close_button = { bg = bl_bg, fg = bl_fg },
close_button_visible = { bg = bl_bg, fg = bl_fg },
close_button_selected = { bg = bl_sel_bg, fg = bl_sel_fg },
},
})
require("blink.cmp").setup({ keymap = { preset = "super-tab" } })
-- Treesitter (main branch: no configs.setup; install parsers manually)