init.lua 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886
  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.defer_fn(function()
  549. -- vim.schedule(function()
  550. -- vim.cmd.colorscheme("jonathandarker")
  551. -- end)
  552. -- end, 100)
  553. vim.opt.list = true
  554. vim.opt.fillchars = "horiz:-," .. "horizup:-," .. "horizdown:-," ..
  555. "vert:¦," .. "verthoriz:¦," ..
  556. "vertleft:¦," .. "vertright:¦," ..
  557. "eob:⠀"
  558. vim.opt.listchars = "extends:›," .. "precedes:‹," ..
  559. "tab:\\ ," .. "nbsp:·," .. "trail:·," ..
  560. "space:·"
  561. end
  562. local function config_status_beast()
  563. require("status-beast.highlights").setup()
  564. require("status-beast").setup()
  565. vim.api.nvim_create_autocmd({ "BufEnter" },
  566. {
  567. group = vim.api.nvim_create_augroup('StatusBeast',
  568. { clear = true }),
  569. callback =
  570. require("status-beast").setup
  571. })
  572. vim.diagnostic.config({
  573. virtual_lines = {
  574. current_line = true,
  575. format = function(d)
  576. return "[" .. d.source .. "] " .. d.message
  577. end
  578. },
  579. float = false,
  580. virtual_text = false,
  581. update_in_insert = true
  582. })
  583. local palette = require("command-palette")
  584. palette.add({
  585. {
  586. "Status Beast", "Options for status bars and columns", { {
  587. "Toggle Relnum", "Toggle relative line numbers on/off",
  588. ":setl rnu!" } } }
  589. })
  590. end
  591. local function config_jxdash()
  592. require("jxdash").setup()
  593. end
  594. local function config_colorizer()
  595. require("colorizer").setup({ "*" }, {
  596. mode = "background",
  597. RGB = true,
  598. RRGGBB = true,
  599. RRGGBBAA = true,
  600. names = false,
  601. rgb_fn = false,
  602. hsl_fn = false,
  603. css = false,
  604. css_fn = false
  605. })
  606. end
  607. local function config_virt_column()
  608. vim.opt.colorcolumn = tostring(80 + 1)
  609. local cc_group = vim.api.nvim_create_augroup("colorcolumn",
  610. { clear = true })
  611. local filetype_colorcolumn_map = {
  612. python = 88,
  613. kotlin = 100,
  614. julia = 92
  615. }
  616. vim.api.nvim_create_autocmd({ "FileType" }, {
  617. pattern = { "*" },
  618. group = cc_group,
  619. callback = function(event)
  620. local filetype = vim.bo[event.buf].filetype
  621. local colorcolumn = filetype_colorcolumn_map[filetype]
  622. if colorcolumn == nil then
  623. colorcolumn = 80
  624. end
  625. for _, w in pairs(vim.api.nvim_list_wins()) do
  626. if vim.api.nvim_win_get_buf(w) == event.buf then
  627. vim.wo[w].colorcolumn = tostring(colorcolumn + 1)
  628. end
  629. end
  630. end
  631. })
  632. require("virt-column").setup({ char = "⁚" })
  633. end
  634. local function config_telescope()
  635. local builtin = require("telescope.builtin")
  636. require("telescope").setup({
  637. extensions = {
  638. ["ui-select"] = { require("telescope.themes").get_dropdown() }
  639. },
  640. defaults = {
  641. ["borderchars"] = {
  642. "-", "¦", "-", "¦", "⌌", "⌍", "⌏", "⌎"
  643. },
  644. layout_strategy = "horizontal",
  645. layout_config = {
  646. horizontal = { width = { padding = 0 }, height = 0.99 }
  647. },
  648. cache_picker = {
  649. num_pickers = 100,
  650. limit_entries = 100,
  651. ignore_empty_prompt = true
  652. }
  653. },
  654. pickers = {
  655. live_grep = {
  656. additional_args = function(_)
  657. return { "--hidden", "--glob=!**/.git/*" }
  658. end
  659. }
  660. }
  661. })
  662. vim.keymap.set("n", "<Leader>f", function()
  663. require("telescope").extensions.file_browser.file_browser({
  664. select_buffer = true,
  665. grouped = true,
  666. no_ignore = true,
  667. hidden = true,
  668. respect_gitignore = false,
  669. path = vim.fn.expand("%:p:h")
  670. })
  671. end, {})
  672. vim.keymap.set("n", "<Leader>s", builtin.resume)
  673. vim.keymap.set("n", "<Leader>S", builtin.pickers)
  674. vim.keymap.set("n", "<Leader>T", builtin.treesitter)
  675. vim.keymap.set("n", "<Leader>a", builtin.find_files)
  676. vim.keymap.set("n", "<Leader>g", builtin.git_files)
  677. vim.keymap.set("n", "<Leader>G", builtin.git_status)
  678. vim.keymap.set("n", "<Leader>b", builtin.buffers)
  679. vim.keymap.set("n", "<Leader>j", builtin.jumplist)
  680. vim.keymap.set("n", "<Leader>w", builtin.grep_string)
  681. vim.keymap.set("n", "<Leader>ld", builtin.lsp_definitions)
  682. vim.keymap.set("n", "<Leader>lt", builtin.lsp_type_definitions)
  683. vim.keymap.set("n", "<Leader>lr", builtin.lsp_references)
  684. vim.keymap.set("n", "<Leader>li", builtin.lsp_implementations)
  685. vim.keymap.set("n", "<Leader>ls", builtin.lsp_document_symbols)
  686. vim.keymap.set("n", "<Leader>lS", builtin.lsp_workspace_symbols)
  687. require("telescope").load_extension("ui-select")
  688. require("telescope").load_extension("file_browser")
  689. end
  690. local function config_telescope_file_browser()
  691. require("telescope").setup({
  692. extensions = {
  693. file_browser = {
  694. respect_gitignore = false,
  695. hidden = { file_browser = true, folder_browser = true },
  696. hijack_netrw = true,
  697. display_stat = { date = false, size = true, mode = false },
  698. mappings = {}
  699. }
  700. }
  701. })
  702. require("telescope").load_extension("file_browser")
  703. end
  704. local function config_telescope_shroud()
  705. local shroud = require("telescope-shroud")
  706. local palette = require("command-palette")
  707. palette.add({
  708. {
  709. "Telescope Shroud", "Telescope `grep` filter management", { {
  710. "Populate", "Reload the list of filter options", shroud.populate
  711. }, {
  712. "Clear default", "Reset the default filters", function()
  713. shroud.set_default({})
  714. end
  715. }, {
  716. "Set default", "Set the default filters", shroud.set_default }, {
  717. "Open default", "Set the default filters", shroud.open_default }, {
  718. "Open narrow", "Set the default filters", shroud.open_narrow } } }
  719. })
  720. vim.keymap.set("n", "<Leader>i", shroud.open_default)
  721. vim.keymap.set("n", "<Leader>I", shroud.open_narrow)
  722. end
  723. local function config_nvim_surround()
  724. require("nvim-surround").setup({})
  725. end
  726. local function config_nvim_treesitter_textobjects()
  727. require("nvim-treesitter.configs").setup({
  728. textobjects = {
  729. select = {
  730. enable = true,
  731. lookahead = true,
  732. keymaps = {
  733. ["af"] = "@function.outer",
  734. ["if"] = "@function.inner",
  735. ["ac"] = "@class.outer",
  736. ["ic"] = "@class.inner",
  737. ["ap"] = "@parameter.outer",
  738. ["ip"] = "@parameter.inner",
  739. ["aa"] = "@parameter.outer",
  740. ["ia"] = "@parameter.inner",
  741. ["al"] = "@loop.outer",
  742. ["il"] = "@loop.inner",
  743. ["at"] = "@attribute.outer",
  744. ["it"] = "@attribute.inner",
  745. ["a="] = "@assignment.outer",
  746. ["i="] = "@assignment.inner",
  747. ["ab"] = "@block.outer",
  748. ["ib"] = "@block.inner"
  749. },
  750. include_surrounding_whitespace = true
  751. },
  752. swap = {
  753. enable = true,
  754. swap_next = {
  755. ["csf"] = "@function.inner",
  756. ["csc"] = "@class.inner",
  757. ["csp"] = "@parameter.inner",
  758. ["csa"] = "@parameter.inner",
  759. ["csl"] = "@loop.inner",
  760. ["cst"] = "@attribute.inner",
  761. ["cs="] = "@assignment.inner",
  762. ["csb"] = "@block.inner"
  763. },
  764. swap_previous = {
  765. ["cSf"] = "@function.inner",
  766. ["cSc"] = "@class.inner",
  767. ["cSp"] = "@parameter.inner",
  768. ["cSa"] = "@parameter.inner",
  769. ["cSl"] = "@loop.inner",
  770. ["cSt"] = "@attribute.inner",
  771. ["cS="] = "@assignment.inner",
  772. ["cSb"] = "@block.inner"
  773. }
  774. }
  775. }
  776. })
  777. end
  778. local function config_nvim_treesitter()
  779. local api = require("nvim-treesitter.configs")
  780. api.setup({
  781. ensure_installed = "all",
  782. sync_install = false,
  783. auto_install = true,
  784. ignore_install = { "ipkg" },
  785. highlight = {
  786. enable = true,
  787. additional_vim_regex_highlighting = false
  788. }
  789. })
  790. vim.opt.foldmethod = "expr"
  791. vim.opt.foldexpr = "nvim_treesitter#foldexpr()"
  792. vim.api.nvim_create_autocmd("LspAttach", {
  793. callback = function(args)
  794. local client = vim.lsp.get_client_by_id(args.data.client_id)
  795. if vim.treesitter ~= nil and client ~= nil and
  796. type(vim.treesitter.highlighter.active[args.buf]) ~= "nil" then
  797. client.server_capabilities.semanticTokensProvider = nil
  798. end
  799. end
  800. })
  801. end
  802. local function config_nvim_treesitter_context()
  803. require("treesitter-context").setup({
  804. enable = true,
  805. max_lines = 5,
  806. min_window_height = 0,
  807. line_numbers = true,
  808. multiline_threshold = 20,
  809. trim_scope = "outer",
  810. mode = "cursor",
  811. zindex = 20,
  812. on_attach = nil
  813. })
  814. vim.api.nvim_set_hl(0, "TreesitterContextSeparator",
  815. { link = "WinSeparator" })
  816. vim.keymap.set("n", "<Leader>c", function()
  817. require("treesitter-context").go_to_context(vim.v.count1)
  818. end, { silent = true })
  819. end
  820. local setup_plugins = function()
  821. config_nvim_treesitter()
  822. config_vim_dirtytalk()
  823. config_colorizer()
  824. config_virt_column()
  825. config_nvim_surround()
  826. config_like_a_butterfly()
  827. config_nvim_cmp()
  828. config_telescope()
  829. config_jxdash()
  830. config_nvim_treesitter_textobjects()
  831. config_nvim_treesitter_context()
  832. config_telescope_file_browser()
  833. config_command_palette()
  834. config_maj_peg()
  835. config_bit_browser()
  836. config_save_formatter()
  837. config_pandoctrinated()
  838. config_gitsigns()
  839. config_telescope_shroud()
  840. config_proj_conf()
  841. config_status_beast()
  842. config_jonathandarker()
  843. end
  844. setup_plugins()