diff --git a/lazy-lock.json b/lazy-lock.json index 39ac9a3..07495b7 100644 --- a/lazy-lock.json +++ b/lazy-lock.json @@ -1,51 +1,53 @@ { "Comment.nvim": { "branch": "master", "commit": "e30b7f2008e52442154b66f7c519bfd2f1e32acb" }, "LuaSnip": { "branch": "master", "commit": "458560534a73f7f8d7a11a146c801db00b081df0" }, - "blink.cmp": { "branch": "main", "commit": "022521a8910a5543b0251b21c9e1a1e989745796" }, + "blink.cmp": { "branch": "main", "commit": "9bcb14b43852a6f2bfd5ac9ef29cb5cf09b1b39b" }, "cloak.nvim": { "branch": "main", "commit": "648aca6d33ec011dc3166e7af3b38820d01a71e4" }, - "conform.nvim": { "branch": "master", "commit": "6feb2f28f9a9385e401857b21eeac3c1b66dd628" }, + "conform.nvim": { "branch": "master", "commit": "00d7e92d170139569b1887ff2be298a0cdd7d9ae" }, "fidget.nvim": { "branch": "main", "commit": "d9ba6b7bfe29b3119a610892af67602641da778e" }, "flash.nvim": { "branch": "main", "commit": "3c942666f115e2811e959eabbdd361a025db8b63" }, "friendly-snippets": { "branch": "main", "commit": "572f5660cf05f8cd8834e096d7b4c921ba18e175" }, - "fzf-lua": { "branch": "main", "commit": "29e982dfc96a134fecc80853c8cb8324e43e574b" }, + "fzf-lua": { "branch": "main", "commit": "a4404dee0a65d3c2e2b292206d10b16567d088c9" }, + "git-worktree.nvim": { "branch": "main", "commit": "3ad8c17a3d178ac19be925284389c14114638ebb" }, "gitlinker.nvim": { "branch": "master", "commit": "cc59f732f3d043b626c8702cb725c82e54d35c25" }, - "gitsigns.nvim": { "branch": "main", "commit": "8b729e489f1475615dc6c9737da917b3bc163605" }, - "go.nvim": { "branch": "master", "commit": "e1b763cab2cfd3c60207873dbc925c9be49913c0" }, + "gitsigns.nvim": { "branch": "main", "commit": "1b0350ab707713b2bc6c236151f1a324175347b1" }, + "go.nvim": { "branch": "master", "commit": "a3455f48cff718a86275115523dcc735535a13aa" }, "lazy.nvim": { "branch": "main", "commit": "6c3bda4aca61a13a9c63f1c1d1b16b9d3be90d7a" }, "lazydev.nvim": { "branch": "main", "commit": "2367a6c0a01eb9edb0464731cc0fb61ed9ab9d2c" }, "markdown-preview.nvim": { "branch": "master", "commit": "a923f5fc5ba36a3b17e289dc35dc17f66d0548ee" }, - "mason-lspconfig.nvim": { "branch": "main", "commit": "67da97f8c2fd12d05427bb485ce07ee6418e0a51" }, - "mason-tool-installer.nvim": { "branch": "main", "commit": "75d60a8f928decd8b38897f80849768b7c540a5b" }, + "mason-lspconfig.nvim": { "branch": "main", "commit": "c4c84f4521d62de595c0d0f718a9a40c1890c8ce" }, + "mason-tool-installer.nvim": { "branch": "main", "commit": "517ef5994ef9d6b738322664d5fdd948f0fdeb46" }, "mason.nvim": { "branch": "main", "commit": "8024d64e1330b86044fed4c8494ef3dcd483a67c" }, - "mini.ai": { "branch": "main", "commit": "4b5348fac5912f1957f4c012c2e0ab0c4b865386" }, - "mini.icons": { "branch": "main", "commit": "397ed3807e96b59709ef3292f0a3e253d5c1dc0a" }, - "mini.statusline": { "branch": "main", "commit": "e331175f10d9f400b42523b3890841aba202ce16" }, - "mini.surround": { "branch": "main", "commit": "f4307f935ad87cfe3e570dbaae485b35cce4e5ec" }, + "mini.ai": { "branch": "main", "commit": "d172ada7b0281044a06cb9a625a862553c457b6f" }, + "mini.icons": { "branch": "main", "commit": "94848dad1589a199f876539bd79befb0c5e3abf0" }, + "mini.statusline": { "branch": "main", "commit": "452d27d764720cddcb9909b786598bb9e80c1ce8" }, + "mini.surround": { "branch": "main", "commit": "1a2b59c77a0c4713a5bd8972da322f842f4821b1" }, "nightfox.nvim": { "branch": "main", "commit": "ba47d4b4c5ec308718641ba7402c143836f35aa9" }, "nvim-colorizer.lua": { "branch": "master", "commit": "a065833f35a3a7cc3ef137ac88b5381da2ba302e" }, "nvim-lastplace": { "branch": "main", "commit": "0bb6103c506315044872e0f84b1f736c4172bb20" }, - "nvim-lint": { "branch": "master", "commit": "b47cbb249351873e3a571751c3fb66ed6369852f" }, - "nvim-lspconfig": { "branch": "master", "commit": "b8e7957bde4cbb3cb25a13a62548f7c273b026e9" }, + "nvim-lint": { "branch": "master", "commit": "2b0039b8be9583704591a13129c600891ac2c596" }, + "nvim-lspconfig": { "branch": "master", "commit": "1cb30b1bafe5a63a5c6ac20dc39f83487df38855" }, "nvim-spectre": { "branch": "master", "commit": "72f56f7585903cd7bf92c665351aa585e150af0f" }, "nvim-treesitter": { "branch": "master", "commit": "42fc28ba918343ebfd5565147a42a26580579482" }, "nvim-ts-context-commentstring": { "branch": "main", "commit": "1b212c2eee76d787bbea6aa5e92a2b534e7b4f8f" }, - "nvim-ufo": { "branch": "main", "commit": "3c7a3570e9c9dc198a2ad4491b0b0e51c4d4ba08" }, + "nvim-ufo": { "branch": "main", "commit": "80fe8215ba566df2fbf3bf4d25f59ff8f41bc0e1" }, "obsidian.nvim": { "branch": "main", "commit": "ae1f76a75c7ce36866e1d9342a8f6f5b9c2caf9b" }, - "oil.nvim": { "branch": "master", "commit": "685cdb4ffa74473d75a1b97451f8654ceeab0f4a" }, + "oil.nvim": { "branch": "master", "commit": "08c2bce8b00fd780fb7999dbffdf7cd174e896fb" }, "plenary.nvim": { "branch": "master", "commit": "857c5ac632080dba10aae49dba902ce3abf91b35" }, "presenterm.nvim": { "branch": "main", "commit": "2db942337aeeca99e33f627459df2264b3987634" }, "promise-async": { "branch": "main", "commit": "119e8961014c9bfaf1487bf3c2a393d254f337e2" }, "quicker.nvim": { "branch": "master", "commit": "51d3926f183c2d98fbc237cc237ae0926839af3a" }, - "render-markdown.nvim": { "branch": "main", "commit": "0b0bec653f47d9d56cb80f426479ef0527814119" }, - "schemastore.nvim": { "branch": "main", "commit": "a9ba109549de51e3b4594d39a1c07f14b9d0cfa5" }, + "render-markdown.nvim": { "branch": "main", "commit": "3115ff748d6885fe1af349feb6b73de03eda8e12" }, + "schemastore.nvim": { "branch": "main", "commit": "e4f80f37cd11ed58a6e914cc30850749f021b6a7" }, "snacks.nvim": { "branch": "main", "commit": "bc0630e43be5699bb94dadc302c0d21615421d93" }, "suda.vim": { "branch": "master", "commit": "9adda7d195222d4e2854efb2a88005a120296c47" }, "todo-comments.nvim": { "branch": "main", "commit": "304a8d204ee787d2544d8bc23cd38d2f929e7cc5" }, - "undotree": { "branch": "master", "commit": "b951b87b46c34356d44aa71886aecf9dd7f5788a" }, + "typst-preview.nvim": { "branch": "master", "commit": "dea4525d5420b7c32eebda7de15a6beb9d6574fa" }, + "undotree": { "branch": "master", "commit": "7a8b831e9bfb9f6fe05cc33294882648dd6801fb" }, "vim-dadbod": { "branch": "master", "commit": "e95afed23712f969f83b4857a24cf9d59114c2e6" }, "vim-dadbod-completion": { "branch": "master", "commit": "a8dac0b3cf6132c80dc9b18bef36d4cf7a9e1fe6" }, - "vim-dadbod-ui": { "branch": "master", "commit": "460432301a5cb280ea265ddfa15c9f3dcd1d26b7" }, - "vim-fugitive": { "branch": "master", "commit": "4a745ea72fa93bb15dd077109afbb3d1809383f2" }, + "vim-dadbod-ui": { "branch": "master", "commit": "2900a1617b3df1a48683d872eadbe1101146a49a" }, + "vim-fugitive": { "branch": "master", "commit": "593f831d6f6d779cbabb70a4d1e6b1b1936a88af" }, "vim-hugo": { "branch": "master", "commit": "324fb8c7371d31701349c1192e25a0bdcf9898f8" }, "vim-sleuth": { "branch": "master", "commit": "be69bff86754b1aa5adcbb527d7fcd1635a84080" }, "which-key.nvim": { "branch": "main", "commit": "370ec46f710e058c9c1646273e6b225acf47cbed" }, diff --git a/lsp/tsgo.lua b/lsp/tsgo.lua new file mode 100644 index 0000000..c96cf3f --- /dev/null +++ b/lsp/tsgo.lua @@ -0,0 +1,16 @@ +return { + settings = {}, + flags = {}, + filetypes = { "typescript" }, + cmd = { + "/home/forbi/local/local/tsgo", + "--lsp", + "-stdio", + }, + root_markers = { + "tsconfig.json", + "package.json", + "jsconfig.json", + ".git", + }, +} diff --git a/lua/plugins/format.lua b/lua/plugins/format.lua index a26929a..7e80321 100644 --- a/lua/plugins/format.lua +++ b/lua/plugins/format.lua @@ -28,6 +28,7 @@ return { cpp = { "clang-format" }, hcl = { "hcl" }, toml = { "taplo" }, + typst = { "prettypst" }, }, formatters = { csharpier = { diff --git a/lua/plugins/fzf.lua b/lua/plugins/fzf.lua index b4707a9..e730ae8 100644 --- a/lua/plugins/fzf.lua +++ b/lua/plugins/fzf.lua @@ -32,7 +32,6 @@ M.config = function() nmap("D", fzf_lua.lsp_typedefs, { desc = "Type Definition" }) nmap("ca", fzf_lua.lsp_code_actions, { desc = "Code Action" }) nmap("ds", fzf_lua.lsp_document_symbols, { desc = "Document Symbols" }) - nmap("ws", fzf_lua.lsp_workspace_symbols, { desc = "Workspace Symbols" }) nmap("ic", fzf_lua.lsp_incoming_calls, { desc = "Incoming Calls" }) nmap("oc", fzf_lua.lsp_outgoing_calls, { desc = "Outgoing Calls" }) nmap("gf", fzf_lua.live_grep, { desc = "Find Live Grep" }) diff --git a/lua/plugins/git.lua b/lua/plugins/git.lua index 4b5f1df..b99bea9 100644 --- a/lua/plugins/git.lua +++ b/lua/plugins/git.lua @@ -88,6 +88,149 @@ local M = { nmap("gy", "lua require('gitlinker').get_buf_range_url('n')") end, }, + { + "polarmutex/git-worktree.nvim", + version = "^2", + dependencies = { "nvim-lua/plenary.nvim", "ibhagwan/fzf-lua", "folke/snacks.nvim" }, + config = function() + local fzf_lua = require("fzf-lua") + local git_worktree = require("git-worktree") + + -- Basic hooks + local Hooks = require("git-worktree.hooks") + Hooks.register(Hooks.type.SWITCH, Hooks.builtins.update_current_buffer_on_switch) + + -- Switch worktrees + local function switch_worktree() + vim.system({ "git", "worktree", "list" }, {}, function(result) + if result.code ~= 0 then + return + end + + local items = {} + for line in result.stdout:gmatch("[^\n]+") do + local path, branch = line:match("^([^%s]+)%s+%[?([^%]]*)") + if path and branch then + table.insert(items, path .. " (" .. (branch ~= "" and branch or "detached") .. ")") + end + end + + vim.schedule(function() + fzf_lua.fzf_exec(items, { + prompt = "Worktrees> ", + actions = { + default = function(selected) + local path = selected[1]:match("^([^%(]+)") + git_worktree.switch_worktree(path:gsub("%s+$", "")) + end, + }, + }) + end) + end) + end + + -- Create worktree + local function create_worktree() + -- Get the git directory (works for both regular and bare repos) + vim.system({ "git", "rev-parse", "--git-dir" }, {}, function(result) + if result.code ~= 0 then + vim.schedule(function() + vim.notify("Not in a git repository", vim.log.levels.ERROR) + end) + return + end + + local git_dir = result.stdout:gsub("\n", "") + -- For bare repos, git-dir is the repo itself; for regular repos, get parent + local repo_root = git_dir:match("%.git$") and git_dir:gsub("/%.git$", "") or git_dir + + vim.system({ "git", "branch", "-a" }, { cwd = repo_root }, function(branch_result) + if branch_result.code ~= 0 then + return + end + + local branches = {} + for line in branch_result.stdout:gmatch("[^\n]+") do + local branch = line:gsub("^%s*%*?%s*", ""):gsub("^remotes/", "") + if branch ~= "" and not branch:match("HEAD") then + table.insert(branches, branch) + end + end + + vim.schedule(function() + fzf_lua.fzf_exec(branches, { + prompt = "Base Branch> ", + actions = { + default = function(selected) + if not selected or #selected == 0 then + return + end + local base_branch = selected[1] + local default_name = base_branch:gsub(".*/", "") + + require("snacks").input({ + prompt = "Worktree name", + default = default_name, + icon = "🌿", + }, function(name) + if name then + git_worktree.create_worktree(name, base_branch, "origin") + end + end) + end, + }, + }) + end) + end) + end) + end + + -- Delete worktree + local function delete_worktree() + local cwd = vim.fn.getcwd() -- Get this before async call + + vim.system({ "git", "worktree", "list" }, {}, function(result) + if result.code ~= 0 then + return + end + + local items = {} + + for line in result.stdout:gmatch("[^\n]+") do + local path, branch = line:match("^([^%s]+)%s+%[?([^%]]*)") + if path and path ~= cwd then + table.insert(items, path .. " (" .. (branch ~= "" and branch or "detached") .. ")") + end + end + + vim.schedule(function() + fzf_lua.fzf_exec(items, { + prompt = "Delete> ", + actions = { + default = function(selected) + local path = selected[1]:match("^([^%(]+)"):gsub("%s+$", "") + + -- Simple vim.ui.select for yes/no + vim.ui.select({ "Yes", "No" }, { + prompt = "Delete worktree '" .. path .. "'?", + }, function(choice) + if choice == "Yes" then + git_worktree.delete_worktree(path, true) + end + end) + end, + }, + }) + end) + end) + end + + -- Keymaps + vim.keymap.set("n", "ws", switch_worktree, { desc = "Switch Worktree" }) + vim.keymap.set("n", "wc", create_worktree, { desc = "Create Worktree" }) + vim.keymap.set("n", "wd", delete_worktree, { desc = "Delete Worktree" }) + end, + }, } return M diff --git a/lua/plugins/lsp/init.lua b/lua/plugins/lsp/init.lua index 60d2fe9..86d74bf 100644 --- a/lua/plugins/lsp/init.lua +++ b/lua/plugins/lsp/init.lua @@ -1,155 +1,206 @@ -local M = { - "WhoIsSethDaniel/mason-tool-installer.nvim", +return { + "neovim/nvim-lspconfig", dependencies = { + require("plugins.lsp.extras.lazydev"), + require("plugins.lsp.extras.gopher"), "mason-org/mason-lspconfig.nvim", "mason-org/mason.nvim", "j-hui/fidget.nvim", "ibhagwan/fzf-lua", - require("plugins.lsp.extras.lazydev"), - require("plugins.lsp.extras.gopher"), + "WhoIsSethDaniel/mason-tool-installer.nvim", }, + + config = function() + -- Mason setup + require("mason").setup({ max_concurrent_installers = 4 }) + require("fidget").setup({}) + + -- Enhance floating preview windows + local orig_util_open_floating_preview = vim.lsp.util.open_floating_preview + function vim.lsp.util.open_floating_preview(contents, syntax, opts, ...) + opts = opts or {} + opts.border = opts.border or "rounded" + opts.max_width = opts.max_width or 80 + opts.max_height = opts.max_height or 20 + return orig_util_open_floating_preview(contents, syntax, opts, ...) + end + + -- Diagnostics configuration + vim.diagnostic.config({ + virtual_text = { spacing = 2, source = "if_many" }, + float = { border = "rounded", source = "if_many" }, + signs = vim.g.have_nerd_font and { + text = { + [vim.diagnostic.severity.ERROR] = "󰅚", + [vim.diagnostic.severity.WARN] = "󰀪", + [vim.diagnostic.severity.INFO] = "󰋽", + [vim.diagnostic.severity.HINT] = "󰌶", + }, + } or true, + underline = true, + update_in_insert = true, + severity_sort = true, + }) + + -- Global floating options + _G.floating_options = { + focusable = true, + focus = false, + max_height = 50, + max_width = 100, + } + + -- Auto-format on save + vim.api.nvim_create_autocmd("BufWritePre", { + callback = function() + if vim.lsp.buf_is_attached() then + vim.lsp.buf.format() + end + end, + }) + + -- Filter out unwanted code actions + vim.lsp.buf.code_action = (function(orig) + return function(opts) + opts = opts or {} + opts.filter = function(action) + if not action then + return false + end + -- Ignore gopls "Browse" actions + if action.title and action.title:match("Browse gopls") then + return false + end + return true + end + return orig(opts) + end + end)(vim.lsp.buf.code_action) + + -- Keymaps setup function + local function setup_keymaps(bufnr) + local fzf = require("fzf-lua") + local opts = { buffer = bufnr } + + -- Helper function for mapping + local function nmap(key, func, desc_opts) + vim.keymap.set("n", key, func, desc_opts) + end + + -- Basic LSP + nmap("K", vim.lsp.buf.hover, vim.tbl_extend("force", opts, { desc = "Hover Doc" })) + nmap("", vim.lsp.buf.signature_help, vim.tbl_extend("force", opts, { desc = "Signature Help" })) + nmap("r", vim.lsp.buf.rename, vim.tbl_extend("force", opts, { desc = "Rename" })) + nmap("ca", vim.lsp.buf.code_action, vim.tbl_extend("force", opts, { desc = "Code Action" })) + + -- Navigation + nmap("gd", fzf.lsp_definitions, vim.tbl_extend("force", opts, { desc = "Go to Definition" })) + nmap("gr", fzf.lsp_references, vim.tbl_extend("force", opts, { desc = "Go to References" })) + nmap("gD", vim.lsp.buf.declaration, vim.tbl_extend("force", opts, { desc = "Go to Declaration" })) + nmap("gi", fzf.lsp_implementations, vim.tbl_extend("force", opts, { desc = "Go to Implementation" })) + nmap("gt", fzf.lsp_typedefs, vim.tbl_extend("force", opts, { desc = "Go to Type Definition" })) + + -- Diagnostics + nmap("vd", vim.diagnostic.open_float, vim.tbl_extend("force", opts, { desc = "View Diagnostics" })) + nmap("dl", fzf.diagnostics_document, vim.tbl_extend("force", opts, { desc = "Document Diagnostics" })) + nmap("dw", fzf.diagnostics_workspace, vim.tbl_extend("force", opts, { desc = "Workspace Diagnostics" })) + nmap("ds", fzf.lsp_document_symbols, vim.tbl_extend("force", opts, { desc = "Document Symbols" })) + nmap("ws", fzf.lsp_workspace_symbols, vim.tbl_extend("force", opts, { desc = "Workspace Symbols" })) + + -- LSP management + nmap("lr", function() + local clients = vim.lsp.get_clients({ bufnr = bufnr }) + if #clients == 0 then + vim.notify("No LSP clients attached to buffer", vim.log.levels.WARN) + return + end + + local client_names = {} + for _, client in ipairs(clients) do + table.insert(client_names, client.name) + vim.cmd("LspRestart " .. client.name) + end + vim.notify("Restarted LSP clients: " .. table.concat(client_names, ", "), vim.log.levels.INFO) + end, vim.tbl_extend("force", opts, { desc = "Restart LSP" })) + nmap("li", ":LspInfo", vim.tbl_extend("force", opts, { desc = "LSP Info" })) + end + + -- LSP servers configuration + local servers = { + "gopls", + "jsonls", + "lua_ls", + "yamlls", + "graphql", + "html", + "omnisharp", + "svelte", + "vtsls", + "ccls", + "templ", + "tinymist", + } + + -- Tools for mason-tool-installer + local tools = { + "prettierd", + "shfmt", + "stylua", + "latexindent", + "clang-format", + "csharpier", + "quick-lint-js", + } + + -- Servers not supported by mason + local mason_unsupported = { "ccls" } + + local mason_servers = vim.tbl_filter(function(server) + return not vim.tbl_contains(mason_unsupported, server) + end, servers) + + -- Mason setup + require("mason-lspconfig").setup({ + ensure_installed = mason_servers, + automatic_installation = true, + automatic_enable = false, + }) + require("mason-tool-installer").setup({ ensure_installed = tools }) + + -- Enable LSP servers + vim.lsp.enable(servers) + + -- LSP Attach autocmd + vim.api.nvim_create_autocmd("LspAttach", { + group = vim.api.nvim_create_augroup("UserLspConfig", { clear = true }), + callback = function(args) + local client = vim.lsp.get_client_by_id(args.data.client_id) + if not client then + return + end + + -- Setup keymaps + setup_keymaps(args.buf) + + -- Inlay hints + if client:supports_method(vim.lsp.protocol.Methods.textDocument_inlayHint, args.buf) then + vim.keymap.set("n", "th", function() + vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled({ bufnr = args.buf }), { bufnr = args.buf }) + end, { buffer = args.buf, desc = "Toggle Inlay Hints" }) + end + + -- Document highlights + if client.server_capabilities.documentHighlightProvider then + vim.api.nvim_create_autocmd({ "CursorHold", "CursorHoldI" }, { + buffer = args.buf, + callback = vim.lsp.buf.document_highlight, + }) + vim.api.nvim_create_autocmd({ "CursorMoved", "CursorMovedI" }, { + buffer = args.buf, + callback = vim.lsp.buf.clear_references, + }) + end + end, + }) + end, } - -local function setup_keymaps(bufnr) - local fzf = require("fzf-lua") - local opts = { buffer = bufnr } - - -- Basic LSP - nmap("K", vim.lsp.buf.hover, vim.tbl_extend("force", opts, { desc = "Hover Doc" })) - nmap("", vim.lsp.buf.signature_help, vim.tbl_extend("force", opts, { desc = "Signature Help" })) - nmap("r", vim.lsp.buf.rename, vim.tbl_extend("force", opts, { desc = "Rename" })) - nmap("ca", vim.lsp.buf.code_action, vim.tbl_extend("force", opts, { desc = "Code Action" })) - - -- Navigation - nmap("gd", fzf.lsp_definitions, vim.tbl_extend("force", opts, { desc = "Go to Definition" })) - nmap("gr", fzf.lsp_references, vim.tbl_extend("force", opts, { desc = "Go to References" })) - nmap("gD", vim.lsp.buf.declaration, vim.tbl_extend("force", opts, { desc = "Go to Declaration" })) - nmap("gi", fzf.lsp_implementations, vim.tbl_extend("force", opts, { desc = "Go to Implementation" })) - nmap("gt", fzf.lsp_typedefs, vim.tbl_extend("force", opts, { desc = "Go to Type Definition" })) - - -- Diagnostics - nmap("vd", vim.diagnostic.open_float, vim.tbl_extend("force", opts, { desc = "View Diagnostics" })) - nmap("dl", fzf.diagnostics_document, vim.tbl_extend("force", opts, { desc = "Document Diagnostics" })) - nmap("dw", fzf.diagnostics_workspace, vim.tbl_extend("force", opts, { desc = "Workspace Diagnostics" })) - nmap("ds", fzf.lsp_document_symbols, vim.tbl_extend("force", opts, { desc = "Document Symbols" })) - nmap("ws", fzf.lsp_workspace_symbols, vim.tbl_extend("force", opts, { desc = "Workspace Symbols" })) - - -- LSP management - nmap("lr", function() - local clients = vim.lsp.get_clients({ bufnr = bufnr }) - if #clients == 0 then - vim.notify("No LSP clients attached to buffer", vim.log.levels.WARN) - return - end - - local client_names = {} - for _, client in ipairs(clients) do - table.insert(client_names, client.name) - vim.cmd("LspRestart " .. client.name) - end - vim.notify("Restarted LSP clients: " .. table.concat(client_names, ", "), vim.log.levels.INFO) - end, vim.tbl_extend("force", opts, { desc = "Restart LSP" })) - nmap("li", ":LspInfo", vim.tbl_extend("force", opts, { desc = "LSP Info" })) -end - -function M.config() - require("mason").setup({ max_concurrent_installers = 4 }) - require("fidget").setup({}) - - local orig_util_open_floating_preview = vim.lsp.util.open_floating_preview - function vim.lsp.util.open_floating_preview(contents, syntax, opts, ...) - opts = opts or {} - opts.border = opts.border or "rounded" - opts.max_width = opts.max_width or 80 - opts.max_height = opts.max_height or 20 - return orig_util_open_floating_preview(contents, syntax, opts, ...) - end - - -- Diagnostics - vim.diagnostic.config({ - virtual_text = { spacing = 2, source = "if_many" }, - float = { border = "rounded", source = "if_many" }, - severity_sort = true, - signs = vim.g.have_nerd_font and { - text = { - [vim.diagnostic.severity.ERROR] = "󰅚", - [vim.diagnostic.severity.WARN] = "󰀪", - [vim.diagnostic.severity.INFO] = "󰋽", - [vim.diagnostic.severity.HINT] = "󰌶", - }, - } or {}, - }) - - local servers = { - "gopls", - "jsonls", - "lua_ls", - "yamlls", - "graphql", - "html", - "omnisharp", - "svelte", - "vtsls", - "ccls", - "templ", - } - - local tools = { - "prettierd", - "shfmt", - "stylua", - "latexindent", - "clang-format", - "csharpier", - "quick-lint-js", - } - - local mason_unsupported = { "ccls" } - - local mason_servers = vim.tbl_filter(function(server) - return not vim.tbl_contains(mason_unsupported, server) - end, servers) - - require("mason-lspconfig").setup({ - ensure_installed = mason_servers, - automatic_installation = true, - automatic_enable = true, - }) - require("mason-tool-installer").setup({ ensure_installed = tools }) - - vim.lsp.enable(servers) - - -- LSP Attach - vim.api.nvim_create_autocmd("LspAttach", { - group = vim.api.nvim_create_augroup("UserLspConfig", { clear = true }), - callback = function(args) - local client = vim.lsp.get_client_by_id(args.data.client_id) - if not client then - return - end - - setup_keymaps(args.buf) - - -- Inlay hints - if client:supports_method(vim.lsp.protocol.Methods.textDocument_inlayHint, args.buf) then - nmap("th", function() - vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled({ bufnr = args.buf }), { bufnr = args.buf }) - end, { buffer = args.buf, desc = "Toggle Inlay Hints" }) - end - - -- Document highlights - if client.server_capabilities.documentHighlightProvider then - vim.api.nvim_create_autocmd({ "CursorHold", "CursorHoldI" }, { - buffer = args.buf, - callback = vim.lsp.buf.document_highlight, - }) - vim.api.nvim_create_autocmd({ "CursorMoved", "CursorMovedI" }, { - buffer = args.buf, - callback = vim.lsp.buf.clear_references, - }) - end - end, - }) -end - -return M diff --git a/lua/plugins/mini.lua b/lua/plugins/mini.lua index e5379b6..0533519 100644 --- a/lua/plugins/mini.lua +++ b/lua/plugins/mini.lua @@ -28,6 +28,7 @@ local M = { require("mini.surround").setup({}) end, }, + { "echasnovski/mini.statusline", version = false, @@ -37,16 +38,42 @@ local M = { MiniStatusline.section_codeium = function(args) args = args or {} local trunc_width = args.trunc_width or 75 + if MiniStatusline.is_truncated(trunc_width) then + return "" + end + local status = vim.fn["codeium#GetStatusString"]() + if status and status ~= "" then + local icon = args.icon or "󰘦 " + return icon .. status + end + return "" + end + MiniStatusline.section_worktree = function(args) + args = args or {} + local trunc_width = args.trunc_width or 75 if MiniStatusline.is_truncated(trunc_width) then return "" end - local status = vim.fn["codeium#GetStatusString"]() + -- Get current directory + local cwd = vim.fn.getcwd() - if status and status ~= "" then - local icon = args.icon or "󰘦 " - return icon .. status + -- Run git worktree list to check if we're in a worktree + local handle = io.popen("git worktree list 2>/dev/null") + if not handle then + return "" + end + + local output = handle:read("*a") + handle:close() + + for line in output:gmatch("[^\n]+") do + local path, branch = line:match("^([^%s]+)%s+%[?([^%]]*)") + if path and path == cwd and branch and branch ~= "" then + local icon = args.icon or "🌿 " + return icon .. branch + end end return "" @@ -63,6 +90,7 @@ local M = { local location = MiniStatusline.section_location({ trunc_width = 75 }) local search = MiniStatusline.section_searchcount({ trunc_width = 75 }) local codeium = MiniStatusline.section_codeium({ trunc_width = 75 }) + local worktree = MiniStatusline.section_worktree({ trunc_width = 75 }) return MiniStatusline.combine_groups({ { hl = mode_hl, strings = { mode } }, @@ -70,7 +98,7 @@ local M = { "%<", -- Mark general truncate point { hl = "MiniStatuslineFilename", strings = { filename } }, "%=", -- End left alignment - { hl = "MiniStatuslineFileinfo", strings = { fileinfo } }, + { hl = "MiniStatuslineFileinfo", strings = { fileinfo, worktree } }, { hl = mode_hl, strings = { codeium, search, location } }, }) end diff --git a/lua/plugins/typ.lua b/lua/plugins/typ.lua new file mode 100644 index 0000000..93c2170 --- /dev/null +++ b/lua/plugins/typ.lua @@ -0,0 +1,6 @@ +return { + "chomosuke/typst-preview.nvim", + ft = "typst", + version = "1.*", + opts = {}, +}