238 lines
9.3 KiB
Lua
238 lines
9.3 KiB
Lua
-- ── 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)
|
|
|
|
-- ── Plugins ───────────────────────────────────────────────────────────────────
|
|
require("lazy").setup({
|
|
{ dir = vim.fn.expand("~/Dotfiles/nvim/theme/cyberqueer.nvim") },
|
|
"rktjmp/lush.nvim",
|
|
"tpope/vim-sensible",
|
|
"junegunn/goyo.vim",
|
|
"arecarn/vim-crunch",
|
|
"preservim/nerdtree",
|
|
"ryanoasis/vim-devicons",
|
|
{ "junegunn/fzf", build = function() vim.fn["fzf#install"]() end },
|
|
"junegunn/fzf.vim",
|
|
"vim-airline/vim-airline",
|
|
"vim-airline/vim-airline-themes",
|
|
"voldikss/vim-floaterm",
|
|
"rust-lang/rust.vim",
|
|
"norcalli/nvim-colorizer.lua",
|
|
{ "neoclide/coc.nvim", branch = "release" },
|
|
{ "mg979/vim-visual-multi", branch = "master" },
|
|
"SirVer/ultisnips",
|
|
"honza/vim-snippets",
|
|
"mfussenegger/nvim-dap",
|
|
"elihunter173/dirbuf.nvim",
|
|
"tpope/vim-dadbod",
|
|
"kristijanhusak/vim-dadbod-ui",
|
|
"kristijanhusak/vim-dadbod-completion",
|
|
"nvim-mini/mini.icons",
|
|
"tadmccorkle/markdown.nvim",
|
|
{ "ellisonleao/glow.nvim", config = true },
|
|
"itchyny/calendar.vim",
|
|
{
|
|
"greggh/claude-code.nvim",
|
|
dependencies = { "nvim-lua/plenary.nvim" },
|
|
config = function()
|
|
require("claude-code").setup()
|
|
end,
|
|
},
|
|
}, {
|
|
-- keep lazy's own UI out of the way on first install
|
|
install = { colorscheme = { "habamax" } },
|
|
})
|
|
|
|
-- ── Colorscheme & UI ──────────────────────────────────────────────────────────
|
|
vim.cmd("colorscheme cyberqueer")
|
|
|
|
vim.g.airline_powerline_fonts = 1
|
|
vim.g.airline_theme = "cyberqueer"
|
|
|
|
local ipaddr = vim.trim(vim.fn.system("hostname -i"))
|
|
local hostname = vim.trim(vim.fn.system("hostname -s"))
|
|
vim.g.airline_section_x = "IP:" .. ipaddr .. " DNS:" .. hostname
|
|
|
|
-- ── Providers ─────────────────────────────────────────────────────────────────
|
|
vim.g.loaded_ruby_provider = 0
|
|
vim.g.loaded_perl_provider = 0
|
|
|
|
-- ── Editor options ────────────────────────────────────────────────────────────
|
|
vim.cmd("filetype plugin indent on")
|
|
vim.cmd("syntax enable")
|
|
|
|
vim.opt.number = true
|
|
vim.opt.relativenumber = true
|
|
vim.opt.cursorline = true
|
|
vim.opt.cursorcolumn = true
|
|
vim.opt.showmode = false
|
|
vim.opt.shiftwidth = 4
|
|
vim.opt.scrolloff = 5
|
|
vim.opt.wrap = false
|
|
vim.opt.incsearch = true
|
|
vim.opt.ignorecase = true
|
|
vim.opt.smartcase = true
|
|
vim.opt.showcmd = true
|
|
vim.opt.showmatch = true
|
|
vim.opt.hlsearch = true
|
|
vim.opt.history = 1000
|
|
vim.opt.wildmenu = true
|
|
vim.opt.wildmode = "list:longest"
|
|
|
|
-- ── Keymaps ───────────────────────────────────────────────────────────────────
|
|
-- window navigation
|
|
vim.keymap.set("n", "<C-l>", "<C-w>w")
|
|
vim.keymap.set("n", "<C-h>", "<C-w>h")
|
|
vim.keymap.set("n", "<C-j>", "<C-w>j")
|
|
vim.keymap.set("n", "<C-k>", "<C-w>k")
|
|
|
|
-- calendar.vim steals <C-hjkl> for month nav; restore window movement
|
|
vim.api.nvim_create_autocmd("FileType", {
|
|
pattern = "calendar",
|
|
callback = function()
|
|
local o = { buffer = true, silent = true }
|
|
vim.keymap.set("n", "<C-l>", "<C-w>w", o)
|
|
vim.keymap.set("n", "<C-h>", "<C-w>h", o)
|
|
vim.keymap.set("n", "<C-j>", "<C-w>j", o)
|
|
vim.keymap.set("n", "<C-k>", "<C-w>k", o)
|
|
end,
|
|
})
|
|
|
|
-- quick actions
|
|
vim.keymap.set("n", "t", ":FloatermNew<CR>", { silent = true })
|
|
vim.keymap.set("n", "e", ":NERDTreeToggle<CR><C-W>l", { silent = true })
|
|
vim.keymap.set("n", "s", ":DBUIToggle<CR>", { silent = true })
|
|
vim.keymap.set("n", "x", "<Plug>(DBUI_ExecuteQuery)", { remap = true })
|
|
vim.keymap.set("n", "q", function()
|
|
local ok = pcall(vim.cmd, "wq")
|
|
if not ok then vim.cmd("q") end
|
|
end, { silent = true })
|
|
|
|
-- insert mode completion
|
|
vim.keymap.set("i", "<TAB>", "<C-N>")
|
|
vim.keymap.set("i", "<S-TAB>", "<TAB>")
|
|
|
|
-- sudo save
|
|
vim.cmd("ca w!! w !sudo tee '%'")
|
|
|
|
-- visual block shorthand
|
|
vim.cmd("command! Vb normal! <C-v>")
|
|
|
|
-- ── UltiSnips ─────────────────────────────────────────────────────────────────
|
|
vim.g.UltiSnipsExpandTrigger = "<C-tab>"
|
|
vim.g.UltiSnipsJumpForwardTrigger = "<c-b>"
|
|
vim.g.UltiSnipsJumpBackwardTrigger = "<c-z>"
|
|
vim.g.UltiSnipsEditSplit = "vertical"
|
|
|
|
-- ── CoC ───────────────────────────────────────────────────────────────────────
|
|
vim.g.coc_global_extensions = {
|
|
"coc-snippets", "coc-powershell", "coc-sh", "coc-omnisharp",
|
|
"coc-clangd", "coc-json", "coc-css", "coc-git", "coc-pyright", "coc-sql",
|
|
}
|
|
|
|
vim.g.coc_snippet_next = "<c-j>"
|
|
vim.g.coc_snippet_prev = "<c-k>"
|
|
|
|
vim.keymap.set("i", "<C-l>", "<Plug>(coc-snippets-expand)", { remap = true })
|
|
vim.keymap.set("v", "<C-j>", "<Plug>(coc-snippets-select)", { remap = true })
|
|
vim.keymap.set("i", "<C-j>", "<Plug>(coc-snippets-expand-jump)", { remap = true })
|
|
vim.keymap.set("x", "<leader>x", "<Plug>(coc-convert-snippet)", { remap = true })
|
|
|
|
-- tab/s-tab navigate CoC pum, else fall through
|
|
vim.keymap.set("i", "<Tab>", function()
|
|
return vim.fn["coc#pum#visible"]() == 1 and vim.fn["coc#pum#next"](1) or "<Tab>"
|
|
end, { expr = true, silent = true })
|
|
|
|
vim.keymap.set("i", "<S-Tab>", function()
|
|
return vim.fn["coc#pum#visible"]() == 1 and vim.fn["coc#pum#prev"](1) or "<S-Tab>"
|
|
end, { expr = true, silent = true })
|
|
|
|
-- CR confirms CoC selection
|
|
vim.keymap.set("i", "<CR>", function()
|
|
return vim.fn["coc#pum#visible"]() == 1 and vim.fn["coc#pum#confirm"]() or "<CR>"
|
|
end, { expr = true, silent = true })
|
|
|
|
-- ── PIM sidebar (calendar / notmuch / abook) ──────────────────────────────────
|
|
local function _pim_scratch(label, err)
|
|
vim.cmd("enew")
|
|
vim.bo.buftype = "nofile"
|
|
vim.bo.buflisted = false
|
|
vim.api.nvim_buf_set_lines(0, 0, -1, false, { "[" .. label .. " unavailable]", "", err or "" })
|
|
end
|
|
|
|
local function _pim_close_win(win)
|
|
if not vim.api.nvim_win_is_valid(win) then return end
|
|
local buf = vim.api.nvim_win_get_buf(win)
|
|
vim.api.nvim_win_close(win, true)
|
|
if vim.api.nvim_buf_is_valid(buf) and vim.bo[buf].buftype == "terminal" then
|
|
pcall(vim.api.nvim_buf_delete, buf, { force = true })
|
|
end
|
|
end
|
|
|
|
-- individual toggles: n = notmuch/alot, g = calendar, f = find/abook
|
|
local _solo = {}
|
|
|
|
local function toggle_solo(key, cmd, label, width)
|
|
local win = _solo[key]
|
|
if win and vim.api.nvim_win_is_valid(win) then
|
|
_pim_close_win(win)
|
|
_solo[key] = nil
|
|
else
|
|
local prev = vim.api.nvim_get_current_win()
|
|
vim.cmd("topleft vsplit")
|
|
vim.api.nvim_win_set_width(0, width)
|
|
local ok, err = pcall(vim.cmd, cmd)
|
|
if not ok then _pim_scratch(label, err) end
|
|
_solo[key] = vim.api.nvim_get_current_win()
|
|
vim.api.nvim_set_current_win(prev)
|
|
end
|
|
end
|
|
|
|
vim.keymap.set("n", "n", function() toggle_solo("n", "terminal alot", "alot", 55) end, { silent = true })
|
|
vim.keymap.set("n", "g", function() toggle_solo("g", "Calendar", "calendar.vim", 35) end, { silent = true })
|
|
vim.keymap.set("n", "f", function() toggle_solo("f", "terminal abook", "abook", 80) end, { silent = true })
|
|
|
|
-- r = full-screen PIM tab (mail top, calendar bottom-left, abook bottom-right)
|
|
local _pim_tab = nil
|
|
|
|
local function toggle_pim()
|
|
if _pim_tab and vim.api.nvim_tabpage_is_valid(_pim_tab) then
|
|
vim.cmd("tabclose " .. vim.api.nvim_tabpage_get_number(_pim_tab))
|
|
_pim_tab = nil
|
|
return
|
|
end
|
|
|
|
vim.cmd("tabnew")
|
|
_pim_tab = vim.api.nvim_get_current_tabpage()
|
|
|
|
-- top pane: alot (mail), full width
|
|
local ok, err = pcall(vim.cmd, "terminal alot")
|
|
if not ok then _pim_scratch("alot", err) end
|
|
|
|
-- split bottom third for calendar + abook
|
|
vim.cmd("belowright split")
|
|
vim.cmd("resize 24")
|
|
|
|
-- bottom-left: calendar
|
|
vim.cmd("leftabove vsplit")
|
|
ok, err = pcall(vim.cmd, "Calendar")
|
|
if not ok then _pim_scratch("calendar.vim", err) end
|
|
|
|
-- bottom-right: abook
|
|
vim.cmd("wincmd l")
|
|
ok, err = pcall(vim.cmd, "terminal abook")
|
|
if not ok then _pim_scratch("abook", err) end
|
|
|
|
-- focus mail
|
|
vim.cmd("wincmd k")
|
|
end
|
|
|
|
vim.keymap.set("n", "r", toggle_pim, { silent = true })
|