init.lua 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881
  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/hrsh7th/cmp-buffer",
  138. "https://github.com/hrsh7th/cmp-calc",
  139. "https://github.com/hrsh7th/cmp-cmdline",
  140. "https://github.com/hrsh7th/cmp-nvim-lsp",
  141. "https://github.com/hrsh7th/cmp-nvim-lsp-signature-help",
  142. "https://github.com/hrsh7th/cmp-nvim-lua",
  143. "https://github.com/hrsh7th/cmp-path",
  144. "https://github.com/hrsh7th/nvim-cmp",
  145. "https://github.com/kylechui/nvim-surround",
  146. "https://github.com/lewis6991/gitsigns.nvim",
  147. "https://github.com/lukas-reineke/virt-column.nvim",
  148. "https://github.com/norcalli/nvim-colorizer.lua",
  149. "https://github.com/nvim-lua/plenary.nvim",
  150. "https://github.com/nvim-telescope/telescope-file-browser.nvim",
  151. "https://github.com/nvim-telescope/telescope-ui-select.nvim",
  152. "https://github.com/nvim-telescope/telescope.nvim",
  153. "https://github.com/nvim-treesitter/nvim-treesitter",
  154. "https://github.com/nvim-treesitter/nvim-treesitter-context",
  155. "https://github.com/nvim-treesitter/nvim-treesitter-textobjects",
  156. "https://github.com/psliwka/vim-dirtytalk",
  157. "https://github.com/tpope/vim-commentary"
  158. })
  159. for _, plugin in ipairs({
  160. "like-a-butterfly",
  161. "bit-browser",
  162. "command-palette",
  163. "jonathandarker",
  164. "jxdash",
  165. "like-a-butterfly",
  166. "maj-peg",
  167. "pandoctrinated",
  168. "proj-conf",
  169. "save-formatter",
  170. "status-beast",
  171. "telescope-shroud",
  172. }) do
  173. vim.opt.runtimepath:prepend(vim.fn.stdpath("config") ..
  174. "/custom/" .. plugin)
  175. end
  176. -- === === === === === === === === === === === === === === === === === === ===
  177. --
  178. -- Plugins Configurations
  179. --
  180. -- === === === === === === === === === === === === === === === === === === ===
  181. local function config_command_palette()
  182. local palette = require("command-palette")
  183. palette.add({
  184. {
  185. "Manage project", "", {
  186. {
  187. "Close project",
  188. "Safely close the project and then close the associated tmux pane",
  189. function()
  190. vim.api.nvim_create_autocmd({ "VimLeave" }, {
  191. pattern = { "*" },
  192. group = vim.api.nvim_create_augroup(
  193. "tmux_close_group", { clear = true }),
  194. callback = function()
  195. vim.api.nvim_exec("!tmux kill-pane",
  196. false)
  197. end
  198. })
  199. vim.api.nvim_exec("qa", true)
  200. end
  201. }
  202. }
  203. }, {
  204. "Manage Neovim", "", {
  205. {
  206. "Update plugins",
  207. "",
  208. function() vim.pack.update() end
  209. }
  210. }
  211. }
  212. })
  213. vim.keymap.set("n", "<Leader>P", palette.open)
  214. vim.keymap.set("n", "<Leader>p", palette.open_full)
  215. vim.keymap.set("n", "<Leader>L", function()
  216. palette.open({}, "LSP Finders", {
  217. { "Treesitter", "", ":Telescope treesitter" },
  218. { "LSP References", "", ":Telescope lsp_references" },
  219. { "LSP Incoming Calls", "", ":Telescope lsp_incoming_calls" },
  220. { "LSP Outgoing Calls", "", ":Telescope lsp_outgoing_calls" },
  221. {
  222. "LSP Document Symbols", "",
  223. ":Telescope lsp_document_symbols"
  224. },
  225. {
  226. "LSP Workspace Symbols", "",
  227. ":Telescope lsp_workspace_symbols"
  228. }, {
  229. "LSP Dynamic Workspace Symbols", "",
  230. ":Telescope lsp_workspace_symbols"
  231. }, { "Diagnostics", "", ":Telescope diagnostics" },
  232. {
  233. "LSP Implementations", "",
  234. ":Telescope lsp_implementations"
  235. }, { "LSP Definitions", "", ":Telescope lsp_definitions" },
  236. {
  237. "LSP Type Definitions", "",
  238. ":Telescope lsp_type_definitions"
  239. }
  240. })
  241. end)
  242. end
  243. local function config_bit_browser()
  244. local bitbrowser = require("bit-browser")
  245. vim.keymap.set("n", "n", bitbrowser.next)
  246. vim.keymap.set("n", "N", bitbrowser.prev)
  247. for i, v in pairs({ 'e', 'w', 'i', 'd', 's', 'g' }) do
  248. vim.keymap.set("n", "<Leader>n" .. v, function()
  249. bitbrowser.set_target(i);
  250. bitbrowser.next()
  251. end)
  252. vim.keymap.set("n", "<Leader>N" .. v, function()
  253. bitbrowser.set_target(i);
  254. bitbrowser.prev()
  255. end)
  256. end
  257. end
  258. local function config_save_formatter()
  259. local formatter = require("save-formatter")
  260. formatter.setup()
  261. vim.keymap.set("n", "Sw",
  262. function() vim.api.nvim_exec2("write", {}) end)
  263. require("command-palette").add({ {
  264. "Save Formatter", "Configure automatic formatters", formatter.picker }
  265. })
  266. end
  267. local function config_pandoctrinated()
  268. local pandoctrinated = require("pandoctrinated")
  269. vim.keymap.set("n", "Sfd", pandoctrinated.pandoc_format_docstring)
  270. require("command-palette").add({ {
  271. "Pandoctrinated", "Format \"\"\"docstring\"\"\" with `pandoc`",
  272. pandoctrinated.pandoc_format_docstring }
  273. })
  274. end
  275. local function config_nvim_cmp()
  276. local cmp = require("cmp")
  277. local mapping = {
  278. ["<Tab>"] = function(fallback)
  279. if cmp.visible() then
  280. cmp.select_next_item(
  281. { behavior = cmp.SelectBehavior.Select })
  282. else
  283. fallback()
  284. end
  285. end,
  286. ["<S-Tab>"] = function(fallback)
  287. if cmp.visible() then
  288. cmp.select_prev_item(
  289. { behavior = cmp.SelectBehavior.Select })
  290. else
  291. fallback()
  292. end
  293. end,
  294. ["<CR>"] = function(fallback)
  295. if cmp.visible() and cmp.get_active_entry() then
  296. cmp.confirm({ behavior = cmp.ConfirmBehavior.Replace })
  297. else
  298. fallback()
  299. end
  300. end
  301. }
  302. cmp.setup({
  303. snippet = {},
  304. mapping = mapping,
  305. sources = cmp.config.sources({ { name = "nvim_lsp" } }, {
  306. { name = "buffer" }, { name = "nvim_lua" }, { name = "calc" },
  307. { name = "nvim_lsp_signature_help" }, { name = "path" }
  308. })
  309. })
  310. cmp.setup.cmdline("/", {
  311. mapping = cmp.mapping.preset.cmdline(),
  312. sources = { { name = "buffer" } }
  313. })
  314. cmp.setup.cmdline(":", {
  315. mapping = cmp.mapping.preset.cmdline(),
  316. sources = cmp.config.sources({ { name = "path" } }, {
  317. { name = "cmdline", option = { ignore_cmds = { "Man", "!" } } }
  318. })
  319. })
  320. vim.api.nvim_create_autocmd("LspAttach", {
  321. callback = function(args)
  322. local client = vim.lsp.get_client_by_id(args.data.client_id)
  323. if client == nil then return end
  324. if client:supports_method('textDocument/completion') then
  325. vim.lsp.completion.enable(true, client.id, args.buf,
  326. { autotrigger = false })
  327. end
  328. end
  329. })
  330. end
  331. local function config_maj_peg()
  332. local mp = require("maj-peg")
  333. mp.setup()
  334. require("command-palette").add({
  335. {
  336. "maj-peg", "Diagnostic integration for `mypy`", {
  337. {
  338. "Toggle maj-peg",
  339. function()
  340. if mp.status().enabled then
  341. return "Disable `mypy` integration"
  342. else
  343. return "Enable `mypy` integration"
  344. end
  345. end,
  346. mp.toggle } }
  347. }
  348. })
  349. end
  350. local function config_like_a_butterfly()
  351. local lab = require('like-a-butterfly')
  352. local augroup = vim.api.nvim_create_augroup(
  353. 'like-a-butterfly', { clear = true })
  354. function MakeTerm(shortcut, name, command, flaky)
  355. lab.create_term(name, command)
  356. vim.keymap.set("n", "<Leader>" .. shortcut, function()
  357. if flaky then
  358. local flaky_redraw_time = 10
  359. vim.api.nvim_create_autocmd({ "BufEnter" },
  360. {
  361. pattern = { "*" },
  362. group = augroup,
  363. once = true,
  364. callback = function()
  365. if (vim.bo.filetype ~= "butterfly") then
  366. return
  367. end
  368. local window = vim.api
  369. .nvim_get_current_win()
  370. vim.cmd(
  371. "setlocal sidescrolloff=" ..
  372. vim.o
  373. .columns)
  374. vim.defer_fn(function()
  375. vim.api.nvim_win_set_height(
  376. window,
  377. vim.api
  378. .nvim_win_get_height(
  379. window) -
  380. 1)
  381. vim.defer_fn(function()
  382. vim.api
  383. .nvim_win_set_height(
  384. window,
  385. vim.api
  386. .nvim_win_get_height(
  387. window) + 1)
  388. vim.api.nvim_feedkeys(
  389. vim.api
  390. .nvim_replace_termcodes(
  391. '<C-\\><C-n>^zei',
  392. true, true, true),
  393. 'i', true)
  394. vim.schedule(function()
  395. vim.cmd("redraw!")
  396. end)
  397. end, flaky_redraw_time)
  398. end, flaky_redraw_time)
  399. vim.cmd("redraw!")
  400. end
  401. })
  402. end
  403. lab.open_term(name)
  404. end)
  405. end
  406. vim.api.nvim_create_autocmd({ "BufEnter" },
  407. {
  408. pattern = { "*" },
  409. group = augroup,
  410. callback = function()
  411. vim
  412. .schedule(function()
  413. if (vim.bo.filetype ~= "butterfly") then
  414. lab.close_all()
  415. end
  416. end)
  417. end
  418. })
  419. MakeTerm("tt", "Alpha", "zsh")
  420. MakeTerm("ts", "Beta", "zsh")
  421. MakeTerm("tr", "Gamma", "zsh")
  422. MakeTerm("ta", "Delta", "zsh")
  423. MakeTerm("tn", "Epsilon", "gemini --model gemini-2.5-pro")
  424. MakeTerm("te", "Zeta", "/bin/zsh $DOTFILES_DIR/.scripts/omniscratch.zsh")
  425. MakeTerm("ti", "Eta", "lazydocker", true)
  426. MakeTerm("to", "Theta", "lazygit", true)
  427. vim.keymap.set("t", "<C-S-t>", "<C-\\><C-n>")
  428. vim.keymap.set("t", "<S-Space>", "<Esc>")
  429. local timer_var = "lab_doubletap_timer"
  430. vim.keymap.set("t", "<Esc>", function()
  431. if vim.b[timer_var] then
  432. vim.fn.timer_stop(vim.b[timer_var])
  433. vim.b[timer_var] = nil
  434. lab.close_all()
  435. else
  436. vim.b[timer_var] = vim.fn.timer_start(150, function()
  437. vim.b[timer_var] = nil
  438. vim.api.nvim_chan_send(
  439. vim.b.terminal_job_id,
  440. vim.api.nvim_replace_termcodes("<Esc>", true, false, true))
  441. end)
  442. end
  443. end, { noremap = true, silent = true })
  444. end
  445. local function config_gitsigns()
  446. local gitsigns = require("gitsigns")
  447. gitsigns.setup {
  448. diff_opts = {
  449. internal = true,
  450. linematch = 1,
  451. algorithm = "minimal"
  452. },
  453. signcolumn = true,
  454. numhl = false,
  455. linehl = false,
  456. max_file_length = 50000,
  457. word_diff = false,
  458. auto_attach = true,
  459. attach_to_untracked = true
  460. }
  461. local pickers = require("telescope.pickers")
  462. local actions = require("telescope.actions")
  463. local action_state = require("telescope.actions.state")
  464. local finders = require("telescope.finders")
  465. local conf = require("telescope.config").values
  466. local entry_display = require("telescope.pickers.entry_display")
  467. local palette = require("command-palette")
  468. local open_picker = function(title, command)
  469. local displayer = entry_display.create({
  470. separator = " ▏",
  471. items = {
  472. { width = 16 }, { width = 64 }, { width = 24 },
  473. { remaining = true }
  474. }
  475. })
  476. local results = vim.split(vim.fn.system(
  477. "git log --branches=\\* --pretty='format:%H ||!|| %cr ||!|| %(decorate:prefix=,suffix=,separator= ) ||!|| %an ||!|| %s' --since='last month'"),
  478. "\n")
  479. pickers.new({}, {
  480. prompt_title = title,
  481. finder = finders.new_table({
  482. results = results,
  483. entry_maker = function(entry)
  484. local s = vim.split(entry, "||!||")
  485. return {
  486. value = s[1],
  487. display = function()
  488. return displayer({
  489. { s[2] }, { s[3] }, { s[4] }, { s[5] }
  490. })
  491. end,
  492. ordinal = string.format("%s %s", s[3], s[5])
  493. }
  494. end
  495. }),
  496. sorter = conf.generic_sorter(),
  497. attach_mappings = function(prompt_bufnr, _)
  498. actions.select_default:replace(function()
  499. actions.close(prompt_bufnr)
  500. local hash = action_state.get_selected_entry().value
  501. if command == "base" then
  502. vim.api.nvim_exec(
  503. ":Gitsigns change_base " .. hash .. " true",
  504. true)
  505. elseif command == "diff" then
  506. vim.api.nvim_exec(":Gitsigns diffthis " .. hash,
  507. true)
  508. end
  509. end)
  510. return true
  511. end
  512. }):find()
  513. end
  514. local open_diff_picker =
  515. function()
  516. open_picker("Gitsigns Diff", "diff")
  517. end
  518. local open_base_picker = function()
  519. open_picker("Gitsigns Change Base", "base")
  520. end
  521. vim.keymap.set("n", "Sgd", open_diff_picker)
  522. vim.keymap.set("n", "Sgb", open_base_picker)
  523. palette.add({
  524. {
  525. "Gitsigns", "", {
  526. {
  527. "Diff file",
  528. "Open the Gitsigns differ for this file",
  529. open_diff_picker
  530. },
  531. {
  532. "Change diff base",
  533. "Change base branch for Gitsigns to diff again",
  534. open_base_picker
  535. }
  536. }
  537. }
  538. })
  539. end
  540. local function config_proj_conf()
  541. require("proj-conf").setup()
  542. end
  543. local function config_vim_dirtytalk()
  544. vim.opt.spelllang = { "en_us", "programming" }
  545. end
  546. local function config_jonathandarker()
  547. vim.cmd.colorscheme("jonathandarker")
  548. vim.opt.list = true
  549. vim.opt.fillchars = "horiz:-," .. "horizup:-," .. "horizdown:-," ..
  550. "vert:¦," .. "verthoriz:¦," ..
  551. "vertleft:¦," .. "vertright:¦," ..
  552. "eob:⠀"
  553. vim.opt.listchars = "extends:›," .. "precedes:‹," ..
  554. "tab:\\ ," .. "nbsp:·," .. "trail:·," ..
  555. "space:·"
  556. end
  557. local function config_status_beast()
  558. require("status-beast.highlights").setup()
  559. require("status-beast").setup()
  560. vim.api.nvim_create_autocmd({ "BufEnter" },
  561. {
  562. group = vim.api.nvim_create_augroup('StatusBeast',
  563. { clear = true }),
  564. callback =
  565. require("status-beast").setup
  566. })
  567. vim.diagnostic.config({
  568. virtual_lines = {
  569. current_line = true,
  570. format = function(d)
  571. return "[" .. d.source .. "] " .. d.message
  572. end
  573. },
  574. float = false,
  575. virtual_text = false,
  576. update_in_insert = true
  577. })
  578. local palette = require("command-palette")
  579. palette.add({
  580. {
  581. "Status Beast", "Options for status bars and columns", { {
  582. "Toggle Relnum", "Toggle relative line numbers on/off",
  583. ":setl rnu!" } } }
  584. })
  585. end
  586. local function config_jxdash()
  587. require("jxdash").setup()
  588. end
  589. local function config_colorizer()
  590. require("colorizer").setup({ "*" }, {
  591. mode = "background",
  592. RGB = true,
  593. RRGGBB = true,
  594. RRGGBBAA = true,
  595. names = false,
  596. rgb_fn = false,
  597. hsl_fn = false,
  598. css = false,
  599. css_fn = false
  600. })
  601. end
  602. local function config_virt_column()
  603. vim.opt.colorcolumn = tostring(80 + 1)
  604. local cc_group = vim.api.nvim_create_augroup("colorcolumn",
  605. { clear = true })
  606. local filetype_colorcolumn_map = {
  607. python = 88,
  608. kotlin = 100,
  609. julia = 92
  610. }
  611. vim.api.nvim_create_autocmd({ "FileType" }, {
  612. pattern = { "*" },
  613. group = cc_group,
  614. callback = function(event)
  615. local filetype = vim.bo[event.buf].filetype
  616. local colorcolumn = filetype_colorcolumn_map[filetype]
  617. if colorcolumn == nil then
  618. colorcolumn = 80
  619. end
  620. for _, w in pairs(vim.api.nvim_list_wins()) do
  621. if vim.api.nvim_win_get_buf(w) == event.buf then
  622. vim.wo[w].colorcolumn = tostring(colorcolumn + 1)
  623. end
  624. end
  625. end
  626. })
  627. require("virt-column").setup({ char = "⁚" })
  628. end
  629. local function config_telescope()
  630. local builtin = require("telescope.builtin")
  631. require("telescope").setup({
  632. extensions = {
  633. ["ui-select"] = { require("telescope.themes").get_dropdown() }
  634. },
  635. defaults = {
  636. ["borderchars"] = {
  637. "-", "¦", "-", "¦", "⌌", "⌍", "⌏", "⌎"
  638. },
  639. layout_strategy = "horizontal",
  640. layout_config = {
  641. horizontal = { width = { padding = 0 }, height = 0.99 }
  642. },
  643. cache_picker = {
  644. num_pickers = 100,
  645. limit_entries = 100,
  646. ignore_empty_prompt = true
  647. }
  648. },
  649. pickers = {
  650. live_grep = {
  651. additional_args = function(_)
  652. return { "--hidden", "--glob=!**/.git/*" }
  653. end
  654. }
  655. }
  656. })
  657. vim.keymap.set("n", "<Leader>f", function()
  658. require("telescope").extensions.file_browser.file_browser({
  659. select_buffer = true,
  660. grouped = true,
  661. no_ignore = true,
  662. hidden = true,
  663. respect_gitignore = false,
  664. path = vim.fn.expand("%:p:h")
  665. })
  666. end, {})
  667. vim.keymap.set("n", "<Leader>s", builtin.resume)
  668. vim.keymap.set("n", "<Leader>S", builtin.pickers)
  669. vim.keymap.set("n", "<Leader>T", builtin.treesitter)
  670. vim.keymap.set("n", "<Leader>a", builtin.find_files)
  671. vim.keymap.set("n", "<Leader>g", builtin.git_files)
  672. vim.keymap.set("n", "<Leader>G", builtin.git_status)
  673. vim.keymap.set("n", "<Leader>b", builtin.buffers)
  674. vim.keymap.set("n", "<Leader>j", builtin.jumplist)
  675. vim.keymap.set("n", "<Leader>w", builtin.grep_string)
  676. vim.keymap.set("n", "<Leader>ld", builtin.lsp_definitions)
  677. vim.keymap.set("n", "<Leader>lt", builtin.lsp_type_definitions)
  678. vim.keymap.set("n", "<Leader>lr", builtin.lsp_references)
  679. vim.keymap.set("n", "<Leader>li", builtin.lsp_implementations)
  680. vim.keymap.set("n", "<Leader>ls", builtin.lsp_document_symbols)
  681. vim.keymap.set("n", "<Leader>lS", builtin.lsp_workspace_symbols)
  682. require("telescope").load_extension("ui-select")
  683. require("telescope").load_extension("file_browser")
  684. end
  685. local function config_telescope_file_browser()
  686. require("telescope").setup({
  687. extensions = {
  688. file_browser = {
  689. respect_gitignore = false,
  690. hidden = { file_browser = true, folder_browser = true },
  691. hijack_netrw = true,
  692. display_stat = { date = false, size = true, mode = false },
  693. mappings = {}
  694. }
  695. }
  696. })
  697. require("telescope").load_extension("file_browser")
  698. end
  699. local function config_telescope_shroud()
  700. local shroud = require("telescope-shroud")
  701. local palette = require("command-palette")
  702. palette.add({
  703. {
  704. "Telescope Shroud", "Telescope `grep` filter management", { {
  705. "Populate", "Reload the list of filter options", shroud.populate
  706. }, {
  707. "Clear default", "Reset the default filters", function()
  708. shroud.set_default({})
  709. end
  710. }, {
  711. "Set default", "Set the default filters", shroud.set_default }, {
  712. "Open default", "Set the default filters", shroud.open_default }, {
  713. "Open narrow", "Set the default filters", shroud.open_narrow } } }
  714. })
  715. vim.keymap.set("n", "<Leader>i", shroud.open_default)
  716. vim.keymap.set("n", "<Leader>I", shroud.open_narrow)
  717. end
  718. local function config_nvim_surround()
  719. require("nvim-surround").setup({})
  720. end
  721. local function config_nvim_treesitter_textobjects()
  722. require("nvim-treesitter.configs").setup({
  723. textobjects = {
  724. select = {
  725. enable = true,
  726. lookahead = true,
  727. keymaps = {
  728. ["af"] = "@function.outer",
  729. ["if"] = "@function.inner",
  730. ["ac"] = "@class.outer",
  731. ["ic"] = "@class.inner",
  732. ["ap"] = "@parameter.outer",
  733. ["ip"] = "@parameter.inner",
  734. ["aa"] = "@parameter.outer",
  735. ["ia"] = "@parameter.inner",
  736. ["al"] = "@loop.outer",
  737. ["il"] = "@loop.inner",
  738. ["at"] = "@attribute.outer",
  739. ["it"] = "@attribute.inner",
  740. ["a="] = "@assignment.outer",
  741. ["i="] = "@assignment.inner",
  742. ["ab"] = "@block.outer",
  743. ["ib"] = "@block.inner"
  744. },
  745. include_surrounding_whitespace = true
  746. },
  747. swap = {
  748. enable = true,
  749. swap_next = {
  750. ["csf"] = "@function.inner",
  751. ["csc"] = "@class.inner",
  752. ["csp"] = "@parameter.inner",
  753. ["csa"] = "@parameter.inner",
  754. ["csl"] = "@loop.inner",
  755. ["cst"] = "@attribute.inner",
  756. ["cs="] = "@assignment.inner",
  757. ["csb"] = "@block.inner"
  758. },
  759. swap_previous = {
  760. ["cSf"] = "@function.inner",
  761. ["cSc"] = "@class.inner",
  762. ["cSp"] = "@parameter.inner",
  763. ["cSa"] = "@parameter.inner",
  764. ["cSl"] = "@loop.inner",
  765. ["cSt"] = "@attribute.inner",
  766. ["cS="] = "@assignment.inner",
  767. ["cSb"] = "@block.inner"
  768. }
  769. }
  770. }
  771. })
  772. end
  773. local function config_nvim_treesitter()
  774. local api = require("nvim-treesitter.configs")
  775. api.setup({
  776. ensure_installed = "all",
  777. sync_install = false,
  778. auto_install = true,
  779. ignore_install = { "ipkg" },
  780. highlight = {
  781. enable = true,
  782. additional_vim_regex_highlighting = false
  783. }
  784. })
  785. vim.opt.foldmethod = "expr"
  786. vim.opt.foldexpr = "nvim_treesitter#foldexpr()"
  787. vim.api.nvim_create_autocmd("LspAttach", {
  788. callback = function(args)
  789. local client = vim.lsp.get_client_by_id(args.data.client_id)
  790. if vim.treesitter ~= nil and client ~= nil and
  791. type(vim.treesitter.highlighter.active[args.buf]) ~= "nil" then
  792. client.server_capabilities.semanticTokensProvider = nil
  793. end
  794. end
  795. })
  796. end
  797. local function config_nvim_treesitter_context()
  798. require("treesitter-context").setup({
  799. enable = true,
  800. max_lines = 5,
  801. min_window_height = 0,
  802. line_numbers = true,
  803. multiline_threshold = 20,
  804. trim_scope = "outer",
  805. mode = "cursor",
  806. zindex = 20,
  807. on_attach = nil
  808. })
  809. vim.api.nvim_set_hl(0, "TreesitterContextSeparator",
  810. { link = "WinSeparator" })
  811. vim.keymap.set("n", "<Leader>c", function()
  812. require("treesitter-context").go_to_context(vim.v.count1)
  813. end, { silent = true })
  814. end
  815. local setup_plugins = function()
  816. config_jonathandarker()
  817. config_nvim_treesitter()
  818. config_vim_dirtytalk()
  819. config_colorizer()
  820. config_virt_column()
  821. config_nvim_surround()
  822. config_like_a_butterfly()
  823. config_nvim_cmp()
  824. config_telescope()
  825. config_jxdash()
  826. config_nvim_treesitter_textobjects()
  827. config_nvim_treesitter_context()
  828. config_telescope_file_browser()
  829. config_command_palette()
  830. config_maj_peg()
  831. config_bit_browser()
  832. config_save_formatter()
  833. config_pandoctrinated()
  834. config_gitsigns()
  835. config_telescope_shroud()
  836. config_proj_conf()
  837. config_status_beast()
  838. end
  839. setup_plugins()