{"id":13412840,"url":"https://github.com/windwp/nvim-autopairs","last_synced_at":"2025-05-13T21:06:08.251Z","repository":{"id":37037115,"uuid":"328285572","full_name":"windwp/nvim-autopairs","owner":"windwp","description":"autopairs for neovim written in lua","archived":false,"fork":false,"pushed_at":"2025-04-13T03:19:44.000Z","size":894,"stargazers_count":3584,"open_issues_count":16,"forks_count":130,"subscribers_count":11,"default_branch":"master","last_synced_at":"2025-05-08T20:49:49.122Z","etag":null,"topics":["autopairs","lua","neovim","nvim","vim"],"latest_commit_sha":null,"homepage":"","language":"Lua","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/windwp.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":["windwp"],"custom":"https://paypal.me/trieule1vn"}},"created_at":"2021-01-10T02:11:54.000Z","updated_at":"2025-05-08T16:49:38.000Z","dependencies_parsed_at":"2023-10-16T03:35:28.818Z","dependency_job_id":"5c080ae7-624e-42eb-af2a-7e6846c5e5c0","html_url":"https://github.com/windwp/nvim-autopairs","commit_stats":{"total_commits":385,"total_committers":102,"mean_commits":"3.7745098039215685","dds":0.6701298701298701,"last_synced_commit":"f158dcb865c36f72c92358f87787dab2c272eaf3"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/windwp%2Fnvim-autopairs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/windwp%2Fnvim-autopairs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/windwp%2Fnvim-autopairs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/windwp%2Fnvim-autopairs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/windwp","download_url":"https://codeload.github.com/windwp/nvim-autopairs/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254028664,"owners_count":22002277,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["autopairs","lua","neovim","nvim","vim"],"created_at":"2024-07-30T20:01:29.900Z","updated_at":"2025-05-13T21:06:03.234Z","avatar_url":"https://github.com/windwp.png","language":"Lua","readme":"##  nvim-autopairs\n\nA super powerful autopair plugin for Neovim that supports multiple characters.\n\nRequires neovim 0.7\n\n## Installation\n\nInstall the plugin with your preferred package manager:\n\n### [lazy.nvim](https://github.com/folke/lazy.nvim)\n\n```lua\n{\n    'windwp/nvim-autopairs',\n    event = \"InsertEnter\",\n    config = true\n    -- use opts = {} for passing setup options\n    -- this is equivalent to setup({}) function\n}\n```\n\n### [vim-plug](https://github.com/junegunn/vim-plug)\n\n```vim\nPlug 'windwp/nvim-autopairs'\n\nlua \u003c\u003c EOF\nrequire(\"nvim-autopairs\").setup {}\nEOF\n```\n\n### [packer](https://github.com/wbthomason/packer.nvim)\n\n```lua\nuse {\n    \"windwp/nvim-autopairs\",\n    event = \"InsertEnter\",\n    config = function()\n        require(\"nvim-autopairs\").setup {}\n    end\n}\n```\n\n## Default values\n\n``` lua\n{\n    enabled = function(bufnr) return true end, -- control if auto-pairs should be enabled when attaching to a buffer\n    disable_filetype = { \"TelescopePrompt\", \"spectre_panel\", \"snacks_picker_input\" },\n    disable_in_macro = true, -- disable when recording or executing a macro\n    disable_in_visualblock = false, -- disable when insert after visual block mode\n    disable_in_replace_mode = true,\n    ignored_next_char = [=[[%w%%%'%[%\"%.%`%$]]=],\n    enable_moveright = true,\n    enable_afterquote = true, -- add bracket pairs after quote\n    enable_check_bracket_line = true, --- check bracket in same line\n    enable_bracket_in_quote = true, --\n    enable_abbr = false, -- trigger abbreviation\n    break_undo = true, -- switch for basic rule break undo sequence\n    check_ts = false,\n    map_cr = true,\n    map_bs = true, -- map the \u003cBS\u003e key\n    map_c_h = false, -- Map the \u003cC-h\u003e key to delete a pair\n    map_c_w = false, -- map \u003cc-w\u003e to delete a pair if possible\n}\n```\n\n### Override default values\n\n``` lua\nrequire('nvim-autopairs').setup({\n  disable_filetype = { \"TelescopePrompt\" , \"vim\" },\n})\n```\n\n\n#### Mapping `\u003cCR\u003e`\n```\nBefore        Input         After\n------------------------------------\n{|}           \u003cCR\u003e          {\n                                |\n                            }\n------------------------------------\n```\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003envim-cmp\u003c/b\u003e\u003c/summary\u003e\n\u003ch3\u003e\nYou need to add mapping `CR` on nvim-cmp setup.\nCheck readme.md on nvim-cmp repo.\n\u003c/h3\u003e\n\n``` lua\n-- If you want insert `(` after select function or method item\nlocal cmp_autopairs = require('nvim-autopairs.completion.cmp')\nlocal cmp = require('cmp')\ncmp.event:on(\n  'confirm_done',\n  cmp_autopairs.on_confirm_done()\n)\n```\n\nYou can customize the kind of completion to add `(` or any character.\n\n```lua\nlocal handlers = require('nvim-autopairs.completion.handlers')\n\ncmp.event:on(\n  'confirm_done',\n  cmp_autopairs.on_confirm_done({\n    filetypes = {\n      -- \"*\" is a alias to all filetypes\n      [\"*\"] = {\n        [\"(\"] = {\n          kind = {\n            cmp.lsp.CompletionItemKind.Function,\n            cmp.lsp.CompletionItemKind.Method,\n          },\n          handler = handlers[\"*\"]\n        }\n      },\n      lua = {\n        [\"(\"] = {\n          kind = {\n            cmp.lsp.CompletionItemKind.Function,\n            cmp.lsp.CompletionItemKind.Method\n          },\n          ---@param char string\n          ---@param item table item completion\n          ---@param bufnr number buffer number\n          ---@param rules table\n          ---@param commit_character table\u003cstring\u003e\n          handler = function(char, item, bufnr, rules, commit_character)\n            -- Your handler function. Inspect with print(vim.inspect{char, item, bufnr, rules, commit_character})\n          end\n        }\n      },\n      -- Disable for tex\n      tex = false\n    }\n  })\n)\n```\n\nDon't use `nil` to disable a filetype. If a filetype is `nil` then `*` is used as fallback.\n\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003ecoq_nvim\u003c/b\u003e\u003c/summary\u003e\n\n``` lua\nlocal remap = vim.api.nvim_set_keymap\nlocal npairs = require('nvim-autopairs')\n\nnpairs.setup({ map_bs = false, map_cr = false })\n\nvim.g.coq_settings = { keymap = { recommended = false } }\n\n-- these mappings are coq recommended mappings unrelated to nvim-autopairs\nremap('i', '\u003cesc\u003e', [[pumvisible() ? \"\u003cc-e\u003e\u003cesc\u003e\" : \"\u003cesc\u003e\"]], { expr = true, noremap = true })\nremap('i', '\u003cc-c\u003e', [[pumvisible() ? \"\u003cc-e\u003e\u003cc-c\u003e\" : \"\u003cc-c\u003e\"]], { expr = true, noremap = true })\nremap('i', '\u003ctab\u003e', [[pumvisible() ? \"\u003cc-n\u003e\" : \"\u003ctab\u003e\"]], { expr = true, noremap = true })\nremap('i', '\u003cs-tab\u003e', [[pumvisible() ? \"\u003cc-p\u003e\" : \"\u003cbs\u003e\"]], { expr = true, noremap = true })\n\n-- skip it, if you use another global object\n_G.MUtils= {}\n\nMUtils.CR = function()\n  if vim.fn.pumvisible() ~= 0 then\n    if vim.fn.complete_info({ 'selected' }).selected ~= -1 then\n      return npairs.esc('\u003cc-y\u003e')\n    else\n      return npairs.esc('\u003cc-e\u003e') .. npairs.autopairs_cr()\n    end\n  else\n    return npairs.autopairs_cr()\n  end\nend\nremap('i', '\u003ccr\u003e', 'v:lua.MUtils.CR()', { expr = true, noremap = true })\n\nMUtils.BS = function()\n  if vim.fn.pumvisible() ~= 0 and vim.fn.complete_info({ 'mode' }).mode == 'eval' then\n    return npairs.esc('\u003cc-e\u003e') .. npairs.autopairs_bs()\n  else\n    return npairs.autopairs_bs()\n  end\nend\nremap('i', '\u003cbs\u003e', 'v:lua.MUtils.BS()', { expr = true, noremap = true })\n```\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003ewithout completion plugin\u003c/b\u003e\u003c/summary\u003e\n\n```lua\n-- add option map_cr\nnpairs.setup({ map_cr = true })\n```\n\u003c/details\u003e\n\n[another completion plugin](https://github.com/windwp/nvim-autopairs/wiki/Completion-plugin)\n\nIf you have a problem with indent after you press ` \u003cCR\u003e `\nplease check the settings of treesitter indent or install a plugin that has indent support for your filetype.\n\n### Rule\n\nnvim-autopairs uses rules with conditions to check pairs.\n\n``` lua\nlocal Rule = require('nvim-autopairs.rule')\nlocal npairs = require('nvim-autopairs')\n\nnpairs.add_rule(Rule(\"$$\",\"$$\",\"tex\"))\n\n-- you can use some built-in conditions\n\nlocal cond = require('nvim-autopairs.conds')\nprint(vim.inspect(cond))\n\nnpairs.add_rules({\n  Rule(\"$\", \"$\",{\"tex\", \"latex\"})\n    -- don't add a pair if the next character is %\n    :with_pair(cond.not_after_regex(\"%%\"))\n    -- don't add a pair if  the previous character is xxx\n    :with_pair(cond.not_before_regex(\"xxx\", 3))\n    -- don't move right when repeat character\n    :with_move(cond.none())\n    -- don't delete if the next character is xx\n    :with_del(cond.not_after_regex(\"xx\"))\n    -- disable adding a newline when you press \u003ccr\u003e\n    :with_cr(cond.none())\n  },\n  -- disable for .vim files, but it work for another filetypes\n  Rule(\"a\",\"a\",\"-vim\")\n)\n\nnpairs.add_rules({\n  Rule(\"$$\",\"$$\",\"tex\")\n    :with_pair(function(opts)\n        print(vim.inspect(opts))\n        if opts.line==\"aa $$\" then\n        -- don't add pair on that line\n          return false\n        end\n    end)\n   }\n)\n\n-- you can use regex\n-- press u1234 =\u003e u1234number\nnpairs.add_rules({\n    Rule(\"u%d%d%d%d$\", \"number\", \"lua\")\n      :use_regex(true)\n})\n\n\n\n-- press x1234 =\u003e x12341234\nnpairs.add_rules({\n    Rule(\"x%d%d%d%d$\", \"number\", \"lua\")\n      :use_regex(true)\n      :replace_endpair(function(opts)\n          -- print(vim.inspect(opts))\n          return opts.prev_char:sub(#opts.prev_char - 3,#opts.prev_char)\n      end)\n})\n\n\n-- you can do anything with regex +special key\n-- example press tab to uppercase text:\n-- press b1234s\u003ctab\u003e =\u003e B1234S1234S\n\nnpairs.add_rules({\n  Rule(\"b%d%d%d%d%w$\", \"\", \"vim\")\n    :use_regex(true,\"\u003ctab\u003e\")\n    :replace_endpair(function(opts)\n          return\n              opts.prev_char:sub(#opts.prev_char - 4,#opts.prev_char)\n              ..\"\u003cesc\u003eviwU\"\n    end)\n})\n\n-- you can exclude filetypes\nnpairs.add_rule(\n  Rule(\"$$\",\"$$\")\n    :with_pair(cond.not_filetypes({\"lua\"}))\n)\n--- check ./lua/nvim-autopairs/rules/basic.lua\n\n```\n[Rules API](https://github.com/windwp/nvim-autopairs/wiki/Rules-API)\n\n### Treesitter\nYou can use treesitter to check for a pair.\n\n```lua\nlocal npairs = require(\"nvim-autopairs\")\nlocal Rule = require('nvim-autopairs.rule')\n\nnpairs.setup({\n    check_ts = true,\n    ts_config = {\n        lua = {'string'},-- it will not add a pair on that treesitter node\n        javascript = {'template_string'},\n        java = false,-- don't check treesitter on java\n    }\n})\n\nlocal ts_conds = require('nvim-autopairs.ts-conds')\n\n\n-- press % =\u003e %% only while inside a comment or string\nnpairs.add_rules({\n  Rule(\"%\", \"%\", \"lua\")\n    :with_pair(ts_conds.is_ts_node({'string','comment'})),\n  Rule(\"$\", \"$\", \"lua\")\n    :with_pair(ts_conds.is_not_ts_node({'function'}))\n})\n```\n\n### Don't add pairs if it already has a close pair in the same line\nif **next character** is a close pair and it doesn't have an open pair in same line, then it will not add a close pair\n\n``` text\nBefore        Input         After\n------------------------------------\n(  |))         (            (  (|))\n\n```\n\n``` lua\nrequire('nvim-autopairs').setup({\n  enable_check_bracket_line = false\n})\n```\n\n### Don't add pairs if the next char is alphanumeric\n\nYou can customize how nvim-autopairs will behave if it encounters a specific\ncharacter\n``` lua\nrequire('nvim-autopairs').setup({\n  ignored_next_char = \"[%w%.]\" -- will ignore alphanumeric and `.` symbol\n})\n```\n\n``` text\nBefore        Input         After\n------------------------------------\n|foobar        (            (|foobar\n|.foobar       (            (|.foobar\n```\n\n### Plugin Integration\n``` lua\n  require('nvim-autopairs').disable()\n  require('nvim-autopairs').enable()\n  require('nvim-autopairs').toggle()\n  require('nvim-autopairs').remove_rule('(') -- remove rule (\n  require('nvim-autopairs').clear_rules() -- clear all rules\n  require('nvim-autopairs').get_rules('\"')\n```\n\n* Sample\n```lua\n-- remove add single quote on filetype scheme or lisp\nrequire(\"nvim-autopairs\").get_rules(\"'\")[1].not_filetypes = { \"scheme\", \"lisp\" }\nrequire(\"nvim-autopairs\").get_rules(\"'\")[1]:with_pair(cond.not_after_text(\"[\"))\n```\n\n### FastWrap\n\n``` text\nBefore        Input                    After         Note\n-----------------------------------------------------------------\n(|foobar      \u003cM-e\u003e then press $       (|foobar)\n(|)(foobar)   \u003cM-e\u003e then press q       (|(foobar))\n(|foo bar     \u003cM-e\u003e then press qh      (|foo) bar\n(|foo bar     \u003cM-e\u003e then press qH      (foo|) bar\n(|foo bar     \u003cM-e\u003e then press qH      (foo)| bar    if cursor_pos_before = false\n```\n\n```lua\n-- put this to setup function and press \u003ca-e\u003e to use fast_wrap\nnpairs.setup({\n    fast_wrap = {},\n})\n\n-- change default fast_wrap\nnpairs.setup({\n    fast_wrap = {\n      map = '\u003cM-e\u003e',\n      chars = { '{', '[', '(', '\"', \"'\" },\n      pattern = [=[[%'%\"%\u003e%]%)%}%,]]=],\n      end_key = '$',\n      before_key = 'h',\n      after_key = 'l',\n      cursor_pos_before = true,\n      keys = 'qwertyuiopzxcvbnmasdfghjkl',\n      manual_position = true,\n      highlight = 'Search',\n      highlight_grey='Comment'\n    },\n})\n```\n\n### autotag html and tsx\n\n[autotag](https://github.com/windwp/nvim-ts-autotag)\n\n### Endwise\n\n[endwise](https://github.com/windwp/nvim-autopairs/wiki/Endwise)\n\n### Custom rules\n[rules](https://github.com/windwp/nvim-autopairs/wiki/Custom-rules)\n\n## Sponsors\n\nThanks to everyone who sponsors my projects and makes continued development maintenance possible!\n\n\u003c!-- sponsors --\u003e\u003ca href=\"https://github.com/looshch\"\u003e\u003cimg src=\"https:\u0026#x2F;\u0026#x2F;github.com\u0026#x2F;looshch.png\" width=\"60px\" alt=\"User avatar: george looshch\" /\u003e\u003c/a\u003e\u003c!-- sponsors --\u003e\n","funding_links":["https://github.com/sponsors/windwp","https://paypal.me/trieule1vn"],"categories":["Editing Support","Lua","Neovim"],"sub_categories":["Scrollbar"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwindwp%2Fnvim-autopairs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwindwp%2Fnvim-autopairs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwindwp%2Fnvim-autopairs/lists"}