plugins.lua 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  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. require('telescope').setup({
  15. defaults = {
  16. mappings = {
  17. i = {
  18. ['jj'] = 'close',
  19. },
  20. },
  21. layout_config = {
  22. prompt_position = 'top',
  23. },
  24. sorting_strategy = 'ascending',
  25. -- use filename as preview window title
  26. dynamic_preview_title = true,
  27. preview = {
  28. -- don't preview files larger than 1MB
  29. filesize_limit = 1,
  30. timeout = 500,
  31. },
  32. -- ignore things we're likely not to edit
  33. file_ignore_patterns = {
  34. "%.zip$",
  35. "%.yarn/releases/",
  36. "%.yarn/plugins/"
  37. },
  38. },
  39. pickers = {
  40. buffers = {
  41. sort_lastused = true,
  42. sort_mru = true,
  43. mappings = {
  44. i = {
  45. ['<C-k>'] = 'delete_buffer'
  46. },
  47. },
  48. },
  49. find_files = {
  50. find_command = { "fd", "--type", "f", "--strip-cwd-prefix" }
  51. },
  52. },
  53. })
  54. -- use native sorter for better performance
  55. require('telescope').load_extension('fzf')
  56. local telescope_builtin = require('telescope.builtin')
  57. local telescope_pickers = require('telescope.pickers')
  58. local telescope_finders = require('telescope.finders')
  59. local telescope_previewers = require('telescope.previewers')
  60. local telescope_putils = require('telescope.previewers.utils')
  61. local telescope_conf = require('telescope.config').values
  62. -- custom picker to fallback to files if no git
  63. _G.project_files = function()
  64. local ok = pcall(telescope_builtin.git_files, { show_untracked = true })
  65. if not ok then telescope_builtin.find_files({}) end
  66. end
  67. -- custom picker for files within a commit
  68. _G.commit_files = function(opts)
  69. local current_path = vim.api.nvim_buf_get_name(0)
  70. local parsed = vim.fn.FugitiveParse(current_path)
  71. local resolved_path = parsed[1]
  72. local repo = parsed[2]
  73. if resolved_path == "" then
  74. vim.print("current file is not a fugitive path")
  75. return
  76. end
  77. local parts = vim.split(resolved_path, ':')
  78. local commit = parts[1]
  79. opts = opts or {}
  80. telescope_pickers.new(opts, {
  81. prompt_title = commit,
  82. finder = telescope_finders.new_oneshot_job({ "git", "ls-tree", "--name-only", "-r", commit }, {
  83. entry_maker = function(entry)
  84. local path = string.format("fugitive://%s//%s/%s", repo, commit, entry)
  85. return {
  86. path = path,
  87. value = entry,
  88. display = entry,
  89. ordinal = entry,
  90. }
  91. end,
  92. }),
  93. sorter = telescope_conf.file_sorter(opts),
  94. -- the builtin previewer has fancy async loading which doesn't work for
  95. -- fugitive paths so we have to define our own
  96. previewer = telescope_previewers.new_buffer_previewer({
  97. title = function(self)
  98. return 'Commit Files'
  99. end,
  100. dyn_title = function(self, entry)
  101. return entry.value
  102. end,
  103. define_preview = function(self, entry, status)
  104. -- the builtin previewer does more things like using mime type
  105. -- fallbacks as well as binary file detection which ours doesn't do
  106. local ft = telescope_putils.filetype_detect(entry.value)
  107. vim.api.nvim_buf_call(self.state.bufnr, function()
  108. vim.cmd('Gread ' .. entry.path)
  109. telescope_putils.highlighter(self.state.bufnr, ft, opts)
  110. end)
  111. end,
  112. }),
  113. }):find()
  114. end
  115. -- shows added/removed/changed lines
  116. require('gitsigns').setup()
  117. require('mini.statusline').setup({
  118. content = {
  119. -- copy-pasted from default, we just want to remove the icon
  120. active = function()
  121. local mode, mode_hl = MiniStatusline.section_mode({ trunc_width = 120 })
  122. local git = MiniStatusline.section_git({ trunc_width = 75, icon = '' })
  123. local diagnostics = MiniStatusline.section_diagnostics({ trunc_width = 75, icon = '' })
  124. local filename = MiniStatusline.section_filename({ trunc_width = 140 })
  125. local fileinfo = MiniStatusline.section_fileinfo({ trunc_width = 120 })
  126. local location = MiniStatusline.section_location({ trunc_width = 75 })
  127. return MiniStatusline.combine_groups({
  128. { hl = mode_hl, strings = { mode } },
  129. { hl = 'MiniStatuslineDevinfo', strings = { git, diagnostics } },
  130. '%<', -- Mark general truncate point
  131. { hl = 'MiniStatuslineFilename', strings = { filename } },
  132. '%=', -- End left alignment
  133. { hl = 'MiniStatuslineFileinfo', strings = { fileinfo } },
  134. { hl = mode_hl, strings = { location } },
  135. })
  136. end
  137. },
  138. })
  139. -- delete buffer while preserving layout
  140. require('mini.bufremove').setup()
  141. -- shows a line indicating the current indentation scope
  142. require('mini.indentscope').setup()
  143. -- comment actions
  144. require('mini.comment').setup()
  145. -- surround actions
  146. require('mini.surround').setup()
  147. local spec_treesitter = require('mini.ai').gen_spec.treesitter
  148. require('mini.ai').setup({
  149. custom_textobjects = {
  150. [','] = spec_treesitter({
  151. a = '@parameter.outer',
  152. i = '@parameter.inner',
  153. }),
  154. },
  155. });
  156. -- align actions
  157. require('mini.align').setup()
  158. -- repeatable f/t
  159. require('mini.jump').setup({
  160. mappings = {
  161. repeat_jump = '',
  162. },
  163. delay = {
  164. highlight = 10000000,
  165. },
  166. })
  167. -- notifications
  168. require('mini.notify').setup()
  169. vim.notify = require('mini.notify').make_notify()
  170. -- rest client
  171. require('rest-nvim').setup({})
  172. -- Use Treesitter for syntax highlighting
  173. require('nvim-treesitter.configs').setup({
  174. highlight = {
  175. enable = true,
  176. },
  177. incremental_selection = {
  178. enable = true,
  179. keymaps = {
  180. init_selection = "]t",
  181. node_incremental = "]t",
  182. node_decremental = "[t",
  183. },
  184. },
  185. textobjects = {
  186. swap = {
  187. enable = true,
  188. swap_next = {
  189. ['>,'] = '@parameter.inner',
  190. },
  191. swap_previous = {
  192. ['<,'] = '@parameter.inner',
  193. },
  194. },
  195. },
  196. })
  197. local tsj_utils = require('treesj.langs.utils')
  198. -- Treesitter-aware split/join
  199. require('treesj').setup({
  200. use_default_keymaps = false,
  201. })
  202. -- completion
  203. local cmp = require('cmp')
  204. local cmp_types = require('cmp.types')
  205. cmp.setup({
  206. snippet = {
  207. expand = function(args)
  208. vim.fn['vsnip#anonymous'](args.body)
  209. end,
  210. },
  211. mapping = cmp.mapping.preset.insert({
  212. ['<C-b>'] = cmp.mapping.scroll_docs(-4),
  213. ['<C-f>'] = cmp.mapping.scroll_docs(4),
  214. ['<C-Space>'] = cmp.mapping.complete(),
  215. ['<C-e>'] = cmp.mapping.abort(),
  216. ['<CR>'] = cmp.mapping.confirm({ select = true }), -- Accept currently selected item. Set `select` to `false` to only confirm explicitly selected items.
  217. }),
  218. sources = cmp.config.sources({
  219. {
  220. name = "nvim_lsp",
  221. entry_filter = function(entry, ctx)
  222. -- don't autocomplete keywords
  223. return cmp_types.lsp.CompletionItemKind[entry:get_kind()] ~= 'Keyword'
  224. end
  225. },
  226. { name = "vsnip" },
  227. }),
  228. completion = {
  229. autocomplete = false,
  230. },
  231. matching = {
  232. -- disable non-prefix matching
  233. disallow_fuzzy_matching = true,
  234. disallow_partial_matching = true,
  235. disallow_prefix_unmatching = true,
  236. },
  237. sorting = {
  238. comparators = {
  239. -- since we only have prefix matches, just sort the results
  240. cmp.config.compare.sort_text,
  241. },
  242. },
  243. })
  244. -- format on save
  245. local format_on_save = require("format-on-save")
  246. local formatters = require("format-on-save.formatters")
  247. local vim_notify = require("format-on-save.error-notifiers.vim-notify")
  248. -- only format with LSP if there are clients attached
  249. local lsp_formatter = formatters.custom({
  250. format = function()
  251. local bufnr = vim.api.nvim_get_current_buf()
  252. local clients = vim.lsp.get_active_clients({ bufnr = bufnr })
  253. if #clients > 0 then
  254. vim.lsp.buf.format({ timeout_ms = 4000, bufnr = bufnr })
  255. end
  256. end
  257. })
  258. local js = {
  259. lsp_formatter,
  260. formatters.if_file_exists({
  261. pattern = {
  262. "dprint.json",
  263. "dprint.jsonc",
  264. ".dprint.json",
  265. ".dprint.jsonc",
  266. },
  267. formatter = formatters.shell({ cmd = { "dprint", "fmt", "--stdin", "%" }}),
  268. }),
  269. }
  270. format_on_save.setup({
  271. error_notifier = vim_notify,
  272. exclude_path_patterns = {
  273. "/node_modules/",
  274. },
  275. formatter_by_ft = {
  276. javascript = js,
  277. typescript = js,
  278. typescriptreact = js,
  279. },
  280. fallback_formatter = {
  281. formatters.remove_trailing_whitespace,
  282. lsp_formatter,
  283. },
  284. })
  285. -- typescript-vim compiler options
  286. vim.g.typescript_compiler_options = '--incremental --noEmit'