0
0

init.lua 31 KB

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