local Rule = require("nvim-autopairs.rule") local cond = require("nvim-autopairs.conds") local npairs = require("nvim-autopairs") local cmp = require("cmp") local cmp_autopairs = require("nvim-autopairs.completion.cmp") local langs = { haskell_like = { "haskell", "nix", "ruler" }, ml_like = { "ocaml", "why3", "skel", "isabelle" }, html_like = { "html", "htmldjango" }, latex_like = { "typst", "latex" }, lisps = { "fennel", "clojure", "lisp", "racket", "scheme" }, has_bracket = { "typst", "python", "haskell", "nix", "sh" }, c_style_block_comment = { "typst", "go", "java", "rust", "rust", "scss", "nix" }, all = nil, } npairs.setup { disable_filetype = langs.lisps, } cmp.event:on("confirm_done", cmp_autopairs.on_confirm_done()) local function has_pair_on_line(opts, pattern) return select(2, opts.line:gsub(pattern, "")) % 2 == 0 end local function pair_with_insertion(a1, ins, a2, lang) npairs.add_rule( Rule(ins, ins, lang) :with_pair(function(opts) return a1 .. a2 == opts.line:sub(opts.col - #a1, opts.col + #a2 - 1) end) :with_move(cond.none()) :with_cr(cond.none()) :with_del(function(opts) local col = vim.api.nvim_win_get_cursor(0)[2] return a1 .. ins .. ins .. a2 == opts.line:sub(col - #a1 - #ins + 1, col + #ins + #a2) -- insert only works for #ins == 1 anyway end) ) end for _, punct in pairs { ",", ";" } do npairs.add_rule( Rule("", punct) :with_move(function(opts) return opts.char == punct end) :with_pair(function() return false end) :with_del(function() return false end) :with_cr(function() return false end) :use_key(punct) ) end pair_with_insertion("(", "*", ")", langs.ml_like) pair_with_insertion("(*", " ", "*)", langs.ml_like) pair_with_insertion("[", " ", "]", langs.has_bracket) pair_with_insertion("{", " ", "}", langs.all) npairs.add_rules { Rule("/*", "*/", { "typst", "go", "rust", "scss", "nix" }):with_del(cond.done()):with_move(cond.none()), -- allow java doc } pair_with_insertion("/*", " ", "*/", langs.c_style_block_comment) pair_with_insertion("{", "#", "}", langs.html_like) pair_with_insertion("{#", " ", "#}", langs.html_like) pair_with_insertion("{#", "-", "#}", langs.html_like) pair_with_insertion("{#-", " ", "-#}", langs.html_like) pair_with_insertion("{", "%", "}", langs.html_like) pair_with_insertion("{%", " ", "%}", langs.html_like) pair_with_insertion("{%", "-", "%}", langs.html_like) pair_with_insertion("{%-", " ", "-%}", langs.html_like) pair_with_insertion("{{", " ", "}}", langs.html_like) pair_with_insertion("{{", "-", "}}", langs.html_like) pair_with_insertion("{{-", " ", "-}}", langs.html_like) npairs.add_rules { Rule("$", "$", "typst") :with_pair(function(opts) return has_pair_on_line(opts, "%$") end) :with_del(function(opts) return has_pair_on_line(opts, "%$") end) :with_move(cond.done()), } pair_with_insertion("$", " ", "$", langs.latex_like) pair_with_insertion("{", "-", "}", langs.haskell_like) pair_with_insertion("{-", " ", "-}", langs.haskell_like) -- block comment pair_with_insertion("{-", "#", "-}", langs.haskell_like) -- language flags pair_with_insertion("{-#", " ", "#-}", langs.haskell_like) pair_with_insertion("(", " ", ")", langs.haskell_like) npairs.add_rules { Rule("<", ">", langs.html_like) :with_pair(function(opts) return has_pair_on_line(opts, "[<>]") end) :with_del(function(opts) return has_pair_on_line(opts, "[<>]") end) :with_move(function(opts) return opts.char == ">" end), }