Migrate to chezmoi with per-host sway/waybar configs
- Restructure repo into chezmoi source layout (dot_ prefix) - Add .chezmoi.toml.tmpl mapping hostname to hosttype (laptop/desktop) - Template sway config.d fragments (outputs/inputs/binds) per host - Template waybar config.jsonc with shared bar/module definitions - Host-scope pulsemeeter (flow) and teams-for-linux (desktop hosts) via .chezmoiignore - Trim install.sh package lists to configured software + config deps - Remove stale kitty.conf.bak and untracked host fragments
This commit is contained in:
@@ -0,0 +1,143 @@
|
||||
local function augroup(name)
|
||||
return vim.api.nvim_create_augroup("user_" .. name, { clear = true })
|
||||
end
|
||||
|
||||
-- Check if we need to reload the file when it changed
|
||||
vim.api.nvim_create_autocmd({ "FocusGained", "TermClose", "TermLeave" }, {
|
||||
group = augroup("checktime"),
|
||||
callback = function()
|
||||
if vim.o.buftype ~= "nofile" then
|
||||
vim.cmd("checktime")
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
-- Highlight on yank
|
||||
vim.api.nvim_create_autocmd("TextYankPost", {
|
||||
group = augroup("highlight_yank"),
|
||||
callback = function()
|
||||
(vim.hl or vim.highlight).on_yank()
|
||||
end,
|
||||
})
|
||||
|
||||
-- resize splits if window got resized
|
||||
vim.api.nvim_create_autocmd({ "VimResized" }, {
|
||||
group = augroup("resize_splits"),
|
||||
callback = function()
|
||||
local current_tab = vim.fn.tabpagenr()
|
||||
vim.cmd("tabdo wincmd =")
|
||||
vim.cmd("tabnext " .. current_tab)
|
||||
end,
|
||||
})
|
||||
|
||||
|
||||
-- make it easier to close man-files when opened inline
|
||||
vim.api.nvim_create_autocmd("FileType", {
|
||||
group = augroup("man_unlisted"),
|
||||
pattern = { "man" },
|
||||
callback = function(event)
|
||||
vim.bo[event.buf].buflisted = false
|
||||
end,
|
||||
})
|
||||
|
||||
-- close some filetypes with <q>
|
||||
vim.api.nvim_create_autocmd("FileType", {
|
||||
group = augroup("close_with_q"),
|
||||
pattern = {
|
||||
"PlenaryTestPopup",
|
||||
"checkhealth",
|
||||
"dbout",
|
||||
"gitsigns-blame",
|
||||
"grug-far",
|
||||
"help",
|
||||
"lspinfo",
|
||||
"neotest-output",
|
||||
"neotest-output-panel",
|
||||
"neotest-summary",
|
||||
"notify",
|
||||
"qf",
|
||||
"spectre_panel",
|
||||
"startuptime",
|
||||
"tsplayground",
|
||||
},
|
||||
callback = function(event)
|
||||
vim.bo[event.buf].buflisted = false
|
||||
vim.schedule(function()
|
||||
vim.keymap.set("n", "q", function()
|
||||
vim.cmd("close")
|
||||
pcall(vim.api.nvim_buf_delete, event.buf, { force = true })
|
||||
end, {
|
||||
buffer = event.buf,
|
||||
silent = true,
|
||||
desc = "Quit buffer",
|
||||
})
|
||||
end)
|
||||
end,
|
||||
})
|
||||
|
||||
-- wrap and check for spell in text filetypes
|
||||
vim.api.nvim_create_autocmd("FileType", {
|
||||
group = augroup("wrap_spell"),
|
||||
pattern = { "text", "plaintex", "typst", "gitcommit", "markdown" },
|
||||
callback = function()
|
||||
vim.opt_local.wrap = true
|
||||
vim.opt_local.spell = true
|
||||
end,
|
||||
})
|
||||
|
||||
-- Fix conceallevel for json files
|
||||
vim.api.nvim_create_autocmd({ "FileType" }, {
|
||||
group = augroup("json_conceal"),
|
||||
pattern = { "json", "jsonc", "json5" },
|
||||
callback = function()
|
||||
vim.opt_local.conceallevel = 0
|
||||
end,
|
||||
})
|
||||
|
||||
-- Auto create dir when saving a file, in case some intermediate directory does not exist
|
||||
vim.api.nvim_create_autocmd({ "BufWritePre" }, {
|
||||
group = augroup("auto_create_dir"),
|
||||
callback = function(event)
|
||||
if event.match:match("^%w%w+:[/][/]") then
|
||||
return
|
||||
end
|
||||
local file = vim.uv.fs_realpath(event.match) or event.match
|
||||
vim.fn.mkdir(vim.fn.fnamemodify(file, ":p:h"), "p")
|
||||
end,
|
||||
})
|
||||
|
||||
-- Set filetype for .env and .env.* files
|
||||
vim.api.nvim_create_autocmd({ "BufRead", "BufNewFile" }, {
|
||||
group = augroup("env_filetype"),
|
||||
pattern = { "*.env", ".env.*" },
|
||||
callback = function()
|
||||
vim.opt_local.filetype = "sh"
|
||||
end,
|
||||
})
|
||||
|
||||
-- Set filetype for .toml files
|
||||
vim.api.nvim_create_autocmd({ "BufRead", "BufNewFile" }, {
|
||||
group = augroup("toml_filetype"),
|
||||
pattern = { "*.tomg-config*" },
|
||||
callback = function()
|
||||
vim.opt_local.filetype = "toml"
|
||||
end,
|
||||
})
|
||||
|
||||
-- Set filetype for .ejs files
|
||||
vim.api.nvim_create_autocmd({ "BufRead", "BufNewFile" }, {
|
||||
group = augroup("ejs_filetype"),
|
||||
pattern = { "*.ejs", "*.ejs.t" },
|
||||
callback = function()
|
||||
vim.opt_local.filetype = "embedded_template"
|
||||
end,
|
||||
})
|
||||
|
||||
-- Set filetype for .code-snippets files
|
||||
vim.api.nvim_create_autocmd({ "BufRead", "BufNewFile" }, {
|
||||
group = augroup("code_snippets_filetype"),
|
||||
pattern = { "*.code-snippets" },
|
||||
callback = function()
|
||||
vim.opt_local.filetype = "json"
|
||||
end,
|
||||
})
|
||||
@@ -0,0 +1,72 @@
|
||||
--- diagnostic settings
|
||||
local map = vim.keymap.set
|
||||
|
||||
local palette = {
|
||||
err = "#51202A",
|
||||
warn = "#3B3B1B",
|
||||
info = "#1F3342",
|
||||
hint = "#1E2E1E",
|
||||
}
|
||||
|
||||
vim.api.nvim_set_hl(0, "DiagnosticErrorLine", { bg = palette.err, blend = 20 })
|
||||
vim.api.nvim_set_hl(0, "DiagnosticWarnLine", { bg = palette.warn, blend = 15 })
|
||||
vim.api.nvim_set_hl(0, "DiagnosticInfoLine", { bg = palette.info, blend = 10 })
|
||||
vim.api.nvim_set_hl(0, "DiagnosticHintLine", { bg = palette.hint, blend = 10 })
|
||||
|
||||
vim.api.nvim_set_hl(0, "DapBreakpointSign", { fg = "#FF0000", bg = nil, bold = true })
|
||||
vim.fn.sign_define("DapBreakpoint", {
|
||||
text = "●", -- a large dot; change as desired
|
||||
texthl = "DapBreakpointSign", -- the highlight group you just defined
|
||||
linehl = "", -- no full-line highlight
|
||||
numhl = "", -- no number-column highlight
|
||||
})
|
||||
|
||||
local sev = vim.diagnostic.severity
|
||||
|
||||
vim.diagnostic.config({
|
||||
-- keep underline & severity_sort on for quick scanning
|
||||
underline = true,
|
||||
severity_sort = true,
|
||||
update_in_insert = false, -- less flicker
|
||||
float = {
|
||||
border = "rounded",
|
||||
source = true,
|
||||
},
|
||||
-- keep signs & virtual text, but tune them as you like
|
||||
signs = {
|
||||
text = {
|
||||
[sev.ERROR] = " ",
|
||||
[sev.WARN] = " ",
|
||||
[sev.INFO] = " ",
|
||||
[sev.HINT] = " ",
|
||||
},
|
||||
},
|
||||
virtual_text = {
|
||||
spacing = 4,
|
||||
source = "if_many",
|
||||
prefix = "●",
|
||||
},
|
||||
-- NEW in 0.11 — dim whole line
|
||||
linehl = {
|
||||
[sev.ERROR] = "DiagnosticErrorLine",
|
||||
[sev.WARN] = "DiagnosticWarnLine",
|
||||
[sev.INFO] = "DiagnosticInfoLine",
|
||||
[sev.HINT] = "DiagnosticHintLine",
|
||||
},
|
||||
})
|
||||
|
||||
-- diagnostic keymaps
|
||||
local diagnostic_goto = function(next, severity)
|
||||
severity = severity and vim.diagnostic.severity[severity] or nil
|
||||
return function()
|
||||
vim.diagnostic.jump({ count = next and 1 or -1, float = true, severity = severity })
|
||||
end
|
||||
end
|
||||
|
||||
map("n", "<leader>cd", vim.diagnostic.open_float, { desc = "Line Diagnostics" })
|
||||
map("n", "]d", diagnostic_goto(true), { desc = "Next Diagnostic" })
|
||||
map("n", "[d", diagnostic_goto(false), { desc = "Prev Diagnostic" })
|
||||
map("n", "]e", diagnostic_goto(true, "ERROR"), { desc = "Next Error" })
|
||||
map("n", "[e", diagnostic_goto(false, "ERROR"), { desc = "Prev Error" })
|
||||
map("n", "]w", diagnostic_goto(true, "WARN"), { desc = "Next Warning" })
|
||||
map("n", "[w", diagnostic_goto(false, "WARN"), { desc = "Prev Warning" })
|
||||
@@ -0,0 +1,5 @@
|
||||
require("config.options")
|
||||
require("config.keymaps")
|
||||
require("config.diagnostics")
|
||||
require("config.autocmds")
|
||||
require("config.lsp")
|
||||
@@ -0,0 +1,222 @@
|
||||
local map = vim.keymap.set
|
||||
local opts = { noremap = true, silent = true }
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
-- BUFFER NAVIGATION (think browser tabs)
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
|
||||
-- Tab/Shift-Tab: Like browser tabs, feels natural
|
||||
map("n", "<Tab>", ":bnext<CR>", { desc = "Next buffer" })
|
||||
map("n", "<S-Tab>", ":bprevious<CR>", { desc = "Previous buffer" })
|
||||
|
||||
-- Alternative buffer switching (vim-style)
|
||||
map("n", "<leader>bn", ":bnext<CR>", { desc = "Next buffer" })
|
||||
map("n", "<leader>bp", ":bprevious<CR>", { desc = "Previous buffer" })
|
||||
map("n", "<S-h>", "<cmd>bprevious<cr>", { desc = "Prev Buffer" })
|
||||
map("n", "<S-l>", "<cmd>bnext<cr>", { desc = "Next Buffer" })
|
||||
map("n", "[b", "<cmd>bprevious<cr>", { desc = "Prev Buffer" })
|
||||
map("n", "]b", "<cmd>bnext<cr>", { desc = "Next Buffer" })
|
||||
|
||||
-- Quick switch to last edited file (super useful!)
|
||||
map("n", "<leader>bb", "<cmd>e #<cr>", { desc = "Switch to Other Buffer" })
|
||||
map("n", "<leader>`", "<cmd>e #<cr>", { desc = "Switch to Other Buffer" })
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
-- WINDOW MANAGEMENT (splitting and navigation)
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
|
||||
-- Move between windows with Ctrl+hjkl (like tmux)
|
||||
map("n", "<C-h>", "<C-w>h", { desc = "Go to Left Window", remap = true })
|
||||
map("n", "<C-j>", "<C-w>j", { desc = "Go to Lower Window", remap = true })
|
||||
map("n", "<C-k>", "<C-w>k", { desc = "Go to Upper Window", remap = true })
|
||||
map("n", "<C-l>", "<C-w>l", { desc = "Go to Right Window", remap = true })
|
||||
|
||||
-- Resize windows with Ctrl+Shift+arrows (macOS friendly)
|
||||
map("n", "<C-S-Up>", "<cmd>resize +5<CR>", opts)
|
||||
map("n", "<C-S-Down>", "<cmd>resize -5<CR>", opts)
|
||||
map("n", "<C-S-Left>", "<cmd>vertical resize -5<CR>", opts)
|
||||
map("n", "<C-S-Right>", "<cmd>vertical resize +5<CR>", opts)
|
||||
|
||||
-- Window splitting
|
||||
map("n", "<leader>ww", "<C-W>p", { desc = "Other Window", remap = true })
|
||||
map("n", "<leader>wd", "<C-W>c", { desc = "Delete Window", remap = true })
|
||||
map("n", "<leader>w-", "<C-W>s", { desc = "Split Window Below", remap = true })
|
||||
map("n", "<leader>sh", "<C-W>s", { desc = "Split Window Below", remap = true })
|
||||
map("n", "<leader>w|", "<C-W>v", { desc = "Split Window Right", remap = true })
|
||||
map("n", "<leader>|", "<C-W>v", { desc = "Split Window Right", remap = true })
|
||||
map("n", "<leader>sv", "<C-W>v", { desc = "Split Window Right", remap = true })
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
-- SMART LINE MOVEMENT (the VSCode experience)
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
|
||||
-- Smart j/k: moves by visual lines when no count, real lines with count
|
||||
map({ "n", "x" }, "j", "v:count == 0 ? 'gj' : 'j'", { desc = "Down", expr = true, silent = true })
|
||||
map({ "n", "x" }, "<Down>", "v:count == 0 ? 'gj' : 'j'", { desc = "Down", expr = true, silent = true })
|
||||
map({ "n", "x" }, "k", "v:count == 0 ? 'gk' : 'k'", { desc = "Up", expr = true, silent = true })
|
||||
map({ "n", "x" }, "<Up>", "v:count == 0 ? 'gk' : 'k'", { desc = "Up", expr = true, silent = true })
|
||||
|
||||
-- Move lines up/down (Alt+j/k like VSCode)
|
||||
map("n", "<A-j>", "<cmd>execute 'move .+' . v:count1<cr>==", { desc = "Move Down" })
|
||||
map("n", "<A-k>", "<cmd>execute 'move .-' . (v:count1 + 1)<cr>==", { desc = "Move Up" })
|
||||
map("i", "<A-j>", "<esc><cmd>m .+1<cr>==gi", { desc = "Move Down" })
|
||||
map("i", "<A-k>", "<esc><cmd>m .-2<cr>==gi", { desc = "Move Up" })
|
||||
map("v", "<A-j>", ":<C-u>execute \"'<,'>move '>+\" . v:count1<cr>gv=gv", { desc = "Move Down" })
|
||||
map("v", "<A-k>", ":<C-u>execute \"'<,'>move '<-\" . (v:count1 + 1)<cr>gv=gv", { desc = "Move Up" })
|
||||
|
||||
-- Alternative line movement (for terminals that don't support Alt)
|
||||
map("v", "J", ":move '>+1<CR>gv=gv", { desc = "Move Block Down" })
|
||||
map("v", "K", ":move '<-2<CR>gv=gv", { desc = "Move Block Up" })
|
||||
map("n", "<A-Down>", ":m .+1<CR>", opts)
|
||||
map("n", "<A-Up>", ":m .-2<CR>", opts)
|
||||
map("i", "<A-Down>", "<Esc>:m .+1<CR>==gi", opts)
|
||||
map("i", "<A-Up>", "<Esc>:m .-2<CR>==gi", opts)
|
||||
map("v", "<A-Down>", ":m '>+1<CR>gv=gv", opts)
|
||||
map("v", "<A-Up>", ":m '<-2<CR>gv=gv", opts)
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
-- SEARCH & NAVIGATION (ergonomic improvements)
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
|
||||
-- Better line start/end (more comfortable than $ and ^)
|
||||
map("n", "gl", "$", { desc = "Go to end of line" })
|
||||
map("n", "gh", "^", { desc = "Go to start of line" })
|
||||
map("n", "<A-h>", "^", { desc = "Go to start of line", silent = true })
|
||||
map("n", "<A-l>", "$", { desc = "Go to end of line", silent = true })
|
||||
|
||||
-- Select all content
|
||||
map("n", "==", "gg<S-v>G")
|
||||
map("n", "<A-a>", "ggVG", { noremap = true, silent = true, desc = "Select all" })
|
||||
|
||||
-- Clear search highlighting
|
||||
map({ "i", "n" }, "<esc>", "<cmd>noh<cr><esc>", { desc = "Escape and Clear hlsearch" })
|
||||
map("n", "<leader>ur", "<Cmd>nohlsearch<Bar>diffupdate<Bar>normal! <C-L><CR>", { desc = "Redraw / Clear hlsearch / Diff Update" })
|
||||
|
||||
-- Smart search navigation (n always goes forward, N always backward)
|
||||
map("n", "n", "'Nn'[v:searchforward].'zv'", { expr = true, desc = "Next Search Result" })
|
||||
map("x", "n", "'Nn'[v:searchforward]", { expr = true, desc = "Next Search Result" })
|
||||
map("o", "n", "'Nn'[v:searchforward]", { expr = true, desc = "Next Search Result" })
|
||||
map("n", "N", "'nN'[v:searchforward].'zv'", { expr = true, desc = "Prev Search Result" })
|
||||
map("x", "N", "'nN'[v:searchforward]", { expr = true, desc = "Prev Search Result" })
|
||||
map("o", "N", "'nN'[v:searchforward]", { expr = true, desc = "Prev Search Result" })
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
-- SMART TEXT EDITING
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
|
||||
-- Better indenting (stay in visual mode)
|
||||
map("v", "<", "<gv")
|
||||
map("v", ">", ">gv")
|
||||
|
||||
-- Better paste (doesn't replace clipboard with deleted text)
|
||||
map("v", "p", '"_dP', opts)
|
||||
|
||||
-- Copy whole file to clipboard
|
||||
map("n", "<C-c>", ":%y+<CR>", opts)
|
||||
|
||||
-- Smart undo break-points (create undo points at logical stops)
|
||||
map("i", ",", ",<c-g>u")
|
||||
map("i", ".", ".<c-g>u")
|
||||
map("i", ";", ";<c-g>u")
|
||||
|
||||
-- Auto-close pairs (simple, no plugin needed)
|
||||
map("i", "`", "``<left>")
|
||||
map("i", '"', '""<left>')
|
||||
map("i", "(", "()<left>")
|
||||
map("i", "[", "[]<left>")
|
||||
map("i", "{", "{}<left>")
|
||||
map("i", "<", "<><left>")
|
||||
-- Note: Single quotes commented out to avoid conflicts in some contexts
|
||||
-- map("i", "'", "''<left>")
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
-- FILE OPERATIONS
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
|
||||
-- Save file (works in all modes)
|
||||
map({ "i", "x", "n", "s" }, "<C-s>", "<cmd>w<cr><esc>", { desc = "Save File" })
|
||||
|
||||
-- Create new file
|
||||
map("n", "<leader>fn", "<cmd>enew<cr>", { desc = "New File" })
|
||||
|
||||
-- Quit operations
|
||||
map("n", "<leader>qq", "<cmd>qa<cr>", { desc = "Quit All" })
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
-- DEVELOPMENT TOOLS
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
|
||||
-- Commenting (add comment above/below current line)
|
||||
map("n", "gco", "o<esc>Vcx<esc><cmd>normal gcc<cr>fxa<bs>", { desc = "Add Comment Below" })
|
||||
map("n", "gcO", "O<esc>Vcx<esc><cmd>normal gcc<cr>fxa<bs>", { desc = "Add Comment Above" })
|
||||
|
||||
-- Quickfix and location lists
|
||||
map("n", "<leader>xl", function()
|
||||
local success, err = pcall(vim.fn.getloclist(0, { winid = 0 }).winid ~= 0 and vim.cmd.lclose or vim.cmd.lopen)
|
||||
if not success and err then
|
||||
vim.notify(err, vim.log.levels.ERROR)
|
||||
end
|
||||
end, { desc = "Location List" })
|
||||
|
||||
map("n", "<leader>xq", function()
|
||||
local success, err = pcall(vim.fn.getqflist({ winid = 0 }).winid ~= 0 and vim.cmd.cclose or vim.cmd.copen)
|
||||
if not success and err then
|
||||
vim.notify(err, vim.log.levels.ERROR)
|
||||
end
|
||||
end, { desc = "Quickfix List" })
|
||||
|
||||
map("n", "[q", vim.cmd.cprev, { desc = "Previous Quickfix" })
|
||||
map("n", "]q", vim.cmd.cnext, { desc = "Next Quickfix" })
|
||||
|
||||
-- Inspection tools (useful for debugging highlights and treesitter)
|
||||
map("n", "<leader>ui", vim.show_pos, { desc = "Inspect Pos" })
|
||||
map("n", "<leader>uI", "<cmd>InspectTree<cr>", { desc = "Inspect Tree" })
|
||||
|
||||
-- Keyword program (K for help on word under cursor)
|
||||
map("n", "<leader>K", "<cmd>norm! K<cr>", { desc = "Keywordprg" })
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
-- TERMINAL INTEGRATION
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
|
||||
-- Terminal mode navigation
|
||||
map("t", "<esc><esc>", "<c-\\><c-n>", { desc = "Enter Normal Mode" })
|
||||
map("t", "<C-h>", "<cmd>wincmd h<cr>", { desc = "Go to Left Window" })
|
||||
map("t", "<C-j>", "<cmd>wincmd j<cr>", { desc = "Go to Lower Window" })
|
||||
map("t", "<C-k>", "<cmd>wincmd k<cr>", { desc = "Go to Upper Window" })
|
||||
map("t", "<C-l>", "<cmd>wincmd l<cr>", { desc = "Go to Right Window" })
|
||||
map("t", "<C-/>", "<cmd>close<cr>", { desc = "Hide Terminal" })
|
||||
map("t", "<c-_>", "<cmd>close<cr>", { desc = "which_key_ignore" })
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
-- TAB MANAGEMENT (when you need multiple workspaces)
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
|
||||
map("n", "<leader><tab>l", "<cmd>tablast<cr>", { desc = "Last Tab" })
|
||||
map("n", "<leader><tab>o", "<cmd>tabonly<cr>", { desc = "Close Other Tabs" })
|
||||
map("n", "<leader><tab>f", "<cmd>tabfirst<cr>", { desc = "First Tab" })
|
||||
map("n", "<leader><tab><tab>", "<cmd>tabnew<cr>", { desc = "New Tab" })
|
||||
map("n", "<leader><tab>]", "<cmd>tabnext<cr>", { desc = "Next Tab" })
|
||||
map("n", "<leader><tab>d", "<cmd>tabclose<cr>", { desc = "Close Tab" })
|
||||
map("n", "<leader><tab>[", "<cmd>tabprevious<cr>", { desc = "Previous Tab" })
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
-- FOLDING NAVIGATION (for code organization)
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
|
||||
-- Close all folds except current one (great for focus)
|
||||
map("n", "zv", "zMzvzz", { desc = "Close all folds except the current one" })
|
||||
|
||||
-- Smart fold navigation (closes current, opens next/previous)
|
||||
map("n", "zj", "zcjzOzz", { desc = "Close current fold when open. Always open next fold." })
|
||||
map("n", "zk", "zckzOzz", { desc = "Close current fold when open. Always open previous fold." })
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
-- UTILITY SHORTCUTS
|
||||
-- ═══════════════════════════════════════════════════════════
|
||||
|
||||
-- Toggle line wrapping
|
||||
map("n", "<leader>tw", "<cmd>set wrap!<CR>", { desc = "Toggle Wrap", silent = true })
|
||||
|
||||
-- Fix spelling (picks first suggestion)
|
||||
map("n", "z0", "1z=", { desc = "Fix word under cursor" })
|
||||
@@ -0,0 +1,62 @@
|
||||
-- LSP
|
||||
local function augroup(name)
|
||||
return vim.api.nvim_create_augroup("user_" .. name, { clear = true })
|
||||
end
|
||||
|
||||
local default_keymaps = {
|
||||
{ keys = "<leader>ca", func = vim.lsp.buf.code_action, desc = "Code Actions" },
|
||||
{ keys = "<leader>cr", func = vim.lsp.buf.rename, desc = "Code Rename" },
|
||||
{ keys = "<leader>k", func = vim.lsp.buf.hover, desc = "Hover Documentation", has = "hoverProvider" },
|
||||
{ keys = "K", func = vim.lsp.buf.hover, desc = "Hover (alt)", has = "hoverProvider" },
|
||||
{ keys = "gd", func = vim.lsp.buf.definition, desc = "Goto Definition", has = "definitionProvider" },
|
||||
}
|
||||
|
||||
-- I use blink.cmp for completion, but you can use native completion too
|
||||
local completion = vim.g.completion_mode or "blink" -- or 'native' for built-in completion
|
||||
vim.api.nvim_create_autocmd("LspAttach", {
|
||||
group = augroup("lsp_attach"),
|
||||
callback = function(args)
|
||||
local client = vim.lsp.get_client_by_id(args.data.client_id)
|
||||
local buf = args.buf
|
||||
if client then
|
||||
-- Built-in completion
|
||||
if completion == "native" and client:supports_method("textDocument/completion") then
|
||||
vim.lsp.completion.enable(true, client.id, args.buf, { autotrigger = true })
|
||||
end
|
||||
|
||||
-- Inlay hints
|
||||
if client:supports_method("textDocument/inlayHints") then
|
||||
vim.lsp.inlay_hint.enable(true, { bufnr = args.buf })
|
||||
end
|
||||
|
||||
if client:supports_method("textDocument/documentColor") then
|
||||
vim.lsp.document_color.enable(true, args.buf, {
|
||||
style = "background", -- 'background', 'foreground', or 'virtual'
|
||||
})
|
||||
end
|
||||
|
||||
for _, km in ipairs(default_keymaps) do
|
||||
-- Only bind if there's no `has` requirement, or the server supports it
|
||||
if not km.has or client.server_capabilities[km.has] then
|
||||
vim.keymap.set(
|
||||
km.mode or "n",
|
||||
km.keys,
|
||||
km.func,
|
||||
{ buffer = buf, desc = "LSP: " .. km.desc, nowait = km.nowait }
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
-- Enable LSP servers for Neovim 0.11+
|
||||
vim.lsp.enable({
|
||||
"lua_ls",
|
||||
})
|
||||
|
||||
-- Load Lsp on-demand, e.g: eslint is disable by default
|
||||
-- e.g: We could enable eslint by set vim.g.lsp_on_demands = {"eslint"}
|
||||
if vim.g.lsp_on_demands then
|
||||
vim.lsp.enable(vim.g.lsp_on_demands)
|
||||
end
|
||||
@@ -0,0 +1,137 @@
|
||||
local opt = vim.opt
|
||||
|
||||
opt.number = true -- Line numbers
|
||||
opt.relativenumber = true -- Relative line numbers
|
||||
opt.cursorline = true -- Highlight current line
|
||||
opt.wrap = false -- Don't wrap lines
|
||||
opt.scrolloff = 10 -- Keep 10 lines above/below cursor
|
||||
opt.sidescrolloff = 8 -- Keep 8 columns left/right of cursor
|
||||
|
||||
-- Indentation
|
||||
opt.tabstop = 2 -- Tab width
|
||||
opt.shiftwidth = 2 -- Indent width
|
||||
opt.softtabstop = 2 -- Soft tab stop
|
||||
opt.expandtab = true -- Use spaces instead of tabs
|
||||
opt.smartindent = true -- Smart auto-indenting
|
||||
opt.autoindent = true -- Copy indent from current line
|
||||
|
||||
-- Search settings
|
||||
opt.ignorecase = true -- Case insensitive search
|
||||
opt.smartcase = true -- Case sensitive if uppercase in search
|
||||
opt.hlsearch = false -- Don't highlight search results
|
||||
opt.incsearch = true -- Show matches as you type
|
||||
|
||||
-- Visual settings
|
||||
opt.termguicolors = true -- Enable 24-bit colors
|
||||
opt.signcolumn = "yes" -- Always show sign column
|
||||
opt.showmatch = true -- Highlight matching brackets
|
||||
opt.matchtime = 2 -- How long to show matching bracket
|
||||
opt.cmdheight = 1 -- Command line height
|
||||
opt.showmode = false -- Don't show mode in command line
|
||||
opt.pumheight = 10 -- Popup menu height
|
||||
opt.pumblend = 10 -- Popup menu transparency
|
||||
opt.winblend = 0 -- Floating window transparency
|
||||
opt.completeopt = "menu,menuone,noselect"
|
||||
opt.conceallevel = 2 -- Hide * markup for bold and italic, but not markers with substitutions
|
||||
opt.confirm = true -- Confirm to save changes before exiting modified buffer
|
||||
opt.concealcursor = "" -- Don't hide cursor line markup
|
||||
opt.synmaxcol = 300 -- Syntax highlighting limit
|
||||
opt.ruler = false -- Disable the default ruler
|
||||
opt.virtualedit = "block" -- Allow cursor to move where there is no text in visual block mode
|
||||
opt.winminwidth = 5 -- Minimum window width
|
||||
|
||||
-- File handling
|
||||
opt.backup = false -- Don't create backup files
|
||||
opt.writebackup = false -- Don't create backup before writing
|
||||
opt.swapfile = false -- Don't create swap files
|
||||
opt.undofile = true -- Persistent undo
|
||||
opt.undolevels = 10000
|
||||
opt.undodir = vim.fn.expand("~/.vim/undodir") -- Undo directory
|
||||
opt.updatetime = 300 -- Faster completion
|
||||
opt.timeoutlen = vim.g.vscode and 1000 or 300 -- Lower than default (1000) to quickly trigger which-key
|
||||
opt.ttimeoutlen = 0 -- Key code timeout
|
||||
opt.autoread = true -- Auto reload files changed outside vim
|
||||
opt.autowrite = true -- Auto save
|
||||
|
||||
-- Behavior settings
|
||||
opt.hidden = true -- Allow hidden buffers
|
||||
opt.errorbells = false -- No error bells
|
||||
opt.backspace = "indent,eol,start" -- Better backspace behavior
|
||||
opt.autochdir = false -- Don't auto change directory
|
||||
opt.iskeyword:append("-") -- Treat dash as part of word
|
||||
opt.path:append("**") -- include subdirectories in search
|
||||
opt.selection = "exclusive" -- Selection behavior
|
||||
opt.mouse = "a" -- Enable mouse support
|
||||
opt.clipboard = vim.env.SSH_TTY and "" or "unnamedplus" -- Sync with system clipboard
|
||||
opt.modifiable = true -- Allow buffer modifications
|
||||
opt.encoding = "UTF-8" -- Set encoding
|
||||
|
||||
-- Folding settings
|
||||
opt.smoothscroll = true
|
||||
vim.wo.foldmethod = "expr"
|
||||
opt.foldlevel = 99 -- Start with all folds open
|
||||
opt.formatoptions = "jcroqlnt" -- tcqj
|
||||
opt.grepformat = "%f:%l:%c:%m"
|
||||
opt.grepprg = "rg --vimgrep"
|
||||
|
||||
-- Split behavior
|
||||
opt.splitbelow = true -- Horizontal splits go below
|
||||
opt.splitright = true -- Vertical splits go right
|
||||
opt.splitkeep = "screen"
|
||||
|
||||
-- Command-line completion
|
||||
opt.wildmenu = true
|
||||
opt.wildmode = "longest:full,full"
|
||||
opt.wildignore:append({ "*.o", "*.obj", "*.pyc", "*.class", "*.jar" })
|
||||
|
||||
-- Better diff options
|
||||
opt.diffopt:append("linematch:60")
|
||||
|
||||
-- Performance improvements
|
||||
opt.redrawtime = 10000
|
||||
opt.maxmempattern = 20000
|
||||
|
||||
-- Create undo directory if it doesn't exist
|
||||
local undodir = vim.fn.expand("~/.vim/undodir")
|
||||
if vim.fn.isdirectory(undodir) == 0 then
|
||||
vim.fn.mkdir(undodir, "p")
|
||||
end
|
||||
|
||||
vim.g.autoformat = true
|
||||
vim.g.trouble_lualine = true
|
||||
|
||||
--[[
|
||||
opt.fillchars = {
|
||||
foldopen = "",
|
||||
foldclose = "",
|
||||
fold = " ",
|
||||
foldsep = " ",
|
||||
diff = "╱",
|
||||
eob = " ",
|
||||
}
|
||||
]]
|
||||
|
||||
opt.jumpoptions = "view"
|
||||
opt.laststatus = 3 -- global statusline
|
||||
opt.list = false
|
||||
opt.linebreak = true -- Wrap lines at convenient points
|
||||
opt.list = true -- Show some invisible characters (tabs...
|
||||
opt.shiftround = true -- Round indent
|
||||
opt.shiftwidth = 2 -- Size of an indent
|
||||
opt.shortmess:append({ W = true, I = true, c = true, C = true })
|
||||
|
||||
vim.g.markdown_recommended_style = 0
|
||||
|
||||
vim.filetype.add({
|
||||
extension = {
|
||||
env = "dotenv",
|
||||
},
|
||||
filename = {
|
||||
[".env"] = "dotenv",
|
||||
["env"] = "dotenv",
|
||||
},
|
||||
pattern = {
|
||||
["[jt]sconfig.*.json"] = "jsonc",
|
||||
["%.env%.[%w_.-]+"] = "dotenv",
|
||||
},
|
||||
})
|
||||
@@ -0,0 +1,21 @@
|
||||
return {
|
||||
"saghen/blink.cmp",
|
||||
version = "^1",
|
||||
event = "InsertEnter", -- Lazy's native equivalent of the manual InsertEnter augroup
|
||||
config = function()
|
||||
require("blink.cmp").setup({
|
||||
keymap = { preset = "super-tab" },
|
||||
appearance = {
|
||||
nerd_font_variant = "mono",
|
||||
use_nvim_cmp_as_default = true,
|
||||
},
|
||||
completion = {
|
||||
documentation = { auto_show = false },
|
||||
},
|
||||
sources = {
|
||||
default = { "lsp", "path", "snippets", "buffer" },
|
||||
},
|
||||
fuzzy = { implementation = "prefer_rust_with_warning" },
|
||||
})
|
||||
end,
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
return {
|
||||
"stevearc/conform.nvim",
|
||||
config = function()
|
||||
require("conform").setup({
|
||||
formatters_by_ft = {
|
||||
lua = { "stylua" },
|
||||
go = { "goimports", "gofmt" },
|
||||
python = { "ruff_format", "black", stop_after_first = true },
|
||||
json = { "biome", "prettier", stop_after_first = true },
|
||||
markdown = { "prettier" },
|
||||
javascript = { "biome", "prettier", stop_after_first = true },
|
||||
typescript = { "biome", "prettier", stop_after_first = true },
|
||||
javascriptreact = { "biome", "prettier", stop_after_first = true },
|
||||
typescriptreact = { "biome", "prettier", stop_after_first = true },
|
||||
css = { "prettier" },
|
||||
html = { "prettier" },
|
||||
toml = { "taplo" },
|
||||
},
|
||||
formatters = {
|
||||
biome = { require_cwd = true },
|
||||
},
|
||||
default_format_opts = {
|
||||
lsp_format = "fallback",
|
||||
},
|
||||
})
|
||||
|
||||
vim.api.nvim_create_user_command("FormatDisable", function(opts)
|
||||
if opts.bang then
|
||||
vim.b.disable_autoformat = true
|
||||
else
|
||||
vim.g.disable_autoformat = true
|
||||
end
|
||||
vim.notify("Autoformat disabled" .. (opts.bang and " (buffer)" or " (global)"), vim.log.levels.WARN)
|
||||
end, { desc = "Disable autoformat-on-save", bang = true })
|
||||
|
||||
vim.api.nvim_create_user_command("FormatEnable", function()
|
||||
vim.b.disable_autoformat = false
|
||||
vim.g.disable_autoformat = false
|
||||
vim.notify("Autoformat enabled", vim.log.levels.INFO)
|
||||
end, { desc = "Re-enable autoformat-on-save" })
|
||||
|
||||
local auto_format = true
|
||||
|
||||
vim.keymap.set("n", "<leader>uf", function()
|
||||
auto_format = not auto_format
|
||||
if auto_format then
|
||||
vim.cmd("FormatEnable")
|
||||
else
|
||||
vim.cmd("FormatDisable")
|
||||
end
|
||||
end, { desc = "Toggle Autoformat" })
|
||||
|
||||
vim.keymap.set({ "n", "v" }, "<leader>cn", "<cmd>ConformInfo<cr>", { desc = "Conform Info" })
|
||||
|
||||
vim.keymap.set({ "n", "v" }, "<leader>cf", function()
|
||||
require("conform").format({ async = true }, function(err, did_edit)
|
||||
if not err and did_edit then
|
||||
vim.notify("Code formatted", vim.log.levels.INFO, { title = "Conform" })
|
||||
end
|
||||
end)
|
||||
end, { desc = "Format buffer" })
|
||||
|
||||
vim.keymap.set({ "n", "v" }, "<leader>cF", function()
|
||||
require("conform").format({ formatters = { "injected" }, timeout_ms = 3000 })
|
||||
end, { desc = "Format Injected Langs" })
|
||||
end,
|
||||
}
|
||||
@@ -0,0 +1,289 @@
|
||||
return {
|
||||
{
|
||||
"lewis6991/gitsigns.nvim",
|
||||
config = function()
|
||||
require("gitsigns").setup({
|
||||
signs = {
|
||||
add = { text = "┃" },
|
||||
change = { text = "┃" },
|
||||
delete = { text = "_" },
|
||||
topdelete = { text = "‾" },
|
||||
changedelete = { text = "~" },
|
||||
untracked = { text = "┆" },
|
||||
},
|
||||
signs_staged = {
|
||||
add = { text = "┃" },
|
||||
change = { text = "┃" },
|
||||
delete = { text = "_" },
|
||||
topdelete = { text = "‾" },
|
||||
changedelete = { text = "~" },
|
||||
untracked = { text = "┆" },
|
||||
},
|
||||
signs_staged_enable = true,
|
||||
signcolumn = true,
|
||||
numhl = false,
|
||||
linehl = false,
|
||||
word_diff = false,
|
||||
watch_gitdir = { follow_files = true },
|
||||
auto_attach = true,
|
||||
attach_to_untracked = false,
|
||||
current_line_blame = false,
|
||||
current_line_blame_opts = {
|
||||
virt_text = true,
|
||||
virt_text_pos = "eol",
|
||||
delay = 1000,
|
||||
ignore_whitespace = false,
|
||||
virt_text_priority = 100,
|
||||
use_focus = true,
|
||||
},
|
||||
current_line_blame_formatter = "<author>, <author_time:%R> - <summary>",
|
||||
sign_priority = 6,
|
||||
update_debounce = 100,
|
||||
status_formatter = nil,
|
||||
max_file_length = 40000,
|
||||
preview_config = {
|
||||
style = "minimal",
|
||||
relative = "cursor",
|
||||
row = 0,
|
||||
col = 1,
|
||||
},
|
||||
on_attach = function(bufnr)
|
||||
local gitsigns = require("gitsigns")
|
||||
|
||||
local function map(mode, l, r, opts)
|
||||
opts = opts or {}
|
||||
opts.buffer = bufnr
|
||||
vim.keymap.set(mode, l, r, opts)
|
||||
end
|
||||
|
||||
-- Navigation
|
||||
map("n", "]c", function()
|
||||
if vim.wo.diff then vim.cmd.normal({ "]c", bang = true })
|
||||
else gitsigns.nav_hunk("next") end
|
||||
end)
|
||||
map("n", "[c", function()
|
||||
if vim.wo.diff then vim.cmd.normal({ "[c", bang = true })
|
||||
else gitsigns.nav_hunk("prev") end
|
||||
end)
|
||||
|
||||
-- Actions
|
||||
map("n", "<leader>hs", gitsigns.stage_hunk)
|
||||
map("n", "<leader>hr", gitsigns.reset_hunk)
|
||||
map("v", "<leader>hs", function() gitsigns.stage_hunk({ vim.fn.line("."), vim.fn.line("v") }) end)
|
||||
map("v", "<leader>hr", function() gitsigns.reset_hunk({ vim.fn.line("."), vim.fn.line("v") }) end)
|
||||
map("n", "<leader>hS", gitsigns.stage_buffer)
|
||||
map("n", "<leader>hR", gitsigns.reset_buffer)
|
||||
map("n", "<leader>hp", gitsigns.preview_hunk)
|
||||
map("n", "<leader>hi", gitsigns.preview_hunk_inline)
|
||||
map("n", "<leader>hb", function() gitsigns.blame_line({ full = true }) end)
|
||||
map("n", "<leader>hd", gitsigns.diffthis)
|
||||
map("n", "<leader>hD", function() gitsigns.diffthis("~") end)
|
||||
map("n", "<leader>hQ", function() gitsigns.setqflist("all") end)
|
||||
map("n", "<leader>hq", gitsigns.setqflist)
|
||||
|
||||
-- Toggles
|
||||
map("n", "<leader>tb", gitsigns.toggle_current_line_blame)
|
||||
map("n", "<leader>tw", gitsigns.toggle_word_diff)
|
||||
|
||||
-- Text object
|
||||
map({ "o", "x" }, "ih", gitsigns.select_hunk)
|
||||
end,
|
||||
})
|
||||
end,
|
||||
},
|
||||
{
|
||||
"sindrets/diffview.nvim",
|
||||
dependencies = { "nvim-lua/plenary.nvim" },
|
||||
config = function()
|
||||
local actions = require("diffview.actions")
|
||||
|
||||
require("diffview").setup({
|
||||
diff_binaries = false,
|
||||
enhanced_diff_hl = false,
|
||||
git_cmd = { "git" },
|
||||
hg_cmd = { "hg" },
|
||||
use_icons = true,
|
||||
show_help_hints = true,
|
||||
watch_index = true,
|
||||
icons = {
|
||||
folder_closed = "",
|
||||
folder_open = "",
|
||||
},
|
||||
signs = {
|
||||
fold_closed = "",
|
||||
fold_open = "",
|
||||
done = "✓",
|
||||
},
|
||||
view = {
|
||||
default = {
|
||||
layout = "diff2_horizontal",
|
||||
disable_diagnostics = false,
|
||||
winbar_info = false,
|
||||
},
|
||||
merge_tool = {
|
||||
layout = "diff3_horizontal",
|
||||
disable_diagnostics = true,
|
||||
winbar_info = true,
|
||||
},
|
||||
file_history = {
|
||||
layout = "diff2_horizontal",
|
||||
disable_diagnostics = false,
|
||||
winbar_info = false,
|
||||
},
|
||||
},
|
||||
file_panel = {
|
||||
listing_style = "tree",
|
||||
tree_options = {
|
||||
flatten_dirs = true,
|
||||
folder_statuses = "only_folded",
|
||||
},
|
||||
win_config = {
|
||||
position = "left",
|
||||
width = 35,
|
||||
win_opts = {},
|
||||
},
|
||||
},
|
||||
file_history_panel = {
|
||||
log_options = {
|
||||
git = {
|
||||
single_file = { diff_merges = "combined" },
|
||||
multi_file = { diff_merges = "first-parent" },
|
||||
},
|
||||
hg = {
|
||||
single_file = {},
|
||||
multi_file = {},
|
||||
},
|
||||
},
|
||||
win_config = {
|
||||
position = "bottom",
|
||||
height = 16,
|
||||
win_opts = {},
|
||||
},
|
||||
},
|
||||
commit_log_panel = {
|
||||
win_config = {},
|
||||
},
|
||||
default_args = {
|
||||
DiffviewOpen = {},
|
||||
DiffviewFileHistory = {},
|
||||
},
|
||||
hooks = {},
|
||||
keymaps = {
|
||||
disable_defaults = false,
|
||||
view = {
|
||||
{ "n", "<tab>", actions.select_next_entry, { desc = "Open the diff for the next file" } },
|
||||
{ "n", "<s-tab>", actions.select_prev_entry, { desc = "Open the diff for the previous file" } },
|
||||
{ "n", "[F", actions.select_first_entry, { desc = "Open the diff for the first file" } },
|
||||
{ "n", "]F", actions.select_last_entry, { desc = "Open the diff for the last file" } },
|
||||
{ "n", "gf", actions.goto_file_edit, { desc = "Open the file in the previous tabpage" } },
|
||||
{ "n", "<C-w><C-f>", actions.goto_file_split, { desc = "Open the file in a new split" } },
|
||||
{ "n", "<C-w>gf", actions.goto_file_tab, { desc = "Open the file in a new tabpage" } },
|
||||
{ "n", "<leader>e", actions.focus_files, { desc = "Bring focus to the file panel" } },
|
||||
{ "n", "<leader>b", actions.toggle_files, { desc = "Toggle the file panel." } },
|
||||
{ "n", "g<C-x>", actions.cycle_layout, { desc = "Cycle through available layouts." } },
|
||||
{ "n", "[x", actions.prev_conflict, { desc = "In the merge-tool: jump to the previous conflict" } },
|
||||
{ "n", "]x", actions.next_conflict, { desc = "In the merge-tool: jump to the next conflict" } },
|
||||
{ "n", "<leader>co", actions.conflict_choose("ours"), { desc = "Choose the OURS version of a conflict" } },
|
||||
{ "n", "<leader>ct", actions.conflict_choose("theirs"), { desc = "Choose the THEIRS version of a conflict" } },
|
||||
{ "n", "<leader>cb", actions.conflict_choose("base"), { desc = "Choose the BASE version of a conflict" } },
|
||||
{ "n", "<leader>ca", actions.conflict_choose("all"), { desc = "Choose all the versions of a conflict" } },
|
||||
{ "n", "dX", actions.conflict_choose("none"), { desc = "Delete the conflict region" } },
|
||||
{ "n", "<leader>cO", actions.conflict_choose_all("ours"), { desc = "Choose OURS for the whole file" } },
|
||||
{ "n", "<leader>cT", actions.conflict_choose_all("theirs"), { desc = "Choose THEIRS for the whole file" } },
|
||||
{ "n", "<leader>cB", actions.conflict_choose_all("base"), { desc = "Choose BASE for the whole file" } },
|
||||
{ "n", "<leader>cA", actions.conflict_choose_all("all"), { desc = "Choose all versions for the whole file" } },
|
||||
{ "n", "g?", actions.help("view"), { desc = "Open the help panel" } },
|
||||
},
|
||||
file_panel = {
|
||||
{ "n", "j", actions.next_entry, { desc = "Bring the cursor to the next file entry" } },
|
||||
{ "n", "<down>", actions.next_entry, { desc = "Bring the cursor to the next file entry" } },
|
||||
{ "n", "k", actions.prev_entry, { desc = "Bring the cursor to the previous file entry" } },
|
||||
{ "n", "<up>", actions.prev_entry, { desc = "Bring the cursor to the previous file entry" } },
|
||||
{ "n", "<cr>", actions.select_entry, { desc = "Open the diff for the selected entry" } },
|
||||
{ "n", "o", actions.select_entry, { desc = "Open the diff for the selected entry" } },
|
||||
{ "n", "l", actions.select_entry, { desc = "Open the diff for the selected entry" } },
|
||||
{ "n", "<2-LeftMouse>", actions.select_entry, { desc = "Open the diff for the selected entry" } },
|
||||
{ "n", "-", actions.toggle_stage_entry, { desc = "Stage / unstage the selected entry" } },
|
||||
{ "n", "s", actions.toggle_stage_entry, { desc = "Stage / unstage the selected entry" } },
|
||||
{ "n", "S", actions.stage_all, { desc = "Stage all entries" } },
|
||||
{ "n", "U", actions.unstage_all, { desc = "Unstage all entries" } },
|
||||
{ "n", "X", actions.restore_entry, { desc = "Restore entry to the state on the left side" } },
|
||||
{ "n", "L", actions.open_commit_log, { desc = "Open the commit log panel" } },
|
||||
{ "n", "zo", actions.open_fold, { desc = "Expand fold" } },
|
||||
{ "n", "h", actions.close_fold, { desc = "Collapse fold" } },
|
||||
{ "n", "zc", actions.close_fold, { desc = "Collapse fold" } },
|
||||
{ "n", "za", actions.toggle_fold, { desc = "Toggle fold" } },
|
||||
{ "n", "zR", actions.open_all_folds, { desc = "Expand all folds" } },
|
||||
{ "n", "zM", actions.close_all_folds, { desc = "Collapse all folds" } },
|
||||
{ "n", "<c-b>", actions.scroll_view(-0.25), { desc = "Scroll the view up" } },
|
||||
{ "n", "<c-f>", actions.scroll_view(0.25), { desc = "Scroll the view down" } },
|
||||
{ "n", "<tab>", actions.select_next_entry, { desc = "Open the diff for the next file" } },
|
||||
{ "n", "<s-tab>", actions.select_prev_entry, { desc = "Open the diff for the previous file" } },
|
||||
{ "n", "[F", actions.select_first_entry, { desc = "Open the diff for the first file" } },
|
||||
{ "n", "]F", actions.select_last_entry, { desc = "Open the diff for the last file" } },
|
||||
{ "n", "gf", actions.goto_file_edit, { desc = "Open the file in the previous tabpage" } },
|
||||
{ "n", "<C-w><C-f>", actions.goto_file_split, { desc = "Open the file in a new split" } },
|
||||
{ "n", "<C-w>gf", actions.goto_file_tab, { desc = "Open the file in a new tabpage" } },
|
||||
{ "n", "i", actions.listing_style, { desc = "Toggle between 'list' and 'tree' views" } },
|
||||
{ "n", "f", actions.toggle_flatten_dirs, { desc = "Flatten empty subdirectories in tree listing style" } },
|
||||
{ "n", "R", actions.refresh_files, { desc = "Update stats and entries in the file list" } },
|
||||
{ "n", "<leader>e", actions.focus_files, { desc = "Bring focus to the file panel" } },
|
||||
{ "n", "<leader>b", actions.toggle_files, { desc = "Toggle the file panel" } },
|
||||
{ "n", "g<C-x>", actions.cycle_layout, { desc = "Cycle available layouts" } },
|
||||
{ "n", "[x", actions.prev_conflict, { desc = "Go to the previous conflict" } },
|
||||
{ "n", "]x", actions.next_conflict, { desc = "Go to the next conflict" } },
|
||||
{ "n", "g?", actions.help("file_panel"), { desc = "Open the help panel" } },
|
||||
{ "n", "<leader>cO", actions.conflict_choose_all("ours"), { desc = "Choose OURS for the whole file" } },
|
||||
{ "n", "<leader>cT", actions.conflict_choose_all("theirs"), { desc = "Choose THEIRS for the whole file" } },
|
||||
{ "n", "<leader>cB", actions.conflict_choose_all("base"), { desc = "Choose BASE for the whole file" } },
|
||||
{ "n", "<leader>cA", actions.conflict_choose_all("all"), { desc = "Choose all versions for the whole file" } },
|
||||
{ "n", "dX", actions.conflict_choose_all("none"), { desc = "Delete the conflict region for the whole file" } },
|
||||
},
|
||||
file_history_panel = {
|
||||
{ "n", "g!", actions.options, { desc = "Open the option panel" } },
|
||||
{ "n", "<C-A-d>", actions.open_in_diffview, { desc = "Open the entry under the cursor in a diffview" } },
|
||||
{ "n", "y", actions.copy_hash, { desc = "Copy the commit hash of the entry under the cursor" } },
|
||||
{ "n", "L", actions.open_commit_log, { desc = "Show commit details" } },
|
||||
{ "n", "X", actions.restore_entry, { desc = "Restore file to the state from the selected entry" } },
|
||||
{ "n", "zo", actions.open_fold, { desc = "Expand fold" } },
|
||||
{ "n", "zc", actions.close_fold, { desc = "Collapse fold" } },
|
||||
{ "n", "h", actions.close_fold, { desc = "Collapse fold" } },
|
||||
{ "n", "za", actions.toggle_fold, { desc = "Toggle fold" } },
|
||||
{ "n", "zR", actions.open_all_folds, { desc = "Expand all folds" } },
|
||||
{ "n", "zM", actions.close_all_folds, { desc = "Collapse all folds" } },
|
||||
{ "n", "j", actions.next_entry, { desc = "Bring the cursor to the next file entry" } },
|
||||
{ "n", "<down>", actions.next_entry, { desc = "Bring the cursor to the next file entry" } },
|
||||
{ "n", "k", actions.prev_entry, { desc = "Bring the cursor to the previous file entry" } },
|
||||
{ "n", "<up>", actions.prev_entry, { desc = "Bring the cursor to the previous file entry" } },
|
||||
{ "n", "<cr>", actions.select_entry, { desc = "Open the diff for the selected entry" } },
|
||||
{ "n", "o", actions.select_entry, { desc = "Open the diff for the selected entry" } },
|
||||
{ "n", "l", actions.select_entry, { desc = "Open the diff for the selected entry" } },
|
||||
{ "n", "<2-LeftMouse>", actions.select_entry, { desc = "Open the diff for the selected entry" } },
|
||||
{ "n", "<c-b>", actions.scroll_view(-0.25), { desc = "Scroll the view up" } },
|
||||
{ "n", "<c-f>", actions.scroll_view(0.25), { desc = "Scroll the view down" } },
|
||||
{ "n", "<tab>", actions.select_next_entry, { desc = "Open the diff for the next file" } },
|
||||
{ "n", "<s-tab>", actions.select_prev_entry, { desc = "Open the diff for the previous file" } },
|
||||
{ "n", "[F", actions.select_first_entry, { desc = "Open the diff for the first file" } },
|
||||
{ "n", "]F", actions.select_last_entry, { desc = "Open the diff for the last file" } },
|
||||
{ "n", "gf", actions.goto_file_edit, { desc = "Open the file in the previous tabpage" } },
|
||||
{ "n", "<C-w><C-f>", actions.goto_file_split, { desc = "Open the file in a new split" } },
|
||||
{ "n", "<C-w>gf", actions.goto_file_tab, { desc = "Open the file in a new tabpage" } },
|
||||
{ "n", "<leader>e", actions.focus_files, { desc = "Bring focus to the file panel" } },
|
||||
{ "n", "<leader>b", actions.toggle_files, { desc = "Toggle the file panel" } },
|
||||
{ "n", "g<C-x>", actions.cycle_layout, { desc = "Cycle available layouts" } },
|
||||
{ "n", "g?", actions.help("file_history_panel"), { desc = "Open the help panel" } },
|
||||
},
|
||||
option_panel = {
|
||||
{ "n", "<tab>", actions.select_entry, { desc = "Change the current option" } },
|
||||
{ "n", "q", actions.close, { desc = "Close the panel" } },
|
||||
{ "n", "g?", actions.help("option_panel"), { desc = "Open the help panel" } },
|
||||
},
|
||||
help_panel = {
|
||||
{ "n", "q", actions.close, { desc = "Close help menu" } },
|
||||
{ "n", "<esc>", actions.close, { desc = "Close help menu" } },
|
||||
},
|
||||
},
|
||||
})
|
||||
end,
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
return {
|
||||
"fei6409/log-highlight.nvim",
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
return {
|
||||
"nvim-lualine/lualine.nvim",
|
||||
dependencies = { "nvim-tree/nvim-web-devicons" },
|
||||
config = function()
|
||||
require("lualine").setup({
|
||||
options = {
|
||||
icons_enabled = true,
|
||||
theme = "auto",
|
||||
component_separators = { left = "", right = "" },
|
||||
section_separators = { left = "", right = "" },
|
||||
disabled_filetypes = {
|
||||
statusline = {},
|
||||
winbar = {},
|
||||
},
|
||||
ignore_focus = {},
|
||||
always_divide_middle = true,
|
||||
always_show_tabline = true,
|
||||
globalstatus = false,
|
||||
refresh = {
|
||||
statusline = 1000,
|
||||
tabline = 1000,
|
||||
winbar = 1000,
|
||||
refresh_time = 16,
|
||||
events = {
|
||||
"WinEnter", "BufEnter", "BufWritePost", "SessionLoadPost",
|
||||
"FileChangedShellPost", "VimResized", "Filetype",
|
||||
"CursorMoved", "CursorMovedI", "ModeChanged",
|
||||
},
|
||||
},
|
||||
},
|
||||
sections = {
|
||||
lualine_a = { "mode" },
|
||||
lualine_b = { "branch", "diff", "diagnostics" },
|
||||
lualine_c = { "filename" },
|
||||
lualine_x = { "encoding", "fileformat", "filetype" },
|
||||
lualine_y = { "progress" },
|
||||
lualine_z = { "location" },
|
||||
},
|
||||
inactive_sections = {
|
||||
lualine_a = {},
|
||||
lualine_b = {},
|
||||
lualine_c = { "filename" },
|
||||
lualine_x = { "location" },
|
||||
lualine_y = {},
|
||||
lualine_z = {},
|
||||
},
|
||||
tabline = {},
|
||||
winbar = {},
|
||||
inactive_winbar = {},
|
||||
extensions = {},
|
||||
})
|
||||
end,
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
return {
|
||||
"MeanderingProgrammer/render-markdown.nvim",
|
||||
dependencies = {
|
||||
"nvim-treesitter/nvim-treesitter",
|
||||
"nvim-tree/nvim-web-devicons",
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
return {
|
||||
"nvim-neo-tree/neo-tree.nvim",
|
||||
version = "3.*",
|
||||
dependencies = {
|
||||
"nvim-lua/plenary.nvim",
|
||||
"MunifTanjim/nui.nvim",
|
||||
"nvim-tree/nvim-web-devicons",
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
return {
|
||||
"nvim-telescope/telescope.nvim",
|
||||
dependencies = {
|
||||
"nvim-lua/plenary.nvim",
|
||||
"nvim-tree/nvim-web-devicons",
|
||||
{
|
||||
"nvim-telescope/telescope-fzf-native.nvim",
|
||||
build = "make",
|
||||
},
|
||||
},
|
||||
config = function()
|
||||
local builtin = require("telescope.builtin")
|
||||
vim.keymap.set("n", "<leader>ff", builtin.find_files, { desc = "Telescope find files" })
|
||||
vim.keymap.set("n", "<leader>fg", builtin.live_grep, { desc = "Telescope live grep" })
|
||||
vim.keymap.set("n", "<leader>fb", builtin.buffers, { desc = "Telescope buffers" })
|
||||
vim.keymap.set("n", "<leader>fh", builtin.help_tags, { desc = "Telescope help tags" })
|
||||
end,
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
return {
|
||||
"catppuccin/nvim",
|
||||
name = "catppuccin",
|
||||
priority = 1000, -- Load before other plugins so colorscheme is set first
|
||||
config = function()
|
||||
vim.cmd("colorscheme catppuccin")
|
||||
end,
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
return {
|
||||
{
|
||||
"nvim-treesitter/nvim-treesitter",
|
||||
branch = "main",
|
||||
build = ":TSUpdate",
|
||||
config = function()
|
||||
require("nvim-treesitter").setup({})
|
||||
require("nvim-treesitter").install({
|
||||
"bash", "blade", "c", "comment", "css", "diff", "dockerfile",
|
||||
"fish", "gitcommit", "gitignore", "go", "gomod", "gosum", "gowork",
|
||||
"html", "ini", "javascript", "jsdoc", "json", "lua", "luadoc",
|
||||
"luap", "make", "markdown", "markdown_inline", "nginx", "nix",
|
||||
"proto", "python", "query", "regex", "rust", "scss", "sql",
|
||||
"terraform", "toml", "tsx", "typescript", "vim", "vimdoc",
|
||||
"xml", "yaml", "zig",
|
||||
})
|
||||
|
||||
vim.wo.foldexpr = "v:lua.vim.treesitter.foldexpr()"
|
||||
vim.bo.indentexpr = "v:lua.require'nvim-treesitter'.indentexpr()"
|
||||
|
||||
vim.api.nvim_create_autocmd("FileType", {
|
||||
pattern = { "*" },
|
||||
callback = function()
|
||||
local filetype = vim.bo.filetype
|
||||
if filetype and filetype ~= "" then
|
||||
pcall(vim.treesitter.start)
|
||||
end
|
||||
end,
|
||||
})
|
||||
end,
|
||||
},
|
||||
{
|
||||
"nvim-treesitter/nvim-treesitter-textobjects",
|
||||
branch = "main",
|
||||
dependencies = { "nvim-treesitter/nvim-treesitter" },
|
||||
config = function()
|
||||
require("nvim-treesitter-textobjects").setup({
|
||||
select = {
|
||||
enable = true,
|
||||
lookahead = true,
|
||||
selection_modes = {
|
||||
["@parameter.outer"] = "v",
|
||||
["@function.outer"] = "V",
|
||||
["@class.outer"] = "<c-v>",
|
||||
},
|
||||
include_surrounding_whitespace = false,
|
||||
},
|
||||
move = {
|
||||
enable = true,
|
||||
set_jumps = true,
|
||||
},
|
||||
})
|
||||
|
||||
-- SELECT keymaps
|
||||
local sel = require("nvim-treesitter-textobjects.select")
|
||||
for _, map in ipairs({
|
||||
{ { "x", "o" }, "af", "@function.outer" },
|
||||
{ { "x", "o" }, "if", "@function.inner" },
|
||||
{ { "x", "o" }, "ac", "@class.outer" },
|
||||
{ { "x", "o" }, "ic", "@class.inner" },
|
||||
{ { "x", "o" }, "aa", "@parameter.outer" },
|
||||
{ { "x", "o" }, "ia", "@parameter.inner" },
|
||||
{ { "x", "o" }, "ad", "@comment.outer" },
|
||||
{ { "x", "o" }, "as", "@statement.outer" },
|
||||
}) do
|
||||
vim.keymap.set(map[1], map[2], function()
|
||||
sel.select_textobject(map[3], "textobjects")
|
||||
end, { desc = "Select " .. map[3] })
|
||||
end
|
||||
|
||||
-- MOVE keymaps
|
||||
local mv = require("nvim-treesitter-textobjects.move")
|
||||
for _, map in ipairs({
|
||||
{ { "n", "x", "o" }, "]m", mv.goto_next_start, "@function.outer" },
|
||||
{ { "n", "x", "o" }, "[m", mv.goto_previous_start, "@function.outer" },
|
||||
{ { "n", "x", "o" }, "]]", mv.goto_next_start, "@class.outer" },
|
||||
{ { "n", "x", "o" }, "[[", mv.goto_previous_start, "@class.outer" },
|
||||
{ { "n", "x", "o" }, "]M", mv.goto_next_end, "@function.outer" },
|
||||
{ { "n", "x", "o" }, "[M", mv.goto_previous_end, "@function.outer" },
|
||||
{ { "n", "x", "o" }, "]o", mv.goto_next_start, { "@loop.inner", "@loop.outer" } },
|
||||
{ { "n", "x", "o" }, "[o", mv.goto_previous_start, { "@loop.inner", "@loop.outer" } },
|
||||
}) do
|
||||
local modes, lhs, fn, query = map[1], map[2], map[3], map[4]
|
||||
local qstr = (type(query) == "table") and table.concat(query, ",") or query
|
||||
vim.keymap.set(modes, lhs, function()
|
||||
fn(query, "textobjects")
|
||||
end, { desc = "Move to " .. qstr })
|
||||
end
|
||||
end,
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
return {
|
||||
"folke/which-key.nvim",
|
||||
event = "VeryLazy",
|
||||
config = function()
|
||||
local wk = require("which-key")
|
||||
wk.setup({
|
||||
preset = "helix",
|
||||
})
|
||||
wk.add({
|
||||
{ "<leader><tab>", group = "tabs" },
|
||||
{ "<leader>c", group = "code" },
|
||||
{ "<leader>d", group = "debug" },
|
||||
{ "<leader>D", group = "Diffview", icon = { icon = "", color = "orange" } },
|
||||
{ "<leader>p", group = "Yanky", icon = { icon = " ", color = "yellow" } },
|
||||
{ "<leader>dp", group = "profiler" },
|
||||
{ "<leader>f", group = "file/find" },
|
||||
{ "<leader>g", group = "git" },
|
||||
{ "<leader>gh", group = "hunks" },
|
||||
{ "<leader>q", group = "quit/session" },
|
||||
{ "<leader>s", group = "search" },
|
||||
{ "<leader>u", group = "ui", icon = { icon = " ", color = "cyan" } },
|
||||
{ "<leader>x", group = "diagnostics/quickfix", icon = { icon = " ", color = "green" } },
|
||||
{ "[", group = "prev" },
|
||||
{ "]", group = "next" },
|
||||
{ "g", group = "goto" },
|
||||
{ "gs", group = "surround" },
|
||||
{ "z", group = "fold" },
|
||||
{
|
||||
"<leader>b",
|
||||
group = "buffer",
|
||||
expand = function()
|
||||
return require("which-key.extras").expand.buf()
|
||||
end,
|
||||
},
|
||||
{
|
||||
"<leader>w",
|
||||
group = "windows",
|
||||
proxy = "<c-w>",
|
||||
expand = function()
|
||||
return require("which-key.extras").expand.win()
|
||||
end,
|
||||
},
|
||||
{ "gx", desc = "Open with system app" },
|
||||
{
|
||||
"<leader>fC",
|
||||
group = "Copy Path",
|
||||
{
|
||||
"<leader>fCf",
|
||||
function()
|
||||
vim.fn.setreg("+", vim.fn.expand("%:p"))
|
||||
vim.notify("Copied full file path: " .. vim.fn.expand("%:p"))
|
||||
end,
|
||||
desc = "Copy full file path",
|
||||
},
|
||||
{
|
||||
"<leader>fCn",
|
||||
function()
|
||||
vim.fn.setreg("+", vim.fn.expand("%:t"))
|
||||
vim.notify("Copied file name: " .. vim.fn.expand("%:t"))
|
||||
end,
|
||||
desc = "Copy file name",
|
||||
},
|
||||
{
|
||||
"<leader>fCr",
|
||||
function()
|
||||
local cwd = vim.fn.getcwd()
|
||||
local full_path = vim.fn.expand("%:p")
|
||||
local rel_path = full_path:sub(#cwd + 2)
|
||||
vim.fn.setreg("+", rel_path)
|
||||
vim.notify("Copied relative file path: " .. rel_path)
|
||||
end,
|
||||
desc = "Copy relative file path",
|
||||
},
|
||||
{
|
||||
"<leader>?",
|
||||
function()
|
||||
require("which-key").show({ global = false })
|
||||
end,
|
||||
desc = "Buffer Keymaps (which-key)",
|
||||
},
|
||||
{
|
||||
"<c-w><space>",
|
||||
function()
|
||||
require("which-key").show({ keys = "<c-w>", loop = true })
|
||||
end,
|
||||
desc = "Window Hydra Mode (which-key)",
|
||||
},
|
||||
},
|
||||
{
|
||||
mode = { "n", "v" },
|
||||
{ "<leader>q", "<cmd>q<cr>", desc = "Quit" },
|
||||
{ "<leader>w", "<cmd>w<cr>", desc = "Write" },
|
||||
},
|
||||
})
|
||||
end,
|
||||
}
|
||||
Reference in New Issue
Block a user