diff --git a/lua/hover.lua b/lua/hover.lua deleted file mode 100644 index 990833e..0000000 --- a/lua/hover.lua +++ /dev/null @@ -1,182 +0,0 @@ --- Cycling hover: K shows line diagnostics one at a time, then the LSP hover. --- Repeated K cycles through them; 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 ) 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 can enter it. - M.items = build_items() - M.idx = 1 - show() -end - --- Mapped to : focus the float if open, otherwise default . -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("", true, false, true), "n", false) - end -end - -return M diff --git a/lua/keymaps.lua b/lua/keymaps.lua index d16ae5c..47df2c5 100644 --- a/lua/keymaps.lua +++ b/lua/keymaps.lua @@ -5,24 +5,22 @@ local silent = { silent = true } map("n", "", "nohlsearch", 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. enters. -local hover = require("hover") -map("n", "K", hover.hover, { desc = "Hover (cycle diagnostics / LSP)" }) -map("n", "", 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", "gf", function() require("conform").format({ lsp_format = "fallback" }) end, { desc = "Format buffer" }) map("n", "gd", vim.lsp.buf.definition) map("n", "gD", vim.lsp.buf.declaration) -map("n", "ca", vim.lsp.buf.code_action, { desc = "Code Action" }) -map("n", "rn", vim.lsp.buf.rename, { desc = "Rename symbol" }) -- Trouble map("n", "xx", "Trouble diagnostics toggle focus=true", @@ -34,6 +32,7 @@ map("n", "xt", "Trouble todo toggle", { desc = "Todo (Trouble)" -- Pickers / files map("n", "", "Pick files") map("n", "", "Pick grep_live") +map("n", "", "Pick buffers") map("n", "", "Pick help") map("n", "", "Oil") map("n", "", "Pick keymaps") @@ -44,28 +43,6 @@ map("n", "duc", function() require("dapui").close() end) map("n", "dbp", function() require("dap").toggle_breakpoint() end) map("n", "drc", function() require("dap").run_to_cursor() end) --- Bufferline -map("n", "", "BufferLineCyclePrev", silent) -map("n", "", "BufferLineCycleNext", silent) -map("n", "[b", "BufferLineCyclePrev", silent) -map("n", "]b", "BufferLineCycleNext", silent) -map("n", "<", "BufferLineMovePrev", silent) -map("n", ">", "BufferLineMoveNext", silent) -map("n", "bp", "BufferLineTogglePin", { desc = "Toggle pin" }) -map("n", "bP", "BufferLineGroupClose ungrouped", { desc = "Close non-pinned" }) -map("n", "bo", "BufferLineCloseOthers", { desc = "Close others" }) -map("n", "br", "BufferLineCloseRight", { desc = "Close right" }) -map("n", "bl", "BufferLineCloseLeft", { desc = "Close left" }) -map("n", "bd", "bdelete", { desc = "Delete buffer" }) -map("n", "bb", "BufferLinePick", { desc = "Pick buffer" }) -map("n", "bse", "BufferLineSortByExtension", { desc = "Sort by extension" }) -map("n", "bsd", "BufferLineSortByDirectory", { desc = "Sort by directory" }) -map("n", "bsr", "BufferLineSortByRelativeDirectory", { desc = "Sort by relative dir" }) -map("n", "bst", "BufferLineSortByTabs", { desc = "Sort by tabs" }) -for i = 1, 9 do - map("n", ("%d"):format(i), ("BufferLineGoToBuffer %d"):format(i), silent) -end - -- Spell map("n", "sc", function() vim.wo.spell = not vim.wo.spell diff --git a/lua/options.lua b/lua/options.lua index 92b5675..5efe8a3 100644 --- a/lua/options.lua +++ b/lua/options.lua @@ -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, }) diff --git a/lua/plugins.lua b/lua/plugins.lua index e89718a..812dd84 100644 --- a/lua/plugins.lua +++ b/lua/plugins.lua @@ -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", "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)