local get_disable_cmp_filetypes = require('plugin_utils').get_disable_cmp_filetypes local base_colors = require('color').base_colors local codicons = require('font').codicons local misc_icons = require('font').misc_icons local list_concat = require('utils').list_concat return { { 'hrsh7th/nvim-cmp', event = { 'InsertEnter', 'CmdlineEnter' }, dependencies = { { 'hrsh7th/cmp-nvim-lsp' }, { 'hrsh7th/cmp-nvim-lua' }, { 'ray-x/cmp-treesitter' }, { 'hrsh7th/cmp-buffer' }, { 'andersevenrud/cmp-tmux' }, { 'lukas-reineke/cmp-rg' }, { 'octaltree/cmp-look' }, { 'hrsh7th/cmp-path' }, { 'onsails/lspkind-nvim' }, { 'L3MON4D3/LuaSnip' }, { 'saadparwaiz1/cmp_luasnip' }, { 'kento-ogata/cmp-tsnip', dependencies = { { 'yuki-yano/tsnip.nvim' }, }, }, { 'tzachar/cmp-tabnine', build = './install.sh' }, { 'zbirenbaum/copilot-cmp', dependencies = { { 'zbirenbaum/copilot.lua' }, }, }, { 'hrsh7th/cmp-cmdline' }, { 'tzachar/cmp-fuzzy-path', dependencies = { { 'tzachar/fuzzy.nvim', dependencies = { { 'romgrk/fzy-lua-native' }, }, }, }, }, { 'kyazdani42/nvim-web-devicons' }, { 'cohama/lexima.vim' }, -- NOTE: Load before cmp }, init = function() vim.api.nvim_create_autocmd({ 'CmdlineEnter' }, { callback = function() require('cmp').setup({ enabled = true, }) end, }) vim.api.nvim_create_autocmd({ 'CmdlineLeave' }, { callback = function() require('cmp').setup({ enabled = vim.env.LSP == 'nvim', }) end, }) vim.api.nvim_create_autocmd({ 'ColorScheme' }, { pattern = { 'gruvbox-material' }, callback = function() vim.api.nvim_set_hl(0, 'CmpItemKindUnit', { fg = base_colors.yellow }) vim.api.nvim_set_hl(0, 'CmpItemKindNumber', { fg = base_colors.magenta }) vim.api.nvim_set_hl(0, 'CmpItemKindFunction', { fg = base_colors.green }) vim.api.nvim_set_hl(0, 'CmpItemKindKey', { fg = base_colors.blue }) vim.api.nvim_set_hl(0, 'CmpItemKindKeyword', { fg = base_colors.red }) vim.api.nvim_set_hl(0, 'CmpItemKindReference', { fg = base_colors.cyan }) vim.api.nvim_set_hl(0, 'CmpItemKindFolder', { fg = base_colors.yellow }) vim.api.nvim_set_hl(0, 'CmpItemKindVariable', { fg = base_colors.magenta }) vim.api.nvim_set_hl(0, 'CmpItemKindNull', { fg = base_colors.yellow }) vim.api.nvim_set_hl(0, 'CmpItemKindValue', { fg = base_colors.yellow }) vim.api.nvim_set_hl(0, 'CmpItemKindConstant', { fg = base_colors.white }) vim.api.nvim_set_hl(0, 'CmpItemKindText', { fg = base_colors.green }) vim.api.nvim_set_hl(0, 'CmpItemKindModule', { fg = base_colors.red }) vim.api.nvim_set_hl(0, 'CmpItemKindPackage', { fg = base_colors.red }) vim.api.nvim_set_hl(0, 'CmpItemKindClass', { fg = base_colors.green }) vim.api.nvim_set_hl(0, 'CmpItemKindOperator', { fg = base_colors.orange }) vim.api.nvim_set_hl(0, 'CmpItemKindStruct', { fg = base_colors.red }) vim.api.nvim_set_hl(0, 'CmpItemKindObject', { fg = base_colors.yellow }) vim.api.nvim_set_hl(0, 'CmpItemKindMethod', { fg = base_colors.green }) vim.api.nvim_set_hl(0, 'CmpItemKindArray', { fg = base_colors.yellow }) vim.api.nvim_set_hl(0, 'CmpItemKindEnum', { fg = base_colors.yellow }) vim.api.nvim_set_hl(0, 'CmpItemKindField', { fg = base_colors.blue }) vim.api.nvim_set_hl(0, 'CmpItemKindInterface', { fg = base_colors.yellow }) vim.api.nvim_set_hl(0, 'CmpItemKindProperty', { fg = base_colors.blue }) vim.api.nvim_set_hl(0, 'CmpItemKindColor', { fg = base_colors.magenta }) vim.api.nvim_set_hl(0, 'CmpItemKindFile', { fg = base_colors.red }) vim.api.nvim_set_hl(0, 'CmpItemKindEvent', { fg = base_colors.white }) vim.api.nvim_set_hl(0, 'CmpItemKindTypeParameter', { fg = base_colors.white }) vim.api.nvim_set_hl(0, 'CmpItemKindConstructor', { fg = base_colors.green }) vim.api.nvim_set_hl(0, 'CmpItemKindSnippet', { fg = base_colors.yellow }) vim.api.nvim_set_hl(0, 'CmpItemKindBoolean', { fg = base_colors.magenta }) vim.api.nvim_set_hl(0, 'CmpItemKindNamespace', { fg = base_colors.yellow }) vim.api.nvim_set_hl(0, 'CmpItemKindString', { fg = base_colors.cyan }) vim.api.nvim_set_hl(0, 'CmpItemKindEnumMember', { fg = base_colors.blue }) end, }) end, config = function() local cmp = require('cmp') local luasnip = require('luasnip') local lspkind = require('lspkind') require('cmp.utils.misc').redraw.incsearch_redraw_keys = '' lspkind.init({ preset = 'codicons', symbol_map = codicons, }) -- NOTE: After load lexima key mappings require('copilot').setup({ suggestion = { auto_trigger = true, keymap = { accept = '', -- is used for insx dismiss = false, }, }, filetypes = { ['.'] = true, -- typescript = true, -- typescriptreact = true, -- lua = true, -- vim = true, }, }) require('copilot_cmp').setup() -- NOTE: force_keyword_length is used from manual complete local sources = { { name = 'luasnip', keyword_length = 2, force_keyword_length = true }, { name = 'tsnip', keyword_length = 2, force_keyword_length = true }, { name = 'copilot' }, { name = 'nvim_lsp', max_item_count = 30 }, { name = 'treesitter' }, { name = 'nvim_lua', max_item_count = 20 }, { name = 'cmp_tabnine' }, { name = 'buffer' }, { name = 'tmux', keyword_length = 4, max_item_count = 10, option = { all_panes = true } }, { name = 'rg', keyword_length = 4, max_item_count = 10 }, { name = 'look', keyword_length = 4, max_item_count = 10, option = { convert_case = true, loud = true } }, { name = 'path' }, } cmp.setup({ enabled = vim.env.LSP == 'nvim', mapping = vim.env.LSP == 'nvim' and cmp.mapping.preset.insert({ [''] = cmp.mapping.scroll_docs(-4), [''] = cmp.mapping.scroll_docs(4), [''] = cmp.mapping(function() local input = vim.api.nvim_get_current_line():sub(1, vim.api.nvim_win_get_cursor(0)[2]) local match_list = vim.fn.matchlist(input, [[\k\+$]]) local length = vim.fn.len(match_list) == 0 and 0 or vim.fn.len(match_list[1]) -- Force use of keyword_length if force_keyword_length is true local manual_sources = {} for _, source in ipairs(sources) do if source.force_keyword_length then if length >= source.keyword_length then table.insert(manual_sources, source) end else table.insert(manual_sources, source) end end cmp.mapping.complete({ config = { sources = cmp.config.sources(manual_sources), }, })() end), [''] = cmp.mapping.abort(), [''] = cmp.mapping(function(fallback) if cmp.visible() and cmp.get_selected_entry() then cmp.confirm({ select = true }) else fallback() end end), [''] = cmp.mapping(function(fallback) if luasnip.jumpable(1) then luasnip.jump(1) else fallback() end end, { 'i', 's' }), [''] = cmp.mapping(function(fallback) if luasnip.jumpable(-1) then luasnip.jump(-1) else fallback() end end, { 'i', 's' }), }) or {}, window = { completion = cmp.config.window.bordered({}), documentation = cmp.config.window.bordered({}), }, sources = cmp.config.sources(sources), formatting = { fields = { 'kind', 'abbr', 'menu' }, format = lspkind.cmp_format({ mode = 'symbol', menu = { luasnip = '[Snippet]', tsnip = '[TSnip]', copilot = '[Copilot]', nvim_lsp = '[LSP]', treesitter = '[Tree]', nvim_lua = '[Lua]', cmp_tabnine = '[Tabnine]', buffer = '[Buffer]', tmux = '[Tmux]', rg = '[Rg]', look = '[Look]', path = '[Path]', }, }), }, snippet = { expand = function(args) luasnip.lsp_expand(args.body) end, }, }) local incsearch_settings = { mapping = cmp.mapping.preset.cmdline({ [''] = vim.NIL, [''] = vim.NIL, [''] = vim.NIL, }), sources = cmp.config.sources({ { name = 'buffer' }, }), formatting = { fields = { 'kind', 'abbr' }, format = lspkind.cmp_format({ mode = 'symbol' }), }, } cmp.setup.cmdline('/', incsearch_settings) cmp.setup.cmdline('?', incsearch_settings) cmp.setup.cmdline(':', { mapping = cmp.mapping.preset.cmdline({ [''] = vim.NIL, [''] = vim.NIL, [''] = vim.NIL, }), sources = cmp.config.sources({ { name = 'cmdline' }, { name = 'path' }, { name = 'fuzzy_path', trigger_characters = { ' ', '.', '/', '~' }, options = { fd_cmd = { 'fd', '--hidden', '--max-depth', '20', '--full-path', '--exclude', '.git', }, }, entry_filter = function(entry) return not vim.tbl_contains({ 'No matches found', 'Searching...' }, entry:get_word()) end, }, }), formatting = { fields = { 'kind', 'abbr', 'menu' }, format = function(entry, vim_item) if vim.tbl_contains({ 'path', 'fuzzy_path' }, entry.source.name) then local icon, hl_group = require('nvim-web-devicons').get_icon(entry:get_completion_item().label) if icon then vim_item.kind = icon vim_item.kind_hl_group = hl_group else vim_item.kind = misc_icons.file end elseif 'cmdline' == entry.source.name then vim_item.kind = misc_icons.cmd vim_item.dup = true end return lspkind.cmp_format()(entry, vim_item) end, }, }) -- Insert '(' after confirm function or method item cmp.event:on('confirm_done', function(evt) local Kind = cmp.lsp.CompletionItemKind -- TypeScript imported functions are completed as variable with the format `(alias) function {func_name} ...`. local ts_extra_matcher = function(item) return item.kind == Kind.Variable and string.match(item.detail, '^%(alias%) function ') ~= nil end local rules = { -- NOTE: Disabled because vtsls returns snippet -- typescript = { -- ['('] = { -- kind = { Kind.Function, Kind.Method }, -- extra_matcher = ts_extra_matcher, -- }, -- }, -- typescriptreact = { -- ['('] = { -- kind = { Kind.Function, Kind.Method }, -- extra_matcher = ts_extra_matcher, -- }, -- }, } local filetype = vim.o.filetype local item = evt.entry:get_completion_item() if rules[filetype] then for key, rule in pairs(rules[filetype]) do if vim.tbl_contains(rule.kind, item.kind) or rule.extra_matcher(item) then vim.api.nvim_feedkeys(key, 'i', true) end end end end) vim.api.nvim_create_autocmd({ 'FileType' }, { pattern = get_disable_cmp_filetypes(), callback = function() cmp.setup.buffer({ completion = { autocomplete = false }, }) end, }) end, }, { 'L3MON4D3/LuaSnip', config = function() require('luasnip.loaders.from_vscode').lazy_load({ paths = '~/.config/nvim/luasnip' }) end, }, { 'yuki-yano/tsnip.nvim', dependencies = { { 'vim-denops/denops.vim' }, { 'yuki-yano/denops-lazy.nvim' }, { 'MunifTanjim/nui.nvim' }, }, event = { 'InsertEnter' }, cmd = { 'TSnip' }, config = function() require('denops-lazy').load('tsnip.nvim', { wait_load = false }) end, }, { 'machakann/vim-sandwich', dependencies = { { 'machakann/vim-textobj-functioncall' }, { 'kana/vim-textobj-entire' }, { 'kana/vim-textobj-line' }, { 'thinca/vim-textobj-between' }, { 'yuki-yano/vim-textobj-cursor-context' }, }, event = { 'ModeChanged' }, keys = { { '(sandwich-add)', mode = { 'n', 'x' } }, { '(sandwich-delete)', mode = { 'n', 'x' } }, { '(sandwich-delete-auto)', mode = { 'n', 'x' } }, { '(sandwich-replace)', mode = { 'n', 'x' } }, { '(sandwich-replace-auto)', mode = { 'n', 'x' } }, { '(textobj-sandwich-auto-i)', mode = { 'o', 'x' } }, { '(textobj-sandwich-auto-a)', mode = { 'o', 'x' } }, }, init = function() vim.g.sandwich_no_default_key_mappings = true vim.keymap.set({ 'n', 'x' }, 'sa', '(sandwich-add)') vim.keymap.set({ 'n', 'x' }, 'sd', '(sandwich-delete)') vim.keymap.set({ 'n', 'x' }, 'sdb', '(sandwich-delete-auto)') vim.keymap.set({ 'n', 'x' }, 'sr', '(sandwich-replace)') vim.keymap.set({ 'n', 'x' }, 'srb', '(sandwich-replace-auto)') vim.keymap.set({ 'o', 'x' }, 'ib', '(textobj-sandwich-auto-i)') vim.keymap.set({ 'o', 'x' }, 'ab', '(textobj-sandwich-auto-a)') end, config = function() local vimx = require('artemis') local sandwich_recipes = vim.fn.deepcopy(vim.g['sandwich#default_recipes']) sandwich_recipes = list_concat({ sandwich_recipes, { { buns = { '_', '_' }, quoteescape = 1, expand_range = 0, nesting = 1, linewise = 0, match_syntax = 1, }, { buns = { '-', '-' }, quoteescape = 1, expand_range = 0, nesting = 1, linewise = 0, match_syntax = 1, }, { buns = { '/', '/' }, quoteescape = 1, expand_range = 0, nesting = 0, linewise = 0, match_syntax = 1, }, { buns = { '${', '}' }, input = { '$' }, filetype = { 'typescript', 'typescriptreact' }, }, { buns = { '[[', ']]' }, input = { 's' }, nesting = 0, filetype = { 'lua' }, }, { buns = { '[=[', ']=]' }, input = { 'S' }, nesting = 0, filetype = { 'lua' }, }, }, }) vim.g['sandwich#magicchar#f#patterns'] = { { header = [[\<\%(\h\k*\.\)*\h\k*]], bra = '(', ket = ')', footer = '', }, } sandwich_recipes = list_concat({ sandwich_recipes, { { buns = { 'textobj#generics#input_generics()', '">"' }, expr = 1, cursor = 'inner_tail', kind = { 'add', 'replace' }, action = { 'add' }, input = { 'g' }, }, { external = { 'i<', vim.api.nvim_eval([["\(textobj-generics-i)"]]), }, noremap = 0, kind = { 'delete', 'replace', 'query' }, input = { 'g' }, }, }, }) vim.g['sandwich#recipes'] = sandwich_recipes vimx.fn.operator.sandwich.set('add', 'char', 'skip_space', 1) vim.cmd([[autocmd ModeChanged [vV\x16]*:* call operator#sandwich#set('add', 'char', 'skip_space', 1)]]) vim.cmd([[autocmd ModeChanged *:[vV\x16]* call operator#sandwich#set('add', 'char', 'skip_space', 0)]]) end, }, { 'machakann/vim-swap', keys = { { '(swap-prev)', mode = { 'n' } }, { '(swap-next)', mode = { 'n' } }, { '(swap-interactive)', mode = { 'n' } }, { '(swap-textobject-i)', mode = { 'o', 'x' } }, { '(swap-textobject-a)', mode = { 'o', 'x' } }, }, init = function() vim.keymap.set({ 'n' }, 'g<', '(swap-prev)') vim.keymap.set({ 'n' }, 'g>', '(swap-next)') vim.keymap.set({ 'n' }, 'gs', '(swap-interactive)') vim.keymap.set({ 'o', 'x' }, 'i,', '(swap-textobject-i)') vim.keymap.set({ 'o', 'x' }, 'a,', '(swap-textobject-a)') end, }, { 'cohama/lexima.vim', dependencies = { { 'windwp/nvim-ts-autotag' }, }, event = { 'InsertEnter', 'CmdlineEnter' }, init = function() vim.g.lexima_enable_space_rules = false end, config = function() local vimx = require('artemis') local rules = {} -- Base rule rules = list_concat({ rules, { { char = '', input = 'U', priority = 10 }, }, }) -- Parenthesis rules = list_concat({ rules, { { char = '', at = [[(\%#)]], input = '' }, { char = '', at = [[(\%#)]], input = '' }, }, }) -- Brace rules = list_concat({ rules, { { char = '', at = [[{\%#}]], input = '' }, { char = '', at = [[{\%#}]], input = '' }, { char = '', at = [[{\%#}]], input_after = '' }, { char = '', at = [[{\ \%# }]], delete = 1 }, }, }) -- Bracket rules = list_concat({ rules, { { char = '', at = [=[\[\%#\]]=], input = '' }, { char = '', at = [=[\[\%#\]]=], input = '' }, }, }) -- Single quote rules = list_concat({ rules, { { char = '', at = [['\%#']], input = '' }, { char = '', at = [['\%#']], input = '' }, }, }) -- Double quote rules = list_concat({ rules, { { char = '', at = [["\%#"]], input = '' }, { char = '', at = [["\%#"]], input = '' }, }, }) -- Back quote rules = list_concat({ rules, { { char = '', at = [[`\%#`]], input = '' }, { char = '', at = [[`\%#`]], input = '' }, }, }) -- Surround function -- NOTE: Use nvim-insx fast_wrap -- rules = list_concat({ -- rules, -- { -- { char = ';', at = [[);\%#]], input = ':normal! $a)' }, -- { char = ';', at = [[);\%#.*(.*]], input = ':normal! f(:normal %a)' }, -- }, -- }) -- TypeScript -- NOTE: `a` is a workaround to disable copilot rules = list_concat({ rules, -- const { { filetype = { 'typescript', 'typescriptreact' }, char = '', at = [[^\s*c\%#$]], input = 'const ', input_after = ' = ', }, { filetype = { 'typescript', 'typescriptreact' }, char = '', at = [[^\s*const \S\+\%# = $]], input = 'a', }, }, -- const arrow function { { filetype = { 'typescript', 'typescriptreact' }, char = '', at = [[^\s*cf\%#$]], input = 'const ', input_after = ' = () => {}', }, { filetype = { 'typescript', 'typescriptreact' }, char = '', at = [[^\s*const \S\+\%# = () => {$]], input = 'a:normal! f)a', }, { filetype = { 'typescript', 'typescriptreact' }, char = '', at = [[^\s*const \S\+ = (.*\%#) => {$]], input = 'a', }, }, -- function { { filetype = { 'typescript', 'typescriptreact' }, char = '', at = [[^\s*f\%#$]], input = 'function ', input_after = '() {}', }, { filetype = { 'typescript', 'typescriptreact' }, char = '', at = [[^\s*function \S\+(.*\%#) {$]], input = 'a', }, }, -- if { { filetype = { 'typescript', 'typescriptreact' }, char = '', at = [[^\s*if\%#$]], input = 'if (', input_after = ') {}', }, { filetype = { 'typescript', 'typescriptreact' }, char = '', at = [[^\s*if (.*\%#) {$]], input = 'a', }, }, -- expand arrow function -- NOTE: Try `cf` shorthand -- { -- { -- filetype = { 'typescript', 'typescriptreact' }, -- char = ';', -- at = [[\.[a-zA-Z]\+([a-zA-Z,]*;\%#)]], -- input = ' => {', -- input_after = '}', -- }, -- { -- filetype = { 'typescript', 'typescriptreact' }, -- char = ';', -- at = [[\.[a-zA-Z]\+(([a-zA-Z, :<>]*;\%#))]], -- input = 'U => {', -- input_after = '}', -- }, -- { -- filetype = { 'typescript', 'typescriptreact' }, -- char = ';', -- at = [[([a-zA-Z, :<>]*;\%#)]], -- input = 'U => {', -- input_after = '}', -- }, -- { -- filetype = { 'typescript', 'typescriptreact' }, -- char = ';', -- at = [[({[a-zA-Z, :<>]\+;\%#\s\?})]], -- input = ':normal! f)aU => {}', -- }, -- }, }) -- pp rules = list_concat({ rules, { { filetype = { 'typescript', 'typescriptreact' }, char = 'p', at = [[^\s*p\%#$]], input = 'console.log(', input_after = ')', }, }, }) -- log level rotate for level, next_level in pairs({ log = { next = 'warn', prev = 'info', }, warn = { next = 'error', prev = 'log', }, error = { next = 'debug', prev = 'warn', }, debug = { next = 'info', prev = 'error', }, info = { next = 'log', prev = 'debug', }, }) do rules = list_concat({ rules, { { filetype = { 'typescript', 'typescriptreact' }, at = [[console\.]] .. level .. [[(\%#]], char = '', input = '' .. next_level.next .. '(', }, { filetype = { 'typescript', 'typescriptreact' }, at = [[console\.]] .. level .. [[(\%#]], char = '', input = '' .. next_level.prev .. '(', }, }, }) end -- TSX with nvim-ts-autotag rules = list_concat({ rules, { { filetype = { 'typescript', 'typescriptreact' }, char = '>', at = [[<[a-zA-Z.]\+\(\s\)\?.*\%#]], input = [[>:lua require('nvim-ts-autotag.internal').close_tag()a]], }, }, }) -- Lua rules = list_concat({ rules, { { filetype = { 'lua' }, char = 'p', at = [[^\s*p\%#]], input = 'vim.pretty_print(', input_after = ')', }, }, }) -- Markdown rules = list_concat({ rules, { { filetype = 'markdown', char = '#', at = [=[^\%#\%(#\)\@!]=], input = '#', }, { filetype = 'markdown', char = '#', at = [=[#\s\%#]=], input = '#', }, { filetype = 'markdown', char = '', at = [=[^#\s\%#]=], input = '', }, { filetype = 'markdown', char = '', at = [=[##\s\%#]=], input = '', }, { filetype = 'markdown', char = '', at = [=[^#\s\%#]=], input = '', }, { filetype = 'markdown', char = '', at = [=[##\s\%#]=], input = '', }, { filetype = 'markdown', char = '-', at = [=[^\s*\%#]=], input = '-', }, { filetype = 'markdown', char = '', at = [=[^\s*-\s\%#]=], input = '', }, { filetype = 'markdown', char = '', at = [=[^\s*-\s\w.*\%#]=], input = '', }, { filetype = 'markdown', char = '', at = [=[^\s\+-\s\%#]=], input = '', }, { filetype = 'markdown', char = '', at = [=[^\s\+-\s\w.*\%#]=], input = '', }, { filetype = 'markdown', char = '', at = [=[^-\s\w.*\%#]=], input = '', }, { filetype = 'markdown', char = '', at = [=[^-\s\%#]=], input = '', }, { filetype = 'markdown', char = '', at = [=[^\s\+-\s\%#]=], input = '', }, { filetype = 'markdown', char = '', at = [=[^-\s\%#]=], input = '', }, { filetype = 'markdown', char = '', at = [=[^\s\+-\s\%#]=], input = '', }, { filetype = 'markdown', char = '', at = [=[^-\s\%#]=], input = '', }, { filetype = 'markdown', char = '', at = [=[^\s\+-\s\%#]=], input = '', }, { filetype = 'markdown', char = '', at = [=[^\s*-\s\w.*\%#]=], input = '-', }, { filetype = 'markdown', char = '[', at = [=[^\s*-\s\%#]=], input = '[]', }, { filetype = 'markdown', char = '', at = [=[^\s*-\s\[\%#\]\s]=], input = '', }, { filetype = 'markdown', char = '', at = [=[^-\s\[\%#\]\s]=], input = '', }, { filetype = 'markdown', char = '', at = [=[^\s\+-\s\[\%#\]\s]=], input = '', }, { filetype = 'markdown', char = '', at = [=[^\s*-\s\[\%#\]]=], input = '', }, { filetype = 'markdown', char = '', at = [=[^\s*-\s\[\%#\]]=], input = '', }, { filetype = 'markdown', char = '', at = [=[^\s*-\s\[\%#\]]=], input = '', }, { filetype = 'markdown', char = 'x', at = [=[^\s*-\s\[\%#\]]=], input = 'x', }, { filetype = 'markdown', char = '', at = [=[^-\s\[\%#\]]=], input = '', }, { filetype = 'markdown', char = '', at = [=[^\s\+-\s\[\%#\]]=], input = '', }, { filetype = 'markdown', char = '', at = [=[^\s*-\s\[\(\s\|x\)\]\s\%#]=], input = '', }, { filetype = 'markdown', char = '', at = [=[^\s*-\s\[\(\s\|x\)\]\s\w.*\%#]=], input = '', }, { filetype = 'markdown', char = '', at = [=[^\s\+-\s\[\(\s\|x\)\]\s\%#]=], input = '', }, { filetype = 'markdown', char = '', at = [=[^\s\+-\s\[\(\s\|x\)\]\s\w.*\%#]=], input = '', }, { filetype = 'markdown', char = '', at = [=[^-\s\[\(\s\|x\)\]\s\w.*\%#]=], input = '', }, { filetype = 'markdown', char = '', at = [=[^-\s\[\(\s\|x\)\]\s\%#]=], input = '', }, { filetype = 'markdown', char = '', at = [=[^\s\+-\s\[\(\s\|x\)\]\s\%#]=], input = '', }, { filetype = 'markdown', char = '', at = [=[^-\s\[\(\s\|x\)\]\s\%#]=], input = '', }, { filetype = 'markdown', char = '', at = [=[^\s\+-\s\[\(\s\|x\)\]\s\%#]=], input = '', }, { filetype = 'markdown', char = '', at = [=[^-\s\[\(\s\|x\)\]\s\%#]=], input = '', }, { filetype = 'markdown', char = '', at = [=[^\s\+-\s\[\(\s\|x\)\]\s\%#]=], input = '', }, { filetype = 'markdown', char = '', at = [=[^\s*-\s\[\(\s\|x\)\]\s\w.*\%#]=], input = '-[]', }, }, }) for _, rule in ipairs(rules) do vimx.fn.lexima.add_rule(rule) end end, }, { 'yuki-yano/lexima-alter-command.vim', dependencies = { { 'cohama/lexima.vim' }, }, event = { 'CmdlineEnter' }, config = function() vim.cmd([[ LeximaAlterCommand ee e! LeximaAlterCommand dp diffput LeximaAlterCommand la\%[zy] Lazy LeximaAlterCommand rg Rg LeximaAlterCommand or\%[ganizeimport] OrganizeImport LeximaAlterCommand gina Gina LeximaAlterCommand gin Gin LeximaAlterCommand blame Ginablame LeximaAlterCommand bro\%[wse] Ginabrowse--exact: LeximaAlterCommand cap\%[ture] Capture LeximaAlterCommand r\%[un] QuickRun LeximaAlterCommand tr\%[ouble] TroubleToggle LeximaAlterCommand ss SaveProjectLayout LeximaAlterCommand sl LoadProjectLayout LeximaAlterCommand re\%[view] AiReview LeximaAlterCommand pr\%[ompt] AiPrompt LeximaAlterCommand yr YR LeximaAlterCommand te\%[lescope] Telescope ]]) end, }, { 'hrsh7th/nvim-insx', dependencies = { { 'cohama/lexima.vim' }, -- NOTE: Load before insx }, event = { 'InsertEnter', 'CmdlineEnter' }, config = function() local insx = require('insx') local esc = require('insx.helper.regex').esc local fast_wrap = require('insx.recipe.fast_wrap') local fast_break = require('insx.recipe.fast_break') -- Alias to vim.keymap.set({ 'i', 'c' }, '', '', { remap = true }) -- Not use insert mode preset require('insx.preset.standard').setup_cmdline_mode({ cmdline = { enabled = true, }, }) -- NOTE: Preset maps to `<` and `>`, so set the mappings manually -- quote for _, quote in ipairs({ '"', "'", '`' }) do -- jump next insx.add( quote, require('insx.recipe.jump_next')({ jump_pat = { [[\\\@', require('insx.recipe.delete_pair')({ open_pat = esc(quote), close_pat = esc(quote), ignore_pat = ([[\\%s\%%#]]):format(esc(quote)), }) ) end -- bracket for open, close in pairs({ ['('] = ')', ['['] = ']', ['{'] = '}' }) do -- jump next insx.add(close, require('insx.recipe.jump_next')({ jump_pat = { [[\%#]] .. esc(close) .. [[\zs]] } })) -- auto pair insx.add(open, require('insx.recipe.auto_pair')({ open = open, close = close })) -- delete pair insx.add('', require('insx.recipe.delete_pair')({ open_pat = esc(open), close_pat = esc(close) })) -- fast wrap insx.add('', fast_wrap({ close = close })) -- fast break insx.add('', fast_break({ open_pat = esc(open), close_pat = esc(close), split = true })) end -- spacing `()` and `{}` (ignore `[]`) for open, close in pairs({ ['('] = ')', ['{'] = '}' }) do insx.add( '', require('insx.recipe.pair_spacing').increase({ open_pat = esc(open), close_pat = esc(close) }) ) insx.add('', require('insx.recipe.pair_spacing').decrease({ open_pat = esc(open), close_pat = esc(close) })) end -- Use lexima when markdown insx.add('', { priority = -1, action = function(ctx) ctx.send(vim.fn.keytrans(vim.fn['lexima#expand']('', 'i'))) end, enabled = function() return vim.o.filetype == 'markdown' end, }) end, }, { 'machakann/vim-textobj-functioncall', event = { 'ModeChanged' }, init = function() vim.g.textobj_functioncall_no_default_key_mappings = true vim.g.textobj_functioncall_patterns = { { header = [[\<\%(\h\k*\.\)*\h\k*]], bra = '(', ket = ')', footer = '', }, } vim.keymap.set({ 'o', 'x' }, 'if', '(textobj-functioncall-innerparen-i)') vim.keymap.set({ 'o', 'x' }, 'af', '(textobj-functioncall-i)') vim.g.textobj_functioncall_ts_string_variable_patterns = { { header = [[\$]], bra = '{', ket = '}', footer = '', }, } vim.keymap.set({ 'o', 'x' }, 'i$', '(textobj-functioncall-ts-string-variable-i)') vim.keymap.set({ 'o', 'x' }, 'a$', '(textobj-functioncall-ts-string-variable-a)') end, config = function() vim.keymap.set( { 'o' }, '(textobj-functioncall-ts-string-variable-i)', ':call textobj#functioncall#i("o", g:textobj_functioncall_ts_string_variable_patterns)', { silent = true } ) vim.keymap.set( { 'x' }, '(textobj-functioncall-ts-string-variable-i)', ':call textobj#functioncall#i("x", g:textobj_functioncall_ts_string_variable_patterns)', { silent = true } ) vim.keymap.set( { 'o' }, '(textobj-functioncall-ts-string-variable-a)', ':call textobj#functioncall#a("o", g:textobj_functioncall_ts_string_variable_patterns)', { silent = true } ) vim.keymap.set( { 'x' }, '(textobj-functioncall-ts-string-variable-a)', ':call textobj#functioncall#a("x", g:textobj_functioncall_ts_string_variable_patterns)', { silent = true } ) end, }, { 'yuki-yano/vim-textobj-generics', dependencies = { { 'machakann/vim-textobj-functioncall' }, }, event = { 'ModeChanged' }, init = function() vim.g.textobj_generics_no_default_key_mappings = true vim.keymap.set({ 'o', 'x' }, 'ig', '(textobj-generics-innerparen-i)') vim.keymap.set({ 'o', 'x' }, 'ag', '(textobj-generics-i)') end, }, { 'kana/vim-textobj-entire', dependencies = { { 'kana/vim-textobj-user' }, }, event = { 'ModeChanged' }, init = function() vim.g.textobj_entire_no_default_key_mappings = true vim.keymap.set({ 'o', 'x' }, 'ie', '(textobj-entire-i)') vim.keymap.set({ 'o', 'x' }, 'ae', '(textobj-entire-a)') end, }, { 'kana/vim-textobj-line', dependencies = { { 'kana/vim-textobj-user' }, }, event = { 'ModeChanged' }, init = function() vim.g.textobj_line_no_default_key_mappings = true vim.keymap.set({ 'o', 'x' }, 'il', '(textobj-line-i)') vim.keymap.set({ 'o', 'x' }, 'al', '(textobj-line-a)') end, }, { 'thinca/vim-textobj-between', dependencies = { { 'kana/vim-textobj-user' }, }, event = { 'ModeChanged' }, init = function() vim.g.textobj_between_no_default_key_mappings = true vim.keymap.set({ 'o', 'x' }, 'i/', '(textobj-between-i)/') vim.keymap.set({ 'o', 'x' }, 'a/', '(textobj-between-a)/') vim.keymap.set({ 'o', 'x' }, 'i_', '(textobj-between-i)_') vim.keymap.set({ 'o', 'x' }, 'a_', '(textobj-between-a)_') vim.keymap.set({ 'o', 'x' }, 'i-', '(textobj-between-i)-') vim.keymap.set({ 'o', 'x' }, 'a-', '(textobj-between-a)-') end, }, { 'yuki-yano/vim-textobj-cursor-context', dependencies = { { 'kana/vim-textobj-user' }, }, event = { 'ModeChanged' }, init = function() vim.g.textobj_cursorcontext_no_default_key_mappings = true vim.keymap.set({ 'o', 'x' }, 'ic', '(textobj-cursorcontext-i)') vim.keymap.set({ 'o', 'x' }, 'ac', '(textobj-cursorcontext-a)') end, }, { 'terryma/vim-expand-region', keys = { { '(expand_region_expand)', mode = { 'x' } }, { '(expand_region_shrink)', mode = { 'x' } }, }, init = function() vim.keymap.set({ 'x' }, 'v', '(expand_region_expand)') vim.keymap.set({ 'x' }, 'V', '(expand_region_shrink)') vim.g.expand_region_text_objects = { ['iw'] = 0, ['i"'] = 1, ['a"'] = 1, ["i'"] = 1, ["a'"] = 1, ['i`'] = 1, ['a`'] = 1, ['iu'] = 1, ['au'] = 1, ['i('] = 1, ['a('] = 1, ['i['] = 1, ['a['] = 1, ['i{'] = 1, ['if'] = 1, ['af'] = 1, ['ig'] = 1, ['ag'] = 1, ['i$'] = 1, ['a$'] = 1, ['a{'] = 1, ['i<'] = 1, ['a<'] = 1, ['il'] = 0, ['ii'] = 1, ['ai'] = 1, ['ic'] = 0, ['ac'] = 0, ['ie'] = 0, } end, }, { -- NOTE: Use my fork 'yuki-yano/vim-operator-replace', dependencies = { { 'kana/vim-operator-user' }, }, keys = { { '(operator-replace)', mode = { 'n', 'x' } }, }, init = function() vim.keymap.set({ 'n' }, 'RR', 'R') vim.keymap.set({ 'n', 'x' }, 'R', '(operator-replace)') end, }, { 'mopp/vim-operator-convert-case', dependencies = { { 'kana/vim-operator-user' }, }, keys = { { '(operator-convert-case-loop)', mode = { 'n' } }, }, init = function() vim.keymap.set({ 'n' }, 'cy', '(operator-convert-case-loop)iw') end, }, { -- NOTE: Use my fork 'yuki-yano/caw.vim', dependencies = { { 'kana/vim-operator-user' }, { 'kana/vim-textobj-line' }, { 'JoosepAlviste/nvim-ts-context-commentstring' }, }, keys = { { 'gc', mode = { 'n', 'x' } }, { 'gw', mode = { 'n', 'x' } }, }, init = function() vim.g.caw_no_mappings = 1 end, config = function() -- NOTE: Workaround for comment out in jsx local function caw_hatpos_toggle() require('ts_context_commentstring.internal').update_commentstring() if (vim.o.filetype == 'typescript' or vim.o.filetype == 'typescriptreact') and vim.o.commentstring == [[{/* %s */}]] then vim.b.caw_wrap_oneline_comment = { '{/*', '*/}' } return '(caw:wrap:toggle:operator)' end return '(caw:hatpos:toggle:operator)' end local function caw_wrap_toggle() require('ts_context_commentstring.internal').update_commentstring() if (vim.o.filetype == 'typescript' or vim.o.filetype == 'typescriptreact') and vim.o.commentstring == [[{/* %s */}]] then vim.b.caw_wrap_oneline_comment = { '{/*', '*/}' } elseif vim.o.filetype == 'typescript' or vim.o.filetype == 'typescriptreact' then vim.b.caw_wrap_oneline_comment = { '/*', '*/' } end return '(caw:wrap:toggle:operator)' end vim.keymap.set({ 'n' }, 'gcc', function() return caw_hatpos_toggle() .. '(textobj-line-i)' end, { expr = true }) vim.keymap.set({ 'n', 'x' }, 'gc', caw_hatpos_toggle, { expr = true }) vim.keymap.set({ 'n' }, 'gww', function() return caw_wrap_toggle() .. '(textobj-line-i)' end, { expr = true }) vim.keymap.set({ 'n', 'x' }, 'gw', caw_wrap_toggle, { expr = true }) end, }, { 'LeafCage/yankround.vim', event = { 'VeryLazy' }, init = function() vim.g.yankround_max_history = 1000 vim.g.yankround_use_region_hl = true vim.g.yankround_dir = vim.fn.expand('~/.cache/vim/yankround') vim.keymap.set({ 'n', 'x' }, 'p', '(yankround-p)') vim.keymap.set({ 'n', 'x' }, 'P', '(yankround-P)') vim.keymap.set({ 'n' }, '', function() return vim.fn['yankround#is_active']() == 1 and '(yankround-prev)' or '(ctrl-p)' end, { expr = true }) vim.keymap.set({ 'n' }, '', function() return vim.fn['yankround#is_active']() == 1 and '(yankround-next)' or '(ctrl-n)' end, { expr = true }) vim.api.nvim_create_autocmd({ 'ColorScheme' }, { pattern = { 'gruvbox-material' }, callback = function() vim.api.nvim_set_hl(0, 'YankRoundRegion', { fg = base_colors.orange, bg = base_colors.black }) end, }) end, }, { 'monaqa/dial.nvim', keys = { { '(dial-increment)', mode = { 'n', 'x' } }, { '(dial-decrement)', mode = { 'n', 'x' } }, }, init = function() vim.keymap.set({ 'n', 'x' }, '', '(dial-increment)') vim.keymap.set({ 'n', 'x' }, '', '(dial-decrement)') vim.keymap.set({ 'x' }, 'g', 'g(dial-increment)') vim.keymap.set({ 'x' }, 'g', 'g(dial-decrement)') end, config = function() local config = require('dial.config') local augend = require('dial.augend') config.augends:register_group({ default = { augend.integer.alias.decimal_int, augend.integer.alias.hex, augend.constant.alias.bool, augend.constant.new({ elements = { '&&', '||' }, word = false, cyclic = true, }), augend.constant.new({ elements = { 'log', 'warn', 'error', 'debug', 'info' }, word = false, cyclic = true, }), augend.semver.alias.semver, }, }) end, }, { 'thinca/vim-qfreplace', cmd = { 'Qfreplace' } }, { 'yuki-yano/deindent-yank.vim', keys = { { '(deindent-yank-normal)', mode = { 'n' } }, { '(deindent-yank-visual)', mode = { 'x' } }, }, init = function() vim.keymap.set({ 'n' }, 'gy', '(deindent-yank-normal)') vim.keymap.set({ 'x' }, 'gy', '(deindent-yank-visual)') end, }, { 'tommcdo/vim-exchange', keys = { { '(Exchange)', mode = { 'x' } }, }, init = function() vim.keymap.set({ 'x' }, 'X', '(Exchange)') end, }, { 'osyo-manga/vim-jplus', keys = { { '(jplus)', mode = { 'n', 'x' } }, { '(jplus-input)', mode = { 'n', 'x' } }, }, init = function() vim.keymap.set({ 'n', 'x' }, 'J', '(jplus)') vim.keymap.set({ 'n', 'x' }, 'J', '(jplus-input)') end, }, { 'booperlv/nvim-gomove', keys = { { 'GoVSMLeft', mode = { 'x' } }, { 'GoVSMUp', mode = { 'x' } }, { 'GoVSMDown', mode = { 'x' } }, { 'GoVSMRight', mode = { 'x' } }, }, init = function() vim.keymap.set({ 'x' }, '', 'GoVSMLeft') vim.keymap.set({ 'x' }, '', 'GoVSMUp') vim.keymap.set({ 'x' }, '', 'GoVSMDown') vim.keymap.set({ 'x' }, '', 'GoVSMRight') end, config = function() require('gomove').setup({ map_defaults = true, reindent_mode = 'none' }) end, }, { 'danymat/neogen', dependencies = { { 'nvim-treesitter/nvim-treesitter' }, }, cmd = { 'Neogen' }, config = function() require('neogen').setup() end, }, }