-- Encoding / basics
vim.opt.encoding = "utf-8"
vim.opt.number = true
vim.opt.relativenumber = true
vim.opt.wrap = false
-- Toggle relative numbers in insert mode
local auto_numbers = vim.api.nvim_create_augroup("auto_numbers", { clear = true })
vim.api.nvim_create_autocmd("InsertEnter", {
group = auto_numbers,
callback = function()
vim.opt.relativenumber = false
end,
})
vim.api.nvim_create_autocmd("InsertLeave", {
group = auto_numbers,
callback = function()
vim.opt.number = true
vim.opt.relativenumber = true
end,
})
-- Files / UI
vim.opt.backup = false
vim.opt.swapfile = false
vim.opt.mouse = "n"
vim.opt.path:append("**")
vim.opt.wildmenu = true
vim.opt.lazyredraw = true
vim.opt.maxmempattern = 20000
-- Tabs
vim.opt.tabstop = 2
vim.opt.shiftwidth = 2
vim.opt.softtabstop = 2
vim.opt.expandtab = true
vim.opt.smarttab = true
-- Splits
vim.opt.splitbelow = true
vim.opt.splitright = true
-- Autoreload changed files on disk
vim.opt.autoread = true
local auto_reload = vim.api.nvim_create_augroup("auto_reload", { clear = true })
vim.api.nvim_create_autocmd({ "FocusGained", "BufEnter", "CursorHold", "CursorHoldI" }, {
group = auto_reload,
callback = function()
-- Don't mess with special modes / cmdwin
if vim.fn.getcmdwintype() ~= "" then return end
local m = vim.fn.mode()
if m:match("^[c]") then return end -- command-line mode
if m:match("^r") then return end -- hit-enter / prompt
if m == "!" then return end -- shell / external cmd
if m == "t" then return end -- terminal-mode
-- checktime triggers FileChangedShellPost when needed
vim.cmd("checktime")
end,
})
vim.api.nvim_create_autocmd("FileChangedShellPost", {
group = auto_reload,
callback = function()
vim.notify("File changed on disk. Buffer reloaded.", vim.log.levels.WARN)
end,
})
-- Odin: format on save
local odin = vim.api.nvim_create_augroup("odin", { clear = true })
vim.api.nvim_create_autocmd("BufWritePre", {
group = odin,
pattern = "*.odin",
callback = function(args)
-- Avoid formatting if no LSP attached
local clients = vim.lsp.get_clients({ bufnr = args.buf })
if #clients == 0 then return end
-- Modern API; async=false keeps it "format-before-write"
vim.lsp.buf.format({ bufnr = args.buf, async = false })
end,
})
-- netrw
vim.g.netrw_bufsettings = "noma nomod nu nowrap ro nobl"
-- Eyecandy: cursorline only in active window
vim.opt.cursorline = true
local dynamic_cursorline = vim.api.nvim_create_augroup("dynamic_cursorline", { clear = true })
vim.api.nvim_create_autocmd({ "WinEnter", "BufEnter", "BufWinEnter" }, {
group = dynamic_cursorline,
callback = function()
vim.opt_local.cursorline = true
end,
})
vim.api.nvim_create_autocmd({ "WinLeave", "BufLeave", "BufWinLeave" }, {
group = dynamic_cursorline,
callback = function()
vim.opt_local.cursorline = false
end,
})
-- vim.cmd("highlight clear")
vim.opt.background = "dark"
vim.opt.termguicolors = true
vim.cmd.colorscheme "catppuccin"
-- Split / UI
vim.opt.fillchars = { vert = "│" }
vim.opt.signcolumn = "auto:2"
-- Neovim note: VertSplit highlight group was replaced by WinSeparator in newer versions.
-- Setting both keeps it working across versions/colorschemes.
vim.api.nvim_set_hl(0, "VertSplit", { fg = "darkgray" })
vim.api.nvim_set_hl(0, "WinSeparator",{ fg = "darkgray" })
-- folds
vim.keymap.set("n", "", "za", { desc = "Toggle fold" })
vim.opt.foldmethod = "indent"
vim.opt.foldenable = false -- set nofoldenable