Files
2026-06-30 18:50:31 +08:00

409 lines
12 KiB
Lua

-- ~/.config/nvim/init.lua
-- ============================================================================
-- Leader
-- ============================================================================
vim.g.mapleader = " "
vim.g.maplocalleader = " "
-- ============================================================================
-- Options
-- ============================================================================
vim.o.number = true
vim.o.relativenumber = true
vim.o.mouse = "a"
vim.opt.cursorline = true
vim.o.clipboard = "unnamedplus"
vim.o.swapfile = false
vim.o.backup = false
vim.o.writebackup = false
vim.o.undofile = true
vim.o.ignorecase = true
vim.o.smartcase = true
vim.o.signcolumn = "yes"
vim.o.splitright = true
vim.o.splitbelow = true
vim.o.termguicolors = true
vim.o.winborder = "rounded"
vim.o.updatetime = 250
vim.o.timeoutlen = 1000
vim.o.expandtab = true
vim.o.shiftwidth = 2
vim.o.tabstop = 2
vim.o.softtabstop = 2
vim.o.showmode = false
vim.o.completeopt = "menu,menuone,noselect"
-- ============================================================================
-- Plugins
-- ============================================================================
vim.pack.add({
{ src = "https://github.com/vague-theme/vague.nvim" },
{ src = "https://github.com/neovim/nvim-lspconfig" },
{ src = "https://github.com/saghen/blink.lib" },
{ src = "https://github.com/saghen/blink.cmp" },
{ src = "https://github.com/nvim-treesitter/nvim-treesitter", version = "main" },
{ src = "https://github.com/echasnovski/mini.nvim" },
{ src = "https://github.com/nvim-neo-tree/neo-tree.nvim", version = vim.version.range("3") },
{ src = "https://github.com/nvim-lua/plenary.nvim" },
{ src = "https://github.com/MunifTanjim/nui.nvim" },
{ src = "https://github.com/ibhagwan/fzf-lua" },
{ src = "https://github.com/lewis6991/gitsigns.nvim" },
{ src = "https://github.com/folke/which-key.nvim" },
{ src = "https://github.com/goolord/alpha-nvim" },
{ src = "https://github.com/nvim-tree/nvim-web-devicons" },
{ src = "https://github.com/christoomey/vim-tmux-navigator" },
{ src = "https://github.com/folke/todo-comments.nvim" },
})
-- ============================================================================
-- Theme
-- ============================================================================
vim.cmd.colorscheme("vague")
-- ============================================================================
-- Diagnostics
-- ============================================================================
vim.diagnostic.config({
virtual_text = true,
underline = true,
severity_sort = true,
signs = {
text = {
[vim.diagnostic.severity.ERROR] = "E",
[vim.diagnostic.severity.WARN] = "W",
[vim.diagnostic.severity.INFO] = "I",
[vim.diagnostic.severity.HINT] = "H",
},
},
})
-- ============================================================================
-- Completion
-- ============================================================================
require("blink.cmp").build():pwait()
require("blink.cmp").setup({
completion = {
menu = { auto_show = true },
trigger = { show_on_trigger_character = true },
ghost_text = { enabled = false },
documentation = {
auto_show = true,
auto_show_delay_ms = 200,
},
list = {
selection = {
preselect = false,
auto_insert = false,
},
},
},
keymap = {
preset = "none",
["<C-space>"] = { "show", "show_documentation", "hide_documentation" },
["<C-e>"] = { "hide" },
["<C-up>"] = { "scroll_documentation_up" },
["<C-down>"] = { "scroll_documentation_down" },
["<CR>"] = { "accept", "fallback" },
["<Tab>"] = { "select_next", "fallback" },
["<S-Tab>"] = { "select_prev", "fallback" },
},
sources = {
default = { "lsp", "path", "snippets", "buffer" },
},
fuzzy = {
implementation = "rust",
},
})
-- ============================================================================
-- Treesitter
-- ============================================================================
require("nvim-treesitter").setup({
install_dir = vim.fn.stdpath("data") .. "/site",
})
vim.api.nvim_create_autocmd("FileType", {
group = vim.api.nvim_create_augroup("treesitter_start", { clear = true }),
callback = function(args)
pcall(vim.treesitter.start, args.buf)
end,
})
-- ============================================================================
-- mini.nvim
-- ============================================================================
require("mini.ai").setup()
require("mini.surround").setup()
require("mini.pairs").setup()
require("mini.comment").setup()
require("mini.statusline").setup()
require("mini.tabline").setup()
require("mini.bracketed").setup()
require("mini.icons").setup()
vim.api.nvim_set_hl(0, "MiniTablineCurrent", { link = "Search" })
vim.api.nvim_set_hl(0, "MiniTablineModifiedCurrent", { link = "Search" })
vim.api.nvim_set_hl(0, "MiniTablineModifiedVisible", { link = "DiagnosticWarn" })
vim.api.nvim_set_hl(0, "MiniTablineModifiedHidden", { link = "DiagnosticWarn" })
-- ============================================================================
-- Icons
-- ============================================================================
require("nvim-web-devicons").setup()
-- ============================================================================
-- Todo comments
-- ============================================================================
require("todo-comments").setup()
-- ============================================================================
-- File explorer
-- ============================================================================
require("neo-tree").setup({
close_if_last_window = true,
popup_border_style = "", -- use vim.o.winborder on modern Neovim
enable_git_status = true,
enable_diagnostics = true,
filesystem = {
follow_current_file = {
enabled = true,
},
use_libuv_file_watcher = true,
},
window = {
width = 63,
},
})
vim.keymap.set("n", "<leader>e", "<cmd>Neotree filesystem reveal right toggle<CR>", {
desc = "File explorer",
})
vim.keymap.set("n", "<leader>E", "<cmd>Neotree filesystem reveal current<CR>", {
desc = "File explorer full screen",
})
-- ============================================================================
-- Picker
-- ============================================================================
require("fzf-lua").setup({
{ "fzf-native", "hide" },
actions = {
files = { ["enter"] = require("fzf-lua.actions").file_edit }
},
files = {
formatter = "path.filename_first",
},
oldfiles = {
formatter = "path.filename_first",
},
grep = {
rg_opts = "--column --line-number --no-heading --color=always --smart-case --max-columns=4096",
},
winopts = {
width = 0.56,
height = 0.82,
row = 0.50,
col = 0.50,
preview = {
layout = "horizontal",
horizontal = "right:45%",
},
},
})
vim.keymap.set("n", "<leader>ff", function()
require("fzf-lua").files()
end, { desc = "Find files" })
vim.keymap.set("n", "<leader>fg", function()
require("fzf-lua").live_grep()
end, { desc = "Live grep" })
vim.keymap.set("n", "<leader>fb", function()
require("fzf-lua").buffers()
end, { desc = "Buffers" })
vim.keymap.set("n", "<leader>fh", function()
require("fzf-lua").helptags()
end, { desc = "Help tags" })
vim.keymap.set("n", "<leader>fr", function()
require("fzf-lua").resume()
end, { desc = "Resume picker" })
vim.keymap.set("n", "<leader>fd", function()
require("fzf-lua").diagnostics_document()
end, { desc = "Buffer diagnostics" })
vim.keymap.set("n", "<leader>fD", function()
require("fzf-lua").diagnostics_workspace()
end, { desc = "Workspace diagnostics" })
vim.keymap.set("n", "<leader>fo", function()
require("fzf-lua").oldfiles()
end, { desc = "Recent files" })
vim.keymap.set("n", "<leader>fc", function()
require("fzf-lua").git_status()
end, { desc = "Git status" })
-- ============================================================================
-- Dashboard
-- ============================================================================
require("alpha").setup(require("alpha.themes.theta").config)
-- ============================================================================
-- Git
-- ============================================================================
require("gitsigns").setup()
-- ============================================================================
-- LSP
-- ============================================================================
-- nvim-lspconfig supplies default configs for these.
-- Install the actual language server binaries separately:
-- lua-language-server
-- pyright
-- gopls
vim.lsp.config("lua_ls", {
settings = {
Lua = {
runtime = {
version = "LuaJIT",
},
diagnostics = {
globals = { "vim" },
},
workspace = {
library = vim.api.nvim_get_runtime_file("", true),
},
telemetry = {
enable = false,
},
},
},
})
vim.lsp.enable({
"lua_ls",
"pyright",
"gopls",
"rust_analyzer",
})
vim.api.nvim_create_autocmd("LspAttach", {
group = vim.api.nvim_create_augroup("lsp_attach", { clear = true }),
callback = function(event)
local map = function(lhs, rhs, desc)
vim.keymap.set("n", lhs, rhs, {
buffer = event.buf,
desc = desc,
})
end
-- Navigation
map("gd", vim.lsp.buf.definition, "Go to definition")
map("gD", vim.lsp.buf.declaration, "Go to declaration")
map("gi", vim.lsp.buf.implementation, "Go to implementation")
-- Language / LSP actions
map("<leader>lr", vim.lsp.buf.rename, "LSP rename")
map("<leader>lf", function()
vim.lsp.buf.format({ async = true })
end, "LSP format")
map("<leader>la", vim.lsp.buf.code_action, "LSP code action")
map("<leader>lh", vim.lsp.buf.hover, "LSP hover")
map("<leader>ls", vim.lsp.buf.signature_help, "LSP signature help")
map("<leader>ld", vim.diagnostic.open_float, "Line diagnostics")
map("<leader>lq", vim.diagnostic.setloclist, "Diagnostics to loclist")
end,
})
-- ============================================================================
-- General keymaps
-- ============================================================================
vim.keymap.set("n", "<C-h>", "<cmd>TmuxNavigateLeft<CR>", { silent = true })
vim.keymap.set("n", "<C-j>", "<cmd>TmuxNavigateDown<CR>", { silent = true })
vim.keymap.set("n", "<C-k>", "<cmd>TmuxNavigateUp<CR>", { silent = true })
vim.keymap.set("n", "<C-l>", "<cmd>TmuxNavigateRight<CR>", { silent = true })
vim.keymap.set("n", "<Esc>", "<cmd>nohlsearch<CR>", { desc = "Clear search highlight" })
vim.keymap.set("n", "<S-h>", "<cmd>bprevious<CR>", { desc = "Previous buffer" })
vim.keymap.set("n", "<S-l>", "<cmd>bnext<CR>", { desc = "Next buffer" })
vim.keymap.set("n", "<leader>bd", "<cmd>bdelete<CR>", { desc = "Delete buffer" })
vim.keymap.set("n", "<leader>bD", "<cmd>bdelete!<CR>", { desc = "Force delete buffer" })
vim.keymap.set("n", "<leader>bw", "<cmd>bwipe<CR>", { desc = "Wipe buffers" })
vim.keymap.set("n", "<leader>bW", "<cmd>bwipe!<CR>", { desc = "Force wipe buffers" })
vim.keymap.set("n", "<leader>bl", "<cmd>ls<CR>", { desc = "List buffers" })
vim.keymap.set("n", "<leader>bb", "<cmd>buffer #<CR>", { desc = "Switch to last buffer" })
vim.keymap.set("n", "<leader>bf", "<cmd>bfirst<CR>", { desc = "First buffer" })
vim.keymap.set("n", "<leader>bL", "<cmd>blast<CR>", { desc = "Last buffer" })
vim.keymap.set("n", "[d", function()
vim.diagnostic.jump({ count = -1 })
end, {
desc = "Previous diagnostic",
})
vim.keymap.set("n", "]d", function()
vim.diagnostic.jump({ count = 1 })
end, {
desc = "Next diagnostic",
})
-- ============================================================================
-- Keymap help
-- ============================================================================
require("which-key").setup({
preset = "helix",
})
require("which-key").add({
{ "<leader>e", desc = "File explorer" },
{ "<leader>E", desc = "File explorer full screen" },
{ "<leader>f", group = "find" },
{ "<leader>l", group = "language/lsp" },
{ "<leader>g", group = "git" },
{ "<leader>b", group = "buffer" },
})