diff options
| author | Elvis Claros Castro <elvis@claros.ar> | 2026-09-27 12:46:49 -0300 |
|---|---|---|
| committer | Elvis Claros Castro <elvis@claros.ar> | 2026-09-27 12:46:49 -0300 |
| commit | df7c711e2a49d51249350f52c63274b72aacb739 (patch) | |
| tree | 426da3b65371f857f3ee3d9893d7ff3279aac02e /lua/pi | |
| parent | a0bd84df02ce235123dfc939327e8bd33dffdd7e (diff) | |
| download | nvim-conf-df7c711e2a49d51249350f52c63274b72aacb739.tar.gz nvim-conf-df7c711e2a49d51249350f52c63274b72aacb739.zip | |
Migración de plugins a funcionalidad nativa: statusline y treesitter propios, se quitan mason, lualine, mini, notify y otros
Diffstat (limited to 'lua/pi')
| -rw-r--r-- | lua/pi/animations.lua | 71 | ||||
| -rw-r--r-- | lua/pi/dap/configs/cpp.lua | 46 | ||||
| -rw-r--r-- | lua/pi/lsp/attach.lua | 2 | ||||
| -rw-r--r-- | lua/pi/lsp/default.lua | 4 | ||||
| -rw-r--r-- | lua/pi/lsp/init.lua | 13 | ||||
| -rw-r--r-- | lua/pi/lsp/mason.lua | 33 | ||||
| -rw-r--r-- | lua/pi/snips/ft/go.lua | 24 | ||||
| -rw-r--r-- | lua/pi/treesitter.lua | 248 |
8 files changed, 327 insertions, 114 deletions
diff --git a/lua/pi/animations.lua b/lua/pi/animations.lua index 3ff711f..e4bc859 100644 --- a/lua/pi/animations.lua +++ b/lua/pi/animations.lua @@ -1,48 +1,39 @@ -local redraw_buffer = function() - local Animation = require "animation" - local fps = 15 -- frames per second - local easing = require "animation.easing" - - local buffer = 0 - local len = 0 - local place_holder = {} +-- Animación de "retipeo" del buffer, con vim.uv (antes dependía de animation.nvim). +local fps = 15 -- un caracter por frame, como la versión original +local redraw_buffer = function() + local buffer = vim.api.nvim_get_current_buf() local lines = vim.api.nvim_buf_get_lines(buffer, 0, -1, true) - for _, line in ipairs(lines) do - len = len + string.len(line) + local place_holder = {} + for _ = 1, #lines do table.insert(place_holder, "") end - - vim.api.nvim_buf_set_lines(buffer, 0, #lines, true, place_holder) - - local duration = math.ceil(len / fps * 1000) - - local i = 1 - local line_nr = 1 - local insertLine = "" - - local function callback() - if lines[line_nr] == nil then - return true - end - local char = string.sub(lines[line_nr], i, i) - if char == nil then - return true - end - insertLine = insertLine .. char - i = i + 1 - vim.api.nvim_buf_set_lines(buffer, line_nr - 1, line_nr, true, { insertLine }) - - if insertLine == lines[line_nr] then - i = 1 - line_nr = line_nr + 1 - insertLine = "" - end - end - - local animation = Animation(duration, fps, easing.line, callback) - animation:run() + vim.api.nvim_buf_set_lines(buffer, 0, -1, true, place_holder) + + local line_nr, col = 1, 0 + local timer = assert(vim.uv.new_timer()) + + timer:start( + 0, + math.floor(1000 / fps), + vim.schedule_wrap(function() + if not vim.api.nvim_buf_is_valid(buffer) or line_nr > #lines then + timer:stop() + timer:close() + return + end + + col = col + 1 + local line = lines[line_nr] + vim.api.nvim_buf_set_lines(buffer, line_nr - 1, line_nr, true, { line:sub(1, col) }) + + if col >= #line then + line_nr = line_nr + 1 + col = 0 + end + end) + ) end return { diff --git a/lua/pi/dap/configs/cpp.lua b/lua/pi/dap/configs/cpp.lua index a2718b0..4f47345 100644 --- a/lua/pi/dap/configs/cpp.lua +++ b/lua/pi/dap/configs/cpp.lua @@ -1,24 +1,47 @@ local dap = require("dap") +-- gdb DAP nativo (gdb >= 14). No usa runInTerminal, así que evita el bug +-- de nvim-dap `terminals.acquire` en Neovim 0.13-dev. La salida del programa +-- aparece en la consola/repl de dap-ui. +dap.adapters.gdb = { + type = "executable", + command = "gdb", + args = { "--interpreter=dap", "--eval-command", "set print pretty on" }, +} + +-- Adaptador cpptools/OpenDebugAD7 (Microsoft) como fallback. dap.adapters.cppdbg = { id = 'cppdbg', type = 'executable', command = '/home/elvis/.local/share/nvim/mason/packages/cpptools/extension/debugAdapters/bin/OpenDebugAD7', } +local function pick_program() + return vim.fn.input('Path to executable: ', vim.fn.getcwd() .. '/', 'file') +end + +local function pick_args() + return vim.split(vim.fn.input('Program arguments: ', ''), " ") +end + dap.configurations.cpp = { { - name = "Launch file", + name = "Launch (gdb)", + type = "gdb", + request = "launch", + program = pick_program, + cwd = "${workspaceFolder}", + args = pick_args, + stopAtBeginningOfMainSubprogram = true, -- equivalente a stopAtEntry en gdb DAP + }, + { + name = "Launch (cppdbg / cpptools)", type = "cppdbg", request = "launch", - program = function() - return vim.fn.input('Path to executable: ', vim.fn.getcwd() .. '/', 'file') - end, + program = pick_program, cwd = '${workspaceFolder}', stopAtEntry = true, - args = function() - return vim.split(vim.fn.input('Program arguments: ', ''), " ") - end, + args = pick_args, }, { name = 'Attach to gdbserver :1234', @@ -28,14 +51,9 @@ dap.configurations.cpp = { miDebuggerServerAddress = 'localhost:1234', miDebuggerPath = '/usr/bin/gdb', cwd = '${workspaceFolder}', - program = function() - return vim.fn.input('Path to executable: ', vim.fn.getcwd() .. '/', 'file') - end, - args = function() - return vim.split(vim.fn.input('Program arguments: ', ''), " ") - end, + program = pick_program, + args = pick_args, }, } dap.configurations.c = dap.configurations.cpp - diff --git a/lua/pi/lsp/attach.lua b/lua/pi/lsp/attach.lua index 7030cbd..e05f3f3 100644 --- a/lua/pi/lsp/attach.lua +++ b/lua/pi/lsp/attach.lua @@ -23,7 +23,7 @@ return function(client, bufnr) vim.keymap.set("n", "gr", function() Snacks.picker.lsp_references() end, { buffer = bufnr, desc = "LSP References of symbol on cursor" }) vim.keymap.set("n", "<leader>pv", function() Snacks.picker.lsp_workspace_symbols() end, { buffer = bufnr, desc = "LSP find symbol on the project" }) vim.keymap.set("n", "<leader>pd", function() Snacks.picker.lsp_symbols() end, { buffer = bufnr, desc = "LSP document symbols" }) - vim.keymap.set("n", "<C-S-[>", function() Snacks.picker.lsp_definitions() end, { buffer = bufnr, desc = "LSP go to definition" }) + vim.keymap.set("n", "gd", function() Snacks.picker.lsp_definitions() end, { buffer = bufnr, desc = "LSP go to definition" }) vim.bo.omnifunc = "v:lua.vim.lsp.omnifunc" diff --git a/lua/pi/lsp/default.lua b/lua/pi/lsp/default.lua index efde87a..1f4dfb0 100644 --- a/lua/pi/lsp/default.lua +++ b/lua/pi/lsp/default.lua @@ -35,10 +35,6 @@ local server_commands = { } return { - mason = { - enable = true, - auto_install = false, - }, get_server_cmd = function(server) return server_commands[server] or { server } end, diff --git a/lua/pi/lsp/init.lua b/lua/pi/lsp/init.lua index de6e95b..ebc8fab 100644 --- a/lua/pi/lsp/init.lua +++ b/lua/pi/lsp/init.lua @@ -10,7 +10,6 @@ return { return orig_open_floating_preview(contents, syntax, opts, ...) end - local mason_servers = {} for server, options in pairs(ops.servers) do if options.enable == true then local ok, definition = pcall(require, "pi.lsp.servers." .. server) @@ -53,19 +52,7 @@ return { end, }) end - - table.insert(mason_servers, server) - end - end - - -- Mason - if ops.mason.enable then - local mason_ops = {} - if ops.mason.auto_install == true then - mason_ops.ensure_installed = mason_servers end - local mason_lspconfig = require "mason-lspconfig" - mason_lspconfig.setup(mason_ops) end -- TODO: implement null ls with options diff --git a/lua/pi/lsp/mason.lua b/lua/pi/lsp/mason.lua deleted file mode 100644 index 6c959a6..0000000 --- a/lua/pi/lsp/mason.lua +++ /dev/null @@ -1,33 +0,0 @@ -local mason_lspconfig = require "mason-lspconfig" -local servers = require "pi.lsp.servers" - --- Note: This file is deprecated in favor of native LSP configuration --- Keeping for reference/compatibility - -local mason_servers = {} - --- Since we're using native LSP, we'll check for executables differently -local server_commands = { - lua_ls = "lua-language-server", - gopls = "gopls", - ts_ls = "typescript-language-server", - -- Add other servers as needed -} - -for server, _ in pairs(servers) do - local cmd = server_commands[server] or server - if vim.fn.executable(cmd) == 0 then - table.insert(mason_servers, server) - end -end - -mason_lspconfig.setup { - -- ensure_installed = mason_servers, -} - --- filter the list for the ones not globally installed --- require("mason-tool-installer").setup { --- ensure_installed = vim.tbl_filter(function (tool) --- return vim.fn.executable(tool) == 0 --- end, require "pi.lsp.tools"), --- } diff --git a/lua/pi/snips/ft/go.lua b/lua/pi/snips/ft/go.lua index 9c3977f..4490e63 100644 --- a/lua/pi/snips/ft/go.lua +++ b/lua/pi/snips/ft/go.lua @@ -8,9 +8,6 @@ local i = ls.insert_node local rep = require("luasnip.extras").rep local fmt = require("luasnip.extras.fmt").fmt -local ts_locals = require "nvim-treesitter.locals" -local ts_utils = require "nvim-treesitter.ts_utils" - local get_node_text = vim.treesitter.get_node_text vim.treesitter.query.set( @@ -71,19 +68,28 @@ local handlers = { end, } +-- `nvim-treesitter.locals`/`ts_utils` no existen en la rama `main`; subimos a +-- mano por los padres del nodo bajo el cursor hasta la función que lo contiene. local function go_result_type(info) - local cursor_node = ts_utils.get_node_at_cursor() - local scope = ts_locals.get_scope_tree(cursor_node, 0) - local function_node - for _, v in ipairs(scope) do - if v:type() == "function_declaration" or v:type() == "method_declaration" or v:type() == "func_literal" then - function_node = v + local node = vim.treesitter.get_node() + while node do + local kind = node:type() + if kind == "function_declaration" or kind == "method_declaration" or kind == "func_literal" then + function_node = node break end + node = node:parent() + end + + if not function_node then + return end local query = vim.treesitter.query.get("go", "LuaSnip_Result") + if not query then + return + end for _, node in query:iter_captures(function_node, 0) do if handlers[node:type()] then return handlers[node:type()](node, info) diff --git a/lua/pi/treesitter.lua b/lua/pi/treesitter.lua new file mode 100644 index 0000000..d137ac5 --- /dev/null +++ b/lua/pi/treesitter.lua @@ -0,0 +1,248 @@ +-- Integración de treesitter para Neovim 0.13 + nvim-treesitter rama `main`. +-- +-- La rama `main` es una reescritura sin sistema de módulos: sólo instala parsers +-- y provee queries. Highlight, indent, folds e injections los da Neovim, así que +-- el enganche lo hacemos nosotros en un autocomando FileType. + +local M = {} + +local install_dir = vim.fs.joinpath(vim.fn.stdpath "data", "site") + +--- Parsers que queremos siempre disponibles. +M.ensure_installed = { + "bash", + "blade", + "css", + "dockerfile", + "cpp", + "elixir", + "erlang", + "go", + "gomod", + "html", + "javascript", + "json", + "latex", + "lua", + "luadoc", + "markdown", + "markdown_inline", + "nix", + "php", + "php_only", + "phpdoc", + "python", + "query", + "regex", + "rust", + "sql", + "svelte", + "twig", + "typescript", + "typst", + "vim", + "yaml", +} + +--- Filetypes de buffers de plugins que reusan el parser de otro lenguaje. +M.language_aliases = { + codecompanion = "markdown", + snacks_notif = "markdown", + oil = "markdown", +} + +--- Filetypes donde no queremos highlight ni indent de treesitter. +M.disabled_filetypes = { + oil = true, + snacks_notif = true, +} + +---@param lang string +---@return boolean +local function parser_available(lang) + return #vim.api.nvim_get_runtime_file("parser/" .. lang .. ".so", false) > 0 +end + +--- Reemplazo de `auto_install`: instala el parser que falte, una sola vez por +--- lenguaje y sin bloquear, y engancha el buffer cuando termina. +local installing = {} ---@type table<string, true> + +---@param lang string +---@param on_ready fun() +local function install_missing(lang, on_ready) + if installing[lang] then + return + end + local ok, parsers = pcall(require, "nvim-treesitter.parsers") + if not ok or not parsers[lang] then + return + end + installing[lang] = true + require("nvim-treesitter").install({ lang }):await(function() + installing[lang] = nil + vim.schedule(on_ready) + end) +end + +---@param buf integer +local function attach(buf) + if not vim.api.nvim_buf_is_valid(buf) then + return + end + + local ft = vim.bo[buf].filetype + if ft == "" or M.disabled_filetypes[ft] then + return + end + + local lang = vim.treesitter.language.get_lang(ft) + if not lang then + return + end + + if not parser_available(lang) then + install_missing(lang, function() + attach(buf) + end) + return + end + + if not pcall(vim.treesitter.start, buf, lang) then + return + end + + -- Indent de nvim-treesitter (experimental, era el módulo `indent` en master). + -- Sólo si el lenguaje trae query `indents`; si no, dejamos el indentexpr del + -- ftplugin, que es mejor que un fallback vacío. + if vim.treesitter.query.get(lang, "indents") then + vim.bo[buf].indentexpr = "v:lua.require'nvim-treesitter'.indentexpr()" + end +end + +function M.setup() + require("nvim-treesitter").setup { install_dir = install_dir } + + for ft, lang in pairs(M.language_aliases) do + vim.treesitter.language.register(lang, ft) + end + + vim.filetype.add { + pattern = { + [".*%.blade%.php"] = "blade", + }, + } + + require("nvim-treesitter").install(M.ensure_installed) + + vim.api.nvim_create_autocmd("FileType", { + group = vim.api.nvim_create_augroup("pi_treesitter", { clear = true }), + callback = function(args) + attach(args.buf) + end, + }) + + -- El autocomando llega tarde para los buffers que ya se abrieron al arrancar. + for _, buf in ipairs(vim.api.nvim_list_bufs()) do + if vim.api.nvim_buf_is_loaded(buf) then + attach(buf) + end + end + + M.setup_incremental_selection() +end + +-------------------------------------------------------------------------------- +-- Selección incremental +-- +-- El módulo `incremental_selection` desapareció con la rama `main` y Neovim no +-- trae equivalente. Esto reimplementa los cuatro mapeos que había: gnn / grn / +-- grc / grm. +-------------------------------------------------------------------------------- + +local stacks = {} ---@type table<integer, TSNode[]> + +---@param node TSNode +local function select_node(node) + local srow, scol, erow, ecol = node:range() + if ecol == 0 and erow > srow then + erow = erow - 1 + ecol = #(vim.api.nvim_buf_get_lines(0, erow, erow + 1, false)[1] or "") + end + if vim.fn.mode() ~= "n" then + vim.cmd "normal! \27" + end + vim.fn.setpos("'<", { 0, srow + 1, scol + 1, 0 }) + vim.fn.setpos("'>", { 0, erow + 1, math.max(ecol, 1), 0 }) + vim.cmd "normal! gv" +end + +---@return TSNode[] +local function stack() + local buf = vim.api.nvim_get_current_buf() + stacks[buf] = stacks[buf] or {} + return stacks[buf] +end + +local function init_selection() + local node = vim.treesitter.get_node() + if not node then + return + end + local s = stack() + for i = #s, 1, -1 do + s[i] = nil + end + s[1] = node + select_node(node) +end + +--- Sube al ancestro más chico que sea estrictamente más grande que el actual. +---@param predicate? fun(node: TSNode, from: TSNode): boolean +local function grow(predicate) + local s = stack() + local node = s[#s] or vim.treesitter.get_node() + if not node then + return + end + local parent = node:parent() + while parent do + local same = vim.deep_equal({ parent:range() }, { node:range() }) + if not same and (not predicate or predicate(parent, node)) then + s[#s + 1] = parent + select_node(parent) + return + end + parent = parent:parent() + end + select_node(node) +end + +local function shrink() + local s = stack() + if #s > 1 then + s[#s] = nil + end + local node = s[#s] + if node then + select_node(node) + end +end + +function M.setup_incremental_selection() + local map = vim.keymap.set + map("n", "gnn", init_selection, { desc = "Treesitter: iniciar selección" }) + map("x", "grn", function() + grow() + end, { desc = "Treesitter: expandir al nodo padre" }) + map("x", "grc", function() + -- "scope": el primer ancestro que abarque más líneas que el nodo actual. + grow(function(parent, from) + local psrow, _, perow = parent:range() + local srow, _, erow = from:range() + return (perow - psrow) > (erow - srow) + end) + end, { desc = "Treesitter: expandir al scope" }) + map("x", "grm", shrink, { desc = "Treesitter: reducir selección" }) +end + +return M |