0
0

init.lua 30 KB

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