nvim/.config/nvim/init.lua

-- ~/.config/nvim/init.lua
-- Minimal neovim config; plugins live in lua/plugins.lua.
-- See mercemay.top/src/dotfiles/

-- ---- leader first -----------------------------------------------------
vim.g.mapleader = " "
vim.g.maplocalleader = ","

-- ---- options ----------------------------------------------------------
local o = vim.opt
o.number = true
o.relativenumber = true
o.signcolumn = "yes"
o.cursorline = true
o.wrap = false
o.scrolloff = 6
o.sidescrolloff = 8

o.expandtab = true
o.shiftwidth = 2
o.tabstop = 2
o.softtabstop = 2
o.smartindent = true

o.ignorecase = true
o.smartcase = true
o.incsearch = true
o.hlsearch = true

o.splitright = true
o.splitbelow = true
o.updatetime = 250
o.timeoutlen = 400

o.undofile = true
o.undodir = vim.fn.stdpath("state") .. "/undo"
o.swapfile = false
o.backup = false

o.termguicolors = true
o.background = "dark"
o.clipboard = "unnamedplus"
o.completeopt = { "menu", "menuone", "noselect" }

-- ---- diagnostics ------------------------------------------------------
vim.diagnostic.config({
  virtual_text = { prefix = "*", spacing = 2 },
  severity_sort = true,
  update_in_insert = false,
  float = { border = "rounded", source = "if_many" },
})

-- ---- keymaps ----------------------------------------------------------
local map = function(mode, lhs, rhs, desc)
  vim.keymap.set(mode, lhs, rhs, { silent = true, desc = desc })
end

map("n", "<leader>w", "<cmd>write<cr>", "save buffer")
map("n", "<leader>q", "<cmd>confirm quit<cr>", "quit")
map("n", "<esc>", "<cmd>nohlsearch<cr>", "clear search highlight")

-- split navigation
map("n", "<C-h>", "<C-w>h", "left split")
map("n", "<C-j>", "<C-w>j", "below split")
map("n", "<C-k>", "<C-w>k", "above split")
map("n", "<C-l>", "<C-w>l", "right split")

-- buffer hop
map("n", "<S-h>", "<cmd>bprevious<cr>", "prev buffer")
map("n", "<S-l>", "<cmd>bnext<cr>", "next buffer")
map("n", "<leader>x", "<cmd>bdelete<cr>", "close buffer")

-- keep selection on indent
map("v", "<", "<gv", "indent left")
map("v", ">", ">gv", "indent right")

-- move selected lines
map("v", "J", ":m '>+1<cr>gv=gv", "move selection down")
map("v", "K", ":m '<-2<cr>gv=gv", "move selection up")

-- better join
map("n", "J", "mzJ`z", "join without jump")

-- quickfix nav
map("n", "]q", "<cmd>cnext<cr>", "next qf")
map("n", "[q", "<cmd>cprev<cr>", "prev qf")

-- lsp-ish (wired up in plugins.lua for each attach)
map("n", "gd", vim.lsp.buf.definition, "go to definition")
map("n", "gr", vim.lsp.buf.references, "references")
map("n", "K",  vim.lsp.buf.hover, "hover")
map("n", "<leader>rn", vim.lsp.buf.rename, "rename symbol")
map("n", "<leader>ca", vim.lsp.buf.code_action, "code action")
map("n", "[d", vim.diagnostic.goto_prev, "prev diagnostic")
map("n", "]d", vim.diagnostic.goto_next, "next diagnostic")

-- ---- autocmds ---------------------------------------------------------
local group = vim.api.nvim_create_augroup("mercemay", { clear = true })

vim.api.nvim_create_autocmd("TextYankPost", {
  group = group,
  callback = function() vim.highlight.on_yank({ timeout = 180 }) end,
  desc = "flash on yank",
})

vim.api.nvim_create_autocmd("BufWritePre", {
  group = group,
  pattern = "*",
  callback = function(args)
    local n = vim.fn.getfsize(args.file)
    if n > 512 * 1024 then return end -- skip big files
    -- trim trailing whitespace
    local save = vim.fn.winsaveview()
    vim.cmd([[silent! keeppatterns %s/\s\+$//e]])
    vim.fn.winrestview(save)
  end,
  desc = "trim trailing whitespace on save",
})

-- ---- bootstrap lazy.nvim ---------------------------------------------
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not (vim.uv or vim.loop).fs_stat(lazypath) then
  vim.fn.system({
    "git", "clone", "--filter=blob:none",
    "https://github.com/folke/lazy.nvim.git",
    "--branch=stable", lazypath,
  })
end
vim.opt.rtp:prepend(lazypath)

require("lazy").setup(require("plugins"), {
  change_detection = { notify = false },
  install = { colorscheme = { "habamax" } },
  ui = { border = "rounded" },
})

-- ---- per-host override ------------------------------------------------
pcall(require, "local")