diff --git a/src/user/modules/utils/modules/neovim/config/nvim/lua/config/options.lua b/src/user/modules/utils/modules/neovim/config/nvim/lua/config/options.lua index 06a94d8..96163da 100644 --- a/src/user/modules/utils/modules/neovim/config/nvim/lua/config/options.lua +++ b/src/user/modules/utils/modules/neovim/config/nvim/lua/config/options.lua @@ -4,7 +4,10 @@ vim.g.autoformat = false vim.opt.number = true vim.opt.relativenumber = true vim.opt.cursorline = true -vim.opt.termguicolors = true +-- Enable true color if terminal supports it (disabled in TTY/headless) +if vim.env.COLORTERM == "truecolor" or vim.env.COLORTERM == "24bit" then + vim.opt.termguicolors = true +end vim.opt.tabstop = 2 vim.opt.shiftwidth = 2 @@ -12,14 +15,13 @@ vim.opt.softtabstop = 2 vim.opt.expandtab = true vim.opt.smartindent = true vim.opt.ignorecase = true -vim.opt.smartcase = false +vim.opt.smartcase = true vim.opt.incsearch = false vim.opt.swapfile = false vim.opt.backup = false vim.opt.undofile = true -vim.o.termguicolors = false vim.opt.guicursor = "n-v-c:block,i:block,r:block" vim.opt.fillchars = { eob = " " } diff --git a/src/user/modules/utils/modules/neovim/config/nvim/lua/plugins/bufferline.lua b/src/user/modules/utils/modules/neovim/config/nvim/lua/plugins/bufferline.lua index 307cc1b..8ddec03 100644 --- a/src/user/modules/utils/modules/neovim/config/nvim/lua/plugins/bufferline.lua +++ b/src/user/modules/utils/modules/neovim/config/nvim/lua/plugins/bufferline.lua @@ -4,7 +4,37 @@ return { version = "*", dependencies = "nvim-tree/nvim-web-devicons", config = function() - require("bufferline").setup{} + require("bufferline").setup{ + options = { + separator_style = "thin", + show_buffer_close_buttons = false, + show_close_icon = false, + }, + highlights = { + -- Force all icon backgrounds to transparent + buffer_selected = { bg = "NONE" }, + buffer_visible = { bg = "NONE" }, + background = { bg = "NONE" }, + fill = { bg = "NONE" }, + separator = { bg = "NONE" }, + separator_selected = { bg = "NONE" }, + separator_visible = { bg = "NONE" }, + close_button = { bg = "NONE" }, + close_button_selected = { bg = "NONE" }, + close_button_visible = { bg = "NONE" }, + modified = { bg = "NONE" }, + modified_selected = { bg = "NONE" }, + modified_visible = { bg = "NONE" }, + duplicate = { bg = "NONE" }, + duplicate_selected = { bg = "NONE" }, + duplicate_visible = { bg = "NONE" }, + indicator_selected = { bg = "NONE" }, + indicator_visible = { bg = "NONE" }, + pick = { bg = "NONE" }, + pick_selected = { bg = "NONE" }, + pick_visible = { bg = "NONE" }, + }, + } end } } diff --git a/src/user/modules/utils/modules/neovim/config/nvim/lua/plugins/colorscheme.lua b/src/user/modules/utils/modules/neovim/config/nvim/lua/plugins/colorscheme.lua index 31e0c6e..d637c4e 100644 --- a/src/user/modules/utils/modules/neovim/config/nvim/lua/plugins/colorscheme.lua +++ b/src/user/modules/utils/modules/neovim/config/nvim/lua/plugins/colorscheme.lua @@ -37,6 +37,23 @@ return { hi DiffChange ctermbg=none guibg=none hi DiffDelete ctermbg=none guibg=none hi DiffText ctermbg=none guibg=none + + " Bufferline - dark background, readable text + hi BufferLineFill guibg=NONE ctermbg=NONE + hi BufferLineBackground guibg=NONE ctermbg=NONE guifg=#5c6370 ctermfg=Gray + hi BufferLineBuffer guibg=NONE ctermbg=NONE guifg=#5c6370 ctermfg=Gray + hi BufferLineBufferSelected guibg=NONE ctermbg=NONE guifg=#FFFFFF ctermfg=White gui=bold cterm=bold + hi BufferLineBufferVisible guibg=NONE ctermbg=NONE guifg=#abb2bf ctermfg=White + hi BufferLineCloseButton guibg=NONE ctermbg=NONE guifg=#5c6370 ctermfg=Gray + hi BufferLineCloseButtonSelected guibg=NONE ctermbg=NONE guifg=#e06c75 ctermfg=Red + hi BufferLineCloseButtonVisible guibg=NONE ctermbg=NONE guifg=#5c6370 ctermfg=Gray + hi BufferLineModified guibg=NONE ctermbg=NONE guifg=#e5c07b ctermfg=Yellow + hi BufferLineModifiedSelected guibg=NONE ctermbg=NONE guifg=#e5c07b ctermfg=Yellow + hi BufferLineModifiedVisible guibg=NONE ctermbg=NONE guifg=#e5c07b ctermfg=Yellow + hi BufferLineSeparator guibg=NONE ctermbg=NONE guifg=#3e4452 ctermfg=DarkGray + hi BufferLineSeparatorSelected guibg=NONE ctermbg=NONE guifg=#3e4452 ctermfg=DarkGray + hi BufferLineSeparatorVisible guibg=NONE ctermbg=NONE guifg=#3e4452 ctermfg=DarkGray + hi BufferLineIndicatorSelected guibg=NONE ctermbg=NONE guifg=#61afef ctermfg=Blue ]]) vim.api.nvim_create_autocmd("TextYankPost", { diff --git a/src/user/modules/utils/modules/neovim/config/nvim/lua/plugins/lsp.lua b/src/user/modules/utils/modules/neovim/config/nvim/lua/plugins/lsp.lua index 30ade8e..be26786 100644 --- a/src/user/modules/utils/modules/neovim/config/nvim/lua/plugins/lsp.lua +++ b/src/user/modules/utils/modules/neovim/config/nvim/lua/plugins/lsp.lua @@ -1,19 +1,16 @@ --- https://github.com/neovim/nvim-lspconfig/blob/master/doc/configs.md -local servers = { - "ts_ls", - "pyright", - "nil_ls", - "cssls", - "html", - "lua_ls", - "marksman", - "tailwindcss", - "bashls", - "clangd", - "jsonls", - "vuels", - "rust_analyzer" - --"arduino-language-server" +-- Neovim 0.11+ LSP configuration +-- Uses nvim-lspconfig for server definitions + vim.lsp.enable() API + +-- Detect NixOS (Mason doesn't work on NixOS due to FHS issues) +local is_nixos = vim.fn.filereadable("/etc/NIXOS") == 1 + +-- Servers to ensure are installed via Mason (non-NixOS only) +-- On NixOS, install these via extraPackages or per-project devShells +local mason_ensure_installed = { + "lua_ls", -- Neovim config + "nil_ls", -- Nix + "bashls", -- Shell scripts + "jsonls", -- JSON configs } return { @@ -59,47 +56,6 @@ return { end }, - --{ - -- "nvim-treesitter/nvim-treesitter-context", - -- dependencies = { "nvim-treesitter/nvim-treesitter" }, - -- config = function() - -- require("treesitter-context").setup({ - -- enable = true, -- Enable this plugin (Can be enabled/disabled later via commands) - -- max_lines = 3, -- How many lines the window should span. Values <= 0 mean no limit. - -- min_window_height = 0, -- Minimum editor window height to enable context. Values <= 0 mean no limit. - -- line_numbers = false, - -- multiline_threshold = 20, -- Maximum number of lines to collapse for a single context line - -- trim_scope = "outer", -- Which context lines to discard if `max_lines` is exceeded. Choices: 'inner', 'outer' - -- mode = "cursor", -- Line used to calculate context. Choices: 'cursor', 'topline' - -- -- Separator between context and content. Should be a single character string, like '-'. - -- -- When separator is set, the context will only show up when there are at least 2 lines above cursorline. - -- separator = "x", - -- zindex = 20, -- The Z-index of the context window - -- on_attach = nil, -- (fun(buf: integer): boolean) rurn false to disable attaching - -- }) - -- end, - --}, - - { - "VonHeikemen/lsp-zero.nvim", - branch = "v2.x", - dependencies = { - { "neovim/nvim-lspconfig" }, - - { "hrsh7th/nvim-cmp" }, - { "hrsh7th/cmp-buffer" }, - { "hrsh7th/cmp-path" }, - { "hrsh7th/cmp-nvim-lsp" }, - - { "L3MON4D3/LuaSnip" }, - }, - config = function() - local lsp = require('lsp-zero').preset({}) - lsp.setup_servers(servers) - lsp.setup() - end - }, - { "hrsh7th/nvim-cmp", dependencies = { @@ -152,26 +108,64 @@ return { end }, + -- Mason: portable LSP installer (disabled on NixOS where it doesn't work) + { + "williamboman/mason.nvim", + enabled = not is_nixos, + config = function() + require("mason").setup() + end + }, + { + "williamboman/mason-lspconfig.nvim", + enabled = not is_nixos, + dependencies = { "williamboman/mason.nvim" }, + config = function() + require("mason-lspconfig").setup({ + ensure_installed = mason_ensure_installed, + automatic_installation = false, -- Only install what's in ensure_installed + }) + end + }, + { "neovim/nvim-lspconfig", + dependencies = { + "hrsh7th/cmp-nvim-lsp", + }, config = function() - local lsp = require('lspconfig') - local navic = require('nvim-navic') + local lspconfig = require('lspconfig') + + -- Get all known server names by scanning lspconfig's lsp directory + local function get_all_servers() + local servers = {} + local lsp_path = vim.fn.stdpath('data') .. '/lazy/nvim-lspconfig/lsp' + local files = vim.fn.globpath(lsp_path, '*.lua', false, true) + for _, file in ipairs(files) do + local server = vim.fn.fnamemodify(file, ':t:r') + table.insert(servers, server) + end + return servers + end + + local all_servers = get_all_servers() + + -- local navic = require('nvim-navic') local capabilities = require('cmp_nvim_lsp').default_capabilities() - for _, server in ipairs(servers) do - lsp[server].setup { - -- Prevent LSP from autostarting - autostart = false, - capabilities = capabilities, - on_attach = function(client, bufnr) - if client.server_capabilities.documentSymbolProvider then - navic.attach(client, bufnr) - end - end, - } - end - lsp.lua_ls.setup { + -- Global config applied to all servers + vim.lsp.config('*', { + autostart = false, -- Don't auto-attach, use css to start manually + capabilities = capabilities, + -- on_attach = function(client, bufnr) + -- if client.server_capabilities.documentSymbolProvider then + -- navic.attach(client, bufnr) + -- end + -- end, + }) + + -- Server-specific settings (merged with lspconfig defaults) + vim.lsp.config.lua_ls = { settings = { Lua = { diagnostics = { @@ -180,17 +174,70 @@ return { } } } + + -- Check if server binary is available + local function is_server_installed(config) + if config.default_config and config.default_config.cmd then + local cmd = config.default_config.cmd[1] + return vim.fn.executable(cmd) == 1 + end + return false + end + + -- Find and start LSP server(s) for current filetype + local function lsp_start_smart() + local ft = vim.bo.filetype + if ft == '' then + vim.notify("No filetype detected", vim.log.levels.WARN) + return + end + + -- Find all matching servers (filetype match + binary installed) + local matching = {} + for _, server in ipairs(all_servers) do + local ok, config = pcall(require, 'lspconfig.configs.' .. server) + if ok and config.default_config and config.default_config.filetypes then + if vim.tbl_contains(config.default_config.filetypes, ft) and is_server_installed(config) then + table.insert(matching, server) + end + end + end + + -- Sort for consistent ordering + table.sort(matching) + + local function start_server(server) + vim.lsp.enable(server) -- Register on-demand + vim.cmd('LspStart ' .. server) + end + + if #matching == 0 then + vim.notify("No LSP server installed for filetype: " .. ft, vim.log.levels.WARN) + elseif #matching == 1 then + start_server(matching[1]) + else + vim.ui.select(matching, { + prompt = "Select LSP server:", + }, function(choice) + if choice then + start_server(choice) + end + end) + end + end + + -- LSP keybindings require("which-key").add({ { "cs", group = "LSP Commands" }, - { "cf", ":LspFormat", desc = "Code Format" }, - { "csi", ":LspInfo", desc = "LSP Info" }, - { "csl", ":LspLog", desc = "LSP Log" }, - { "csr", ":LspRestart", desc = "LSP Restart" }, - { "css", ":LspStart", desc = "LSP Start" }, - { "csx", ":LspStop", desc = "LSP Stop" }, + { "cf", function() vim.lsp.buf.format() end, desc = "Code Format" }, + { "csi", ":checkhealth vim.lsp", desc = "LSP Info" }, + { "csr", ":LspRestart", desc = "LSP Restart" }, + { "css", lsp_start_smart, desc = "LSP Start" }, + { "csx", ":LspStop", desc = "LSP Stop" }, }) end }, + { "taproot-wizards/bitcoin-script-hints.nvim", dependencies = { "nvim-treesitter/nvim-treesitter" }, diff --git a/src/user/modules/utils/modules/neovim/config/nvim/lua/plugins/neotree.lua b/src/user/modules/utils/modules/neovim/config/nvim/lua/plugins/neotree.lua index e04584f..de0b8d4 100644 --- a/src/user/modules/utils/modules/neovim/config/nvim/lua/plugins/neotree.lua +++ b/src/user/modules/utils/modules/neovim/config/nvim/lua/plugins/neotree.lua @@ -13,9 +13,16 @@ return { position = "left", width = 20, }, - --filesystem = { - -- hijack_netrw_behavior = "disabled", - --}, + event_handlers = { + { + event = "neo_tree_window_after_open", + handler = function() + local win = vim.api.nvim_get_current_win() + vim.wo[win].winfixwidth = true + vim.wo[win].winfixbuf = true + end + }, + }, }) local function toggle_neotree() diff --git a/src/user/modules/utils/modules/neovim/config/nvim/lua/plugins/telescope.lua b/src/user/modules/utils/modules/neovim/config/nvim/lua/plugins/telescope.lua index 5f4c935..9bffbd4 100644 --- a/src/user/modules/utils/modules/neovim/config/nvim/lua/plugins/telescope.lua +++ b/src/user/modules/utils/modules/neovim/config/nvim/lua/plugins/telescope.lua @@ -10,7 +10,7 @@ end return { { "nvim-telescope/telescope.nvim", - brach = '0.1.x', + branch = '0.1.x', dependencies = { { 'nvim-lua/plenary.nvim' }, { 'nvim-tree/nvim-web-devicons' } @@ -31,7 +31,7 @@ return { -- Code { "gd", function() - local attached = vim.lsp.buf_get_clients(0) + local attached = vim.lsp.get_clients({ bufnr = 0 }) if next(attached) ~= nil then require('telescope.builtin').lsp_definitions() else diff --git a/src/user/modules/utils/modules/neovim/config/pkgs.nix b/src/user/modules/utils/modules/neovim/config/pkgs.nix index 7971a52..35b1e0d 100644 --- a/src/user/modules/utils/modules/neovim/config/pkgs.nix +++ b/src/user/modules/utils/modules/neovim/config/pkgs.nix @@ -1,22 +1,18 @@ { pkgs, ... }: let + # Essential LSPs for config files (project-specific LSPs go in devShells) lsp = with pkgs; [ - nil + nixd + lua-language-server marksman - lua-language-server stylua - nodePackages."@tailwindcss/language-server" - pyright - clang-tools - rust-analyzer - #arduino-language-server + taplo # TOML ]; lsp' = with pkgs.nodePackages; [ - typescript-language-server - vscode-langservers-extracted + vscode-langservers-extracted # jsonls, html, cssls bash-language-server - #vls + yaml-language-server ]; extraPackages = with pkgs; [