plugins.lua 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. -- add extra filetypes for plenary
  2. require('plenary.filetype').add_table({
  3. extension = {
  4. ['elv'] = [[elvish]]
  5. }
  6. })
  7. -- add extra builtin filetypes
  8. vim.filetype.add({
  9. pattern = {
  10. ['.*%.ts$'] = 'typescript'
  11. },
  12. })
  13. -- file/buffer/etc picker
  14. local telescope_actions = require('telescope.actions')
  15. local action_state = require('telescope.actions.state')
  16. local actions = {}
  17. actions.git_show_commit = function(prompt_bufnr)
  18. local selection = action_state.get_selected_entry()
  19. local path = vim.fn.FugitiveFind(selection.value)
  20. telescope_actions.close(prompt_bufnr)
  21. vim.cmd.edit(path)
  22. end
  23. local commit_mappings = {
  24. i = {
  25. ['<CR>'] = actions.git_show_commit,
  26. ['<C-r>c'] = telescope_actions.git_checkout,
  27. }
  28. }
  29. require('telescope').setup({
  30. defaults = {
  31. mappings = {
  32. i = {
  33. ['jj'] = 'close',
  34. },
  35. },
  36. layout_config = {
  37. prompt_position = 'top',
  38. },
  39. sorting_strategy = 'ascending',
  40. -- use filename as preview window title
  41. dynamic_preview_title = true,
  42. path_display = {
  43. -- shorten directory names of everything but the last 3 parts
  44. -- foo/bar/baz/file.txt -> f/boo/bar/file.txt
  45. shorten = { len = 1, exclude = { -3, -2, -1 } },
  46. -- truncate the beginning of the file name if wider than the window
  47. truncate = true,
  48. },
  49. preview = {
  50. -- don't preview files larger than 1MB
  51. filesize_limit = 1,
  52. timeout = 500,
  53. },
  54. vimgrep_arguments = {
  55. -- defaults
  56. "rg",
  57. "--color=never",
  58. "--no-heading",
  59. "--with-filename",
  60. "--line-number",
  61. "--column",
  62. "--smart-case",
  63. -- search "hidden" files except git folder
  64. "--hidden",
  65. "--iglob=!.git"
  66. },
  67. -- ignore things we're likely not to edit
  68. file_ignore_patterns = {
  69. "%.zip$",
  70. "%.yarn/releases/",
  71. "%.yarn/plugins/"
  72. },
  73. -- picker history
  74. cache_picker = {
  75. num_pickers = 10,
  76. },
  77. },
  78. pickers = {
  79. buffers = {
  80. sort_lastused = true,
  81. sort_mru = true,
  82. mappings = {
  83. i = {
  84. ['<C-k>'] = 'delete_buffer'
  85. },
  86. },
  87. },
  88. find_files = {
  89. find_command = { "fd", "--type", "f", "--strip-cwd-prefix" }
  90. },
  91. git_commits = {
  92. mappings = commit_mappings,
  93. },
  94. git_bcommits = {
  95. mappings = commit_mappings,
  96. },
  97. },
  98. })
  99. -- use native sorter for better performance
  100. require('telescope').load_extension('fzf')
  101. local telescope_builtin = require('telescope.builtin')
  102. local telescope_pickers = require('telescope.pickers')
  103. local telescope_finders = require('telescope.finders')
  104. local telescope_previewers = require('telescope.previewers')
  105. local telescope_putils = require('telescope.previewers.utils')
  106. local telescope_conf = require('telescope.config').values
  107. -- arbitrary git log picker
  108. vim.api.nvim_create_user_command('GLg', function(opts)
  109. local git_command = { "git", "log", "--pretty=oneline", "--abbrev-commit" }
  110. vim.list_extend(git_command, opts.fargs)
  111. telescope_builtin.git_commits({ git_command = git_command })
  112. end, { nargs = '*', complete = vim.fn['fugitive#LogComplete'] })
  113. -- custom picker to fallback to files if no git
  114. _G.project_files = function()
  115. local ok = pcall(telescope_builtin.git_files, { show_untracked = true })
  116. if not ok then telescope_builtin.find_files({}) end
  117. end
  118. -- custom picker for files within a commit
  119. _G.commit_files = function(opts)
  120. local current_path = vim.api.nvim_buf_get_name(0)
  121. local parsed = vim.fn.FugitiveParse(current_path)
  122. local resolved_path = parsed[1]
  123. local repo = parsed[2]
  124. if resolved_path == "" then
  125. vim.print("current file is not a fugitive path")
  126. return
  127. end
  128. local parts = vim.split(resolved_path, ':')
  129. local commit = parts[1]
  130. opts = opts or {}
  131. telescope_pickers.new(opts, {
  132. prompt_title = commit,
  133. finder = telescope_finders.new_oneshot_job({ "git", "ls-tree", "--name-only", "-r", commit }, {
  134. entry_maker = function(entry)
  135. local path = string.format("fugitive://%s//%s/%s", repo, commit, entry)
  136. return {
  137. path = path,
  138. value = entry,
  139. display = entry,
  140. ordinal = entry,
  141. }
  142. end,
  143. }),
  144. sorter = telescope_conf.file_sorter(opts),
  145. -- the builtin previewer has fancy async loading which doesn't work for
  146. -- fugitive paths so we have to define our own
  147. previewer = telescope_previewers.new_buffer_previewer({
  148. title = function(self)
  149. return 'Commit Files'
  150. end,
  151. dyn_title = function(self, entry)
  152. return entry.value
  153. end,
  154. define_preview = function(self, entry, status)
  155. -- the builtin previewer does more things like using mime type
  156. -- fallbacks as well as binary file detection which ours doesn't do
  157. local ft = telescope_putils.filetype_detect(entry.value)
  158. vim.api.nvim_buf_call(self.state.bufnr, function()
  159. vim.cmd('Gread ' .. entry.path)
  160. telescope_putils.highlighter(self.state.bufnr, ft, opts)
  161. end)
  162. end,
  163. }),
  164. }):find()
  165. end
  166. -- shows added/removed/changed lines
  167. require('gitsigns').setup()
  168. require('mini.statusline').setup({
  169. content = {
  170. -- copy-pasted from default, we just want to remove the icon
  171. active = function()
  172. local mode, mode_hl = MiniStatusline.section_mode({ trunc_width = 120 })
  173. local git = MiniStatusline.section_git({ trunc_width = 75, icon = '' })
  174. local diagnostics = MiniStatusline.section_diagnostics({ trunc_width = 75, icon = '' })
  175. local filename = MiniStatusline.section_filename({ trunc_width = 140 })
  176. local fileinfo = MiniStatusline.section_fileinfo({ trunc_width = 120 })
  177. local location = MiniStatusline.section_location({ trunc_width = 75 })
  178. return MiniStatusline.combine_groups({
  179. { hl = mode_hl, strings = { mode } },
  180. { hl = 'MiniStatuslineDevinfo', strings = { git, diagnostics } },
  181. '%<', -- Mark general truncate point
  182. { hl = 'MiniStatuslineFilename', strings = { filename } },
  183. '%=', -- End left alignment
  184. { hl = 'MiniStatuslineFileinfo', strings = { fileinfo } },
  185. { hl = mode_hl, strings = { location } },
  186. })
  187. end
  188. },
  189. })
  190. -- delete buffer while preserving layout
  191. require('mini.bufremove').setup()
  192. -- shows a line indicating the current indentation scope
  193. require('mini.indentscope').setup()
  194. -- comment actions
  195. require('mini.comment').setup()
  196. -- surround actions
  197. require('mini.surround').setup()
  198. local spec_treesitter = require('mini.ai').gen_spec.treesitter
  199. require('mini.ai').setup({
  200. custom_textobjects = {
  201. [','] = spec_treesitter({
  202. a = '@parameter.outer',
  203. i = '@parameter.inner',
  204. }),
  205. },
  206. });
  207. -- align actions
  208. require('mini.align').setup()
  209. -- repeatable f/t
  210. require('mini.jump').setup({
  211. mappings = {
  212. repeat_jump = '',
  213. },
  214. delay = {
  215. highlight = 10000000,
  216. },
  217. })
  218. -- autopair brackets
  219. require('mini.pairs').setup({
  220. mappings = {
  221. -- default config includes (, [ and {
  222. -- autopair <> if preceded by a character, otherwise it might be a regular
  223. -- comparison operation
  224. ['<'] = { action = 'open', pair = '<>', neigh_pattern = '%w.' },
  225. ['>'] = { action = 'close', pair = '<>' },
  226. },
  227. })
  228. -- notifications
  229. require('mini.notify').setup()
  230. vim.notify = require('mini.notify').make_notify()
  231. -- file explorer
  232. require('mini.files').setup({
  233. content = {
  234. -- remove icons
  235. prefix = function() end,
  236. }
  237. })
  238. -- rest client
  239. require('kulala').setup({
  240. global_keymaps = true,
  241. global_keymaps_prefix = '<leader>r'
  242. })
  243. -- Use Treesitter for syntax highlighting
  244. require('nvim-treesitter.configs').setup({
  245. highlight = {
  246. enable = true,
  247. },
  248. indent = {
  249. enable = true,
  250. },
  251. incremental_selection = {
  252. enable = true,
  253. keymaps = {
  254. init_selection = "]t",
  255. node_incremental = "]t",
  256. node_decremental = "[t",
  257. },
  258. },
  259. textobjects = {
  260. swap = {
  261. enable = true,
  262. swap_next = {
  263. ['>,'] = '@parameter.inner',
  264. },
  265. swap_previous = {
  266. ['<,'] = '@parameter.inner',
  267. },
  268. },
  269. },
  270. })
  271. local tsj_utils = require('treesj.langs.utils')
  272. -- Treesitter-aware split/join
  273. require('treesj').setup({
  274. use_default_keymaps = false,
  275. })
  276. -- Treesitter context
  277. require('treesitter-context').setup({
  278. enable = true,
  279. multiline_threshold = 5,
  280. })
  281. -- completion
  282. require('blink.cmp').setup({
  283. cmdline = {
  284. enabled = false,
  285. },
  286. completion = {
  287. documentation = {
  288. auto_show = true,
  289. auto_show_delay_ms = 500,
  290. },
  291. trigger = {
  292. prefetch_on_insert = false,
  293. show_on_keyword = false,
  294. show_on_trigger_character = false,
  295. },
  296. menu = {
  297. draw = {
  298. columns = {
  299. { "label", "label_description", gap = 1 },
  300. { "kind" },
  301. },
  302. },
  303. },
  304. },
  305. keymap = {
  306. ['<Enter>'] = { 'select_and_accept', 'fallback' },
  307. ['<C-u>'] = { 'scroll_documentation_up', 'fallback_to_mappings' },
  308. ['<C-d>'] = { 'scroll_documentation_down', 'fallback_to_mappings' },
  309. },
  310. })
  311. -- typescript-vim compiler options
  312. vim.g.typescript_compiler_options = '--incremental --noEmit'