Compare commits

...

4 commits

Author SHA1 Message Date
Bryan Ramos
c57321f850 fixd 2026-04-08 16:16:51 -04:00
Bryan Ramos
0270d78072 fixed 2026-04-08 16:00:17 -04:00
Bryan Ramos
23fb66df0b updated compat 2026-04-08 15:50:18 -04:00
Bryan Ramos
62d06a8bdc fixed 2026-04-08 15:41:59 -04:00
9 changed files with 220 additions and 110 deletions

View file

@ -1,6 +1,6 @@
# Neovim Configuration
Portable Neovim configuration using lazy.nvim and native LSP (Neovim 0.11+).
Portable Neovim configuration using lazy.nvim and native LSP (Neovim 0.11+, tested on 0.12.1).
## Installation
@ -16,8 +16,9 @@ git clone --recurse-submodules git@github.com:itme-brain/nixos.git
## Features
- **Native LSP** (`vim.lsp.config`) - no manual server list needed
- **Native LSP** (`vim.lsp.config` / `vim.lsp.enable`) - no manual server list needed
- **Smart LSP picker** (`<leader>css`) - auto-detects installed servers for current filetype
- **Neovim 0.12 compatible** - uses built-in `:lsp` commands and keeps legacy `:Lsp*` aliases working
- **Portable** - works on NixOS (LSPs via extraPackages) or any system (LSPs via Mason)
- **Mason** - auto-disabled on NixOS, auto-installs essentials elsewhere
@ -39,6 +40,7 @@ On other systems, Mason auto-installs:
- `yamlls` - YAML
The smart picker (`<leader>css`) scans all lspconfig servers and shows only those with binaries installed.
On Neovim 0.12+, start/stop/restart uses the built-in `:lsp` commands under the hood.
## Key Bindings
@ -54,8 +56,8 @@ The smart picker (`<leader>css`) scans all lspconfig servers and shows only thos
| `<leader>gr` | Find references |
| `<leader>e` | Toggle file explorer |
| `<leader>bd` | Delete buffer |
| `<leader>/` | Live grep |
| `<leader>ff` | Find files |
| `<leader>/` | Live grep from git root |
| `<leader>ff` | Find files from git root |
## Plugins

View file

@ -1,9 +1,11 @@
local function load_config_directory(directory)
local config_path = vim.fn.stdpath("config") .. "/lua/" .. directory
local files = vim.fn.glob(config_path .. "/*.lua", false, true)
local files = vim.fn.readdir(config_path, function(name)
return name:sub(-4) == ".lua"
end)
for _, file in ipairs(files) do
local file_name = vim.fn.fnamemodify(file, ":t:r") -- Extract filename without extension
local file_name = file:sub(1, -5)
require(directory .. "." .. file_name)
end
end

View file

@ -26,10 +26,23 @@ vim.opt.guicursor = "n-v-c:block,i:block,r:block"
vim.opt.fillchars = { eob = " " }
vim.cmd([[
autocmd FileType python,haskell,c,cpp setlocal tabstop=4 shiftwidth=4 softtabstop=4
]])
local options_group = vim.api.nvim_create_augroup("config_options", { clear = true })
vim.cmd([[
au BufRead,BufNewFile *.purs set filetype=purescript
]])
vim.api.nvim_create_autocmd("FileType", {
group = options_group,
pattern = { "python", "haskell", "c", "cpp" },
callback = function()
local opt = vim.opt_local
opt.tabstop = 4
opt.shiftwidth = 4
opt.softtabstop = 4
end,
})
vim.api.nvim_create_autocmd({ "BufRead", "BufNewFile" }, {
group = options_group,
pattern = "*.purs",
callback = function(event)
vim.bo[event.buf].filetype = "purescript"
end,
})

View file

@ -2,63 +2,95 @@ return {
{
"chriskempson/base16-vim",
config = function()
vim.cmd("colorscheme base16-onedark")
vim.cmd([[
hi Normal guibg=NONE ctermbg=NONE guifg=#FFFFFF
hi Visual ctermbg=Gray ctermfg=Black guibg=Gray guifg=Black
hi NonText guibg=NONE ctermbg=NONE
hi LineNr guibg=NONE ctermbg=NONE
hi CursorLine guibg=NONE ctermbg=NONE
hi CursorLineNr guibg=NONE ctermbg=NONE guifg=#E5C07B ctermfg=Yellow cterm=bold
hi Search ctermfg=Black guifg=#000000 ctermbg=Gray guibg=#FFCC66
hi Pmenu ctermbg=Black ctermfg=White cterm=NONE guibg=Black guifg=White gui=NONE
hi PmenuSel ctermbg=Green ctermfg=Black cterm=NONE guibg=Green guifg=Black gui=NONE
hi PmenuThumb ctermbg=Green guibg=Green
hi PmenuSbar ctermbg=Black guibg=Black
hi WinSeparator guibg=NONE ctermbg=NONE
local color_group = vim.api.nvim_create_augroup("config_colorscheme", { clear = true })
hi GitGutterChange guibg=NONE ctermbg=NONE
hi GitGutterAdd guibg=NONE ctermbg=NONE
hi GitGutterDelete guibg=NONE ctermbg=NONE
hi SignColumn ctermbg=NONE guibg=NONE
local highlights = {
Normal = { bg = "NONE", fg = "#FFFFFF" },
Visual = { bg = "Gray", fg = "Black" },
NonText = { bg = "NONE" },
LineNr = { bg = "NONE" },
CursorLine = { bg = "NONE" },
CursorLineNr = { bg = "NONE", fg = "#E5C07B", bold = true },
Search = { bg = "#FFCC66", fg = "#000000" },
Pmenu = { bg = "Black", fg = "White" },
PmenuSel = { bg = "Green", fg = "Black" },
PmenuThumb = { bg = "Green" },
PmenuSbar = { bg = "Black" },
WinSeparator = { bg = "NONE" },
GitGutterChange = { bg = "NONE" },
GitGutterAdd = { bg = "NONE" },
GitGutterDelete = { bg = "NONE" },
GitSignsAddNr = { bg = "NONE", fg = "#98c379" },
GitSignsChangeNr = { bg = "NONE", fg = "#61afef" },
GitSignsDeleteNr = { bg = "NONE", fg = "#e06c75" },
SignColumn = { bg = "NONE" },
NeoTreeGitAdded = { bg = "NONE", fg = "#98c379" },
NeoTreeGitModified = { bg = "NONE", fg = "#e5c07b" },
NeoTreeGitDeleted = { bg = "NONE", fg = "#e06c75" },
NeoTreeGitConflict = { bg = "NONE", fg = "#e06c75" },
NeoTreeGitUntracked = { bg = "NONE", fg = "#61afef" },
TelescopeSelection = { bg = "Gray", fg = "Green", bold = true },
TelescopePreviewMatch = { bg = "Yellow", fg = "Black" },
TreesitterContext = { bg = "NONE" },
LazyH1 = { bg = "Black", fg = "Green" },
IblScope = { bg = "NONE", fg = "Yellow" },
ConflictMarker = { fg = "red" },
DiffAdd = { bg = "NONE" },
DiffChange = { bg = "NONE" },
DiffDelete = { bg = "NONE" },
DiffText = { bg = "NONE" },
BufferLineFill = { bg = "NONE" },
BufferLineBackground = { bg = "NONE", fg = "#5c6370" },
BufferLineBuffer = { bg = "NONE", fg = "#5c6370" },
BufferLineBufferSelected = { bg = "NONE", fg = "#FFFFFF", bold = true },
BufferLineBufferVisible = { bg = "NONE", fg = "#abb2bf" },
BufferLineCloseButton = { bg = "NONE", fg = "#5c6370" },
BufferLineCloseButtonSelected = { bg = "NONE", fg = "#e06c75" },
BufferLineCloseButtonVisible = { bg = "NONE", fg = "#5c6370" },
BufferLineModified = { bg = "NONE", fg = "#e5c07b" },
BufferLineModifiedSelected = { bg = "NONE", fg = "#e5c07b" },
BufferLineModifiedVisible = { bg = "NONE", fg = "#e5c07b" },
BufferLineSeparator = { bg = "NONE", fg = "#3e4452" },
BufferLineSeparatorSelected = { bg = "NONE", fg = "#3e4452" },
BufferLineSeparatorVisible = { bg = "NONE", fg = "#3e4452" },
BufferLineIndicatorSelected = { bg = "NONE", fg = "#61afef" },
YankHighlight = { bg = "yellow", fg = "black" },
}
hi TelescopeSelection guibg=Gray guifg=Green gui=bold ctermbg=Black ctermfg=Green cterm=bold
hi TelescopePreviewMatch ctermbg=Yellow ctermfg=Black guibg=Yellow guifg=Black
local function apply_highlights()
for group, spec in pairs(highlights) do
vim.api.nvim_set_hl(0, group, spec)
end
end
hi TreesitterContext guibg=NONE ctermbg=NONE
local conflict_pattern = [[<<<<<<< HEAD\|=======\|>>>>>>> .\+]]
local function apply_conflict_match(win)
if vim.w[win].conflict_marker_match_id then
pcall(vim.fn.matchdelete, vim.w[win].conflict_marker_match_id, win)
end
vim.w[win].conflict_marker_match_id = vim.fn.matchadd("ConflictMarker", conflict_pattern, 10, -1, {
window = win,
})
end
hi LazyH1 ctermbg=Green ctermfg=Black guibg=Black guifg=Green
hi IblScope guibg=NONE guifg=Yellow ctermbg=NONE ctermfg=Yellow
vim.cmd.colorscheme("base16-onedark")
apply_highlights()
hi ConflictMarker ctermfg=red guifg=red
match ConflictMarker /<<<<<<< HEAD\|=======\|>>>>>>> .\+/
vim.api.nvim_create_autocmd("ColorScheme", {
group = color_group,
callback = apply_highlights,
})
hi DiffAdd ctermbg=none guibg=none
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({ "BufWinEnter", "WinEnter" }, {
group = color_group,
callback = function(event)
apply_conflict_match(vim.api.nvim_get_current_win())
end,
})
vim.api.nvim_create_autocmd("TextYankPost", {
group = color_group,
callback = function()
vim.cmd("highlight YankHighlight ctermbg=yellow ctermfg=black guibg=yellow guifg=black")
vim.highlight.on_yank({ higroup = "YankHighlight", timeout = 150 })
end,
})

View file

@ -2,10 +2,17 @@ return {
{
"lukas-reineke/indent-blankline.nvim",
config = function()
local hooks = require("ibl.hooks")
hooks.register(hooks.type.HIGHLIGHT_SETUP, function()
vim.api.nvim_set_hl(0, "IblIndent", { link = "Comment" })
end)
require("ibl").setup({
--indent = { char = "│" },
--indent = { char = "⎸" },
indent = { char = "" },
indent = {
char = "|",
highlight = "IblIndent",
},
scope = {
enabled = false
},

View file

@ -141,6 +141,23 @@ return {
config = function()
local lspconfig = require('lspconfig')
-- Neovim 0.12 exposes built-in :lsp commands and skips lspconfig's legacy
-- :Lsp* aliases. Recreate the old names so existing mappings keep working.
if vim.fn.exists(':lsp') == 2 and vim.fn.exists(':LspStart') == 0 then
vim.api.nvim_create_user_command('LspStart', function(info)
vim.cmd('lsp enable ' .. table.concat(info.fargs, ' '))
end, { nargs = '*' })
vim.api.nvim_create_user_command('LspRestart', function(info)
vim.cmd('lsp restart ' .. table.concat(info.fargs, ' '))
end, { nargs = '*', bang = true })
vim.api.nvim_create_user_command('LspStop', function(info)
local suffix = info.bang and '!' or ''
vim.cmd('lsp stop' .. suffix .. ' ' .. table.concat(info.fargs, ' '))
end, { nargs = '*', bang = true })
end
-- Diagnostic display configuration
vim.diagnostic.config({
virtual_text = {
@ -165,23 +182,30 @@ return {
severity_sort = true,
})
-- Add border to hover and signature help windows
vim.lsp.handlers['textDocument/hover'] = vim.lsp.with(
vim.lsp.handlers.hover,
{ border = 'rounded' }
)
vim.lsp.handlers['textDocument/signatureHelp'] = vim.lsp.with(
vim.lsp.handlers.signature_help,
{ border = 'rounded' }
)
-- Add border to hover and signature help windows.
local hover_handler = vim.lsp.handlers.hover
vim.lsp.handlers['textDocument/hover'] = function(err, result, ctx, config)
return hover_handler(err, result, ctx, vim.tbl_extend('force', config or {}, {
border = 'rounded',
}))
end
local signature_help_handler = vim.lsp.handlers.signature_help
vim.lsp.handlers['textDocument/signatureHelp'] = function(err, result, ctx, config)
return signature_help_handler(err, result, ctx, vim.tbl_extend('force', config or {}, {
border = 'rounded',
}))
end
-- 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)
local files = vim.fn.readdir(lsp_path, function(name)
return name:sub(-4) == '.lua'
end)
for _, file in ipairs(files) do
local server = vim.fn.fnamemodify(file, ':t:r')
local server = file:sub(1, -5)
table.insert(servers, server)
end
return servers
@ -246,8 +270,7 @@ return {
table.sort(matching)
local function start_server(server)
vim.lsp.enable(server) -- Register on-demand
vim.cmd('LspStart ' .. server)
vim.lsp.enable(server)
end
if #matching == 0 then
@ -270,9 +293,9 @@ return {
{ "<leader>cs", group = "LSP Commands" },
{ "<leader>cf", function() vim.lsp.buf.format() end, desc = "Code Format" },
{ "<leader>csi", ":checkhealth vim.lsp<CR>", desc = "LSP Info" },
{ "<leader>csr", ":LspRestart<CR>", desc = "LSP Restart" },
{ "<leader>csr", ":lsp restart<CR>", desc = "LSP Restart" },
{ "<leader>css", lsp_start_smart, desc = "LSP Start" },
{ "<leader>csx", ":LspStop<CR>", desc = "LSP Stop" },
{ "<leader>csx", ":lsp stop<CR>", desc = "LSP Stop" },
})
end
},

View file

@ -41,18 +41,20 @@ return {
},
})
-- Set up cursorline highlight for neo-tree (green text on dark bg)
vim.api.nvim_set_hl(0, "NeoTreeCursorLine", { bg = "#313244", fg = "#a6e3a1" })
-- Keep the selected entry readable without a solid row background.
vim.api.nvim_set_hl(0, "NeoTreeCursorLine", { bg = "NONE", fg = "#a6e3a1" })
-- Apply highlight and re-apply on colorscheme change
vim.api.nvim_create_autocmd({ "FileType", "ColorScheme" }, {
pattern = { "neo-tree", "*" },
callback = function(ev)
if ev.event == "ColorScheme" then
vim.api.nvim_set_hl(0, "NeoTreeCursorLine", { bg = "#313244", fg = "#a6e3a1" })
vim.api.nvim_set_hl(0, "NeoTreeCursorLine", { bg = "NONE", fg = "#a6e3a1" })
end
if vim.bo.filetype == "neo-tree" then
vim.wo.winhighlight = "CursorLine:NeoTreeCursorLine"
local win = vim.api.nvim_get_current_win()
local buf = vim.api.nvim_win_get_buf(win)
if vim.bo[buf].filetype == "neo-tree" then
vim.wo[win].winhighlight = "CursorLine:NeoTreeCursorLine"
end
end,
})
@ -75,12 +77,12 @@ return {
for _, buf in ipairs(bufs) do
local name = api.nvim_buf_get_name(buf)
if name:match("neo%-tree filesystem") then
api.nvim_command(":Neotree close")
vim.cmd("Neotree close")
return
end
end
api.nvim_command(":Neotree")
vim.cmd("Neotree")
end
require("which-key").add({

View file

@ -1,12 +1,15 @@
local function get_root()
local git_dir = vim.fn.systemlist("git rev-parse --show-toplevel")[1]
if git_dir and git_dir ~= "" then
local result = vim.system({ "git", "rev-parse", "--show-toplevel" }, { text = true }):wait()
if result.code == 0 and result.stdout then
local git_dir = vim.trim(result.stdout)
if git_dir ~= "" then
return git_dir
else
return vim.fn.getcwd() -- Fallback to current working directory if not in a Git repo
end
end
return vim.fn.getcwd()
end
return {
{
"nvim-telescope/telescope.nvim",
@ -22,8 +25,10 @@ return {
require('telescope.builtin').live_grep({ cwd = get_root() })
end,
desc = "grep" },
{ "<leader>/", ":Telescope live_grep<CR>", desc = "grep" },
{ "<leader>ff", ":Telescope fd<CR>", desc = "Search for Files" },
{ "<leader>ff", function()
require('telescope.builtin').find_files({ cwd = get_root() })
end,
desc = "Search for Files" },
{ "<leader>fp", ":Telescope oldfiles<CR>", desc = "Oldfiles" },
{ "<leader>?", ":Telescope command_history<CR>", desc = "Command History" },
{ "<leader>cm", ":Telescope man_pages<CR>", desc = "Manpages" },
@ -35,14 +40,14 @@ return {
if next(attached) ~= nil then
require('telescope.builtin').lsp_definitions()
else
vim.api.nvim_command('normal! gd')
vim.api.nvim_feedkeys("gd", "n", false)
end
end,
mode = "n",
desc = "Go to Definition"
},
{ "<leader>gd", ":Telescope lsp_definitions<CR>", desc = "Go to Definition" },
{ "<leader>gr", ":Telescope lsp_references", desc = "Goto References" },
{ "<leader>gr", ":Telescope lsp_references<CR>", desc = "Goto References" },
{ "<leader>gi", ":Telescope lsp_implementations<CR>", desc = "Go to Implementations" },
{ "<leader>gt", ":Telescope lsp_type_definitions<CR>", desc = "Go to Type Definition" },
{ "<leader>cv", ":Telescope treesitter<CR>", desc = "Function Names & Variables" },

View file

@ -7,8 +7,12 @@ return {
{ "<leader>l", ":Lazy<CR>", desc = "Lazy" },
{ "<leader>t",
function()
vim.cmd("botright new | setlocal nonumber norelativenumber | resize 10 | terminal")
vim.cmd("startinsert")
vim.cmd.botright("new")
vim.opt_local.number = false
vim.opt_local.relativenumber = false
vim.cmd.resize(10)
vim.cmd.terminal()
vim.cmd.startinsert()
end,
mode = "n",
desc = "Open Terminal"
@ -24,11 +28,14 @@ return {
{ "<leader>b", group = "Buffers"},
{ "<leader>bd", function()
local function is_neotree()
return vim.bo.filetype == "neo-tree"
local function is_neotree(bufnr)
return vim.bo[bufnr].filetype == "neo-tree"
end
local current_buf = vim.api.nvim_get_current_buf()
-- Skip if in neo-tree
if is_neotree() then
if is_neotree(current_buf) then
vim.notify("Cannot delete buffer from neo-tree", vim.log.levels.WARN)
return
end
@ -38,15 +45,32 @@ return {
vim.notify("Cannot delete last buffer", vim.log.levels.WARN)
return
end
local buf_to_delete = vim.api.nvim_get_current_buf()
vim.cmd('bprevious')
vim.cmd('bdelete ' .. buf_to_delete)
vim.cmd.bprevious()
vim.cmd.bdelete({ args = { tostring(current_buf) } })
-- If we ended up in neo-tree, move back to a regular window
if is_neotree() then
vim.cmd('wincmd l')
local new_buf = vim.api.nvim_get_current_buf()
if is_neotree(new_buf) then
vim.cmd.wincmd("l")
end
end, desc = "Delete Buffer" },
{ "<leader>bD", "execute 'close'<CR> | <cmd>execute 'bd!'", desc = "Delete Window & Buffer" },
{ "<leader>bD", function()
local current_buf = vim.api.nvim_get_current_buf()
local current_win = vim.api.nvim_get_current_win()
if vim.bo[current_buf].filetype == "neo-tree" then
vim.notify("Cannot delete neo-tree buffer", vim.log.levels.WARN)
return
end
local wins = vim.fn.win_findbuf(current_buf)
if #wins > 1 then
vim.api.nvim_win_close(current_win, false)
end
if vim.api.nvim_buf_is_valid(current_buf) then
vim.cmd('bdelete! ' .. current_buf)
end
end, desc = "Delete Window & Buffer" },
{ "<leader>ca", vim.lsp.buf.code_action, desc = "Code Action" },
{ "<leader>cr", vim.lsp.buf.rename, desc = "Rename Variable" },