0
0

init.lua 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953
  1. -- === === === === === === === === Neovim Config === === === === === === === ===
  2. --
  3. -- A configuration for Neovim that aims to be beautiful, intuitive, and
  4. -- pragmatic about plugin usage, while providing a developer experience on par
  5. -- with professional IDEs. It is tuned for usage with a custom keyboard
  6. -- layout and terminal configuration, and may not be as useful in other setups.
  7. --
  8. -- This configuration leverages a combination of keymaps and omnibars to give
  9. -- quick access to a large amount of functionality in an intuitive way. Most
  10. -- keymaps are unchanged from stock Neovim, with the notable exception of
  11. -- remapping most `s<a-Z>` keymaps.
  12. --
  13. -- === === === === === === === === === === === === === === === === === === ===
  14. --
  15. -- Core Options
  16. --
  17. -- === === === === === === === === === === === === === === === === === === ===
  18. -- Incantation to render correctly in Alacritty/tmux/macOS
  19. vim.cmd([[
  20. let &t_8f = "\<Esc>[38;2;%lu;%lu;%lum"
  21. let &t_8b = "\<Esc>[48;2;%lu;%lu;%lum"
  22. set termguicolors
  23. ]])
  24. -- File options
  25. vim.opt.wrap = false
  26. vim.opt.encoding = "UTF-8"
  27. vim.opt.hlsearch = true
  28. vim.opt.spell = true
  29. vim.opt.spelllang = "en_us"
  30. -- Display options
  31. vim.opt.pumheight = 15
  32. vim.opt.laststatus = 2
  33. vim.opt.showtabline = 2
  34. vim.opt.showcmd = true
  35. vim.opt.cmdheight = 0
  36. vim.opt.number = true
  37. vim.opt.relativenumber = true
  38. vim.opt.splitbelow = true
  39. vim.opt.splitright = true
  40. vim.opt.expandtab = true
  41. vim.opt.tabstop = 4
  42. vim.opt.shiftwidth = 4
  43. -- === === === === === === === === === === === === === === === === === === ===
  44. --
  45. -- Leader
  46. --
  47. -- === === === === === === === === === === === === === === === === === === ===
  48. vim.keymap.set({ 'n', 'v' }, 's', '<Nop>', { noremap = true, silent = true })
  49. vim.keymap.set({ 'n', 'v' }, 'S', '<Nop>', { noremap = true, silent = true })
  50. vim.g.mapleader = 's'
  51. vim.g.maplocalleader = vim.g.mapleader
  52. -- === === === === === === === === === === === === === === === === === === ===
  53. --
  54. -- Keymaps
  55. --
  56. -- === === === === === === === === === === === === === === === === === === ===
  57. -- Use `Alt-Arrow` to navigate between panes
  58. vim.keymap.set("i", "<A-left>", "<C-\\><C-N><C-w>W")
  59. vim.keymap.set("i", "<A-right>", "<C-\\><C-N><C-w>w")
  60. vim.keymap.set("i", "<S-A-left>", "<C-\\><C-N>:tabnext<CR>")
  61. vim.keymap.set("i", "<S-A-right>", "<C-\\><C-N>:tabprevious<CR>")
  62. vim.keymap.set("n", "<A-left>", "<C-w>W")
  63. vim.keymap.set("n", "<A-right>", "<C-w>w")
  64. vim.keymap.set("n", "<S-A-left>", ":tabnext<CR>")
  65. vim.keymap.set("n", "<S-A-right>", ":tabprevious<CR>")
  66. -- Folds toggled by homerow roll
  67. vim.keymap.set("n", "sr", ": normal za<CR>")
  68. -- Buffer actions
  69. vim.keymap.set("n", "SV", ":vsp<CR>")
  70. vim.keymap.set("n", "SQ", ":q<CR>")
  71. vim.keymap.set("n", "SH", ":noh<CR>")
  72. -- Yank to system clipboard
  73. vim.keymap.set({ "n", 'v' }, "Y", "\"+y")
  74. -- Yank file properties to system clipboard
  75. local yank_filename = function(full, line)
  76. local filename = vim.fn.expand("%")
  77. if full then filename = vim.fn.expand("%:p") end
  78. if line then filename = filename .. ":" .. vim.api.nvim_win_get_cursor(0)[1] end
  79. vim.fn.setreg("+", filename)
  80. end
  81. vim.keymap.set("n", "Syan", function() yank_filename(true, false) end)
  82. vim.keymap.set("n", "Syal", function() yank_filename(true, true) end)
  83. vim.keymap.set("n", "Syrn", function() yank_filename(false, false) end)
  84. vim.keymap.set("n", "Syrl", function() yank_filename(false, true) end)
  85. vim.keymap.set("n", "Syf", function() yank_filename(false, false) end)
  86. -- === === === === === === === === === === === === === === === === === === ===
  87. --
  88. -- Language Servers
  89. --
  90. -- === === === === === === === === === === === === === === === === === === ===
  91. -- See configurations in `lsp/*.lua`
  92. vim.lsp.config("*", {
  93. cmd_cwd = vim.fn.expand("~"),
  94. root_markers = { ".git" },
  95. })
  96. -- Enable all language servers with extant configurations
  97. for _, filename in pairs(vim.split(io.popen("ls -a " .. vim.fn.stdpath("config")
  98. .. "/lsp"):read("*a"), "\n")) do
  99. if filename:match(".lua$") ~= nil then
  100. vim.lsp.enable(filename:sub(1, -5))
  101. end
  102. end
  103. -- LSP Keymaps
  104. vim.api.nvim_create_autocmd("LspAttach", {
  105. callback = function(_)
  106. vim.keymap.set("n", "SR", vim.lsp.buf.rename)
  107. vim.keymap.set("n", "Sx", vim.lsp.buf.code_action)
  108. vim.keymap.set("n", "<Space>", vim.lsp.buf.hover)
  109. vim.keymap.set("n", "SI", function()
  110. local diagnostic_config = vim.diagnostic.config()
  111. if (vim.lsp.inlay_hint.is_enabled()) then
  112. vim.lsp.inlay_hint.enable(false)
  113. vim.diagnostic.config({
  114. virtual_lines = {
  115. current_line = true,
  116. ---@diagnostic disable-next-line: need-check-nil, undefined-field
  117. format = diagnostic_config.format
  118. }
  119. })
  120. else
  121. vim.lsp.inlay_hint.enable(true)
  122. vim.diagnostic.config({
  123. virtual_lines = true,
  124. ---@diagnostic disable-next-line: need-check-nil, undefined-field
  125. format = diagnostic_config.format
  126. })
  127. end
  128. end)
  129. end
  130. })
  131. -- === === === === === === === === === === === === === === === === === === ===
  132. --
  133. -- Plugins Declarations
  134. --
  135. -- === === === === === === === === === === === === === === === === === === ===
  136. vim.pack.add({
  137. "https://github.com/kylechui/nvim-surround",
  138. "https://github.com/lewis6991/gitsigns.nvim",
  139. "https://github.com/lukas-reineke/virt-column.nvim",
  140. "https://github.com/nvim-lua/plenary.nvim",
  141. "https://github.com/nvim-telescope/telescope-ui-select.nvim",
  142. "https://github.com/nvim-telescope/telescope.nvim",
  143. "https://github.com/nvim-treesitter/nvim-treesitter-context",
  144. { src = "https://github.com/nvim-treesitter/nvim-treesitter-textobjects", version = "master" },
  145. { src = "https://github.com/nvim-treesitter/nvim-treesitter", version = "master" },
  146. "https://github.com/stevearc/aerial.nvim",
  147. "https://github.com/stevearc/oil.nvim",
  148. "https://github.com/saghen/blink.cmp",
  149. "https://github.com/tpope/vim-commentary"
  150. })
  151. for _, plugin in ipairs({
  152. "like-a-butterfly",
  153. "bit-browser",
  154. "command-palette",
  155. "jonathandarker",
  156. "jxdash",
  157. "like-a-butterfly",
  158. "maj-peg",
  159. "pandoctrinated",
  160. "proj-conf",
  161. "save-formatter",
  162. "status-beast",
  163. "telescope-shroud",
  164. }) do
  165. vim.opt.runtimepath:prepend(vim.fn.stdpath("config") ..
  166. "/custom/" .. plugin)
  167. end
  168. -- === === === === === === === === === === === === === === === === === === ===
  169. --
  170. -- Plugins Configurations
  171. --
  172. -- === === === === === === === === === === === === === === === === === === ===
  173. local function config_command_palette()
  174. local palette = require("command-palette")
  175. palette.add({
  176. {
  177. "Manage project", "", {
  178. {
  179. "Close project",
  180. "Safely close the project and then close the associated tmux pane",
  181. function()
  182. vim.api.nvim_create_autocmd({ "VimLeave" }, {
  183. pattern = { "*" },
  184. group = vim.api.nvim_create_augroup(
  185. "tmux_close_group", { clear = true }),
  186. callback = function()
  187. vim.api.nvim_exec("!tmux kill-pane",
  188. false)
  189. end
  190. })
  191. vim.api.nvim_exec("qa", true)
  192. end
  193. }
  194. }
  195. }, {
  196. "Manage Neovim", "", {
  197. {
  198. "Update plugins",
  199. "",
  200. function() vim.pack.update() end
  201. }
  202. }
  203. }
  204. })
  205. vim.keymap.set("n", "<Leader>P", palette.open)
  206. vim.keymap.set("n", "<Leader>p", palette.open_full)
  207. vim.keymap.set("n", "<Leader>L", function()
  208. palette.open({}, "LSP Finders", {
  209. { "Treesitter", "", ":Telescope treesitter" },
  210. { "LSP References", "", ":Telescope lsp_references" },
  211. { "LSP Incoming Calls", "", ":Telescope lsp_incoming_calls" },
  212. { "LSP Outgoing Calls", "", ":Telescope lsp_outgoing_calls" },
  213. {
  214. "LSP Document Symbols", "",
  215. ":Telescope lsp_document_symbols"
  216. },
  217. {
  218. "LSP Workspace Symbols", "",
  219. ":Telescope lsp_workspace_symbols"
  220. }, {
  221. "LSP Dynamic Workspace Symbols", "",
  222. ":Telescope lsp_workspace_symbols"
  223. }, { "Diagnostics", "", ":Telescope diagnostics" },
  224. {
  225. "LSP Implementations", "",
  226. ":Telescope lsp_implementations"
  227. }, { "LSP Definitions", "", ":Telescope lsp_definitions" },
  228. {
  229. "LSP Type Definitions", "",
  230. ":Telescope lsp_type_definitions"
  231. }
  232. })
  233. end)
  234. end
  235. local function config_bit_browser()
  236. local bitbrowser = require("bit-browser")
  237. vim.keymap.set("n", "n", bitbrowser.next)
  238. vim.keymap.set("n", "N", bitbrowser.prev)
  239. for i, v in pairs({ 'e', 'w', 'i', 'd', 's', 'g' }) do
  240. vim.keymap.set("n", "<Leader>n" .. v, function()
  241. bitbrowser.set_target(i);
  242. bitbrowser.next()
  243. end)
  244. vim.keymap.set("n", "<Leader>N" .. v, function()
  245. bitbrowser.set_target(i);
  246. bitbrowser.prev()
  247. end)
  248. end
  249. end
  250. local function config_save_formatter()
  251. local formatter = require("save-formatter")
  252. formatter.setup()
  253. vim.keymap.set("n", "Sw",
  254. function() vim.api.nvim_exec2("write", {}) end)
  255. require("command-palette").add({ {
  256. "Save Formatter", "Configure automatic formatters", formatter.picker }
  257. })
  258. end
  259. local function config_pandoctrinated()
  260. local pandoctrinated = require("pandoctrinated")
  261. vim.keymap.set("n", "Sfd", pandoctrinated.pandoc_format_docstring)
  262. require("command-palette").add({ {
  263. "Pandoctrinated", "Format \"\"\"docstring\"\"\" with `pandoc`",
  264. pandoctrinated.pandoc_format_docstring }
  265. })
  266. end
  267. local function config_blink_cmp()
  268. local blink = require("blink.cmp")
  269. blink.setup({
  270. keymap = {
  271. preset = 'none',
  272. ['<C-space>'] = { 'show', 'show_documentation', 'hide_documentation' },
  273. ['<C-e>'] = { 'hide' },
  274. ['<C-y>'] = { 'select_and_accept' },
  275. ['<Tab>'] = { 'select_next', 'snippet_forward', 'fallback' },
  276. ['<S-Tab>'] = { 'select_prev', 'snippet_backward', 'fallback' },
  277. ['<CR>'] = { 'accept', 'fallback' },
  278. ['<C-p>'] = { 'scroll_documentation_up', 'fallback' },
  279. ['<C-n>'] = { 'scroll_documentation_down', 'fallback' },
  280. },
  281. completion = {
  282. list = {
  283. selection = {
  284. preselect = false,
  285. auto_insert = false
  286. }
  287. },
  288. menu = {
  289. draw = {
  290. columns = { { "kind_icon" }, { "label", "label_description", gap = 1 } },
  291. },
  292. border = { "⌌", "-", "⌍", "¦", "⌏", "-", "⌎", "¦" }
  293. },
  294. documentation = {
  295. auto_show = true,
  296. auto_show_delay_ms = 200,
  297. window = {
  298. border = { "⌌", "-", "⌍", "¦", "⌏", "-", "⌎", "¦" }
  299. }
  300. },
  301. },
  302. appearance = {
  303. use_nvim_cmp_as_default = true,
  304. nerd_font_variant = 'mono',
  305. },
  306. fuzzy = { implementation = "prefer_rust", prebuilt_binaries = { download = true, force_version = "v1.8.0" } },
  307. sources = {
  308. default = { 'lsp', 'path', 'snippets', 'buffer' },
  309. providers = {
  310. lsp = { score_offset = 100 },
  311. buffer = { score_offset = 0 },
  312. }
  313. },
  314. signature = { enabled = true },
  315. cmdline = {
  316. enabled = true,
  317. keymap = {
  318. ['<Tab>'] = { 'show', 'select_next', 'fallback' },
  319. ['<S-Tab>'] = { 'select_prev', 'fallback' },
  320. ['<CR>'] = { 'accept', 'fallback' },
  321. }
  322. },
  323. })
  324. end
  325. local function config_maj_peg()
  326. local mp = require("maj-peg")
  327. mp.setup()
  328. require("command-palette").add({
  329. {
  330. "maj-peg", "Diagnostic integration for `mypy`", {
  331. {
  332. "Toggle maj-peg",
  333. function()
  334. if mp.status().enabled then
  335. return "Disable `mypy` integration"
  336. else
  337. return "Enable `mypy` integration"
  338. end
  339. end,
  340. mp.toggle } }
  341. }
  342. })
  343. end
  344. local function config_like_a_butterfly()
  345. local lab = require('like-a-butterfly')
  346. local augroup = vim.api.nvim_create_augroup(
  347. 'like-a-butterfly', { clear = true })
  348. function MakeTerm(shortcut, name, command, flaky)
  349. lab.create_term(name, command)
  350. vim.keymap.set("n", "<Leader>" .. shortcut, function()
  351. if flaky then
  352. local flaky_redraw_time = 10
  353. vim.api.nvim_create_autocmd({ "BufEnter" },
  354. {
  355. pattern = { "*" },
  356. group = augroup,
  357. once = true,
  358. callback = function()
  359. if (vim.bo.filetype ~= "butterfly") then
  360. return
  361. end
  362. local window = vim.api
  363. .nvim_get_current_win()
  364. vim.cmd(
  365. "setlocal sidescrolloff=" ..
  366. vim.o
  367. .columns)
  368. vim.defer_fn(function()
  369. vim.api.nvim_win_set_height(
  370. window,
  371. vim.api
  372. .nvim_win_get_height(
  373. window) -
  374. 1)
  375. vim.defer_fn(function()
  376. vim.api
  377. .nvim_win_set_height(
  378. window,
  379. vim.api
  380. .nvim_win_get_height(
  381. window) + 1)
  382. vim.api.nvim_feedkeys(
  383. vim.api
  384. .nvim_replace_termcodes(
  385. '<C-\\><C-n>^zei',
  386. true, true, true),
  387. 'i', true)
  388. vim.schedule(function()
  389. vim.cmd("redraw!")
  390. end)
  391. end, flaky_redraw_time)
  392. end, flaky_redraw_time)
  393. vim.cmd("redraw!")
  394. end
  395. })
  396. end
  397. lab.open_term(name)
  398. end)
  399. end
  400. vim.api.nvim_create_autocmd({ "BufEnter" },
  401. {
  402. pattern = { "*" },
  403. group = augroup,
  404. callback = function()
  405. vim
  406. .schedule(function()
  407. if (vim.bo.filetype ~= "butterfly") then
  408. lab.close_all()
  409. end
  410. end)
  411. end
  412. })
  413. MakeTerm("tt", "Alpha", "zsh")
  414. MakeTerm("ts", "Beta", "zsh")
  415. MakeTerm("tr", "Gamma", "zsh")
  416. MakeTerm("ta", "Delta", "zsh")
  417. MakeTerm("tn", "Epsilon", "gemini --model gemini-2.5-pro")
  418. MakeTerm("te", "Zeta", "/bin/zsh $DOTFILES_DIR/.scripts/omniscratch.zsh")
  419. MakeTerm("ti", "Eta", "lazydocker", true)
  420. MakeTerm("to", "Theta", "lazygit", true)
  421. vim.keymap.set("t", "<C-S-t>", "<C-\\><C-n>")
  422. vim.keymap.set("t", "<S-Space>", "<Esc>")
  423. local timer_var = "lab_doubletap_timer"
  424. vim.keymap.set("t", "<Esc>", function()
  425. if vim.b[timer_var] then
  426. vim.fn.timer_stop(vim.b[timer_var])
  427. vim.b[timer_var] = nil
  428. lab.close_all()
  429. else
  430. vim.b[timer_var] = vim.fn.timer_start(150, function()
  431. vim.b[timer_var] = nil
  432. vim.api.nvim_chan_send(
  433. vim.b.terminal_job_id,
  434. vim.api.nvim_replace_termcodes("<Esc>", true, false, true))
  435. end)
  436. end
  437. end, { noremap = true, silent = true })
  438. end
  439. local function config_gitsigns()
  440. local gitsigns = require("gitsigns")
  441. gitsigns.setup {
  442. diff_opts = {
  443. internal = true,
  444. linematch = 1,
  445. algorithm = "minimal"
  446. },
  447. signcolumn = true,
  448. numhl = false,
  449. linehl = false,
  450. max_file_length = 50000,
  451. word_diff = false,
  452. auto_attach = true,
  453. attach_to_untracked = true
  454. }
  455. local pickers = require("telescope.pickers")
  456. local actions = require("telescope.actions")
  457. local action_state = require("telescope.actions.state")
  458. local finders = require("telescope.finders")
  459. local conf = require("telescope.config").values
  460. local entry_display = require("telescope.pickers.entry_display")
  461. local palette = require("command-palette")
  462. local open_picker = function(title, command)
  463. local displayer = entry_display.create({
  464. separator = " ▏",
  465. items = {
  466. { width = 16 }, { width = 64 }, { width = 24 },
  467. { remaining = true }
  468. }
  469. })
  470. local results = vim.split(vim.fn.system(
  471. "git log --branches=\\* --pretty='format:%H ||!|| %cr ||!|| %(decorate:prefix=,suffix=,separator= ) ||!|| %an ||!|| %s' --since='last month'"),
  472. "\n")
  473. pickers.new({}, {
  474. prompt_title = title,
  475. finder = finders.new_table({
  476. results = results,
  477. entry_maker = function(entry)
  478. local s = vim.split(entry, "||!||")
  479. return {
  480. value = s[1],
  481. display = function()
  482. return displayer({
  483. { s[2] }, { s[3] }, { s[4] }, { s[5] }
  484. })
  485. end,
  486. ordinal = string.format("%s %s", s[3], s[5])
  487. }
  488. end
  489. }),
  490. sorter = conf.generic_sorter(),
  491. attach_mappings = function(prompt_bufnr, _)
  492. actions.select_default:replace(function()
  493. actions.close(prompt_bufnr)
  494. local hash = action_state.get_selected_entry().value
  495. if command == "base" then
  496. vim.api.nvim_exec(
  497. ":Gitsigns change_base " .. hash .. " true",
  498. true)
  499. elseif command == "diff" then
  500. vim.api.nvim_exec(":Gitsigns diffthis " .. hash,
  501. true)
  502. end
  503. end)
  504. return true
  505. end
  506. }):find()
  507. end
  508. local open_diff_picker =
  509. function()
  510. open_picker("Gitsigns Diff", "diff")
  511. end
  512. local open_base_picker = function()
  513. open_picker("Gitsigns Change Base", "base")
  514. end
  515. vim.keymap.set("n", "Sgd", open_diff_picker)
  516. vim.keymap.set("n", "Sgb", open_base_picker)
  517. palette.add({
  518. {
  519. "Gitsigns", "", {
  520. {
  521. "Diff file",
  522. "Open the Gitsigns differ for this file",
  523. open_diff_picker
  524. },
  525. {
  526. "Change diff base",
  527. "Change base branch for Gitsigns to diff again",
  528. open_base_picker
  529. }
  530. }
  531. }
  532. })
  533. end
  534. local function config_proj_conf()
  535. require("proj-conf").setup()
  536. end
  537. local function config_jonathandarker()
  538. vim.cmd.colorscheme("jonathandarker")
  539. vim.opt.list = true
  540. vim.opt.fillchars = "horiz:-," .. "horizup:-," .. "horizdown:-," ..
  541. "vert:¦," .. "verthoriz:¦," ..
  542. "vertleft:¦," .. "vertright:¦," ..
  543. "eob:⠀"
  544. vim.opt.listchars = "extends:›," .. "precedes:‹," ..
  545. "tab:\\ ," .. "nbsp:·," .. "trail:·," ..
  546. "space:·"
  547. end
  548. local function config_status_beast()
  549. require("status-beast.highlights").setup()
  550. require("status-beast").setup()
  551. vim.api.nvim_create_autocmd({ "BufEnter" },
  552. {
  553. group = vim.api.nvim_create_augroup('StatusBeast',
  554. { clear = true }),
  555. callback = function(args)
  556. if vim.bo[args.buf].filetype == "aerial" then
  557. return
  558. end
  559. require("status-beast").setup()
  560. end
  561. })
  562. vim.diagnostic.config({
  563. virtual_lines = {
  564. current_line = true,
  565. format = function(d)
  566. return "[" .. d.source .. "] " .. d.message
  567. end
  568. },
  569. float = false,
  570. virtual_text = false,
  571. update_in_insert = true
  572. })
  573. local palette = require("command-palette")
  574. palette.add({
  575. {
  576. "Status Beast", "Options for status bars and columns", { {
  577. "Toggle Relnum", "Toggle relative line numbers on/off",
  578. ":setl rnu!" } } }
  579. })
  580. end
  581. local function config_jxdash()
  582. require("jxdash").setup()
  583. end
  584. local function config_virt_column()
  585. vim.opt.colorcolumn = tostring(80 + 1)
  586. local cc_group = vim.api.nvim_create_augroup("colorcolumn",
  587. { clear = true })
  588. local filetype_colorcolumn_map = {
  589. python = 88,
  590. kotlin = 100,
  591. julia = 92
  592. }
  593. vim.api.nvim_create_autocmd({ "FileType" }, {
  594. pattern = { "*" },
  595. group = cc_group,
  596. callback = function(event)
  597. local filetype = vim.bo[event.buf].filetype
  598. local colorcolumn = filetype_colorcolumn_map[filetype]
  599. if colorcolumn == nil then
  600. colorcolumn = 80
  601. end
  602. for _, w in pairs(vim.api.nvim_list_wins()) do
  603. if vim.api.nvim_win_get_buf(w) == event.buf then
  604. vim.wo[w].colorcolumn = tostring(colorcolumn + 1)
  605. end
  606. end
  607. end
  608. })
  609. require("virt-column").setup({ char = "⁚" })
  610. end
  611. local function config_telescope()
  612. local builtin = require("telescope.builtin")
  613. require("telescope").setup({
  614. extensions = {
  615. ["ui-select"] = { require("telescope.themes").get_dropdown() }
  616. },
  617. defaults = {
  618. ["borderchars"] = {
  619. "-", "¦", "-", "¦", "⌌", "⌍", "⌏", "⌎"
  620. },
  621. layout_strategy = "horizontal",
  622. layout_config = {
  623. horizontal = { width = { padding = 0 }, height = 0.99 }
  624. },
  625. cache_picker = {
  626. num_pickers = 100,
  627. limit_entries = 100,
  628. ignore_empty_prompt = true
  629. }
  630. },
  631. pickers = {
  632. live_grep = {
  633. additional_args = function(_)
  634. return { "--hidden", "--glob=!**/.git/*" }
  635. end
  636. }
  637. }
  638. })
  639. vim.keymap.set("n", "<Leader>s", builtin.resume)
  640. vim.keymap.set("n", "<Leader>S", builtin.pickers)
  641. vim.keymap.set("n", "<Leader>T", builtin.treesitter)
  642. vim.keymap.set("n", "<Leader>a", builtin.find_files)
  643. vim.keymap.set("n", "<Leader>g", builtin.git_files)
  644. vim.keymap.set("n", "<Leader>G", builtin.git_status)
  645. vim.keymap.set("n", "<Leader>b", builtin.buffers)
  646. vim.keymap.set("n", "<Leader>j", builtin.jumplist)
  647. vim.keymap.set("n", "<Leader>w", builtin.grep_string)
  648. vim.keymap.set("n", "<Leader>ld", builtin.lsp_definitions)
  649. vim.keymap.set("n", "<Leader>lt", builtin.lsp_type_definitions)
  650. vim.keymap.set("n", "<Leader>lr", builtin.lsp_references)
  651. vim.keymap.set("n", "<Leader>li", builtin.lsp_implementations)
  652. vim.keymap.set("n", "<Leader>ls", builtin.lsp_document_symbols)
  653. vim.keymap.set("n", "<Leader>lS", builtin.lsp_workspace_symbols)
  654. require("telescope").load_extension("ui-select")
  655. end
  656. local function config_telescope_shroud()
  657. local shroud = require("telescope-shroud")
  658. local palette = require("command-palette")
  659. palette.add({
  660. {
  661. "Telescope Shroud", "Telescope `grep` filter management", { {
  662. "Populate", "Reload the list of filter options", shroud.populate
  663. }, {
  664. "Clear default", "Reset the default filters", function()
  665. shroud.set_default({})
  666. end
  667. }, {
  668. "Set default", "Set the default filters", shroud.set_default }, {
  669. "Open default", "Set the default filters", shroud.open_default }, {
  670. "Open narrow", "Set the default filters", shroud.open_narrow } } }
  671. })
  672. vim.keymap.set("n", "<Leader>i", shroud.open_default)
  673. vim.keymap.set("n", "<Leader>I", shroud.open_narrow)
  674. end
  675. local function config_nvim_surround()
  676. require("nvim-surround").setup({})
  677. end
  678. local function config_nvim_treesitter_textobjects()
  679. require("nvim-treesitter.configs").setup({
  680. textobjects = {
  681. select = {
  682. enable = true,
  683. lookahead = true,
  684. keymaps = {
  685. ["af"] = "@function.outer",
  686. ["if"] = "@function.inner",
  687. ["ac"] = "@class.outer",
  688. ["ic"] = "@class.inner",
  689. ["ap"] = "@parameter.outer",
  690. ["ip"] = "@parameter.inner",
  691. ["aa"] = "@parameter.outer",
  692. ["ia"] = "@parameter.inner",
  693. ["al"] = "@loop.outer",
  694. ["il"] = "@loop.inner",
  695. ["at"] = "@attribute.outer",
  696. ["it"] = "@attribute.inner",
  697. ["a="] = "@assignment.outer",
  698. ["i="] = "@assignment.inner",
  699. ["ab"] = "@block.outer",
  700. ["ib"] = "@block.inner"
  701. },
  702. include_surrounding_whitespace = true
  703. },
  704. swap = {
  705. enable = true,
  706. swap_next = {
  707. ["csf"] = "@function.inner",
  708. ["csc"] = "@class.inner",
  709. ["csp"] = "@parameter.inner",
  710. ["csa"] = "@parameter.inner",
  711. ["csl"] = "@loop.inner",
  712. ["cst"] = "@attribute.inner",
  713. ["cs="] = "@assignment.inner",
  714. ["csb"] = "@block.inner"
  715. },
  716. swap_previous = {
  717. ["cSf"] = "@function.inner",
  718. ["cSc"] = "@class.inner",
  719. ["cSp"] = "@parameter.inner",
  720. ["cSa"] = "@parameter.inner",
  721. ["cSl"] = "@loop.inner",
  722. ["cSt"] = "@attribute.inner",
  723. ["cS="] = "@assignment.inner",
  724. ["cSb"] = "@block.inner"
  725. }
  726. }
  727. }
  728. })
  729. end
  730. local function config_nvim_treesitter()
  731. local api = require("nvim-treesitter.configs")
  732. api.setup({
  733. ensure_installed = "all",
  734. sync_install = false,
  735. auto_install = true,
  736. ignore_install = { "ipkg" },
  737. highlight = {
  738. enable = true,
  739. additional_vim_regex_highlighting = false
  740. }
  741. })
  742. vim.opt.foldmethod = "expr"
  743. vim.opt.foldexpr = "nvim_treesitter#foldexpr()"
  744. vim.api.nvim_create_autocmd("LspAttach", {
  745. callback = function(args)
  746. local client = vim.lsp.get_client_by_id(args.data.client_id)
  747. if vim.treesitter ~= nil and client ~= nil and
  748. type(vim.treesitter.highlighter.active[args.buf]) ~= "nil" then
  749. client.server_capabilities.semanticTokensProvider = nil
  750. end
  751. end
  752. })
  753. end
  754. local function config_nvim_treesitter_context()
  755. require("treesitter-context").setup({
  756. enable = true,
  757. max_lines = 5,
  758. min_window_height = 0,
  759. line_numbers = true,
  760. multiline_threshold = 20,
  761. trim_scope = "outer",
  762. mode = "cursor",
  763. zindex = 20,
  764. on_attach = nil
  765. })
  766. vim.api.nvim_set_hl(0, "TreesitterContextSeparator",
  767. { link = "WinSeparator" })
  768. vim.keymap.set("n", "<Leader>c", function()
  769. require("treesitter-context").go_to_context(vim.v.count1)
  770. end, { silent = true })
  771. end
  772. local function config_aerial()
  773. require("aerial").setup({
  774. backends = { "treesitter", "lsp" },
  775. attach_mode = "global",
  776. highlight_closest = true,
  777. autojump = true,
  778. layout = {
  779. default_direction = "left",
  780. width = 40,
  781. placement = "window",
  782. winopts = {
  783. statuscolumn = ""
  784. }
  785. },
  786. nerd_font = "auto",
  787. icons = {
  788. Array = "[a]",
  789. Boolean = "[b]",
  790. Class = "[C]",
  791. Constant = "[const]",
  792. Constructor = "[Co]",
  793. Enum = "[E]",
  794. EnumMember = "[em]",
  795. Event = "[Ev]",
  796. Field = "[Fld]",
  797. File = "[File]",
  798. Function = "[F]",
  799. Interface = "[I]",
  800. Key = "[K]",
  801. Method = "[M]",
  802. Module = "[Mod]",
  803. Namespace = "[NS]",
  804. Null = "[-]",
  805. Number = "[n]",
  806. Object = "[o]",
  807. Operator = "[+]",
  808. Package = "[Pkg]",
  809. Property = "[P]",
  810. String = "[str]",
  811. Struct = "[S]",
  812. TypeParameter = "[T]",
  813. Variable = "[V]",
  814. Collapsed = "▶",
  815. },
  816. on_attach = function(bufnr)
  817. vim.keymap.set("n", "[[", "<cmd>AerialPrev<CR>", { buffer = bufnr })
  818. vim.keymap.set("n", "]]", "<cmd>AerialNext<CR>", { buffer = bufnr })
  819. end,
  820. })
  821. vim.keymap.set("n", "Sa", ":AerialOpen<CR>")
  822. vim.keymap.set("n", "SA", ":AerialToggle!<CR>")
  823. vim.api.nvim_create_autocmd({ "FileType", "BufEnter" }, {
  824. group = vim.api.nvim_create_augroup("AerialConfig", { clear = true }),
  825. callback = function(args)
  826. for _, win in ipairs(vim.fn.getwininfo()) do
  827. if (win.bufnr == args.buf) then
  828. vim.wo[win.winid].statuscolumn = ""
  829. end
  830. end
  831. end,
  832. })
  833. end
  834. local function config_oil()
  835. require("oil").setup({
  836. keymaps = {
  837. ["q"] = "actions.close",
  838. ["<Esc>"] = "actions.close",
  839. ["<C-p>"] = "actions.preview",
  840. },
  841. default_file_explorer = true,
  842. delete_to_trash = true,
  843. skip_confirm_for_simple_edits = true,
  844. columns = {
  845. "size",
  846. },
  847. view_options = { show_hidden = true },
  848. float = {
  849. padding = 1,
  850. max_width = 999,
  851. max_height = 0.99,
  852. min_width = 0.999,
  853. border = { "⌌", "-", "⌍", "¦", "⌏", "-", "⌎", "¦" },
  854. win_options = {
  855. winblend = 0,
  856. winhl = "Normal:Normal,FloatBorder:WinSeparator",
  857. },
  858. preview_split = "right",
  859. },
  860. preview_win = {
  861. update_on_cursor_moved = true,
  862. preview_method = "fast_scratch",
  863. win_options = {
  864. winblend = 0,
  865. winhl = "Normal:Normal,FloatBorder:WinSeparator",
  866. winbar = "",
  867. statusline = "",
  868. signcolumn = "no",
  869. number = false,
  870. relativenumber = false,
  871. cursorline = false,
  872. foldcolumn = "0",
  873. },
  874. },
  875. confirmation = {
  876. border = { "⌌", "-", "⌍", "¦", "⌏", "-", "⌎", "¦" },
  877. win_options = {
  878. winblend = 0,
  879. winhl = "Normal:Normal,FloatBorder:WinSeparator",
  880. },
  881. },
  882. })
  883. vim.keymap.set("n", "<Leader>f",
  884. function() require("oil").open_float(nil, { preview = {} }) end)
  885. end
  886. local function config_diagnostic_dock()
  887. require("diagnostic-dock").setup()
  888. end
  889. local setup_plugins = function()
  890. config_jonathandarker()
  891. config_nvim_treesitter()
  892. config_virt_column()
  893. config_nvim_surround()
  894. config_like_a_butterfly()
  895. config_blink_cmp()
  896. config_telescope()
  897. config_jxdash()
  898. config_nvim_treesitter_textobjects()
  899. config_nvim_treesitter_context()
  900. config_aerial()
  901. config_command_palette()
  902. config_maj_peg()
  903. config_bit_browser()
  904. config_save_formatter()
  905. config_pandoctrinated()
  906. config_gitsigns()
  907. config_telescope_shroud()
  908. config_proj_conf()
  909. config_status_beast()
  910. config_oil()
  911. end
  912. setup_plugins()