Regenerate nvim config
This commit is contained in:
@ -0,0 +1,19 @@
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[*.lua]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
|
||||
[*.vim]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[*.snippets]
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
2
config/neovim/store/lazy-plugins/nvim-autopairs/.github/FUNDING.yml
vendored
Normal file
2
config/neovim/store/lazy-plugins/nvim-autopairs/.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
custom: https://paypal.me/trieule1vn
|
||||
patreon: windwp
|
||||
71
config/neovim/store/lazy-plugins/nvim-autopairs/.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
71
config/neovim/store/lazy-plugins/nvim-autopairs/.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
@ -0,0 +1,71 @@
|
||||
name: Bug report
|
||||
description: Report a problem with nvim-autopairs
|
||||
labels: [bug]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Before reporting: search [existing issues](https://github.com/windwp/nvim-autopairs/issues) and make sure that both nvim-autopairs and its dependencies are updated to the latest version.
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: "Description"
|
||||
description: "A short description of the problem you are reporting."
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: "Mapping <cr> bug"
|
||||
description: "report a bug about mapping `<cr>` key and completion plugin"
|
||||
value: |
|
||||
1.If you report a bug about indent. Please remember that plugin doesn't do anything about indent.
|
||||
It just trigger the indent of your vim config so if you have wrong indent config then it will do wrong indent.
|
||||
You can check by select a block of code and press `==`
|
||||
2. provide result of command `:verbose imap <cr>`.
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: "Steps to reproduce"
|
||||
description: "Steps to reproduce using the minimal config provided below."
|
||||
placeholder: |
|
||||
- It will beter if you can provide a video of gif
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: "Minimal config"
|
||||
description: "Minimal(!) configuration necessary to reproduce the issue. Save this as `minimal.lua`. If _absolutely_ necessary, add plugins and config options from your `init.lua` at the indicated lines."
|
||||
render: Lua
|
||||
value: |
|
||||
vim.cmd [[set runtimepath=$VIMRUNTIME]]
|
||||
vim.cmd [[set packpath=/tmp/nvim/site]]
|
||||
local package_root = '/tmp/nvim/site/pack'
|
||||
local install_path = package_root .. '/packer/start/packer.nvim'
|
||||
local function load_plugins()
|
||||
require('packer').startup {
|
||||
{
|
||||
'wbthomason/packer.nvim',
|
||||
{
|
||||
'windwp/nvim-autopairs',
|
||||
},
|
||||
-- ADD PLUGINS THAT ARE _NECESSARY_ FOR REPRODUCING THE ISSUE
|
||||
},
|
||||
config = {
|
||||
package_root = package_root,
|
||||
compile_path = install_path .. '/plugin/packer_compiled.lua',
|
||||
display = { non_interactive = true },
|
||||
},
|
||||
}
|
||||
end
|
||||
_G.load_config = function()
|
||||
require('nvim-autopairs').setup()
|
||||
end
|
||||
if vim.fn.isdirectory(install_path) == 0 then
|
||||
print("Installing nvim-autopairs and dependencies.")
|
||||
vim.fn.system { 'git', 'clone', '--depth=1', 'https://github.com/wbthomason/packer.nvim', install_path }
|
||||
end
|
||||
load_plugins()
|
||||
require('packer').sync()
|
||||
vim.cmd [[autocmd User PackerComplete ++once echo "Ready!" | lua load_config()]]
|
||||
validations:
|
||||
required: true
|
||||
2
config/neovim/store/lazy-plugins/nvim-autopairs/.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
2
config/neovim/store/lazy-plugins/nvim-autopairs/.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
blank_issues_enabled: false
|
||||
|
||||
20
config/neovim/store/lazy-plugins/nvim-autopairs/.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
20
config/neovim/store/lazy-plugins/nvim-autopairs/.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: enhancement
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
7
config/neovim/store/lazy-plugins/nvim-autopairs/.github/generated-files-bot.yml
vendored
Normal file
7
config/neovim/store/lazy-plugins/nvim-autopairs/.github/generated-files-bot.yml
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
generatedFiles:
|
||||
- path: "doc/nvim-autopairs.txt"
|
||||
- path: "doc/nvim-autopairs-rules.txt"
|
||||
message: "`nvim-autopairs.txt` is generated from README.md. Make changes there instead."
|
||||
ignoreAuthors:
|
||||
- 'github-actions[bot]'
|
||||
- 'windwp'
|
||||
19
config/neovim/store/lazy-plugins/nvim-autopairs/.github/stale.yml
vendored
Normal file
19
config/neovim/store/lazy-plugins/nvim-autopairs/.github/stale.yml
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 60
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
daysUntilClose: 7
|
||||
# Issues with these labels will never be considered stale
|
||||
exemptLabels:
|
||||
- pinned
|
||||
- security
|
||||
# Label to use when marking an issue as stale
|
||||
staleLabel: wontfix
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
recent activity. It will be closed if no further activity occurs. Thank you
|
||||
for your contributions.
|
||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||
closeComment: false
|
||||
|
||||
only: issues
|
||||
44
config/neovim/store/lazy-plugins/nvim-autopairs/.github/workflows/ci.yml
vendored
Normal file
44
config/neovim/store/lazy-plugins/nvim-autopairs/.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
name: Tests
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
x64-ubuntu:
|
||||
name: X64-ubuntu
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-20.04
|
||||
url: https://github.com/neovim/neovim/releases/latest/download/nvim-linux64.tar.gz
|
||||
manager: sudo apt-get
|
||||
packages: -y fd-find
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- run: date +%F > todays-date
|
||||
- name: Restore from todays cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: _neovim
|
||||
key: ${{ runner.os }}-${{ matrix.url }}-${{ hashFiles('todays-date') }}
|
||||
- name: Prepare
|
||||
run: |
|
||||
${{ matrix.manager }} update
|
||||
${{ matrix.manager }} install ${{ matrix.packages }}
|
||||
test -d _neovim || {
|
||||
mkdir -p _neovim
|
||||
curl -sL ${{ matrix.url }} | tar xzf - --strip-components=1 -C "${PWD}/_neovim"
|
||||
}
|
||||
mkdir -p ~/.local/share/nvim/site/pack/vendor/start
|
||||
git clone --depth 1 https://github.com/nvim-lua/plenary.nvim ~/.local/share/nvim/site/pack/vendor/start/plenary.nvim
|
||||
git clone --depth 1 https://github.com/nvim-treesitter/nvim-treesitter ~/.local/share/nvim/site/pack/vendor/start/nvim-treesitter
|
||||
git clone --depth 1 https://github.com/nvim-treesitter/playground ~/.local/share/nvim/site/pack/vendor/start/playground
|
||||
ln -s $(pwd) ~/.local/share/nvim/site/pack/vendor/start
|
||||
- name: Run tests
|
||||
run: |
|
||||
export PATH="${PWD}/_neovim/bin:${PATH}"
|
||||
export VIM="${PWD}/_neovim/share/nvim/runtime"
|
||||
nvim --headless -u tests/minimal.vim -c "TSInstallSync all" -c "q"
|
||||
make test
|
||||
|
||||
51
config/neovim/store/lazy-plugins/nvim-autopairs/.github/workflows/docs.yml
vendored
Normal file
51
config/neovim/store/lazy-plugins/nvim-autopairs/.github/workflows/docs.yml
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
name: panvimdoc
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- README.md
|
||||
branches:
|
||||
- master
|
||||
jobs:
|
||||
docs:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
name: markdown to vimdoc
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Setup git
|
||||
run: |
|
||||
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
git config --local user.name "github-actions[bot]"
|
||||
printf 'VIMDOC_BRANCH=bot/vimdoc/%s\n' ${GITHUB_REF#refs/heads/} >> $GITHUB_ENV
|
||||
- name: Checkout to vimdoc branch
|
||||
run: git checkout -b ${VIMDOC_BRANCH}
|
||||
- name: panvimdoc
|
||||
uses: kdheepak/panvimdoc@v2.7.1
|
||||
with:
|
||||
vimdoc: nvim-autopairs
|
||||
description: A super powerful autopair for Neovim.
|
||||
- name: clone rules api docs
|
||||
run: |
|
||||
git clone --depth 1 https://github.com/windwp/nvim-autopairs.wiki.git ../nvim-autopairs.wiki
|
||||
cp ../nvim-autopairs.wiki/Rules-API.md ./Rules-API.md
|
||||
- name: panvimdoc
|
||||
uses: kdheepak/panvimdoc@v2.7.1
|
||||
with:
|
||||
vimdoc: nvim-autopairs-rules
|
||||
description: nvim-autopairs rules
|
||||
pandoc: "Rules-API.md"
|
||||
toc: true
|
||||
- name: Create PR
|
||||
run: |
|
||||
if ! [[ -z $(git status -s) ]]; then
|
||||
git add doc/nvim-autopairs.txt
|
||||
git add doc/nvim-autopairs-rules.txt
|
||||
git commit -m "chore: generated vimdoc"
|
||||
git push --force https://${GITHUB_ACTOR}:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY} ${VIMDOC_BRANCH}
|
||||
gh pr create --fill --base ${GITHUB_REF#refs/heads/} --head ${VIMDOC_BRANCH} || true
|
||||
fi
|
||||
1
config/neovim/store/lazy-plugins/nvim-autopairs/.gitignore
vendored
Normal file
1
config/neovim/store/lazy-plugins/nvim-autopairs/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
doc/tags
|
||||
@ -0,0 +1,6 @@
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/sumneko/vscode-lua/master/setting/schema.json",
|
||||
"Lua.diagnostics.disable": [
|
||||
"undefined-field"
|
||||
]
|
||||
}
|
||||
22
config/neovim/store/lazy-plugins/nvim-autopairs/LICENSE
Normal file
22
config/neovim/store/lazy-plugins/nvim-autopairs/LICENSE
Normal file
@ -0,0 +1,22 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 windwp
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
5
config/neovim/store/lazy-plugins/nvim-autopairs/Makefile
Normal file
5
config/neovim/store/lazy-plugins/nvim-autopairs/Makefile
Normal file
@ -0,0 +1,5 @@
|
||||
test:
|
||||
nvim --headless --noplugin -u tests/minimal.vim -c "PlenaryBustedDirectory tests/ {minimal_init = 'tests/minimal.vim'}"
|
||||
|
||||
test-file:
|
||||
nvim --headless --noplugin -u tests/minimal.vim -c "lua require(\"plenary.busted\").run(\"$(FILE)\")"
|
||||
422
config/neovim/store/lazy-plugins/nvim-autopairs/README.md
Normal file
422
config/neovim/store/lazy-plugins/nvim-autopairs/README.md
Normal file
@ -0,0 +1,422 @@
|
||||
## nvim-autopairs
|
||||
|
||||
A super powerful autopair plugin for Neovim that supports multiple characters.
|
||||
|
||||
Requires neovim 0.7
|
||||
|
||||
## Installation
|
||||
|
||||
Install the plugin with your preferred package manager:
|
||||
|
||||
### [lazy.nvim](https://github.com/folke/lazy.nvim)
|
||||
|
||||
```lua
|
||||
{
|
||||
'windwp/nvim-autopairs',
|
||||
event = "InsertEnter",
|
||||
config = true
|
||||
-- use opts = {} for passing setup options
|
||||
-- this is equalent to setup({}) function
|
||||
}
|
||||
```
|
||||
|
||||
### [vim-plug](https://github.com/junegunn/vim-plug)
|
||||
|
||||
```vim
|
||||
Plug 'windwp/nvim-autopairs'
|
||||
|
||||
lua << EOF
|
||||
require("nvim-autopairs").setup {}
|
||||
EOF
|
||||
```
|
||||
|
||||
### [packer](https://github.com/wbthomason/packer.nvim)
|
||||
|
||||
```lua
|
||||
use {
|
||||
"windwp/nvim-autopairs",
|
||||
event = "InsertEnter",
|
||||
config = function()
|
||||
require("nvim-autopairs").setup {}
|
||||
end
|
||||
}
|
||||
```
|
||||
|
||||
## Default values
|
||||
|
||||
``` lua
|
||||
{
|
||||
disable_filetype = { "TelescopePrompt", "spectre_panel" }
|
||||
disable_in_macro = true -- disable when recording or executing a macro
|
||||
disable_in_visualblock = false -- disable when insert after visual block mode
|
||||
disable_in_replace_mode = true
|
||||
ignored_next_char = [=[[%w%%%'%[%"%.%`%$]]=]
|
||||
enable_moveright = true
|
||||
enable_afterquote = true -- add bracket pairs after quote
|
||||
enable_check_bracket_line = true --- check bracket in same line
|
||||
enable_bracket_in_quote = true --
|
||||
enable_abbr = false -- trigger abbreviation
|
||||
break_undo = true -- switch for basic rule break undo sequence
|
||||
check_ts = false
|
||||
map_cr = true
|
||||
map_bs = true -- map the <BS> key
|
||||
map_c_h = false -- Map the <C-h> key to delete a pair
|
||||
map_c_w = false -- map <c-w> to delete a pair if possible
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### Override default values
|
||||
|
||||
``` lua
|
||||
require('nvim-autopairs').setup({
|
||||
disable_filetype = { "TelescopePrompt" , "vim" },
|
||||
})
|
||||
```
|
||||
|
||||
|
||||
#### Mapping `<CR>`
|
||||
```
|
||||
Before Input After
|
||||
------------------------------------
|
||||
{|} <CR> {
|
||||
|
|
||||
}
|
||||
------------------------------------
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary><b>nvim-cmp</b></summary>
|
||||
<h3>
|
||||
You need to add mapping `CR` on nvim-cmp setup.
|
||||
Check readme.md on nvim-cmp repo.
|
||||
</h3>
|
||||
|
||||
``` lua
|
||||
-- If you want insert `(` after select function or method item
|
||||
local cmp_autopairs = require('nvim-autopairs.completion.cmp')
|
||||
local cmp = require('cmp')
|
||||
cmp.event:on(
|
||||
'confirm_done',
|
||||
cmp_autopairs.on_confirm_done()
|
||||
)
|
||||
```
|
||||
|
||||
You can customize the kind of completion to add `(` or any character.
|
||||
|
||||
```lua
|
||||
local handlers = require('nvim-autopairs.completion.handlers')
|
||||
|
||||
cmp.event:on(
|
||||
'confirm_done',
|
||||
cmp_autopairs.on_confirm_done({
|
||||
filetypes = {
|
||||
-- "*" is a alias to all filetypes
|
||||
["*"] = {
|
||||
["("] = {
|
||||
kind = {
|
||||
cmp.lsp.CompletionItemKind.Function,
|
||||
cmp.lsp.CompletionItemKind.Method,
|
||||
},
|
||||
handler = handlers["*"]
|
||||
}
|
||||
},
|
||||
lua = {
|
||||
["("] = {
|
||||
kind = {
|
||||
cmp.lsp.CompletionItemKind.Function,
|
||||
cmp.lsp.CompletionItemKind.Method
|
||||
},
|
||||
---@param char string
|
||||
---@param item table item completion
|
||||
---@param bufnr number buffer number
|
||||
---@param rules table
|
||||
---@param commit_character table<string>
|
||||
handler = function(char, item, bufnr, rules, commit_character)
|
||||
-- Your handler function. Inspect with print(vim.inspect{char, item, bufnr, rules, commit_character})
|
||||
end
|
||||
}
|
||||
},
|
||||
-- Disable for tex
|
||||
tex = false
|
||||
}
|
||||
})
|
||||
)
|
||||
```
|
||||
|
||||
Don't use `nil` to disable a filetype. If a filetype is `nil` then `*` is used as fallback.
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary><b>coq_nvim</b></summary>
|
||||
|
||||
``` lua
|
||||
local remap = vim.api.nvim_set_keymap
|
||||
local npairs = require('nvim-autopairs')
|
||||
|
||||
npairs.setup({ map_bs = false, map_cr = false })
|
||||
|
||||
vim.g.coq_settings = { keymap = { recommended = false } }
|
||||
|
||||
-- these mappings are coq recommended mappings unrelated to nvim-autopairs
|
||||
remap('i', '<esc>', [[pumvisible() ? "<c-e><esc>" : "<esc>"]], { expr = true, noremap = true })
|
||||
remap('i', '<c-c>', [[pumvisible() ? "<c-e><c-c>" : "<c-c>"]], { expr = true, noremap = true })
|
||||
remap('i', '<tab>', [[pumvisible() ? "<c-n>" : "<tab>"]], { expr = true, noremap = true })
|
||||
remap('i', '<s-tab>', [[pumvisible() ? "<c-p>" : "<bs>"]], { expr = true, noremap = true })
|
||||
|
||||
-- skip it, if you use another global object
|
||||
_G.MUtils= {}
|
||||
|
||||
MUtils.CR = function()
|
||||
if vim.fn.pumvisible() ~= 0 then
|
||||
if vim.fn.complete_info({ 'selected' }).selected ~= -1 then
|
||||
return npairs.esc('<c-y>')
|
||||
else
|
||||
return npairs.esc('<c-e>') .. npairs.autopairs_cr()
|
||||
end
|
||||
else
|
||||
return npairs.autopairs_cr()
|
||||
end
|
||||
end
|
||||
remap('i', '<cr>', 'v:lua.MUtils.CR()', { expr = true, noremap = true })
|
||||
|
||||
MUtils.BS = function()
|
||||
if vim.fn.pumvisible() ~= 0 and vim.fn.complete_info({ 'mode' }).mode == 'eval' then
|
||||
return npairs.esc('<c-e>') .. npairs.autopairs_bs()
|
||||
else
|
||||
return npairs.autopairs_bs()
|
||||
end
|
||||
end
|
||||
remap('i', '<bs>', 'v:lua.MUtils.BS()', { expr = true, noremap = true })
|
||||
```
|
||||
</details>
|
||||
<details>
|
||||
<summary><b>without completion plugin</b></summary>
|
||||
|
||||
```lua
|
||||
-- add option map_cr
|
||||
npairs.setup({ map_cr = true })
|
||||
```
|
||||
</details>
|
||||
|
||||
[another completion plugin](https://github.com/windwp/nvim-autopairs/wiki/Completion-plugin)
|
||||
|
||||
If you have a problem with indent after you press ` <CR> `
|
||||
please check the settings of treesitter indent or install a plugin that has indent support for your filetype.
|
||||
|
||||
### Rule
|
||||
|
||||
nvim-autopairs uses rules with conditions to check pairs.
|
||||
|
||||
``` lua
|
||||
local Rule = require('nvim-autopairs.rule')
|
||||
local npairs = require('nvim-autopairs')
|
||||
|
||||
npairs.add_rule(Rule("$$","$$","tex"))
|
||||
|
||||
-- you can use some built-in conditions
|
||||
|
||||
local cond = require('nvim-autopairs.conds')
|
||||
print(vim.inspect(cond))
|
||||
|
||||
npairs.add_rules({
|
||||
Rule("$", "$",{"tex", "latex"})
|
||||
-- don't add a pair if the next character is %
|
||||
:with_pair(cond.not_after_regex("%%"))
|
||||
-- don't add a pair if the previous character is xxx
|
||||
:with_pair(cond.not_before_regex("xxx", 3))
|
||||
-- don't move right when repeat character
|
||||
:with_move(cond.none())
|
||||
-- don't delete if the next character is xx
|
||||
:with_del(cond.not_after_regex("xx"))
|
||||
-- disable adding a newline when you press <cr>
|
||||
:with_cr(cond.none())
|
||||
},
|
||||
-- disable for .vim files, but it work for another filetypes
|
||||
Rule("a","a","-vim")
|
||||
)
|
||||
|
||||
npairs.add_rules({
|
||||
Rule("$$","$$","tex")
|
||||
:with_pair(function(opts)
|
||||
print(vim.inspect(opts))
|
||||
if opts.line=="aa $$" then
|
||||
-- don't add pair on that line
|
||||
return false
|
||||
end
|
||||
end)
|
||||
}
|
||||
)
|
||||
|
||||
-- you can use regex
|
||||
-- press u1234 => u1234number
|
||||
npairs.add_rules({
|
||||
Rule("u%d%d%d%d$", "number", "lua")
|
||||
:use_regex(true)
|
||||
})
|
||||
|
||||
|
||||
|
||||
-- press x1234 => x12341234
|
||||
npairs.add_rules({
|
||||
Rule("x%d%d%d%d$", "number", "lua")
|
||||
:use_regex(true)
|
||||
:replace_endpair(function(opts)
|
||||
-- print(vim.inspect(opts))
|
||||
return opts.prev_char:sub(#opts.prev_char - 3,#opts.prev_char)
|
||||
end)
|
||||
})
|
||||
|
||||
|
||||
-- you can do anything with regex +special key
|
||||
-- example press tab to uppercase text:
|
||||
-- press b1234s<tab> => B1234S1234S
|
||||
|
||||
npairs.add_rules({
|
||||
Rule("b%d%d%d%d%w$", "", "vim")
|
||||
:use_regex(true,"<tab>")
|
||||
:replace_endpair(function(opts)
|
||||
return
|
||||
opts.prev_char:sub(#opts.prev_char - 4,#opts.prev_char)
|
||||
.."<esc>viwU"
|
||||
end)
|
||||
})
|
||||
|
||||
-- you can exclude filetypes
|
||||
npairs.add_rule(
|
||||
Rule("$$","$$")
|
||||
:with_pair(cond.not_filetypes({"lua"}))
|
||||
)
|
||||
--- check ./lua/nvim-autopairs/rules/basic.lua
|
||||
|
||||
```
|
||||
[Rules API](https://github.com/windwp/nvim-autopairs/wiki/Rules-API)
|
||||
|
||||
### Treesitter
|
||||
You can use treesitter to check for a pair.
|
||||
|
||||
```lua
|
||||
local npairs = require("nvim-autopairs")
|
||||
local Rule = require('nvim-autopairs.rule')
|
||||
|
||||
npairs.setup({
|
||||
check_ts = true,
|
||||
ts_config = {
|
||||
lua = {'string'},-- it will not add a pair on that treesitter node
|
||||
javascript = {'template_string'},
|
||||
java = false,-- don't check treesitter on java
|
||||
}
|
||||
})
|
||||
|
||||
local ts_conds = require('nvim-autopairs.ts-conds')
|
||||
|
||||
|
||||
-- press % => %% only while inside a comment or string
|
||||
npairs.add_rules({
|
||||
Rule("%", "%", "lua")
|
||||
:with_pair(ts_conds.is_ts_node({'string','comment'})),
|
||||
Rule("$", "$", "lua")
|
||||
:with_pair(ts_conds.is_not_ts_node({'function'}))
|
||||
})
|
||||
```
|
||||
|
||||
### Don't add pairs if it already has a close pair in the same line
|
||||
if **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
|
||||
|
||||
``` text
|
||||
Before Input After
|
||||
------------------------------------
|
||||
( |)) ( ( (|))
|
||||
|
||||
```
|
||||
|
||||
``` lua
|
||||
require('nvim-autopairs').setup({
|
||||
enable_check_bracket_line = false
|
||||
})
|
||||
```
|
||||
|
||||
### Don't add pairs if the next char is alphanumeric
|
||||
|
||||
You can customize how nvim-autopairs will behave if it encounters a specific
|
||||
character
|
||||
``` lua
|
||||
require('nvim-autopairs').setup({
|
||||
ignored_next_char = "[%w%.]" -- will ignore alphanumeric and `.` symbol
|
||||
})
|
||||
```
|
||||
|
||||
``` text
|
||||
Before Input After
|
||||
------------------------------------
|
||||
|foobar ( (|foobar
|
||||
|.foobar ( (|.foobar
|
||||
```
|
||||
|
||||
### Plugin Integration
|
||||
``` lua
|
||||
require('nvim-autopairs').disable()
|
||||
require('nvim-autopairs').enable()
|
||||
require('nvim-autopairs').remove_rule('(') -- remove rule (
|
||||
require('nvim-autopairs').clear_rules() -- clear all rules
|
||||
require('nvim-autopairs').get_rules('"')
|
||||
```
|
||||
|
||||
* Sample
|
||||
```lua
|
||||
-- remove add single quote on filetype scheme or lisp
|
||||
require("nvim-autopairs").get_rules("'")[1].not_filetypes = { "scheme", "lisp" }
|
||||
require("nvim-autopairs").get_rules("'")[1]:with_pair(cond.not_after_text("["))
|
||||
```
|
||||
|
||||
### FastWrap
|
||||
|
||||
``` text
|
||||
Before Input After Note
|
||||
-----------------------------------------------------------------
|
||||
(|foobar <M-e> then press $ (|foobar)
|
||||
(|)(foobar) <M-e> then press q (|(foobar))
|
||||
(|foo bar <M-e> then press qh (|foo) bar
|
||||
(|foo bar <M-e> then press qH (foo|) bar
|
||||
(|foo bar <M-e> then press qH (foo)| bar if cursor_pos_before = false
|
||||
```
|
||||
|
||||
```lua
|
||||
-- put this to setup function and press <a-e> to use fast_wrap
|
||||
npairs.setup({
|
||||
fast_wrap = {},
|
||||
})
|
||||
|
||||
-- change default fast_wrap
|
||||
npairs.setup({
|
||||
fast_wrap = {
|
||||
map = '<M-e>',
|
||||
chars = { '{', '[', '(', '"', "'" },
|
||||
pattern = [=[[%'%"%>%]%)%}%,]]=],
|
||||
end_key = '$',
|
||||
before_key = 'h',
|
||||
after_key = 'l',
|
||||
cursor_pos_before = true,
|
||||
keys = 'qwertyuiopzxcvbnmasdfghjkl',
|
||||
manual_position = true,
|
||||
highlight = 'Search',
|
||||
highlight_grey='Comment'
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
### autotag html and tsx
|
||||
|
||||
[autotag](https://github.com/windwp/nvim-ts-autotag)
|
||||
|
||||
### Endwise
|
||||
|
||||
[endwise](https://github.com/windwp/nvim-autopairs/wiki/Endwise)
|
||||
|
||||
### Custom rules
|
||||
[rules](https://github.com/windwp/nvim-autopairs/wiki/Custom-rules)
|
||||
|
||||
## Sponsors
|
||||
|
||||
Thanks to everyone who sponsors my projects and makes continued development maintenance possible!
|
||||
<!-- patreon --><a href="https://github.com/t4t5"><img src="https://github.com/t4t5.png" width="60px" alt="" /></a><!-- patreon-->
|
||||
@ -0,0 +1,349 @@
|
||||
*nvim-autopairs-rules.txt* nvim-autopairs rules
|
||||
|
||||
==============================================================================
|
||||
Table of Contents *nvim-autopairs-rules-table-of-contents*
|
||||
|
||||
1. Rule Basics |nvim-autopairs-rules-rule-basics|
|
||||
2. Controlling rule behavior |nvim-autopairs-rules-controlling-rule-behavior|
|
||||
- Method Overview |nvim-autopairs-rules-method-overview|
|
||||
- Conditions |nvim-autopairs-rules-conditions|
|
||||
3. Method Explanations |nvim-autopairs-rules-method-explanations|
|
||||
- The `with_*` methods |nvim-autopairs-rules-the-`with_*`-methods|
|
||||
- The `use_*` methods |nvim-autopairs-rules-the-`use_*`-methods|
|
||||
- Shorthand methods |nvim-autopairs-rules-shorthand-methods|
|
||||
- Advanced methods |nvim-autopairs-rules-advanced-methods|
|
||||
|
||||
==============================================================================
|
||||
1. Rule Basics *nvim-autopairs-rules-rule-basics*
|
||||
|
||||
At its core, a rule consists of two things: a **pair definition** and an
|
||||
optional **declaration of filetypes** where the rule is in effect. A pair
|
||||
definition has an opening part and a closing part. Each of these parts can be
|
||||
as simple as a single character like a pair of parenthesis, or multiple
|
||||
characters like Markdown code fences. Defining a rule is straightforward:
|
||||
|
||||
>
|
||||
Rule(begin_pair, end_pair, filetypes)
|
||||
<
|
||||
|
||||
|
||||
Where `begin_pair` is the opening part of the pair and `end_pair` is the
|
||||
closing part. `filetypes` may be specified in multiple ways:
|
||||
|
||||
>
|
||||
Rule("(", ")") -- Enabled for all filetypes
|
||||
Rule("(", ")", "markdown") -- As a string
|
||||
Rule("(", ")", {"markdown", "vim"}) -- As a table
|
||||
<
|
||||
|
||||
|
||||
Additionally, it is possible to specify filetypes where the rule should **not**
|
||||
be enabled by prefixing it with a `-` character:
|
||||
|
||||
>
|
||||
Rule("(", ")", "-markdown") -- All filetypes *except* markdown
|
||||
<
|
||||
|
||||
|
||||
==============================================================================
|
||||
2. Controlling rule behavior *nvim-autopairs-rules-controlling-rule-behavior*
|
||||
|
||||
By default, rules are very simple and will always complete a pair the moment
|
||||
the opening part is typed. This is fine and in some cases desirable, but the
|
||||
rules API allows you to control the manner and context in which pairs are
|
||||
completed; this is done by attaching **conditions** (predicates) to **events**
|
||||
and adding **modifiers** to the rule. `Rule` objects expose a variety of
|
||||
methods to add these predicates and modifiers to the rule.
|
||||
|
||||
METHOD OVERVIEW *nvim-autopairs-rules-method-overview*
|
||||
|
||||
These methods allow control over if, when, and how rules perform completion of
|
||||
pairs. Each method returns the `Rule` object so that they may be chained
|
||||
together to easily define complex rules.
|
||||
|
||||
│ method │ usage │
|
||||
│with_pair(cond) │add condition to check during pair event │
|
||||
│with_move(cond) │add condition to check during move right event │
|
||||
│with_cr(cond) │add condition to check during line break event │
|
||||
│with_del(cond) │add condition to check during delete pair event │
|
||||
│only_cr(cond) │enable _only_ the line break event; disable everything │
|
||||
│ │else │
|
||||
│use_regex(bool, "<k│interpret begin_pair as regex; optionally set trigger k│
|
||||
│ey>") │ey │
|
||||
│use_key("<key>") │set trigger key │
|
||||
│replace_endpair(fun│define ending part with a function; optionally add with│
|
||||
│c, check_pair) │_pair │
|
||||
│set_end_pair_length│override offset used to position the cursor between the│
|
||||
│(number) │ pair when replace_endpair is used │
|
||||
│replace_map_cr(func│change the mapping for used for <CR> during the line br│
|
||||
│) │eak event │
|
||||
│end_wise(cond) │make the rule an end-wise rule │
|
||||
|
||||
|
||||
AIDING UNDERSTANDING: "WHEN" INSTEAD OF "WITH" ~
|
||||
|
||||
It may be helpful to think of the `with_<event>` functions as reading more like
|
||||
`when_<event>` instead, as the condition is checked **when** `<event>` happens
|
||||
(or wants to happen). This naming scheme more accurately describes how the
|
||||
`Rule` is affected and reads more intuitively when reading a rule definition.
|
||||
|
||||
For example, given a rule definition `Rule("(", ")")`, each method has a
|
||||
certain effect on how and when the ending part of the pair, the closing
|
||||
parenthesis, is completed. The ending part is only completed **when**
|
||||
associated conditions are met upon typing the opening part of the pair.
|
||||
|
||||
CONDITIONS *nvim-autopairs-rules-conditions*
|
||||
|
||||
nvim-autopairs comes with a variety of common predicates ready to use simply by
|
||||
including:
|
||||
|
||||
>
|
||||
local cond = require('nvim-autopairs.conds')
|
||||
<
|
||||
|
||||
|
||||
│ function │ Usage │
|
||||
│none() │always false │
|
||||
│done() │always true │
|
||||
│before_text(text) │text exists before opening part │
|
||||
│after_text(text) │text exists after opening part │
|
||||
│before_regex(regex, length│regex matches before opening part │
|
||||
│) │ │
|
||||
│after_regex(regex, length)│regex matches after opening part │
|
||||
│ │ │
|
||||
│not_before_text(text) │text is not before opening part │
|
||||
│not_after_text(text) │text is not after opening part │
|
||||
│not_before_regex(regex, le│regex doesn’t match before opening part │
|
||||
│ngth) │ │
|
||||
│not_after_regex(regex, len│regex doesn’t match after opening part │
|
||||
│gth) │ │
|
||||
│not_inside_quote() │not currently within quotation marks │
|
||||
│is_inside_quote() │currently within quotation marks │
|
||||
│not_filetypes({table}) │current filetype is not inside table │
|
||||
│is_bracket_in_quote() │check the next char is quote and cursor is insi│
|
||||
│ │de quote │
|
||||
|
||||
|
||||
**N.B.** While `cond.not_filetypes` is available, it’s better to use the
|
||||
minus syntax on the desired filetype in the initial rule declaration, since
|
||||
then the rule is completely removed from the buffer.
|
||||
|
||||
TREESITTER CONDITIONS ~
|
||||
|
||||
Predicates based on the state of the Treesitter graph can be used by including:
|
||||
|
||||
>
|
||||
local ts_conds = require('nvim-autopairs.ts-conds')
|
||||
<
|
||||
|
||||
|
||||
│ function │ Usage │
|
||||
│is_ts_node({node_table}) │check current treesitter node│
|
||||
│is_not_ts_node({node_table})│check not in treesitter node │
|
||||
|
||||
|
||||
==============================================================================
|
||||
3. Method Explanations *nvim-autopairs-rules-method-explanations*
|
||||
|
||||
This section explains each method in more detail: their signatures and how they
|
||||
modify the rule’s behavior are all outlined here.
|
||||
|
||||
THE `WITH_*` METHODS *nvim-autopairs-rules-the-`with_*`-methods*
|
||||
|
||||
Calling these methods on a `Rule` will add predicate functions to their
|
||||
corresponding event, which determines whether the effect of the event actually
|
||||
takes place. There are no predicates if you don’t define any, and so any
|
||||
events without predicates behave as if they had a single predicate that always
|
||||
returns true.
|
||||
|
||||
A `Rule` may have more than one predicate defined for a given event, and the
|
||||
order that they are defined will be the order that they are checked. However,
|
||||
the **first** non-`nil` value returned by a predicate is used and the remaining
|
||||
predicates (if any) are **not** executed. In other words, predicates defined
|
||||
earlier have priority over predicates defined later.
|
||||
|
||||
`WITH_PAIR(COND, POS)` ~
|
||||
|
||||
After typing the opening part, `cond` will fire and the ending part will only
|
||||
be added if `cond` returned true. `with_pair` may be called more than once, and
|
||||
by default, each predicate is appended to a list. When the "pair" event fires,
|
||||
the _first_ predicate to return non-nil is used as the condition result.
|
||||
Specifying `pos` allows explicit control over the order of the predicates.
|
||||
|
||||
`WITH_MOVE(COND)` ~
|
||||
|
||||
If `cond` is true, the cursor is simply moved right when typing the ending part
|
||||
of the pair and the next character is also the ending part, e.g. `|" -> "|`
|
||||
when typing `"`. If `cond` returns false, the ending part is inserted as normal
|
||||
instead.
|
||||
|
||||
`WITH_CR(COND)` ~
|
||||
|
||||
If `cond` is true, then move the ending part of the pair to a new line below
|
||||
the cursor after pressing `<CR>` while the cursor is between the pair (think
|
||||
curly braces opening a block). Otherwise `<CR>` behaves as normal. For example:
|
||||
|
||||
>
|
||||
{|}
|
||||
<
|
||||
|
||||
|
||||
Typing `<CR>` produces the following when `cond` is true:
|
||||
|
||||
>
|
||||
{
|
||||
|
|
||||
}
|
||||
<
|
||||
|
||||
|
||||
`WITH_DEL(COND)` ~
|
||||
|
||||
If `cond` is true, when the cursor is between the pair, pressing `<BS>` to
|
||||
delete the opening part of the pair will delete the ending part as well.
|
||||
|
||||
THE `USE_*` METHODS *nvim-autopairs-rules-the-`use_*`-methods*
|
||||
|
||||
The `use_*` functions alter how auto-pairing is triggered. Normally, the first
|
||||
argument to `Rule` is taken literally as the opening part of the pair and as
|
||||
soon as it is typed the "pair" event fires.
|
||||
|
||||
`USE_KEY(KEY)` ~
|
||||
|
||||
The pair is only completed when `key` is pressed, instead of the moment that
|
||||
the opening part is typed. This is particularly useful in `use_regex`.
|
||||
|
||||
`USE_REGEX(BOOL, KEY)` ~
|
||||
|
||||
Causes the opening part to be interpreted as a lua pattern that triggers
|
||||
insertion of the ending part when matched. If `key` is specified, then it acts
|
||||
as an implicit `use_key`.
|
||||
|
||||
SHORTHAND METHODS *nvim-autopairs-rules-shorthand-methods*
|
||||
|
||||
These methods exist as convenient shortcuts for defining certain behaviors.
|
||||
|
||||
`END_WISE(FUNC)` ~
|
||||
|
||||
This method is used to make "end-wise" rules, which is terminology that should
|
||||
be familiar to users of other auto-pair plugins, e.g. Lexima. Specifically,
|
||||
this method makes it so that the ending part of the pair will be completed
|
||||
_only upon pressing `<CR>` after the opening part_, in which case the "newline"
|
||||
event is fired as usual.
|
||||
|
||||
This behavior is useful for languages with statement constructs like Lua and
|
||||
Bash. For example, defining the following `Rule`:
|
||||
|
||||
>
|
||||
Rule('then', 'end'):end_wise(function(opts))
|
||||
-- Add any context checks here, e.g. line starts with "if"
|
||||
return string.match(opts.line, '^%s*if') ~= nil
|
||||
end)
|
||||
<
|
||||
|
||||
|
||||
And then pressing `<CR>` at the following cursor position:
|
||||
|
||||
>
|
||||
if foo == bar then|
|
||||
<
|
||||
|
||||
|
||||
Would be completed as this (assuming some kind of automatic indent is enabled):
|
||||
|
||||
>
|
||||
if foo == bar then
|
||||
|
|
||||
end
|
||||
<
|
||||
|
||||
|
||||
`ONLY_CR(COND)` ~
|
||||
|
||||
This shortcut method disables the "pair", "del", and "move" events by setting a
|
||||
single predicate for each that is always false. Additionally, the effect of any
|
||||
`use_key` modifiers are removed as well. If `cond` is specified, a "newline"
|
||||
predicate is set as if `with_cr` were called.
|
||||
|
||||
This method is convenient for defining _simple_ end-wise rules. As an example,
|
||||
a default rule is defined with `only_cr` for Markdown code blocks with an
|
||||
explicit language; the closing triple-backtick is not completed until you press
|
||||
`<CR>` after specifying the language:
|
||||
|
||||
>
|
||||
```lua <-- <CR> pressed here
|
||||
|
|
||||
```
|
||||
<
|
||||
|
||||
|
||||
ADVANCED METHODS *nvim-autopairs-rules-advanced-methods*
|
||||
|
||||
These methods allow you to define more complex and dynamic rules. When combined
|
||||
with `with_*` and `use_*` methods, it is possible to create very powerful
|
||||
auto-pairs.
|
||||
|
||||
`REPLACE_ENDPAIR(FUNC, CHECK_PAIR)` ~
|
||||
|
||||
Facilitates the creation of dynamic ending parts. When the "pair" event fires
|
||||
and the ending part is to be completed, `func` is called with a single `opts`
|
||||
argument and should return a string. The returned string will be sent to
|
||||
`nvim_feedkeys` to insert the ending part of the pair.
|
||||
|
||||
The `opts` parameter is a table that provides context for the current pair
|
||||
completion, and can be useful for determining what to return. Note that because
|
||||
`nvim_feedkeys` is used, arbitrary Vim functionality can be leveraged, such as
|
||||
including `<Esc>` to be able to send normal mode commands.
|
||||
|
||||
*nvim-autopairs-rules-Optional-`check_pair`-parameter*
|
||||
|
||||
Optional `check_pair` parameter The `check_pair` parameter is optional,
|
||||
and can either be a boolean or function.
|
||||
If `check_pair` is a function, it is
|
||||
passed as-is to `with_pair` to create a
|
||||
"pair" predicate. If `check_pair` is
|
||||
true, then an implicit
|
||||
`with_pair(cond.after_text(rule.end_pair))`
|
||||
predicate is added, where
|
||||
`rule.end_pair` is the second argument
|
||||
to the `Rule` constructor. If
|
||||
`check_pair` is false, an "always false"
|
||||
`with_pair` predicate is added.
|
||||
|
||||
|
||||
As an example, these two rule definitions are equivalent:
|
||||
|
||||
>
|
||||
-- This...
|
||||
Rule("(", ")")
|
||||
:use_key("<C-h>")
|
||||
:replace_endpair(function() return "<BS><Del>" end, true)
|
||||
|
||||
-- ...is shorthand for this
|
||||
Rule("(", "")
|
||||
:use_key("<C-h>")
|
||||
:with_pair(cond.after_text(")")) -- check that text after cursor is `)`
|
||||
:replace_endpair(function() return "<BS><Del>" end)
|
||||
<
|
||||
|
||||
|
||||
`SET_END_PAIR_LENGTH(LEN)` ~
|
||||
|
||||
When completing the ending part of a pair, the cursor necessarily moves
|
||||
backward so that is in between the opening part and the closing part. In order
|
||||
to do this, the `Rule` must know the length of the ending part, which by
|
||||
default is trivially determined. However, if you would like to override where
|
||||
the cursor is placed after completion, i.e. using `replace_endpair`, you can
|
||||
explicitly set the ending part length with this method.
|
||||
|
||||
`REPLACE_MAP_CR(FUNC)` ~
|
||||
|
||||
This method allows you to set a custom mapping for the "newline" (`<CR>`) event
|
||||
that will be used instead of the normal behavior. This can be helpful for
|
||||
enforcing certain styles or or adding additional edits. `func` is called with a
|
||||
single `opts` argument and should return a string specifying the mapping for
|
||||
`<CR>`. The default mapping is: `<C-g>u<CR><C-c>O`.
|
||||
|
||||
Generated by panvimdoc <https://github.com/kdheepak/panvimdoc>
|
||||
|
||||
vim:tw=78:ts=8:noet:ft=help:norl:
|
||||
@ -0,0 +1,444 @@
|
||||
*nvim-autopairs.txt* A super powerful autopair for Neovim.
|
||||
|
||||
==============================================================================
|
||||
Table of Contents *nvim-autopairs-table-of-contents*
|
||||
|
||||
- nvim-autopairs |nvim-autopairs-nvim-autopairs|
|
||||
- Installation |nvim-autopairs-installation|
|
||||
- Default values |nvim-autopairs-default-values|
|
||||
- Sponsors |nvim-autopairs-sponsors|
|
||||
|
||||
NVIM-AUTOPAIRS *nvim-autopairs-nvim-autopairs*
|
||||
|
||||
A super powerful autopair plugin for Neovim that supports multiple characters.
|
||||
|
||||
Requires neovim 0.7
|
||||
|
||||
INSTALLATION *nvim-autopairs-installation*
|
||||
|
||||
Install the plugin with your preferred package manager:
|
||||
|
||||
VIM-PLUG <HTTPS://GITHUB.COM/JUNEGUNN/VIM-PLUG> ~
|
||||
|
||||
>
|
||||
Plug 'windwp/nvim-autopairs'
|
||||
|
||||
lua << EOF
|
||||
require("nvim-autopairs").setup {}
|
||||
EOF
|
||||
<
|
||||
|
||||
|
||||
PACKER <HTTPS://GITHUB.COM/WBTHOMASON/PACKER.NVIM> ~
|
||||
|
||||
>
|
||||
use {
|
||||
"windwp/nvim-autopairs",
|
||||
config = function() require("nvim-autopairs").setup {} end
|
||||
}
|
||||
<
|
||||
|
||||
|
||||
DEFAULT VALUES *nvim-autopairs-default-values*
|
||||
|
||||
>
|
||||
local disable_filetype = { "TelescopePrompt" }
|
||||
local disable_in_macro = false -- disable when recording or executing a macro
|
||||
local disable_in_visualblock = false -- disable when insert after visual block mode
|
||||
local disable_in_replace_mode = true
|
||||
local ignored_next_char = [=[[%w%%%'%[%"%.%`%$]]=]
|
||||
local enable_moveright = true
|
||||
local enable_afterquote = true -- add bracket pairs after quote
|
||||
local enable_check_bracket_line = true --- check bracket in same line
|
||||
local enable_bracket_in_quote = true --
|
||||
local enable_abbr = false -- trigger abbreviation
|
||||
local break_undo = true -- switch for basic rule break undo sequence
|
||||
local check_ts = false
|
||||
local map_cr = true
|
||||
local map_bs = true -- map the <BS> key
|
||||
local map_c_h = false -- Map the <C-h> key to delete a pair
|
||||
local map_c_w = false -- map <c-w> to delete a pair if possible
|
||||
<
|
||||
|
||||
|
||||
OVERRIDE DEFAULT VALUES ~
|
||||
|
||||
>
|
||||
require('nvim-autopairs').setup({
|
||||
disable_filetype = { "TelescopePrompt" , "vim" },
|
||||
})
|
||||
<
|
||||
|
||||
|
||||
*nvim-autopairs-Mapping-`<CR>`*
|
||||
|
||||
>
|
||||
Before Input After
|
||||
------------------------------------
|
||||
{|} <CR> {
|
||||
|
|
||||
}
|
||||
------------------------------------
|
||||
<
|
||||
|
||||
|
||||
nvim-cmp ~
|
||||
|
||||
<h3>
|
||||
|
||||
You need to add mapping `CR` on nvim-cmp setup.
|
||||
Check readme.md on nvim-cmp repo.
|
||||
|
||||
</h3>
|
||||
|
||||
>
|
||||
-- If you want insert `(` after select function or method item
|
||||
local cmp_autopairs = require('nvim-autopairs.completion.cmp')
|
||||
local cmp = require('cmp')
|
||||
cmp.event:on(
|
||||
'confirm_done',
|
||||
cmp_autopairs.on_confirm_done()
|
||||
)
|
||||
<
|
||||
|
||||
|
||||
Mapping `<CR>` You can customize the kind of completion
|
||||
to add `(` or any character.
|
||||
|
||||
|
||||
>
|
||||
local handlers = require('nvim-autopairs.completion.handlers')
|
||||
|
||||
cmp.event:on(
|
||||
'confirm_done',
|
||||
cmp_autopairs.on_confirm_done({
|
||||
filetypes = {
|
||||
-- "*" is a alias to all filetypes
|
||||
["*"] = {
|
||||
["("] = {
|
||||
kind = {
|
||||
cmp.lsp.CompletionItemKind.Function,
|
||||
cmp.lsp.CompletionItemKind.Method,
|
||||
},
|
||||
handler = handlers["*"]
|
||||
}
|
||||
},
|
||||
lua = {
|
||||
["("] = {
|
||||
kind = {
|
||||
cmp.lsp.CompletionItemKind.Function,
|
||||
cmp.lsp.CompletionItemKind.Method
|
||||
},
|
||||
---@param char string
|
||||
---@param item table item completion
|
||||
---@param bufnr number buffer number
|
||||
---@param rules table
|
||||
---@param commit_character table<string>
|
||||
handler = function(char, item, bufnr, rules, commit_character)
|
||||
-- Your handler function. Inpect with print(vim.inspect{char, item, bufnr, rules, commit_character})
|
||||
end
|
||||
}
|
||||
},
|
||||
-- Disable for tex
|
||||
tex = false
|
||||
}
|
||||
})
|
||||
)
|
||||
<
|
||||
|
||||
|
||||
Don’t use `nil` to disable a filetype. If a filetype is `nil` then `*` is
|
||||
used as fallback.
|
||||
|
||||
coq_nvim ~
|
||||
|
||||
>
|
||||
local remap = vim.api.nvim_set_keymap
|
||||
local npairs = require('nvim-autopairs')
|
||||
|
||||
npairs.setup({ map_bs = false, map_cr = false })
|
||||
|
||||
vim.g.coq_settings = { keymap = { recommended = false } }
|
||||
|
||||
-- these mappings are coq recommended mappings unrelated to nvim-autopairs
|
||||
remap('i', '<esc>', [[pumvisible() ? "<c-e><esc>" : "<esc>"]], { expr = true, noremap = true })
|
||||
remap('i', '<c-c>', [[pumvisible() ? "<c-e><c-c>" : "<c-c>"]], { expr = true, noremap = true })
|
||||
remap('i', '<tab>', [[pumvisible() ? "<c-n>" : "<tab>"]], { expr = true, noremap = true })
|
||||
remap('i', '<s-tab>', [[pumvisible() ? "<c-p>" : "<bs>"]], { expr = true, noremap = true })
|
||||
|
||||
-- skip it, if you use another global object
|
||||
_G.MUtils= {}
|
||||
|
||||
MUtils.CR = function()
|
||||
if vim.fn.pumvisible() ~= 0 then
|
||||
if vim.fn.complete_info({ 'selected' }).selected ~= -1 then
|
||||
return npairs.esc('<c-y>')
|
||||
else
|
||||
return npairs.esc('<c-e>') .. npairs.autopairs_cr()
|
||||
end
|
||||
else
|
||||
return npairs.autopairs_cr()
|
||||
end
|
||||
end
|
||||
remap('i', '<cr>', 'v:lua.MUtils.CR()', { expr = true, noremap = true })
|
||||
|
||||
MUtils.BS = function()
|
||||
if vim.fn.pumvisible() ~= 0 and vim.fn.complete_info({ 'mode' }).mode == 'eval' then
|
||||
return npairs.esc('<c-e>') .. npairs.autopairs_bs()
|
||||
else
|
||||
return npairs.autopairs_bs()
|
||||
end
|
||||
end
|
||||
remap('i', '<bs>', 'v:lua.MUtils.BS()', { expr = true, noremap = true })
|
||||
<
|
||||
|
||||
|
||||
without completion plugin ~
|
||||
|
||||
>
|
||||
-- add option map_cr
|
||||
npairs.setup({ map_cr = true })
|
||||
<
|
||||
|
||||
|
||||
another completion plugin
|
||||
<https://github.com/windwp/nvim-autopairs/wiki/Completion-plugin>
|
||||
|
||||
If you have a problem with indent after you press `<CR>` please check the
|
||||
settings of treesitter indent or install a plugin that has indent support for
|
||||
your filetype.
|
||||
|
||||
RULE ~
|
||||
|
||||
nvim-autopairs uses rules with conditions to check pairs.
|
||||
|
||||
>
|
||||
local Rule = require('nvim-autopairs.rule')
|
||||
local npairs = require('nvim-autopairs')
|
||||
|
||||
npairs.add_rule(Rule("$$","$$","tex"))
|
||||
|
||||
-- you can use some built-in conditions
|
||||
|
||||
local cond = require('nvim-autopairs.conds')
|
||||
print(vim.inspect(cond))
|
||||
|
||||
npairs.add_rules({
|
||||
Rule("$", "$",{"tex", "latex"})
|
||||
-- don't add a pair if the next character is %
|
||||
:with_pair(cond.not_after_regex("%%"))
|
||||
-- don't add a pair if the previous character is xxx
|
||||
:with_pair(cond.not_before_regex("xxx", 3))
|
||||
-- don't move right when repeat character
|
||||
:with_move(cond.none())
|
||||
-- don't delete if the next character is xx
|
||||
:with_del(cond.not_after_regex("xx"))
|
||||
-- disable adding a newline when you press <cr>
|
||||
:with_cr(cond.none())
|
||||
},
|
||||
-- disable for .vim files, but it work for another filetypes
|
||||
Rule("a","a","-vim")
|
||||
)
|
||||
|
||||
npairs.add_rules({
|
||||
Rule("$$","$$","tex")
|
||||
:with_pair(function(opts)
|
||||
print(vim.inspect(opts))
|
||||
if opts.line=="aa $$" then
|
||||
-- don't add pair on that line
|
||||
return false
|
||||
end
|
||||
end)
|
||||
}
|
||||
)
|
||||
|
||||
-- you can use regex
|
||||
-- press u1234 => u1234number
|
||||
npairs.add_rules({
|
||||
Rule("u%d%d%d%d$", "number", "lua")
|
||||
:use_regex(true)
|
||||
})
|
||||
|
||||
|
||||
|
||||
-- press x1234 => x12341234
|
||||
npairs.add_rules({
|
||||
Rule("x%d%d%d%d$", "number", "lua")
|
||||
:use_regex(true)
|
||||
:replace_endpair(function(opts)
|
||||
-- print(vim.inspect(opts))
|
||||
return opts.prev_char:sub(#opts.prev_char - 3,#opts.prev_char)
|
||||
end)
|
||||
})
|
||||
|
||||
|
||||
-- you can do anything with regex +special key
|
||||
-- example press tab to uppercase text:
|
||||
-- press b1234s<tab> => B1234S1234S
|
||||
|
||||
npairs.add_rules({
|
||||
Rule("b%d%d%d%d%w$", "", "vim")
|
||||
:use_regex(true,"<tab>")
|
||||
:replace_endpair(function(opts)
|
||||
return
|
||||
opts.prev_char:sub(#opts.prev_char - 4,#opts.prev_char)
|
||||
.."<esc>viwU"
|
||||
end)
|
||||
})
|
||||
|
||||
-- you can exclude filetypes
|
||||
npairs.add_rule(
|
||||
Rule("$$","$$")
|
||||
:with_pair(cond.not_filetypes({"lua"}))
|
||||
)
|
||||
--- check ./lua/nvim-autopairs/rules/basic.lua
|
||||
<
|
||||
|
||||
|
||||
Rules API <https://github.com/windwp/nvim-autopairs/wiki/Rules-API>
|
||||
|
||||
TREESITTER ~
|
||||
|
||||
You can use treesitter to check for a pair.
|
||||
|
||||
>
|
||||
local npairs = require("nvim-autopairs")
|
||||
local Rule = require('nvim-autopairs.rule')
|
||||
|
||||
npairs.setup({
|
||||
check_ts = true,
|
||||
ts_config = {
|
||||
lua = {'string'},-- it will not add a pair on that treesitter node
|
||||
javascript = {'template_string'},
|
||||
java = false,-- don't check treesitter on java
|
||||
}
|
||||
})
|
||||
|
||||
local ts_conds = require('nvim-autopairs.ts-conds')
|
||||
|
||||
|
||||
-- press % => %% only while inside a comment or string
|
||||
npairs.add_rules({
|
||||
Rule("%", "%", "lua")
|
||||
:with_pair(ts_conds.is_ts_node({'string','comment'})),
|
||||
Rule("$", "$", "lua")
|
||||
:with_pair(ts_conds.is_not_ts_node({'function'}))
|
||||
})
|
||||
<
|
||||
|
||||
|
||||
DON’T ADD PAIRS IF IT ALREADY HAS A CLOSE PAIR IN THE SAME LINE ~
|
||||
|
||||
if **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
|
||||
|
||||
>
|
||||
Before Input After
|
||||
------------------------------------
|
||||
( |)) ( ( (|))
|
||||
<
|
||||
|
||||
|
||||
>
|
||||
require('nvim-autopairs').setup({
|
||||
enable_check_bracket_line = false
|
||||
})
|
||||
<
|
||||
|
||||
|
||||
DON’T ADD PAIRS IF THE NEXT CHAR IS ALPHANUMERIC ~
|
||||
|
||||
You can customize how nvim-autopairs will behave if it encounters a specific
|
||||
character
|
||||
|
||||
>
|
||||
require('nvim-autopairs').setup({
|
||||
ignored_next_char = "[%w%.]" -- will ignore alphanumeric and `.` symbol
|
||||
})
|
||||
<
|
||||
|
||||
|
||||
>
|
||||
Before Input After
|
||||
------------------------------------
|
||||
|foobar ( (|foobar
|
||||
|.foobar ( (|.foobar
|
||||
<
|
||||
|
||||
|
||||
PLUGIN INTEGRATION ~
|
||||
|
||||
>
|
||||
require('nvim-autopairs').disable()
|
||||
require('nvim-autopairs').enable()
|
||||
require('nvim-autopairs').remove_rule('(') -- remove rule (
|
||||
require('nvim-autopairs').clear_rules() -- clear all rules
|
||||
-- get rule " then modify it. It can return a list of rule or just a rule
|
||||
require('nvim-autopairs').get_rule('"')
|
||||
<
|
||||
|
||||
|
||||
|
||||
- Sample
|
||||
|
||||
|
||||
>
|
||||
-- remove add single quote on filetype scheme or lisp
|
||||
require("nvim-autopairs").get_rule("'")[1].not_filetypes = { "scheme", "lisp" }
|
||||
require("nvim-autopairs").get_rule("'")[1]:with_pair(cond.not_after_text("["}))
|
||||
<
|
||||
|
||||
|
||||
FASTWRAP ~
|
||||
|
||||
>
|
||||
Before Input After
|
||||
--------------------------------------------------
|
||||
(|foobar <M-e> then press $ (|foobar)
|
||||
(|)(foobar) <M-e> then press q (|(foobar))
|
||||
<
|
||||
|
||||
|
||||
>
|
||||
-- put this to setup function and press <a-e> to use fast_wrap
|
||||
npairs.setup({
|
||||
fast_wrap = {},
|
||||
})
|
||||
|
||||
-- change default fast_wrap
|
||||
npairs.setup({
|
||||
fast_wrap = {
|
||||
map = '<M-e>',
|
||||
chars = { '{', '[', '(', '"', "'" },
|
||||
pattern = [=[[%'%"%>%]%)%}%,]]=],
|
||||
end_key = '$',
|
||||
keys = 'qwertyuiopzxcvbnmasdfghjkl',
|
||||
check_comma = true,
|
||||
highlight = 'Search',
|
||||
highlight_grey='Comment'
|
||||
},
|
||||
})
|
||||
<
|
||||
|
||||
|
||||
AUTOTAG HTML AND TSX ~
|
||||
|
||||
autotag <https://github.com/windwp/nvim-ts-autotag>
|
||||
|
||||
ENDWISE ~
|
||||
|
||||
endwise <https://github.com/windwp/nvim-autopairs/wiki/Endwise>
|
||||
|
||||
CUSTOM RULES ~
|
||||
|
||||
rules <https://github.com/windwp/nvim-autopairs/wiki/Custom-rules>
|
||||
|
||||
SPONSORS *nvim-autopairs-sponsors*
|
||||
|
||||
Thanks to everyone who sponsors my projects and makes continued development
|
||||
maintenance possible! <!-- patreon --><a href="https://github.com/t4t5"><img
|
||||
src="https://github.com/t4t5.png" width="60px" alt="" /></a><!-- patreon-->
|
||||
|
||||
Generated by panvimdoc <https://github.com/kdheepak/panvimdoc>
|
||||
|
||||
vim:tw=78:ts=8:noet:ft=help:norl:
|
||||
@ -0,0 +1,664 @@
|
||||
local log = require('nvim-autopairs._log')
|
||||
local utils = require('nvim-autopairs.utils')
|
||||
local basic_rule = require('nvim-autopairs.rules.basic')
|
||||
local api = vim.api
|
||||
local highlighter = nil
|
||||
local M = {}
|
||||
|
||||
M.state = {
|
||||
disabled = false,
|
||||
rules = {},
|
||||
buf_ts = {},
|
||||
}
|
||||
|
||||
local default = {
|
||||
map_bs = true,
|
||||
map_c_h = false,
|
||||
map_c_w = false,
|
||||
map_cr = true,
|
||||
disable_filetype = { 'TelescopePrompt', 'spectre_panel' },
|
||||
disable_in_macro = true,
|
||||
disable_in_visualblock = false,
|
||||
disable_in_replace_mode = true,
|
||||
ignored_next_char = [=[[%w%%%'%[%"%.%`%$]]=],
|
||||
break_undo = true,
|
||||
check_ts = false,
|
||||
enable_moveright = true,
|
||||
enable_afterquote = true,
|
||||
enable_check_bracket_line = true,
|
||||
enable_bracket_in_quote = true,
|
||||
enable_abbr = false,
|
||||
ts_config = {
|
||||
lua = { 'string', 'source', 'string_content' },
|
||||
javascript = { 'string', 'template_string' },
|
||||
},
|
||||
}
|
||||
|
||||
M.setup = function(opt)
|
||||
M.config = vim.tbl_deep_extend('force', default, opt or {})
|
||||
if M.config.fast_wrap then
|
||||
require('nvim-autopairs.fastwrap').setup(M.config.fast_wrap)
|
||||
end
|
||||
M.config.rules = basic_rule.setup(M.config)
|
||||
|
||||
if M.config.check_ts then
|
||||
local ok, ts_rule = pcall(require, 'nvim-autopairs.rules.ts_basic')
|
||||
if ok then
|
||||
highlighter = require "vim.treesitter.highlighter"
|
||||
M.config.rules = ts_rule.setup(M.config)
|
||||
end
|
||||
end
|
||||
|
||||
if M.config.map_cr then
|
||||
M.map_cr()
|
||||
end
|
||||
|
||||
M.force_attach()
|
||||
local group = api.nvim_create_augroup('autopairs_buf', { clear = true })
|
||||
api.nvim_create_autocmd({ 'BufEnter', 'BufWinEnter' }, {
|
||||
group = group, pattern = '*',
|
||||
callback = function() M.on_attach() end
|
||||
})
|
||||
api.nvim_create_autocmd('BufDelete', {
|
||||
group = group, pattern = '*',
|
||||
callback = function(data)
|
||||
local cur = api.nvim_get_current_buf()
|
||||
local bufnr = tonumber(data.buf) or 0
|
||||
if bufnr ~= cur then
|
||||
M.set_buf_rule(nil, bufnr)
|
||||
end
|
||||
end,
|
||||
})
|
||||
api.nvim_create_autocmd('FileType', {
|
||||
group = group, pattern = '*',
|
||||
callback = function() M.force_attach() end
|
||||
})
|
||||
end
|
||||
|
||||
M.add_rule = function(rule)
|
||||
M.add_rules({ rule })
|
||||
end
|
||||
|
||||
M.get_rule = function(start_pair)
|
||||
local tbl = M.get_rules(start_pair)
|
||||
if #tbl == 1 then
|
||||
return tbl[1]
|
||||
end
|
||||
return tbl
|
||||
end
|
||||
|
||||
M.get_rules = function(start_pair)
|
||||
local tbl = {}
|
||||
for _, r in pairs(M.config.rules) do
|
||||
if r.start_pair == start_pair then
|
||||
table.insert(tbl, r)
|
||||
end
|
||||
end
|
||||
return tbl
|
||||
end
|
||||
|
||||
M.remove_rule = function(pair)
|
||||
local tbl = {}
|
||||
for _, r in pairs(M.config.rules) do
|
||||
if r.start_pair ~= pair then
|
||||
table.insert(tbl, r)
|
||||
end
|
||||
end
|
||||
M.config.rules = tbl
|
||||
if M.state.rules then
|
||||
local state_tbl = {}
|
||||
local rules = M.get_buf_rules()
|
||||
for _, r in pairs(rules) do
|
||||
if r.start_pair ~= pair then
|
||||
table.insert(state_tbl, r)
|
||||
elseif r.key_map and r.key_map ~= '' then
|
||||
api.nvim_buf_del_keymap(0, 'i', r.key_map)
|
||||
end
|
||||
end
|
||||
M.set_buf_rule(state_tbl, 0)
|
||||
end
|
||||
M.force_attach()
|
||||
end
|
||||
|
||||
M.add_rules = function(rules)
|
||||
for _, rule in pairs(rules) do
|
||||
table.insert(M.config.rules, rule)
|
||||
end
|
||||
M.force_attach()
|
||||
end
|
||||
|
||||
M.clear_rules = function()
|
||||
M.state.rules = {}
|
||||
M.config.rules = {}
|
||||
end
|
||||
|
||||
M.disable = function()
|
||||
M.state.disabled = true
|
||||
end
|
||||
|
||||
M.enable = function()
|
||||
M.state.disabled = false
|
||||
end
|
||||
|
||||
--- force remap key to buffer
|
||||
M.force_attach = function(bufnr)
|
||||
utils.set_attach(bufnr, 0)
|
||||
M.on_attach(bufnr)
|
||||
end
|
||||
|
||||
local del_keymaps = function()
|
||||
local status, autopairs_keymaps = pcall(api.nvim_buf_get_var, 0, 'autopairs_keymaps')
|
||||
if status and autopairs_keymaps and #autopairs_keymaps > 0 then
|
||||
for _, key in pairs(autopairs_keymaps) do
|
||||
pcall(api.nvim_buf_del_keymap, 0, 'i', key)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function is_disable()
|
||||
if M.state.disabled then
|
||||
return true
|
||||
end
|
||||
|
||||
if vim.bo.filetype == '' and api.nvim_win_get_config(0).relative ~= '' then
|
||||
-- disable for any floating window without filetype
|
||||
return true
|
||||
end
|
||||
|
||||
if vim.bo.modifiable == false then
|
||||
return true
|
||||
end
|
||||
|
||||
if M.config.disable_in_macro
|
||||
and (vim.fn.reg_recording() ~= '' or vim.fn.reg_executing() ~= '')
|
||||
then
|
||||
return true
|
||||
end
|
||||
|
||||
if M.config.disable_in_replace_mode and vim.api.nvim_get_mode().mode == "R" then
|
||||
return true
|
||||
end
|
||||
|
||||
if M.config.disable_in_visualblock and utils.is_block_wise_mode() then
|
||||
return true
|
||||
end
|
||||
|
||||
if utils.check_filetype(M.config.disable_filetype, vim.bo.filetype) then
|
||||
del_keymaps()
|
||||
M.set_buf_rule({}, 0)
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
---@return table <number, Rule>
|
||||
M.get_buf_rules = function(bufnr)
|
||||
return M.state.rules[bufnr or api.nvim_get_current_buf()] or {}
|
||||
end
|
||||
|
||||
---@param rules nil|table list or rule
|
||||
---@param bufnr number buffer number
|
||||
M.set_buf_rule = function(rules, bufnr)
|
||||
if bufnr == 0 or bufnr == nil then
|
||||
bufnr = api.nvim_get_current_buf()
|
||||
end
|
||||
M.state.rules[bufnr] = rules
|
||||
end
|
||||
|
||||
M.on_attach = function(bufnr)
|
||||
-- log.debug('on_attach' .. vim.bo.filetype)
|
||||
if is_disable() then
|
||||
return
|
||||
end
|
||||
bufnr = bufnr or api.nvim_get_current_buf()
|
||||
|
||||
local rules = {}
|
||||
for _, rule in pairs(M.config.rules) do
|
||||
if utils.check_filetype(rule.filetypes, vim.bo.filetype)
|
||||
and utils.check_not_filetype(rule.not_filetypes, vim.bo.filetype)
|
||||
then
|
||||
table.insert(rules, rule)
|
||||
end
|
||||
end
|
||||
-- sort by pair and keymap
|
||||
table.sort(rules, function(a, b)
|
||||
if a.start_pair == b.start_pair then
|
||||
if not b.key_map then
|
||||
return a.key_map
|
||||
end
|
||||
if not a.key_map then
|
||||
return b.key_map
|
||||
end
|
||||
return #a.key_map < #b.key_map
|
||||
end
|
||||
if #a.start_pair == #b.start_pair then
|
||||
return string.byte(a.start_pair) > string.byte(b.start_pair)
|
||||
end
|
||||
return #a.start_pair > #b.start_pair
|
||||
end)
|
||||
|
||||
M.set_buf_rule(rules, bufnr)
|
||||
|
||||
if M.config.check_ts then
|
||||
if highlighter and highlighter.active[bufnr] then
|
||||
M.state.ts_node = M.config.ts_config[vim.bo.filetype]
|
||||
else
|
||||
M.state.ts_node = nil
|
||||
end
|
||||
end
|
||||
|
||||
if utils.is_attached(bufnr) then
|
||||
return
|
||||
end
|
||||
del_keymaps()
|
||||
local enable_insert_auto = false
|
||||
local autopairs_keymaps = {}
|
||||
local expr_map = function(key)
|
||||
api.nvim_buf_set_keymap(bufnr, 'i', key, '', {
|
||||
expr = true,
|
||||
noremap = true,
|
||||
desc = "autopairs map key",
|
||||
callback = function() return M.autopairs_map(bufnr, key) end,
|
||||
})
|
||||
table.insert(autopairs_keymaps, key)
|
||||
end
|
||||
for _, rule in pairs(rules) do
|
||||
if rule.key_map ~= nil then
|
||||
if rule.is_regex == false then
|
||||
if rule.key_map == '' then
|
||||
rule.key_map = rule.start_pair:sub(#rule.start_pair)
|
||||
end
|
||||
expr_map(rule.key_map)
|
||||
local key_end = rule.key_end or rule.end_pair:sub(1, 1)
|
||||
if #key_end >= 1 and key_end ~= rule.key_map and rule.move_cond ~= nil then
|
||||
expr_map(key_end)
|
||||
end
|
||||
else
|
||||
if rule.key_map ~= '' then
|
||||
expr_map(rule.key_map)
|
||||
elseif rule.is_endwise == false then
|
||||
enable_insert_auto = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
api.nvim_buf_set_var(bufnr, 'autopairs_keymaps', autopairs_keymaps)
|
||||
|
||||
if enable_insert_auto then
|
||||
-- capture all key use it to trigger regex pairs
|
||||
-- it can make an issue with paste from register
|
||||
api.nvim_create_autocmd('InsertCharPre', {
|
||||
group = api.nvim_create_augroup(string.format("autopairs_insert_%d", bufnr), { clear = true }),
|
||||
buffer = bufnr,
|
||||
callback = function()
|
||||
M.autopairs_insert(bufnr, vim.v.char)
|
||||
end
|
||||
})
|
||||
end
|
||||
|
||||
if M.config.fast_wrap and M.config.fast_wrap.map then
|
||||
api.nvim_buf_set_keymap(
|
||||
bufnr,
|
||||
'i',
|
||||
M.config.fast_wrap.map,
|
||||
"<esc>l<cmd>lua require('nvim-autopairs.fastwrap').show()<cr>",
|
||||
{ noremap = true }
|
||||
)
|
||||
end
|
||||
|
||||
if M.config.map_bs then
|
||||
api.nvim_buf_set_keymap(
|
||||
bufnr,
|
||||
'i',
|
||||
'<bs>',
|
||||
'',
|
||||
{ callback = M.autopairs_bs, expr = true, noremap = true }
|
||||
)
|
||||
end
|
||||
|
||||
if M.config.map_c_h then
|
||||
api.nvim_buf_set_keymap(
|
||||
bufnr,
|
||||
"i",
|
||||
utils.key.c_h,
|
||||
'',
|
||||
{ callback = M.autopairs_c_h, expr = true, noremap = true }
|
||||
)
|
||||
end
|
||||
|
||||
if M.config.map_c_w then
|
||||
api.nvim_buf_set_keymap(
|
||||
bufnr,
|
||||
'i',
|
||||
'<c-w>',
|
||||
'',
|
||||
{ callback = M.autopairs_c_w, expr = true, noremap = true }
|
||||
)
|
||||
end
|
||||
api.nvim_buf_set_var(bufnr, 'nvim-autopairs', 1)
|
||||
end
|
||||
|
||||
local autopairs_delete = function(bufnr, key)
|
||||
if is_disable() then
|
||||
return utils.esc(key)
|
||||
end
|
||||
bufnr = bufnr or api.nvim_get_current_buf()
|
||||
local line = utils.text_get_current_line(bufnr)
|
||||
local _, col = utils.get_cursor()
|
||||
local rules = M.get_buf_rules(bufnr)
|
||||
for _, rule in pairs(rules) do
|
||||
if rule.start_pair then
|
||||
local prev_char, next_char = utils.text_cusor_line(
|
||||
line,
|
||||
col,
|
||||
#rule.start_pair,
|
||||
#rule.end_pair,
|
||||
rule.is_regex
|
||||
)
|
||||
if utils.compare(rule.start_pair, prev_char, rule.is_regex)
|
||||
and utils.compare(rule.end_pair, next_char, rule.is_regex)
|
||||
and rule:can_del({
|
||||
ts_node = M.state.ts_node,
|
||||
rule = rule,
|
||||
bufnr = bufnr,
|
||||
prev_char = prev_char,
|
||||
next_char = next_char,
|
||||
line = line,
|
||||
col = col,
|
||||
})
|
||||
then
|
||||
local input = ''
|
||||
for _ = 1, api.nvim_strwidth(rule.start_pair), 1 do
|
||||
input = input .. utils.key.bs
|
||||
end
|
||||
for _ = 1, api.nvim_strwidth(rule.end_pair), 1 do
|
||||
input = input .. utils.key.del
|
||||
end
|
||||
return utils.esc('<c-g>U' .. input)
|
||||
end
|
||||
end
|
||||
end
|
||||
return utils.esc(key)
|
||||
end
|
||||
|
||||
M.autopairs_c_w = function(bufnr)
|
||||
return autopairs_delete(bufnr, '<c-g>U<c-w>')
|
||||
end
|
||||
|
||||
M.autopairs_c_h = function(bufnr)
|
||||
return autopairs_delete(bufnr, utils.key.c_h)
|
||||
end
|
||||
|
||||
M.autopairs_bs = function(bufnr)
|
||||
return autopairs_delete(bufnr, utils.key.bs)
|
||||
end
|
||||
|
||||
M.autopairs_map = function(bufnr, char)
|
||||
if is_disable() then
|
||||
return char
|
||||
end
|
||||
local line = utils.text_get_current_line(bufnr)
|
||||
local _, col = utils.get_cursor()
|
||||
local new_text = ''
|
||||
local add_char = 1
|
||||
local rules = M.get_buf_rules(bufnr)
|
||||
for _, rule in pairs(rules) do
|
||||
if rule.start_pair then
|
||||
if char:match('<.*>') then
|
||||
new_text = line
|
||||
add_char = 0
|
||||
else
|
||||
new_text = line:sub(1, col) .. char .. line:sub(col + 1, #line)
|
||||
add_char = rule.key_map and #rule.key_map or 1
|
||||
end
|
||||
|
||||
-- log.debug("new_text:[" .. new_text .. "]")
|
||||
local prev_char, next_char = utils.text_cusor_line(
|
||||
new_text,
|
||||
col + add_char,
|
||||
#rule.start_pair,
|
||||
#rule.end_pair,
|
||||
rule.is_regex
|
||||
)
|
||||
local cond_opt = {
|
||||
ts_node = M.state.ts_node,
|
||||
text = new_text,
|
||||
rule = rule,
|
||||
bufnr = bufnr,
|
||||
col = col + 1,
|
||||
char = char,
|
||||
line = line,
|
||||
prev_char = prev_char,
|
||||
next_char = next_char,
|
||||
}
|
||||
-- log.debug("start_pair" .. rule.start_pair)
|
||||
-- log.debug('prev_char' .. prev_char)
|
||||
-- log.debug('next_char' .. next_char)
|
||||
local char_matches_rule = (rule.end_pair == char or rule.key_map == char)
|
||||
-- for simple pairs, char will match end_pair
|
||||
-- for more complex pairs, user should map the wanted end char with `use_key`
|
||||
-- on a dedicated rule
|
||||
if char_matches_rule
|
||||
and utils.compare(rule.end_pair, next_char, rule.is_regex)
|
||||
and rule:can_move(cond_opt)
|
||||
then
|
||||
local end_pair = rule:get_end_pair(cond_opt)
|
||||
local end_pair_length = rule:get_end_pair_length(end_pair)
|
||||
return utils.esc(utils.repeat_key(utils.key.join_right, end_pair_length))
|
||||
end
|
||||
|
||||
if rule.key_map == char
|
||||
and utils.compare(rule.start_pair, prev_char, rule.is_regex)
|
||||
and rule:can_pair(cond_opt)
|
||||
then
|
||||
local end_pair = rule:get_end_pair(cond_opt)
|
||||
local end_pair_length = rule:get_end_pair_length(end_pair)
|
||||
local move_text = utils.repeat_key(utils.key.join_left, end_pair_length)
|
||||
if add_char == 0 then
|
||||
move_text = ''
|
||||
char = ''
|
||||
end
|
||||
if end_pair:match('<.*>') then
|
||||
end_pair = utils.esc(end_pair)
|
||||
end
|
||||
local result = char .. end_pair .. utils.esc(move_text)
|
||||
if rule.is_undo then
|
||||
result = utils.esc(utils.key.undo_sequence) .. result .. utils.esc(utils.key.undo_sequence)
|
||||
end
|
||||
if M.config.enable_abbr then
|
||||
result = utils.esc(utils.key.abbr) .. result
|
||||
end
|
||||
log.debug("key_map :" .. result)
|
||||
return result
|
||||
end
|
||||
end
|
||||
end
|
||||
return M.autopairs_afterquote(new_text, utils.esc(char))
|
||||
end
|
||||
|
||||
M.autopairs_insert = function(bufnr, char)
|
||||
if is_disable() then
|
||||
return char
|
||||
end
|
||||
local line = utils.text_get_current_line(bufnr)
|
||||
local _, col = utils.get_cursor()
|
||||
local new_text = line:sub(1, col) .. char .. line:sub(col + 1, #line)
|
||||
local rules = M.get_buf_rules(bufnr)
|
||||
for _, rule in pairs(rules) do
|
||||
if rule.start_pair and rule.is_regex and rule.key_map == '' then
|
||||
local prev_char, next_char = utils.text_cusor_line(
|
||||
new_text,
|
||||
col + 1,
|
||||
#rule.start_pair,
|
||||
#rule.end_pair,
|
||||
rule.is_regex
|
||||
)
|
||||
local cond_opt = {
|
||||
ts_node = M.state.ts_node,
|
||||
text = new_text,
|
||||
rule = rule,
|
||||
bufnr = bufnr,
|
||||
col = col + 1,
|
||||
char = char,
|
||||
line = line,
|
||||
prev_char = prev_char,
|
||||
next_char = next_char,
|
||||
}
|
||||
-- log.debug("start_pair" .. rule.start_pair)
|
||||
-- log.debug('prev_char' .. prev_char)
|
||||
-- log.debug('next_char' .. next_char)
|
||||
if next_char == rule.end_pair and rule:can_move(cond_opt) then
|
||||
utils.set_vchar('')
|
||||
vim.schedule(function()
|
||||
utils.feed(utils.key.right, -1)
|
||||
end)
|
||||
return false
|
||||
end
|
||||
|
||||
if utils.compare(rule.start_pair, prev_char, rule.is_regex)
|
||||
and rule:can_pair(cond_opt)
|
||||
then
|
||||
local end_pair = rule:get_end_pair(cond_opt)
|
||||
utils.set_vchar(char .. end_pair)
|
||||
vim.schedule(function()
|
||||
utils.feed(utils.key.left, rule:get_end_pair_length(end_pair))
|
||||
end)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
return char
|
||||
end
|
||||
|
||||
M.autopairs_cr = function(bufnr)
|
||||
if is_disable() then
|
||||
return utils.esc('<cr>')
|
||||
end
|
||||
bufnr = bufnr or api.nvim_get_current_buf()
|
||||
local line = utils.text_get_current_line(bufnr)
|
||||
local _, col = utils.get_cursor()
|
||||
-- log.debug("on_cr")
|
||||
local rules = M.get_buf_rules(bufnr)
|
||||
for _, rule in pairs(rules) do
|
||||
if rule.start_pair then
|
||||
local prev_char, next_char = utils.text_cusor_line(
|
||||
line,
|
||||
col,
|
||||
#rule.start_pair,
|
||||
#rule.end_pair,
|
||||
rule.is_regex
|
||||
)
|
||||
|
||||
local cond_opt = {
|
||||
ts_node = M.state.ts_node,
|
||||
check_endwise_ts = true,
|
||||
rule = rule,
|
||||
bufnr = bufnr,
|
||||
col = col,
|
||||
line = line,
|
||||
prev_char = prev_char,
|
||||
next_char = next_char,
|
||||
}
|
||||
-- log.debug('prev_char' .. rule.start_pair)
|
||||
-- log.debug('prev_char' .. prev_char)
|
||||
-- log.debug('next_char' .. next_char)
|
||||
if rule.is_endwise
|
||||
and utils.compare(rule.start_pair, prev_char, rule.is_regex)
|
||||
and rule:can_cr(cond_opt)
|
||||
then
|
||||
local end_pair = rule:get_end_pair(cond_opt)
|
||||
return utils.esc(
|
||||
'<CR>' .. end_pair
|
||||
-- FIXME do i need to re indent twice #118
|
||||
.. '<CMD>normal! ====<CR><up><end><CR>'
|
||||
)
|
||||
end
|
||||
|
||||
cond_opt.check_endwise_ts = false
|
||||
|
||||
if utils.compare(rule.start_pair, prev_char, rule.is_regex)
|
||||
and utils.compare(rule.end_pair, next_char, rule.is_regex)
|
||||
and rule:can_cr(cond_opt)
|
||||
then
|
||||
log.debug('do_cr')
|
||||
return utils.esc(rule:get_map_cr({ rule = rule, line = line, color = col, bufnr = bufnr }))
|
||||
end
|
||||
end
|
||||
end
|
||||
return utils.esc('<cr>')
|
||||
end
|
||||
|
||||
--- add bracket pairs after quote (|"aaaaa" => (|"aaaaaa")
|
||||
M.autopairs_afterquote = function(line, key_char)
|
||||
if M.config.enable_afterquote and not utils.is_block_wise_mode() then
|
||||
line = line or utils.text_get_current_line(0)
|
||||
local _, col = utils.get_cursor()
|
||||
local prev_char, next_char = utils.text_cusor_line(line, col + 1, 1, 1, false)
|
||||
if utils.is_bracket(prev_char)
|
||||
and utils.is_quote(next_char)
|
||||
and not utils.is_in_quotes(line, col, next_char)
|
||||
then
|
||||
local count = 0
|
||||
local index = 0
|
||||
local is_prev_slash = false
|
||||
local char_end = ''
|
||||
for i = col, #line, 1 do
|
||||
local char = line:sub(i, i + #next_char - 1)
|
||||
if not is_prev_slash and char == next_char then
|
||||
count = count + 1
|
||||
char_end = line:sub(i + 1, i + #next_char)
|
||||
index = i
|
||||
end
|
||||
is_prev_slash = char == '\\'
|
||||
end
|
||||
if count == 2 and index >= (#line - 2) then
|
||||
local rules = M.get_buf_rules(api.nvim_get_current_buf())
|
||||
for _, rule in pairs(rules) do
|
||||
if rule.start_pair == prev_char and char_end ~= rule.end_pair then
|
||||
local new_text = line:sub(0, index)
|
||||
.. rule.end_pair
|
||||
.. line:sub(index + 1, #line)
|
||||
M.state.expr_quote = new_text
|
||||
local append = 'a'
|
||||
if col > 0 then
|
||||
append = 'la'
|
||||
end
|
||||
return utils.esc(
|
||||
"<esc><cmd>lua require'nvim-autopairs'.autopairs_closequote_expr()<cr>" .. append
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return key_char
|
||||
end
|
||||
|
||||
M.autopairs_closequote_expr = function()
|
||||
---@diagnostic disable-next-line: param-type-mismatch
|
||||
vim.fn.setline('.', M.state.expr_quote)
|
||||
end
|
||||
|
||||
M.check_break_line_char = function()
|
||||
return M.autopairs_cr()
|
||||
end
|
||||
|
||||
M.completion_confirm =function ()
|
||||
if vim.fn.pumvisible() ~= 0 then
|
||||
return M.esc("<cr>")
|
||||
else
|
||||
return M.autopairs_cr()
|
||||
end
|
||||
end
|
||||
|
||||
M.map_cr = function()
|
||||
api.nvim_set_keymap(
|
||||
'i',
|
||||
'<CR>',
|
||||
"v:lua.require'nvim-autopairs'.completion_confirm()",
|
||||
{ expr = true, noremap = true }
|
||||
)
|
||||
end
|
||||
|
||||
M.esc = utils.esc
|
||||
return M
|
||||
@ -0,0 +1,13 @@
|
||||
---@diagnostic disable: undefined-field
|
||||
local empty = {
|
||||
debug = function(_) end,
|
||||
info = function(_) end,
|
||||
error = function(_) end,
|
||||
}
|
||||
if _G.__is_log then
|
||||
return require('plenary.log').new {
|
||||
plugin = 'nvim-autopairs',
|
||||
level = (_G.__is_log == true and 'debug') or 'warn',
|
||||
} or empty
|
||||
end
|
||||
return empty
|
||||
@ -0,0 +1,97 @@
|
||||
local autopairs = require('nvim-autopairs')
|
||||
local handlers = require('nvim-autopairs.completion.handlers')
|
||||
local cmp = require('cmp')
|
||||
|
||||
local Kind = cmp.lsp.CompletionItemKind
|
||||
|
||||
local M = {}
|
||||
|
||||
M.filetypes = {
|
||||
-- Alias to all filetypes
|
||||
["*"] = {
|
||||
["("] = {
|
||||
kind = { Kind.Function, Kind.Method },
|
||||
handler = handlers["*"]
|
||||
}
|
||||
},
|
||||
python = {
|
||||
["("] = {
|
||||
kind = { Kind.Function, Kind.Method },
|
||||
handler = handlers.python
|
||||
}
|
||||
},
|
||||
clojure = {
|
||||
["("] = {
|
||||
kind = { Kind.Function, Kind.Method },
|
||||
handler = handlers.lisp
|
||||
}
|
||||
},
|
||||
clojurescript = {
|
||||
["("] = {
|
||||
kind = { Kind.Function, Kind.Method },
|
||||
handler = handlers.lisp
|
||||
}
|
||||
},
|
||||
fennel = {
|
||||
["("] = {
|
||||
kind = { Kind.Function, Kind.Method },
|
||||
handler = handlers.lisp
|
||||
}
|
||||
},
|
||||
janet = {
|
||||
["("] = {
|
||||
kind = { Kind.Function, Kind.Method },
|
||||
handler = handlers.lisp
|
||||
}
|
||||
},
|
||||
tex = false,
|
||||
plaintex = false,
|
||||
context = false,
|
||||
haskell = false,
|
||||
purescript = false,
|
||||
sh = false,
|
||||
bash = false,
|
||||
nix = false
|
||||
}
|
||||
|
||||
M.on_confirm_done = function(opts)
|
||||
opts = vim.tbl_deep_extend('force', {
|
||||
filetypes = M.filetypes
|
||||
}, opts or {})
|
||||
|
||||
return function(evt)
|
||||
if evt.commit_character then
|
||||
return
|
||||
end
|
||||
|
||||
local entry = evt.entry
|
||||
local commit_character = entry:get_commit_characters()
|
||||
local bufnr = vim.api.nvim_get_current_buf()
|
||||
local filetype = vim.api.nvim_buf_get_option(bufnr, 'filetype')
|
||||
local item = entry:get_completion_item()
|
||||
|
||||
-- Without options and fallback
|
||||
if not opts.filetypes[filetype] and not opts.filetypes["*"] then
|
||||
return
|
||||
end
|
||||
|
||||
if opts.filetypes[filetype] == false then
|
||||
return
|
||||
end
|
||||
|
||||
-- If filetype is nil then use *
|
||||
local completion_options = opts.filetypes[filetype] or opts.filetypes["*"]
|
||||
|
||||
local rules = vim.tbl_filter(function(rule)
|
||||
return completion_options[rule.key_map]
|
||||
end, autopairs.get_buf_rules(bufnr))
|
||||
|
||||
for char, value in pairs(completion_options) do
|
||||
if vim.tbl_contains(value.kind, item.kind) then
|
||||
value.handler(char, item, bufnr, rules, commit_character)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return M
|
||||
@ -0,0 +1,86 @@
|
||||
local npairs = require('nvim-autopairs')
|
||||
local Completion = require('compe.completion')
|
||||
local utils = require('nvim-autopairs.utils')
|
||||
|
||||
local method_kind = nil
|
||||
local function_kind = nil
|
||||
|
||||
local options = {}
|
||||
|
||||
local M = {}
|
||||
M.completion_done = function()
|
||||
local line = utils.text_get_current_line(0)
|
||||
local _, col = utils.get_cursor()
|
||||
local prev_char, next_char = utils.text_cusor_line(line, col, 1, 1, false)
|
||||
|
||||
local filetype = vim.bo.filetype
|
||||
local char = options.map_char[filetype] or options.map_char["all"] or '('
|
||||
if char == '' then return end
|
||||
|
||||
if prev_char ~= char and next_char ~= char then
|
||||
if method_kind == nil then
|
||||
method_kind = require('vim.lsp.protocol').CompletionItemKind[2]
|
||||
function_kind = require('vim.lsp.protocol').CompletionItemKind[3]
|
||||
end
|
||||
local item = Completion._confirm_item
|
||||
if item.kind == method_kind or item.kind == function_kind then
|
||||
-- check insert text have ( from snippet
|
||||
local completion_item = item.user_data.compe.completion_item
|
||||
if
|
||||
(
|
||||
completion_item.textEdit
|
||||
and completion_item.textEdit.newText
|
||||
and completion_item.textEdit.newText:match('[%(%[%$]')
|
||||
)
|
||||
or (completion_item.insertText and completion_item.insertText:match('[%(%[%$]'))
|
||||
then
|
||||
return
|
||||
end
|
||||
vim.api.nvim_feedkeys(char, 'i', true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
M.setup = function(opt)
|
||||
opt = opt or { map_cr = true, map_complete = true, auto_select = false, map_char = {all = '('}}
|
||||
if not opt.map_char then opt.map_char = {} end
|
||||
options = opt
|
||||
local map_cr = opt.map_cr
|
||||
local map_complete = opt.map_complete
|
||||
vim.g.completion_confirm_key = ''
|
||||
if map_cr then
|
||||
vim.api.nvim_set_keymap(
|
||||
'i',
|
||||
'<CR>',
|
||||
'',
|
||||
{ callback = M.completion_confirm, expr = true, noremap = true }
|
||||
)
|
||||
end
|
||||
if opt.auto_select then
|
||||
M.completion_confirm = function()
|
||||
if vim.fn.pumvisible() ~= 0 then
|
||||
return vim.fn['compe#confirm']({ keys = '<CR>', select = true })
|
||||
else
|
||||
return npairs.autopairs_cr()
|
||||
end
|
||||
end
|
||||
else
|
||||
M.completion_confirm = function()
|
||||
if vim.fn.pumvisible() ~= 0 and vim.fn.complete_info()['selected'] ~= -1 then
|
||||
return vim.fn['compe#confirm'](npairs.esc('<cr>'))
|
||||
else
|
||||
return npairs.autopairs_cr()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if map_complete then
|
||||
vim.cmd([[
|
||||
augroup autopairs_compe
|
||||
autocmd!
|
||||
autocmd User CompeConfirmDone lua require'nvim-autopairs.completion.compe'.completion_done()
|
||||
augroup end
|
||||
]])
|
||||
end
|
||||
end
|
||||
return M
|
||||
@ -0,0 +1,91 @@
|
||||
local autopairs = require('nvim-autopairs')
|
||||
local utils = require('nvim-autopairs.utils')
|
||||
|
||||
local M = {}
|
||||
|
||||
---@param char string
|
||||
---@param item table
|
||||
---@param bufnr number
|
||||
---@param rules table
|
||||
---@param commit_character table<string>
|
||||
M["*"] = function(char, item, bufnr, rules, _)
|
||||
local line = utils.text_get_current_line(bufnr)
|
||||
local _, col = utils.get_cursor()
|
||||
local char_before, char_after = utils.text_cusor_line(line, col, 1, 1, false)
|
||||
|
||||
if char == '' or char_before == char or char_after == char
|
||||
or (item.data and type(item.data) == 'table' and item.data.funcParensDisabled)
|
||||
or (item.textEdit and item.textEdit.newText and item.textEdit.newText:match "[%(%[%$]")
|
||||
or (item.insertText and item.insertText:match "[%(%[%$]")
|
||||
then
|
||||
return
|
||||
end
|
||||
|
||||
if vim.tbl_isempty(rules) then
|
||||
return
|
||||
end
|
||||
|
||||
local new_text = ''
|
||||
local add_char = 1
|
||||
|
||||
for _, rule in pairs(rules) do
|
||||
if rule.start_pair then
|
||||
local prev_char, next_char = utils.text_cusor_line(
|
||||
new_text,
|
||||
col + add_char,
|
||||
#rule.start_pair,
|
||||
#rule.end_pair,
|
||||
rule.is_regex
|
||||
)
|
||||
local cond_opt = {
|
||||
ts_node = autopairs.state.ts_node,
|
||||
text = new_text,
|
||||
rule = rule,
|
||||
bufnr = bufnr,
|
||||
col = col + 1,
|
||||
char = char,
|
||||
line = line,
|
||||
prev_char = prev_char,
|
||||
next_char = next_char,
|
||||
}
|
||||
if rule.key_map and rule:can_pair(cond_opt) then
|
||||
vim.api.nvim_feedkeys(rule.key_map, "i", true)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---Handler with "clojure", "clojurescript", "fennel", "janet
|
||||
M.lisp = function (char, item, bufnr, _, _)
|
||||
local line = utils.text_get_current_line(bufnr)
|
||||
local _, col = utils.get_cursor()
|
||||
local char_before, char_after = utils.text_cusor_line(line, col, 1, 1, false)
|
||||
local length = #item.label
|
||||
|
||||
if char == '' or char_before == char or char_after == char
|
||||
or (item.data and item.data.funcParensDisabled)
|
||||
or (item.textEdit and item.textEdit.newText and item.textEdit.newText:match "[%(%[%$]")
|
||||
or (item.insertText and item.insertText:match "[%(%[%$]")
|
||||
then
|
||||
return
|
||||
end
|
||||
|
||||
if utils.text_sub_char(line, col - length, 1) == "(" then
|
||||
utils.feed("<Space>")
|
||||
return
|
||||
end
|
||||
utils.feed(utils.key.left, length)
|
||||
utils.feed(char)
|
||||
utils.feed(utils.key.right, length)
|
||||
utils.feed("<Space>")
|
||||
end
|
||||
|
||||
M.python = function(char, item, bufnr, rules, _)
|
||||
if item.data then
|
||||
item.data.funcParensDisabled = false
|
||||
end
|
||||
M["*"](char,item,bufnr,rules)
|
||||
end
|
||||
|
||||
return M
|
||||
@ -0,0 +1,350 @@
|
||||
local utils = require('nvim-autopairs.utils')
|
||||
local log = require('nvim-autopairs._log')
|
||||
---@class CondOpts
|
||||
---@field ts_node table
|
||||
---@field text string
|
||||
---@field rule table
|
||||
---@field bufnr number
|
||||
---@field col number
|
||||
---@field char string
|
||||
---@field line string
|
||||
---@field prev_char string
|
||||
---@field next_char string
|
||||
---@field is_endwise string
|
||||
|
||||
local cond = {}
|
||||
|
||||
-- cond
|
||||
-- @return false when it is not correct
|
||||
-- true when it is correct
|
||||
-- nil when it is not determine
|
||||
-- stylua: ignore
|
||||
cond.none = function()
|
||||
return function() return false end
|
||||
end
|
||||
-- stylua: ignore
|
||||
cond.done = function()
|
||||
return function() return true end
|
||||
end
|
||||
|
||||
cond.invert = function(func)
|
||||
return function(...)
|
||||
local result = func(...)
|
||||
if result ~= nil then
|
||||
return not result
|
||||
end
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
cond.before_regex = function(regex, length)
|
||||
length = length or 1
|
||||
if length < 0 then length = nil end
|
||||
length = length and -length
|
||||
---@param opts CondOpts
|
||||
return function(opts)
|
||||
log.debug('before_regex')
|
||||
local str = utils.text_sub_char(opts.line, opts.col - 1, length or -opts.col)
|
||||
if str:match(regex) then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
cond.before_text = function(text)
|
||||
local length = #text
|
||||
---@param opts CondOpts
|
||||
return function(opts)
|
||||
log.debug('before_text')
|
||||
local str = utils.text_sub_char(opts.line, opts.col - 1, -length)
|
||||
if str == text then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
cond.after_text = function(text)
|
||||
local length = #text
|
||||
---@param opts CondOpts
|
||||
return function(opts)
|
||||
log.debug('after_text')
|
||||
local str = utils.text_sub_char(opts.line, opts.col, length)
|
||||
if str == text then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
cond.after_regex = function(regex, length)
|
||||
length = length or 1
|
||||
if length < 0 then length = nil end
|
||||
---@param opts CondOpts
|
||||
return function(opts)
|
||||
log.debug('after_regex')
|
||||
local str = utils.text_sub_char(opts.line, opts.col, length or #opts.line)
|
||||
if str:match(regex) then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
cond.not_before_text = function(text)
|
||||
local length = #text
|
||||
return function(opts)
|
||||
log.debug('not_before_text')
|
||||
local str = utils.text_sub_char(opts.line, opts.col - 1, -length)
|
||||
if str == text then
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
cond.not_after_text = function(text)
|
||||
local length = #text
|
||||
---@param opts CondOpts
|
||||
return function(opts)
|
||||
log.debug('not_after_text')
|
||||
local str = utils.text_sub_char(opts.line, opts.col, length)
|
||||
if str == text then
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
cond.not_before_regex = function(regex, length)
|
||||
length = length or 1
|
||||
if length < 0 then length = nil end
|
||||
length = length and -length
|
||||
---@param opts CondOpts
|
||||
return function(opts)
|
||||
log.debug('not_before_regex')
|
||||
log.debug(length)
|
||||
local str = utils.text_sub_char(opts.line, opts.col - 1, length or -opts.col)
|
||||
if str:match(regex) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
cond.not_after_regex = function(regex, length)
|
||||
length = length or 1
|
||||
if length < 0 then length = nil end
|
||||
---@param opts CondOpts
|
||||
return function(opts)
|
||||
log.debug('not_after_regex')
|
||||
local str = utils.text_sub_char(opts.line, opts.col, length or #opts.line)
|
||||
if str:match(regex) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function count_bracket_char(line, prev_char, next_char)
|
||||
local count_prev_char = 0
|
||||
local count_next_char = 0
|
||||
for i = 1, #line, 1 do
|
||||
local c = line:sub(i, i)
|
||||
if c == prev_char then
|
||||
count_prev_char = count_prev_char + 1
|
||||
elseif c == next_char then
|
||||
count_next_char = count_next_char + 1
|
||||
end
|
||||
end
|
||||
return count_prev_char, count_next_char
|
||||
end
|
||||
|
||||
-- Checks if bracket chars are balanced around specific postion.
|
||||
---@param line string
|
||||
---@param open_char string
|
||||
---@param close_char string
|
||||
---@param col integer position
|
||||
local function is_brackets_balanced_around_position(line, open_char, close_char, col)
|
||||
local balance = 0
|
||||
for i = 1, #line, 1 do
|
||||
local c = line:sub(i, i)
|
||||
if c == open_char then
|
||||
balance = balance + 1
|
||||
elseif balance > 0 and c == close_char then
|
||||
balance = balance - 1
|
||||
if col <= i and balance == 0 then
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
return balance == 0
|
||||
end
|
||||
|
||||
cond.is_bracket_line = function()
|
||||
---@param opts CondOpts
|
||||
return function(opts)
|
||||
log.debug('is_bracket_line')
|
||||
if utils.is_bracket(opts.char) and
|
||||
(opts.next_char == opts.rule.end_pair
|
||||
or opts.next_char == opts.rule.start_pair)
|
||||
then
|
||||
-- (( many char |)) => add
|
||||
-- ( many char |)) => not add
|
||||
local count_prev_char, count_next_char = count_bracket_char(
|
||||
opts.line,
|
||||
opts.rule.start_pair,
|
||||
opts.rule.end_pair
|
||||
)
|
||||
if count_prev_char ~= count_next_char then
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
cond.is_bracket_line_move = function()
|
||||
---@param opts CondOpts
|
||||
return function(opts)
|
||||
log.debug('is_bracket_line_move')
|
||||
if utils.is_close_bracket(opts.char)
|
||||
and opts.char == opts.rule.end_pair
|
||||
then
|
||||
-- (( many char |)) => move
|
||||
-- (( many char |) => not move
|
||||
local is_balanced = is_brackets_balanced_around_position(
|
||||
opts.line,
|
||||
opts.rule.start_pair,
|
||||
opts.char,
|
||||
opts.col
|
||||
)
|
||||
return is_balanced
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
cond.not_inside_quote = function()
|
||||
---@param opts CondOpts
|
||||
return function(opts)
|
||||
log.debug('not_inside_quote')
|
||||
if utils.is_in_quotes(opts.text, opts.col - 1) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
cond.is_inside_quote = function()
|
||||
---@param opts CondOpts
|
||||
return function(opts)
|
||||
log.debug('is_inside_quote')
|
||||
if utils.is_in_quotes(opts.text, opts.col - 1) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
cond.not_add_quote_inside_quote = function()
|
||||
---@param opts CondOpts
|
||||
return function(opts)
|
||||
log.debug('not_add_quote_inside_quote')
|
||||
if utils.is_quote(opts.char)
|
||||
and utils.is_in_quotes(opts.text, opts.col - 1)
|
||||
then
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
cond.move_right = function()
|
||||
---@param opts CondOpts
|
||||
return function(opts)
|
||||
log.debug('move_right')
|
||||
if opts.next_char == opts.char then
|
||||
if utils.is_close_bracket(opts.char) then
|
||||
return
|
||||
end
|
||||
-- move right when have quote on end line or in quote
|
||||
-- situtaion |" => "|
|
||||
if utils.is_quote(opts.char) then
|
||||
if opts.col == string.len(opts.line) then
|
||||
return
|
||||
end
|
||||
-- ("|") => (""|)
|
||||
-- "" |" " => "" "| "
|
||||
if utils.is_in_quotes(opts.line, opts.col - 1, opts.char) then
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
cond.is_end_line = function()
|
||||
---@param opts CondOpts
|
||||
return function(opts)
|
||||
log.debug('is_end_line')
|
||||
local end_text = opts.line:sub(opts.col + 1)
|
||||
-- end text is blank
|
||||
if end_text ~= '' and end_text:match('^%s+$') == nil then
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Check the next char is quote and cursor is inside quote
|
||||
cond.is_bracket_in_quote = function()
|
||||
---@param opts CondOpts
|
||||
return function(opts)
|
||||
log.debug("is_bracket_in_quote")
|
||||
if utils.is_bracket(opts.char)
|
||||
and utils.is_quote(opts.next_char)
|
||||
and utils.is_in_quotes(opts.line, opts.col - 1, opts.next_char)
|
||||
then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
cond.not_filetypes = function(filetypes)
|
||||
return function()
|
||||
log.debug('not_filetypes')
|
||||
for _, filetype in pairs(filetypes) do
|
||||
if vim.bo.filetype == filetype then
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Check the character before the cursor is not equal
|
||||
---@param char string character to compare
|
||||
---@param index number the position of character before current curosr
|
||||
cond.not_before_char = function(char, index)
|
||||
index = index or 1
|
||||
---@param opts CondOpts
|
||||
return function(opts)
|
||||
log.debug('not_before_char')
|
||||
local match_char = #opts.line > index
|
||||
and opts.line:sub(#opts.line - index, #opts.line - index) or ''
|
||||
if match_char == char and match_char ~= "" then
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---@deprecated
|
||||
cond.not_after_regex_check = cond.not_after_regex
|
||||
---@deprecated
|
||||
cond.after_regex_check = cond.after_regex
|
||||
---@deprecated
|
||||
cond.before_regex_check = cond.before_regex
|
||||
---@deprecated
|
||||
cond.not_before_regex_check = cond.not_before_regex
|
||||
---@deprecated
|
||||
cond.after_text_check = cond.after_text
|
||||
---@deprecated
|
||||
cond.not_after_text_check = cond.not_after_text
|
||||
---@deprecated
|
||||
cond.before_text_check = cond.before_text
|
||||
---@deprecated
|
||||
cond.not_before_text_check = cond.not_before_text
|
||||
|
||||
return cond
|
||||
@ -0,0 +1,222 @@
|
||||
local utils = require('nvim-autopairs.utils')
|
||||
local log = require('nvim-autopairs._log')
|
||||
local npairs = require('nvim-autopairs')
|
||||
local M = {}
|
||||
|
||||
local default_config = {
|
||||
map = '<M-e>',
|
||||
chars = { '{', '[', '(', '"', "'" },
|
||||
pattern = [=[[%'%"%>%]%)%}%,%`]]=],
|
||||
end_key = '$',
|
||||
before_key = 'h',
|
||||
after_key = 'l',
|
||||
cursor_pos_before = true,
|
||||
keys = 'qwertyuiopzxcvbnmasdfghjkl',
|
||||
highlight = 'Search',
|
||||
highlight_grey = 'Comment',
|
||||
manual_position = true,
|
||||
use_virt_lines = true
|
||||
}
|
||||
|
||||
M.ns_fast_wrap = vim.api.nvim_create_namespace('autopairs_fastwrap')
|
||||
|
||||
local config = {}
|
||||
|
||||
M.setup = function(cfg)
|
||||
if config.chars == nil then
|
||||
config = vim.tbl_extend('force', default_config, cfg or {}) or {}
|
||||
npairs.config.fast_wrap = config
|
||||
end
|
||||
end
|
||||
|
||||
function M.getchar_handler()
|
||||
local ok, key = pcall(vim.fn.getchar)
|
||||
if not ok then
|
||||
return nil
|
||||
end
|
||||
if key ~= 27 and type(key) == 'number' then
|
||||
local key_str = vim.fn.nr2char(key)
|
||||
return key_str
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
M.show = function(line)
|
||||
line = line or utils.text_get_current_line(0)
|
||||
log.debug(line)
|
||||
local row, col = utils.get_cursor()
|
||||
local prev_char = utils.text_cusor_line(line, col, 1, 1, false)
|
||||
local end_pair = ''
|
||||
if utils.is_in_table(config.chars, prev_char) then
|
||||
local rules = npairs.get_buf_rules()
|
||||
for _, rule in pairs(rules) do
|
||||
if rule.start_pair == prev_char then
|
||||
end_pair = rule.end_pair
|
||||
end
|
||||
end
|
||||
if end_pair == '' then
|
||||
return
|
||||
end
|
||||
local list_pos = {}
|
||||
local index = 1
|
||||
local str_length = #line
|
||||
local offset = -1
|
||||
for i = col + 2, #line, 1 do
|
||||
local char = line:sub(i, i)
|
||||
local char2 = line:sub(i - 1, i)
|
||||
if string.match(char, config.pattern)
|
||||
or (char == ' ' and string.match(char2, '%w'))
|
||||
then
|
||||
local key = config.keys:sub(index, index)
|
||||
index = index + 1
|
||||
if not config.manual_position and (
|
||||
utils.is_quote(char)
|
||||
or (
|
||||
utils.is_close_bracket(char)
|
||||
and utils.is_in_quotes(line, col, prev_char)
|
||||
)
|
||||
)
|
||||
then
|
||||
offset = 0
|
||||
end
|
||||
|
||||
if config.manual_position and i == str_length then
|
||||
key = config.end_key
|
||||
end
|
||||
|
||||
table.insert(
|
||||
list_pos,
|
||||
{ col = i + offset, key = key, char = char, pos = i }
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
local end_col, end_pos
|
||||
if config.manual_position then
|
||||
end_col = str_length + offset
|
||||
end_pos = str_length
|
||||
else
|
||||
end_col = str_length + 1
|
||||
end_pos = str_length + 1
|
||||
end
|
||||
-- add end_key to list extmark
|
||||
if #list_pos == 0 or list_pos[#list_pos].key ~= config.end_key then
|
||||
table.insert(
|
||||
list_pos,
|
||||
{ col = end_col, key = config.end_key, pos = end_pos, char = config.end_key }
|
||||
)
|
||||
end
|
||||
|
||||
-- Create a whitespace string for the current line which replaces every non whitespace
|
||||
-- character with a space and preserves tabs, so we can use it for highlighting with
|
||||
-- virtual lines so that highlighting lines up correctly.
|
||||
-- The string is limited to the last position in list_pos
|
||||
local whitespace_line = line:sub(1, list_pos[#list_pos].end_pos):gsub("[^ \t]", " ")
|
||||
|
||||
M.highlight_wrap(list_pos, row, col, #line, whitespace_line)
|
||||
vim.defer_fn(function()
|
||||
-- get the first char
|
||||
local char = #list_pos == 1 and config.end_key or M.getchar_handler()
|
||||
vim.api.nvim_buf_clear_namespace(0, M.ns_fast_wrap, row, row + 1)
|
||||
for _, pos in pairs(list_pos) do
|
||||
local hl_mark = {
|
||||
{ pos = pos.pos - 1, key = config.before_key },
|
||||
{ pos = pos.pos + 1, key = config.after_key },
|
||||
}
|
||||
if config.manual_position and (char == pos.key or char == string.upper(pos.key)) then
|
||||
M.highlight_wrap(hl_mark, row, col, #line, whitespace_line)
|
||||
M.choose_pos(row, line, pos, end_pair)
|
||||
break
|
||||
end
|
||||
if char == pos.key then
|
||||
M.move_bracket(line, pos.col, end_pair, false)
|
||||
break
|
||||
end
|
||||
if char == string.upper(pos.key) then
|
||||
M.move_bracket(line, pos.col, end_pair, true)
|
||||
break
|
||||
end
|
||||
end
|
||||
vim.cmd('startinsert')
|
||||
end, 10)
|
||||
return
|
||||
end
|
||||
vim.cmd('startinsert')
|
||||
end
|
||||
|
||||
M.choose_pos = function(row, line, pos, end_pair)
|
||||
vim.defer_fn(function()
|
||||
-- select a second key
|
||||
local char =
|
||||
pos.char == nil and config.before_key
|
||||
or pos.char == config.end_key and config.after_key
|
||||
or M.getchar_handler()
|
||||
vim.api.nvim_buf_clear_namespace(0, M.ns_fast_wrap, row, row + 1)
|
||||
if not char then return end
|
||||
local change_pos = false
|
||||
local col = pos.col
|
||||
if char == string.upper(config.before_key) or char == string.upper(config.after_key) then
|
||||
change_pos = true
|
||||
end
|
||||
if char == config.after_key or char == string.upper(config.after_key) then
|
||||
col = pos.col + 1
|
||||
end
|
||||
M.move_bracket(line, col, end_pair, change_pos)
|
||||
vim.cmd('startinsert')
|
||||
end, 10)
|
||||
end
|
||||
|
||||
M.move_bracket = function(line, target_pos, end_pair, change_pos)
|
||||
log.debug(target_pos)
|
||||
line = line or utils.text_get_current_line(0)
|
||||
local row, col = utils.get_cursor()
|
||||
local _, next_char = utils.text_cusor_line(line, col, 1, 1, false)
|
||||
-- remove an autopairs if that exist
|
||||
if next_char == end_pair then
|
||||
line = line:sub(1, col) .. line:sub(col + 2, #line)
|
||||
target_pos = target_pos - 1
|
||||
end
|
||||
|
||||
line = line:sub(1, target_pos) .. end_pair .. line:sub(target_pos + 1, #line)
|
||||
vim.api.nvim_set_current_line(line)
|
||||
if change_pos then
|
||||
vim.api.nvim_win_set_cursor(0, { row + 1, target_pos + (config.cursor_pos_before and 0 or 1) })
|
||||
end
|
||||
end
|
||||
|
||||
M.highlight_wrap = function(tbl_pos, row, col, end_col, whitespace_line)
|
||||
local bufnr = vim.api.nvim_win_get_buf(0)
|
||||
if config.use_virt_lines then
|
||||
local virt_lines = {}
|
||||
local start = 0
|
||||
for _, pos in ipairs(tbl_pos) do
|
||||
virt_lines[#virt_lines + 1] = { whitespace_line:sub(start + 1, pos.pos - 1), 'Normal' }
|
||||
virt_lines[#virt_lines + 1] = { pos.key, config.highlight }
|
||||
start = pos.pos
|
||||
end
|
||||
vim.api.nvim_buf_set_extmark(bufnr, M.ns_fast_wrap, row, 0, {
|
||||
virt_lines = { virt_lines },
|
||||
hl_mode = 'blend',
|
||||
})
|
||||
else
|
||||
if config.highlight_grey then
|
||||
vim.highlight.range(
|
||||
bufnr,
|
||||
M.ns_fast_wrap,
|
||||
config.highlight_grey,
|
||||
{ row, col },
|
||||
{ row, end_col },
|
||||
{}
|
||||
)
|
||||
end
|
||||
for _, pos in ipairs(tbl_pos) do
|
||||
vim.api.nvim_buf_set_extmark(bufnr, M.ns_fast_wrap, row, pos.pos - 1, {
|
||||
virt_text = { { pos.key, config.highlight } },
|
||||
virt_text_pos = 'overlay',
|
||||
hl_mode = 'blend',
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return M
|
||||
@ -0,0 +1,224 @@
|
||||
local Cond = require('nvim-autopairs.conds')
|
||||
|
||||
--- @class Rule
|
||||
--- @field start_pair string
|
||||
--- @field end_pair string
|
||||
--- @field end_pair_func function dynamic change end_pair
|
||||
--- @field map_cr_func function dynamic change mapping_cr
|
||||
--- @field end_pair_length number change end_pair length for key map like <left>
|
||||
--- @field key_map string|nil equal nil mean it will skip on autopairs map
|
||||
--- @field filetypes table|nil
|
||||
--- @field not_filetypes table|nil
|
||||
--- @field is_regex boolean use regex to compare
|
||||
--- @field is_multibyte boolean
|
||||
--- @field is_endwise boolean only use on end_wise
|
||||
--- @field is_undo boolean add break undo sequence
|
||||
|
||||
local Rule = setmetatable({}, {
|
||||
__call = function(self, ...)
|
||||
return self.new(...)
|
||||
end,
|
||||
})
|
||||
|
||||
---@return Rule
|
||||
function Rule.new(...)
|
||||
local params = { ... }
|
||||
local opt = {}
|
||||
if type(params[1]) == 'table' then
|
||||
opt = params[1]
|
||||
else
|
||||
opt.start_pair = params[1]
|
||||
opt.end_pair = params[2]
|
||||
if type(params[3]) == 'string' then
|
||||
opt.filetypes = { params[3] }
|
||||
else
|
||||
opt.filetypes = params[3]
|
||||
end
|
||||
end
|
||||
opt = vim.tbl_extend('force', {
|
||||
key_map = "",
|
||||
start_pair = nil,
|
||||
end_pair = nil,
|
||||
end_pair_func = false,
|
||||
filetypes = nil,
|
||||
not_filetypes = nil,
|
||||
move_cond = nil,
|
||||
del_cond = {},
|
||||
cr_cond = {},
|
||||
pair_cond = {},
|
||||
is_endwise = false,
|
||||
is_regex = false,
|
||||
is_multibyte = false,
|
||||
end_pair_length = nil,
|
||||
}, opt) or {}
|
||||
|
||||
---@param rule Rule
|
||||
local function constructor(rule)
|
||||
-- check multibyte
|
||||
if #rule.start_pair ~= vim.api.nvim_strwidth(rule.start_pair) then
|
||||
rule:use_multibyte()
|
||||
end
|
||||
-- check filetypes and not_filetypes
|
||||
-- if have something like "-vim" it will add to not_filetypes
|
||||
if rule.filetypes then
|
||||
local ft, not_ft = {}, {}
|
||||
for _, value in pairs(rule.filetypes) do
|
||||
if value:sub(1, 1) == '-' then
|
||||
table.insert(not_ft, value:sub(2, #value))
|
||||
else
|
||||
table.insert(ft, value)
|
||||
end
|
||||
end
|
||||
rule.filetypes = #ft > 0 and ft or nil
|
||||
rule.not_filetypes = #not_ft > 0 and not_ft or nil
|
||||
end
|
||||
return rule
|
||||
end
|
||||
|
||||
local r = setmetatable(opt, { __index = Rule })
|
||||
return constructor(r)
|
||||
end
|
||||
|
||||
function Rule:use_regex(value, key_map)
|
||||
self.is_regex = value
|
||||
self.key_map = key_map or ''
|
||||
return self
|
||||
end
|
||||
|
||||
function Rule:use_key(key_map)
|
||||
self.key_map = key_map or ''
|
||||
return self
|
||||
end
|
||||
|
||||
function Rule:use_undo(value)
|
||||
self.is_undo = value
|
||||
return self
|
||||
end
|
||||
|
||||
function Rule:use_multibyte()
|
||||
self.is_multibyte = true
|
||||
self.end_pair_length = vim.fn.strdisplaywidth(self.end_pair)
|
||||
self.key_map = string.match(self.start_pair, "[^\128-\191][\128-\191]*$")
|
||||
self.key_end = string.match(self.end_pair, "[%z\1-\127\194-\244][\128-\191]*")
|
||||
return self
|
||||
end
|
||||
|
||||
function Rule:get_end_pair(opts)
|
||||
if self.end_pair_func then
|
||||
return self.end_pair_func(opts)
|
||||
end
|
||||
return self.end_pair
|
||||
end
|
||||
|
||||
function Rule:get_map_cr(opts)
|
||||
if self.map_cr_func then
|
||||
return self.map_cr_func(opts)
|
||||
end
|
||||
return '<c-g>u<CR><CMD>normal! ====<CR><up><end><CR>'
|
||||
end
|
||||
function Rule:replace_map_cr(value)
|
||||
self.map_cr_func = value
|
||||
return self
|
||||
end
|
||||
|
||||
function Rule:get_end_pair_length(opts)
|
||||
if self.end_pair_length then
|
||||
return self.end_pair_length
|
||||
end
|
||||
if type(opts) == 'string' then
|
||||
return #opts
|
||||
end
|
||||
return #self.get_end_pair(opts)
|
||||
end
|
||||
|
||||
function Rule:replace_endpair(value, check_pair)
|
||||
self.end_pair_func = value
|
||||
if check_pair ~= nil then
|
||||
if check_pair == true then
|
||||
self:with_pair(Cond.after_text(self.end_pair))
|
||||
else
|
||||
self:with_pair(check_pair)
|
||||
end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
function Rule:set_end_pair_length(length)
|
||||
self.end_pair_length = length
|
||||
return self
|
||||
end
|
||||
|
||||
function Rule:with_move(cond)
|
||||
if self.move_cond == nil then self.move_cond = {} end
|
||||
table.insert(self.move_cond, cond)
|
||||
return self
|
||||
end
|
||||
|
||||
function Rule:with_del(cond)
|
||||
if self.del_cond == nil then self.del_cond = {} end
|
||||
table.insert(self.del_cond, cond)
|
||||
return self
|
||||
end
|
||||
|
||||
function Rule:with_cr(cond)
|
||||
if self.cr_cond == nil then self.cr_cond = {} end
|
||||
table.insert(self.cr_cond, cond)
|
||||
return self
|
||||
end
|
||||
|
||||
---add condition to rule
|
||||
---@param cond any
|
||||
---@param pos number|nil = 1. It have higher priority to another condition
|
||||
---@return Rule
|
||||
function Rule:with_pair(cond, pos)
|
||||
if self.pair_cond == nil then self.pair_cond = {} end
|
||||
self.pair_cond[pos or (#self.pair_cond + 1)] = cond
|
||||
return self
|
||||
end
|
||||
|
||||
function Rule:only_cr(cond)
|
||||
self.key_map = nil
|
||||
self.pair_cond = false
|
||||
self.move_cond = false
|
||||
self.del_cond = false
|
||||
if cond then return self:with_cr(cond) end
|
||||
return self
|
||||
end
|
||||
|
||||
function Rule:end_wise(cond)
|
||||
self.is_endwise = true
|
||||
return self:only_cr(cond)
|
||||
end
|
||||
|
||||
local function can_do(conds, opt)
|
||||
if type(conds) == 'table' then
|
||||
for _, cond in pairs(conds) do
|
||||
local result = cond(opt)
|
||||
if result ~= nil then
|
||||
return result
|
||||
end
|
||||
end
|
||||
return true
|
||||
elseif type(conds) == 'function' then
|
||||
return conds(opt) == true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function Rule:can_pair(opt)
|
||||
return can_do(self.pair_cond, opt)
|
||||
end
|
||||
|
||||
function Rule:can_move(opt)
|
||||
return can_do(self.move_cond, opt)
|
||||
end
|
||||
|
||||
function Rule:can_del(opt)
|
||||
return can_do(self.del_cond, opt)
|
||||
end
|
||||
|
||||
function Rule:can_cr(opt)
|
||||
return can_do(self.cr_cond, opt)
|
||||
end
|
||||
|
||||
return Rule
|
||||
@ -0,0 +1,86 @@
|
||||
local Rule = require("nvim-autopairs.rule")
|
||||
local cond = require("nvim-autopairs.conds")
|
||||
local utils = require('nvim-autopairs.utils')
|
||||
|
||||
local function quote_creator(opt)
|
||||
local quote = function(...)
|
||||
local move_func = opt.enable_moveright and cond.move_right or cond.none
|
||||
local rule = Rule(...)
|
||||
:with_move(move_func())
|
||||
:with_pair(cond.not_add_quote_inside_quote())
|
||||
|
||||
if #opt.ignored_next_char > 1 then
|
||||
rule:with_pair(cond.not_after_regex(opt.ignored_next_char))
|
||||
end
|
||||
rule:use_undo(opt.break_undo)
|
||||
return rule
|
||||
end
|
||||
return quote
|
||||
end
|
||||
|
||||
local function bracket_creator(opt)
|
||||
local quote = quote_creator(opt)
|
||||
local bracket = function(...)
|
||||
local rule = quote(...)
|
||||
if opt.enable_check_bracket_line == true then
|
||||
rule:with_pair(cond.is_bracket_line())
|
||||
:with_move(cond.is_bracket_line_move())
|
||||
end
|
||||
if opt.enable_bracket_in_quote then
|
||||
-- still add bracket if text is quote "|" and next_char have "
|
||||
rule:with_pair(cond.is_bracket_in_quote(), 1)
|
||||
end
|
||||
return rule
|
||||
end
|
||||
return bracket
|
||||
end
|
||||
|
||||
local function setup(opt)
|
||||
local quote = quote_creator(opt)
|
||||
local bracket = bracket_creator(opt)
|
||||
local rules = {
|
||||
Rule("<!--", "-->", { "html", "markdown" }):with_cr(cond.none()),
|
||||
Rule("```", "```", { "markdown", "vimwiki", "rmarkdown", "rmd", "pandoc" }),
|
||||
Rule("```.*$", "```", { "markdown", "vimwiki", "rmarkdown", "rmd", "pandoc" }):only_cr():use_regex(true),
|
||||
Rule('"""', '"""', { "python", "elixir", "julia", "kotlin" }):with_pair(cond.not_before_char('"', 3)),
|
||||
Rule("'''", "'''", { "python" }):with_pair(cond.not_before_char('"', 3)),
|
||||
quote("'", "'", { "-rust", "-nix" })
|
||||
:with_pair(function(opts)
|
||||
-- python literals string
|
||||
local str = utils.text_sub_char(opts.line, opts.col - 1, 1)
|
||||
if vim.bo.filetype == 'python' and str:match("[frbuFRBU]") then
|
||||
return true
|
||||
end
|
||||
end)
|
||||
:with_pair(cond.not_before_regex("%w")),
|
||||
quote("'", "'", "rust"):with_pair(cond.not_before_regex("[%w<&]")):with_pair(cond.not_after_text(">")),
|
||||
Rule("''", "''", 'nix'):with_move(cond.after_text("'")),
|
||||
quote("`", "`"),
|
||||
quote('"', '"', "-vim"),
|
||||
quote('"', '"', "vim"):with_pair(cond.not_before_regex("^%s*$", -1)),
|
||||
bracket("(", ")"),
|
||||
bracket("[", "]"),
|
||||
bracket("{", "}"),
|
||||
Rule(
|
||||
">[%w%s]*$",
|
||||
"^%s*</",
|
||||
{
|
||||
"html",
|
||||
"htmldjango",
|
||||
"php",
|
||||
"typescript",
|
||||
"typescriptreact",
|
||||
"javascript",
|
||||
"javascriptreact",
|
||||
"svelte",
|
||||
"vue",
|
||||
"xml",
|
||||
"rescript",
|
||||
"astro",
|
||||
}
|
||||
):only_cr():use_regex(true),
|
||||
}
|
||||
return rules
|
||||
end
|
||||
|
||||
return { setup = setup, quote_creator = quote_creator, bracket_creator = bracket_creator }
|
||||
@ -0,0 +1,9 @@
|
||||
local endwise = require('nvim-autopairs.ts-rule').endwise
|
||||
|
||||
local rules = {
|
||||
endwise('%sdo$', 'end', 'elixir', nil),
|
||||
endwise('fn$', 'end', 'elixir', nil),
|
||||
endwise('fn.*->$', 'end', 'elixir', nil),
|
||||
}
|
||||
|
||||
return rules
|
||||
@ -0,0 +1,9 @@
|
||||
local endwise = require('nvim-autopairs.ts-rule').endwise
|
||||
|
||||
local rules = {
|
||||
endwise('then$', 'end', 'lua', 'if_statement'),
|
||||
endwise('function.*%(.*%)$', 'end', 'lua', {'function_declaration', 'local_function', 'function'}),
|
||||
}
|
||||
|
||||
|
||||
return rules
|
||||
@ -0,0 +1,17 @@
|
||||
local endwise = require('nvim-autopairs.ts-rule').endwise
|
||||
|
||||
local rules = {
|
||||
endwise('%sdo$', 'end', 'ruby', nil),
|
||||
endwise('%sdo%s|.*|$', 'end', 'ruby', nil),
|
||||
endwise('begin$', 'end', 'ruby', nil),
|
||||
endwise('def%s.+$', 'end', 'ruby', nil),
|
||||
endwise('module%s.+$', 'end', 'ruby', nil),
|
||||
endwise('class%s.+$', 'end', 'ruby', nil),
|
||||
endwise('[%s=]%sif%s.+$', 'end', 'ruby', nil),
|
||||
endwise('[%s=]%sunless%s.+$', 'end', 'ruby', nil),
|
||||
endwise('[%s=]%scase%s.+$', 'end', 'ruby', nil),
|
||||
endwise('[%s=]%swhile%s.+$', 'end', 'ruby', nil),
|
||||
endwise('[%s=]%suntil%s.+$', 'end', 'ruby', nil),
|
||||
}
|
||||
|
||||
return rules
|
||||
@ -0,0 +1,22 @@
|
||||
local basic = require('nvim-autopairs.rules.basic')
|
||||
local utils = require('nvim-autopairs.utils')
|
||||
local ts_conds = require('nvim-autopairs.ts-conds')
|
||||
local ts_extend = {
|
||||
"'",
|
||||
'"',
|
||||
'(',
|
||||
'[',
|
||||
'{',
|
||||
'`',
|
||||
}
|
||||
return {
|
||||
setup = function (config)
|
||||
local rules=basic.setup(config)
|
||||
for _, rule in pairs(rules) do
|
||||
if utils.is_in_table(ts_extend, rule.start_pair) then
|
||||
rule:with_pair(ts_conds.is_not_ts_node_comment())
|
||||
end
|
||||
end
|
||||
return rules
|
||||
end
|
||||
}
|
||||
@ -0,0 +1,159 @@
|
||||
local log = require('nvim-autopairs._log')
|
||||
local utils = require('nvim-autopairs.utils')
|
||||
local ts_get_node_text = vim.treesitter.get_node_text or vim.treesitter.query.get_node_text
|
||||
|
||||
local conds = {}
|
||||
|
||||
conds.is_endwise_node = function(nodes)
|
||||
if nodes == nil then return function() return true end end
|
||||
if type(nodes) == 'string' then nodes = {nodes} end
|
||||
|
||||
return function (opts)
|
||||
log.debug('is_endwise_node')
|
||||
if not opts.check_endwise_ts then return true end
|
||||
if nodes == nil then return true end
|
||||
if #nodes == 0 then return true end
|
||||
|
||||
vim.treesitter.get_parser():parse()
|
||||
local target = vim.treesitter.get_node({ ignore_injections = false })
|
||||
if target ~= nil and utils.is_in_table(nodes, target:type()) then
|
||||
local text = ts_get_node_text(target) or {""}
|
||||
local last = text[#text]:match(opts.rule.end_pair)
|
||||
-- check last character is match with end_pair
|
||||
if last == nil then
|
||||
return true
|
||||
end
|
||||
-- log.debug('last:' .. last)
|
||||
-- if match then we need tocheck parent node
|
||||
-- some time treesiter is group 2 node then we need check that
|
||||
local begin_target,_, end_target = target:range()
|
||||
local begin_parent,_, end_parent = target:parent():range()
|
||||
-- log.debug(target:range())
|
||||
-- log.debug(ts_get_node_text(target))
|
||||
-- log.debug(target:parent():range())
|
||||
-- log.debug(ts_get_node_text(target:parent()))
|
||||
if
|
||||
(
|
||||
begin_target ~= begin_parent
|
||||
and end_target == end_parent
|
||||
)
|
||||
or
|
||||
(end_parent - end_target == 1)
|
||||
then
|
||||
return true
|
||||
end
|
||||
-- return true
|
||||
else
|
||||
end
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
conds.is_in_range = function(callback, position)
|
||||
assert(
|
||||
type(callback) == 'function' and type(position) == 'function',
|
||||
'callback and position should be a function'
|
||||
)
|
||||
return function(opts)
|
||||
log.debug('is_in_range')
|
||||
-- `parser` will be a table (on success) or a string (error message)
|
||||
local _, parser = pcall(vim.treesitter.get_parser)
|
||||
if not type(parser) == 'string' then
|
||||
return
|
||||
end
|
||||
local cursor = position()
|
||||
assert(
|
||||
type(cursor) == 'table' and #cursor == 2,
|
||||
'position should be return a table like {line, col}'
|
||||
)
|
||||
local line = cursor[1]
|
||||
local col = cursor[2]
|
||||
|
||||
local bufnr = 0
|
||||
local root_lang_tree = vim.treesitter.get_parser(bufnr)
|
||||
local lang_tree = root_lang_tree:language_for_range({ line, col, line, col })
|
||||
|
||||
local result
|
||||
|
||||
for _, tree in ipairs(lang_tree:trees()) do
|
||||
local root = tree:root()
|
||||
if root and vim.treesitter.is_in_node_range(root, line, col) then
|
||||
local node = root:named_descendant_for_range(line, col, line, col)
|
||||
local anonymous_node = root:descendant_for_range(
|
||||
line,
|
||||
col,
|
||||
line,
|
||||
col
|
||||
)
|
||||
|
||||
result = {
|
||||
node = node,
|
||||
lang = lang_tree:lang(),
|
||||
type = node:type(),
|
||||
cursor = vim.api.nvim_win_get_cursor(0),
|
||||
line = vim.api.nvim_buf_get_lines(bufnr, line, line + 1, true)[1],
|
||||
range = { node:range() },
|
||||
anonymous = anonymous_node:type(),
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
return callback(result)
|
||||
end
|
||||
end
|
||||
|
||||
conds.is_ts_node = function(nodes)
|
||||
if type(nodes) == 'string' then nodes = {nodes} end
|
||||
assert(nodes ~= nil, "ts nodes should be string or table")
|
||||
return function (opts)
|
||||
log.debug('is_ts_node')
|
||||
if #nodes == 0 then return end
|
||||
|
||||
vim.treesitter.get_parser():parse()
|
||||
local target = vim.treesitter.get_node({ ignore_injections = false })
|
||||
if target ~= nil and utils.is_in_table(nodes, target:type()) then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
conds.is_not_ts_node = function(nodes)
|
||||
if type(nodes) == 'string' then nodes = {nodes} end
|
||||
assert(nodes ~= nil, "ts nodes should be string or table")
|
||||
return function (opts)
|
||||
log.debug('is_not_ts_node')
|
||||
if #nodes == 0 then return end
|
||||
|
||||
vim.treesitter.get_parser():parse()
|
||||
local target = vim.treesitter.get_node({ ignore_injections = false })
|
||||
if target ~= nil and utils.is_in_table(nodes, target:type()) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
conds.is_not_ts_node_comment = function()
|
||||
return function(opts)
|
||||
log.debug('not_in_ts_node_comment')
|
||||
if not opts.ts_node then return end
|
||||
|
||||
vim.treesitter.get_parser():parse()
|
||||
local target = vim.treesitter.get_node({ ignore_injections = false })
|
||||
if target ~= nil and utils.is_in_table(opts.ts_node, target:type()) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
conds.is_not_in_context = function()
|
||||
return function(opts)
|
||||
local context = require("nvim-autopairs.ts-utils")
|
||||
.get_language_tree_at_position({ utils.get_cursor() })
|
||||
if not vim.tbl_contains(opts.rule.filetypes, context:lang()) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return conds
|
||||
@ -0,0 +1,18 @@
|
||||
local Rule = require('nvim-autopairs.rule')
|
||||
local cond = require('nvim-autopairs.conds')
|
||||
local ts_conds = require('nvim-autopairs.ts-conds')
|
||||
|
||||
return {
|
||||
endwise = function (...)
|
||||
local params = {...}
|
||||
local rule = Rule(...)
|
||||
:use_regex(true)
|
||||
:end_wise(cond.is_end_line())
|
||||
if params[4] then
|
||||
-- rule:with_cr(ts_conds.is_endwise_node(params[4]))
|
||||
rule:with_cr(ts_conds.is_ts_node(params[4]))
|
||||
end
|
||||
return rule
|
||||
end
|
||||
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
local ts_get_node_text = vim.treesitter.get_node_text or vim.treesitter.query.get_node_text
|
||||
local M = {}
|
||||
|
||||
--- Returns the language tree at the given position.
|
||||
---@return LanguageTree
|
||||
function M.get_language_tree_at_position(position)
|
||||
local language_tree = vim.treesitter.get_parser()
|
||||
language_tree:for_each_tree(function(_, tree)
|
||||
if tree:contains(vim.tbl_flatten({ position, position })) then
|
||||
language_tree = tree
|
||||
end
|
||||
end)
|
||||
return language_tree
|
||||
end
|
||||
|
||||
function M.get_tag_name(node)
|
||||
local tag_name = nil
|
||||
if node ~=nil then
|
||||
tag_name = ts_get_node_text(node)
|
||||
end
|
||||
return tag_name
|
||||
end
|
||||
|
||||
return M
|
||||
@ -0,0 +1,198 @@
|
||||
local M = {}
|
||||
local api = vim.api
|
||||
local log = require('nvim-autopairs._log')
|
||||
|
||||
M.key = {
|
||||
del = "<del>",
|
||||
bs = "<bs>",
|
||||
c_h = "<C-h>",
|
||||
left = "<left>",
|
||||
right = "<right>",
|
||||
join_left = "<c-g>U<left>",
|
||||
join_right = "<c-g>U<right>",
|
||||
undo_sequence = "<c-g>u",
|
||||
noundo_sequence = "<c-g>U",
|
||||
abbr = "<c-]>"
|
||||
}
|
||||
|
||||
M.set_vchar = function(text)
|
||||
text = text:gsub('"', '\\"')
|
||||
vim.v.char = text
|
||||
end
|
||||
|
||||
|
||||
M.is_quote = function(char)
|
||||
return char == "'" or char == '"' or char == '`'
|
||||
end
|
||||
|
||||
M.is_bracket = function(char)
|
||||
return char == "(" or char == '[' or char == '{' or char == '<'
|
||||
end
|
||||
|
||||
|
||||
M.is_close_bracket = function(char)
|
||||
return char == ")" or char == ']' or char == '}' or char == '>'
|
||||
end
|
||||
|
||||
M.compare = function(value, text, is_regex)
|
||||
if is_regex and string.match(text, value) then
|
||||
return true
|
||||
elseif text == value then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
---check cursor is inside a quote
|
||||
---@param line string
|
||||
---@param pos number position in line
|
||||
---@param quote_type nil|string specify a quote
|
||||
---@return boolean
|
||||
M.is_in_quotes = function(line, pos, quote_type)
|
||||
local cIndex = 0
|
||||
local result = false
|
||||
local last_char = quote_type or ''
|
||||
|
||||
while cIndex < string.len(line) and cIndex < pos do
|
||||
cIndex = cIndex + 1
|
||||
local char = line:sub(cIndex, cIndex)
|
||||
local prev_char = line:sub(cIndex - 1, cIndex - 1)
|
||||
if
|
||||
result == true
|
||||
and char == last_char
|
||||
and prev_char ~= "\\"
|
||||
then
|
||||
result = false
|
||||
last_char = quote_type or ''
|
||||
elseif
|
||||
result == false
|
||||
and M.is_quote(char)
|
||||
and (not quote_type or char == quote_type)
|
||||
--a single quote with a word before is not count unless it is a
|
||||
-- prefixed string in python (e.g. f'string {with_brackets}')
|
||||
and not (
|
||||
char == "'"
|
||||
and prev_char:match('%w')
|
||||
and (vim.bo.filetype ~= 'python' or prev_char:match('[^frbuFRBU]'))
|
||||
)
|
||||
then
|
||||
last_char = quote_type or char
|
||||
result = true
|
||||
end
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
M.is_attached = function(bufnr)
|
||||
local _, check = pcall(api.nvim_buf_get_var, bufnr or 0, "nvim-autopairs")
|
||||
return check == 1
|
||||
end
|
||||
|
||||
|
||||
M.set_attach = function(bufnr, value)
|
||||
api.nvim_buf_set_var(bufnr or 0, "nvim-autopairs", value)
|
||||
end
|
||||
|
||||
M.is_in_table = function(tbl, val)
|
||||
if tbl == nil then return false end
|
||||
for _, value in pairs(tbl) do
|
||||
if val == value then return true end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
M.check_filetype = function(tbl, filetype)
|
||||
if tbl == nil then return true end
|
||||
return M.is_in_table(tbl, filetype)
|
||||
end
|
||||
|
||||
M.check_not_filetype = function(tbl, filetype)
|
||||
if tbl == nil then return true end
|
||||
return not M.is_in_table(tbl, filetype)
|
||||
end
|
||||
|
||||
M.is_in_range = function(row, col, range)
|
||||
local start_row, start_col, end_row, end_col = unpack(range)
|
||||
|
||||
return (row > start_row or (start_row == row and col >= start_col))
|
||||
and (row < end_row or (row == end_row and col <= end_col))
|
||||
end
|
||||
|
||||
M.get_cursor = function(bufnr)
|
||||
local row, col = unpack(api.nvim_win_get_cursor(bufnr or 0))
|
||||
return row - 1, col
|
||||
end
|
||||
M.text_get_line = function(bufnr, lnum)
|
||||
return api.nvim_buf_get_lines(bufnr, lnum, lnum + 1, false)[1] or ''
|
||||
end
|
||||
|
||||
M.text_get_current_line = function(bufnr)
|
||||
local row = unpack(api.nvim_win_get_cursor(0)) or 1
|
||||
return M.text_get_line(bufnr, row - 1)
|
||||
end
|
||||
|
||||
M.repeat_key = function(key, num)
|
||||
local text = ''
|
||||
for _ = 1, num, 1 do
|
||||
text = text .. key
|
||||
end
|
||||
return text
|
||||
end
|
||||
--- cut text from position with number character
|
||||
---@param line string text
|
||||
---@param col number position of text
|
||||
---@param prev_count number number char previous
|
||||
---@param next_count number number char next
|
||||
---@param is_regex boolean if it is regex then will cut all
|
||||
M.text_cusor_line = function(line, col, prev_count, next_count, is_regex)
|
||||
if is_regex then
|
||||
prev_count = col
|
||||
next_count = #line - col
|
||||
end
|
||||
local prev = M.text_sub_char(line, col, -prev_count)
|
||||
local next = M.text_sub_char(line, col + 1, next_count)
|
||||
return prev, next
|
||||
end
|
||||
|
||||
M.text_sub_char = function(line, start, num)
|
||||
local finish = start
|
||||
if num < 0 then
|
||||
start = start + num + 1
|
||||
else
|
||||
finish = start + num - 1
|
||||
end
|
||||
return string.sub(line, start, finish)
|
||||
end
|
||||
|
||||
-- P(M.text_sub_char("aa'' aaa", 3, -1))
|
||||
M.insert_char = function(text)
|
||||
api.nvim_put({ text }, "c", false, true)
|
||||
end
|
||||
|
||||
M.feed = function(text, num)
|
||||
num = num or 1
|
||||
if num < 1 then num = 1 end
|
||||
local result = ''
|
||||
for _ = 1, num, 1 do
|
||||
result = result .. text
|
||||
end
|
||||
log.debug("result" .. result)
|
||||
api.nvim_feedkeys(api.nvim_replace_termcodes(
|
||||
result, true, false, true),
|
||||
"n", true)
|
||||
end
|
||||
|
||||
M.esc = function(cmd)
|
||||
return vim.api.nvim_replace_termcodes(cmd, true, false, true)
|
||||
end
|
||||
|
||||
M.is_block_wise_mode = function()
|
||||
return vim.fn.visualmode() == ''
|
||||
end
|
||||
|
||||
--- get prev_char with out key_map
|
||||
M.get_prev_char = function(opt)
|
||||
return opt.line:sub(opt.col - 1, opt.col + #opt.rule.start_pair - 2)
|
||||
end
|
||||
|
||||
return M
|
||||
@ -0,0 +1,4 @@
|
||||
column_width = 85
|
||||
indent_type = "Spaces"
|
||||
quote_style = "AutoPreferSingle"
|
||||
indent_width = 4
|
||||
@ -0,0 +1,99 @@
|
||||
local npairs = require('nvim-autopairs')
|
||||
|
||||
_G.npairs = npairs
|
||||
|
||||
npairs.setup({
|
||||
enable_afterquote = true,
|
||||
})
|
||||
|
||||
local data = {
|
||||
{
|
||||
name = 'add bracket after quote ',
|
||||
filepath = './tests/endwise/init.lua',
|
||||
filetype = 'lua',
|
||||
linenr = 5,
|
||||
key = [[(]],
|
||||
before = [[const abc=|"test" ]],
|
||||
after = [[const abc=(|"test") ]],
|
||||
},
|
||||
{
|
||||
name = 'add bracket after quote ',
|
||||
filepath = './tests/endwise/init.lua',
|
||||
filetype = 'lua',
|
||||
linenr = 5,
|
||||
key = [[(]],
|
||||
before = [[|"test"]],
|
||||
after = [[(|"test")]],
|
||||
},
|
||||
{
|
||||
name = 'check quote without any text on end similar',
|
||||
filepath = './tests/endwise/init.lua',
|
||||
filetype = 'lua',
|
||||
linenr = 5,
|
||||
key = [[(]],
|
||||
before = [[ const [template, setTemplate] = useState|'')]],
|
||||
after = [[ const [template, setTemplate] = useState(|'')]],
|
||||
},
|
||||
|
||||
{
|
||||
name = 'add bracket after quote ',
|
||||
filepath = './tests/endwise/init.lua',
|
||||
filetype = 'lua',
|
||||
linenr = 5,
|
||||
key = [[{]],
|
||||
before = [[(|"test") ]],
|
||||
after = [[({|"test"}) ]],
|
||||
},
|
||||
{
|
||||
name = 'add bracket after quote ',
|
||||
filepath = './tests/endwise/init.lua',
|
||||
filetype = 'lua',
|
||||
linenr = 5,
|
||||
key = [[(]],
|
||||
before = [[const abc=|"visu\"dsa" ]],
|
||||
after = [[const abc=(|"visu\"dsa") ]],
|
||||
},
|
||||
{
|
||||
name = 'not add on exist quote',
|
||||
filepath = './tests/endwise/init.lua',
|
||||
filetype = 'lua',
|
||||
linenr = 5,
|
||||
key = [[(]],
|
||||
before = [[const abc=|"visu\"dsa") ]],
|
||||
after = [[const abc=(|"visu\"dsa") ]],
|
||||
},
|
||||
|
||||
{
|
||||
name = 'test add close quote on match',
|
||||
filepath = './tests/endwise/init.lua',
|
||||
filetype = 'lua',
|
||||
linenr = 5,
|
||||
key = [[(]],
|
||||
before = [[const abc=|"visu\"dsa" ]],
|
||||
after = [[const abc=(|"visu\"dsa") ]],
|
||||
},
|
||||
{
|
||||
name = 'not add bracket with quote have comma',
|
||||
filepath = './tests/endwise/init.lua',
|
||||
filetype = 'lua',
|
||||
linenr = 5,
|
||||
key = [[(]],
|
||||
before = [[|"data", abcdef]],
|
||||
after = [[(|"data", abcdef]],
|
||||
},
|
||||
{
|
||||
name = 'not add bracket with quote have comma',
|
||||
filepath = './tests/endwise/init.lua',
|
||||
filetype = 'lua',
|
||||
linenr = 5,
|
||||
key = [[(]],
|
||||
before = [[|"data", "abcdef"]],
|
||||
after = { [[(|"data", "abcdef"]] },
|
||||
},
|
||||
}
|
||||
|
||||
local run_data = _G.Test_filter(data)
|
||||
|
||||
describe('[afterquote tag]', function()
|
||||
_G.Test_withfile(run_data, {})
|
||||
end)
|
||||
@ -0,0 +1,22 @@
|
||||
local data1, data2
|
||||
local function wind()
|
||||
|
||||
vim.api.nvim_get_current_buf()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
end
|
||||
|
||||
@ -0,0 +1,18 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,15 @@
|
||||
fn main() {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
module MyFirstModule
|
||||
|
||||
|
||||
end
|
||||
@ -0,0 +1,18 @@
|
||||
local M={}
|
||||
|
||||
M.autopairs_bs = function(rules)
|
||||
for _, rule in pairs(rules) do
|
||||
|
||||
if rule.start_pair then
|
||||
end
|
||||
|
||||
|
||||
if rule.start_pair then
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
return M
|
||||
@ -0,0 +1,9 @@
|
||||
# Example Markdown File
|
||||
|
||||
```javascript
|
||||
let;
|
||||
let;
|
||||
let;
|
||||
let;
|
||||
let;
|
||||
```
|
||||
@ -0,0 +1,83 @@
|
||||
local npairs = require('nvim-autopairs')
|
||||
local ts = require('nvim-treesitter.configs')
|
||||
local log = require('nvim-autopairs._log')
|
||||
|
||||
ts.setup({
|
||||
ensure_installed = { 'lua' },
|
||||
highlight = { enable = true },
|
||||
})
|
||||
_G.npairs = npairs
|
||||
vim.api.nvim_set_keymap(
|
||||
'i',
|
||||
'<CR>',
|
||||
'v:lua.npairs.autopairs_cr()',
|
||||
{ expr = true, noremap = true }
|
||||
)
|
||||
|
||||
local data = {
|
||||
{
|
||||
name = 'lua function add endwise',
|
||||
filepath = './tests/endwise/init.lua',
|
||||
filetype = 'lua',
|
||||
linenr = 5,
|
||||
key = [[<cr>]],
|
||||
before = [[function a()| ]],
|
||||
after = {
|
||||
[[function a() ]],
|
||||
[[| ]],
|
||||
[[ end ]],
|
||||
},
|
||||
},
|
||||
{
|
||||
name = 'lua function add endwise',
|
||||
filepath = './tests/endwise/init.lua',
|
||||
filetype = 'lua',
|
||||
linenr = 5,
|
||||
key = [[<cr>]],
|
||||
before = [[function a()|x ab ]],
|
||||
after = {
|
||||
[[function a() ]],
|
||||
[[|x ab]],
|
||||
},
|
||||
},
|
||||
{
|
||||
name = 'add if endwise',
|
||||
filepath = './tests/endwise/init.lua',
|
||||
filetype = 'lua',
|
||||
linenr = 5,
|
||||
key = [[<cr>]],
|
||||
before = [[if data== 'fdsafdsa' then| ]],
|
||||
after = {
|
||||
[[if data== 'fdsafdsa' then ]],
|
||||
[[|]],
|
||||
[[end ]],
|
||||
},
|
||||
},
|
||||
{
|
||||
name = 'undo on<cr> key',
|
||||
filepath = './tests/endwise/init.lua',
|
||||
filetype = 'lua',
|
||||
linenr = 5,
|
||||
key = [[{<cr><esc>u]],
|
||||
before = [[local abc = | ]],
|
||||
after = {
|
||||
[[local abc = {|} ]],
|
||||
[[]],
|
||||
[[]],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
local run_data = _G.Test_filter(data)
|
||||
|
||||
describe('[endwise tag]', function()
|
||||
_G.Test_withfile(run_data, {
|
||||
-- need to understand this ??? new line make change cursor zzz
|
||||
cursor_add = 1,
|
||||
before_each = function(value)
|
||||
npairs.add_rules(
|
||||
require('nvim-autopairs.rules.endwise-' .. value.filetype)
|
||||
)
|
||||
end,
|
||||
})
|
||||
end)
|
||||
@ -0,0 +1,53 @@
|
||||
-- local npairs = require('nvim-autopairs')
|
||||
|
||||
-- _G.npairs = npairs
|
||||
|
||||
-- npairs.setup({
|
||||
-- enable_afterquote = true,
|
||||
-- fast_wrap = true,
|
||||
-- })
|
||||
-- local data = {
|
||||
-- {
|
||||
-- only = true,
|
||||
-- name = 'move end wise after quote ',
|
||||
-- filepath = './tests/endwise/init.lua',
|
||||
-- filetype = 'lua',
|
||||
-- linenr = 5,
|
||||
-- key = [[<M-e>]],
|
||||
-- before = [[const abc=(|"test",data ]],
|
||||
-- after = [[const abc=(|"test"),data ]],
|
||||
-- },
|
||||
-- {
|
||||
-- name = 'move end wise after quote ',
|
||||
-- filepath = './tests/endwise/init.lua',
|
||||
-- filetype = 'lua',
|
||||
-- linenr = 5,
|
||||
-- key = [[<M-e>]],
|
||||
-- before = [[const abc=(|"test"),data ]],
|
||||
-- after = [[const abc=(|"test",data) ]],
|
||||
-- },
|
||||
-- {
|
||||
-- name = 'move end wise after quote ',
|
||||
-- filepath = './tests/endwise/init.lua',
|
||||
-- filetype = 'lua',
|
||||
-- linenr = 5,
|
||||
-- key = [[<M-e>]],
|
||||
-- before = [[const abc=(|"test",data),dadas ]],
|
||||
-- after = [[const abc=(|"test",data,dadas) ]],
|
||||
-- },
|
||||
-- {
|
||||
-- name = 'move end wise after quote ',
|
||||
-- filepath = './tests/endwise/init.lua',
|
||||
-- filetype = 'lua',
|
||||
-- linenr = 5,
|
||||
-- key = [[<M-e>]],
|
||||
-- before = [[Plug {(|'dsfdsa',) on = 'aaa'} ]],
|
||||
-- after = [[Plug {('dsfdsa', on = 'aaa')} ]],
|
||||
-- },
|
||||
-- }
|
||||
|
||||
-- local run_data = _G.Test_filter(data)
|
||||
|
||||
-- describe('[endwise tag]', function()
|
||||
-- _G.Test_withfile(run_data, {})
|
||||
-- end)
|
||||
@ -0,0 +1,30 @@
|
||||
set rtp +=.
|
||||
set rtp +=../plenary.nvim/
|
||||
set rtp +=../nvim-treesitter
|
||||
set rtp +=../playground/
|
||||
|
||||
lua _G.__is_log = true
|
||||
lua vim.fn.setenv("DEBUG_PLENARY", true)
|
||||
runtime! plugin/plenary.vim
|
||||
runtime! plugin/nvim-treesitter.vim
|
||||
runtime! plugin/playground.vim
|
||||
runtime! plugin/nvim-autopairs.vim
|
||||
|
||||
set noswapfile
|
||||
set nobackup
|
||||
|
||||
filetype indent off
|
||||
set expandtab
|
||||
set shiftwidth=4
|
||||
set nowritebackup
|
||||
set noautoindent
|
||||
set nocindent
|
||||
set nosmartindent
|
||||
set indentexpr=
|
||||
|
||||
lua << EOF
|
||||
require("plenary/busted")
|
||||
require("nvim-treesitter").setup()
|
||||
vim.cmd[[luafile ./tests/test_utils.lua]]
|
||||
require("nvim-autopairs").setup()
|
||||
EOF
|
||||
@ -0,0 +1,838 @@
|
||||
local npairs = require('nvim-autopairs')
|
||||
local Rule = require('nvim-autopairs.rule')
|
||||
local cond = require('nvim-autopairs.conds')
|
||||
|
||||
local log = require('nvim-autopairs._log')
|
||||
_G.log = log
|
||||
local utils = require('nvim-autopairs.utils')
|
||||
_G.npairs = npairs;
|
||||
|
||||
-- use only = true to test 1 case
|
||||
-- stylua: ignore
|
||||
local data = {
|
||||
{
|
||||
-- only = true,
|
||||
name = "1 add normal bracket",
|
||||
key = [[{]],
|
||||
before = [[x| ]],
|
||||
after = [[x{|} ]]
|
||||
},
|
||||
|
||||
{
|
||||
name = "2 add bracket inside bracket",
|
||||
key = [[{]],
|
||||
before = [[{|} ]],
|
||||
after = [[{{|}} ]]
|
||||
},
|
||||
{
|
||||
name = "3 test single quote ",
|
||||
filetype = "lua",
|
||||
key = "'",
|
||||
before = [[data,|) ]],
|
||||
after = [[data,'|') ]]
|
||||
},
|
||||
{
|
||||
name = "4 add normal bracket",
|
||||
key = [[(]],
|
||||
before = [[aaaa| x ]],
|
||||
after = [[aaaa(|) x ]]
|
||||
},
|
||||
{
|
||||
name = "5 add normal quote",
|
||||
key = [["]],
|
||||
before = [[aa| aa]],
|
||||
after = [[aa"|" aa]]
|
||||
},
|
||||
{
|
||||
name = "6 add python quote",
|
||||
filetype = "python",
|
||||
key = [["]],
|
||||
before = [[""| ]],
|
||||
after = [["""|""" ]]
|
||||
},
|
||||
{
|
||||
name = "7 don't repeat python quote",
|
||||
filetype = "python",
|
||||
key = [["]],
|
||||
before = [[a"""|""" ]],
|
||||
after = [[a""""|"" ]]
|
||||
},
|
||||
|
||||
{
|
||||
name = "8 add markdown quote",
|
||||
filetype = "markdown",
|
||||
key = [[`]],
|
||||
before = [[``| ]],
|
||||
after = [[```|``` ]]
|
||||
},
|
||||
{
|
||||
name = "9 don't add single quote with previous alphabet char",
|
||||
key = [[']],
|
||||
before = [[aa| aa ]],
|
||||
after = [[aa'| aa ]]
|
||||
},
|
||||
{
|
||||
name = "10 don't add single quote with alphabet char",
|
||||
key = [[']],
|
||||
before = [[a|x ]],
|
||||
after = [[a'|x ]]
|
||||
},
|
||||
{
|
||||
name = "11 don't add single quote on end line",
|
||||
key = [[<right>']],
|
||||
before = [[c aa|]],
|
||||
after = [[c aa'|]]
|
||||
},
|
||||
{
|
||||
name = "12 don't add quote after alphabet char",
|
||||
key = [["]],
|
||||
before = [[aa |aa]],
|
||||
after = [[aa "|aa]]
|
||||
},
|
||||
{
|
||||
name = "13 don't add quote inside quote",
|
||||
key = [["]],
|
||||
before = [["aa | aa]],
|
||||
after = [["aa "| aa]]
|
||||
},
|
||||
{
|
||||
name = "14 add quote if not inside quote",
|
||||
key = [["]],
|
||||
before = [["aa " | aa]],
|
||||
after = [["aa " "|" aa]]
|
||||
},
|
||||
{
|
||||
name = "15 don't add pair after alphabet char",
|
||||
key = [[(]],
|
||||
before = [[aa |aa]],
|
||||
after = [[aa (|aa]]
|
||||
},
|
||||
{
|
||||
name = "16 don't add pair after dot char",
|
||||
key = [[(]],
|
||||
before = [[aa |.aa]],
|
||||
after = [[aa (|.aa]]
|
||||
},
|
||||
{
|
||||
name = "17 don't add bracket have open bracket in same line",
|
||||
key = [[(]],
|
||||
before = [[( many char |))]],
|
||||
after = [[( many char (|))]]
|
||||
},
|
||||
{
|
||||
filetype = 'vim',
|
||||
name = "18 add bracket inside quote when nextchar is ignore",
|
||||
key = [[{]],
|
||||
before = [["|"]],
|
||||
after = [["{|}"]]
|
||||
},
|
||||
{
|
||||
filetype = '',
|
||||
name = "19 add bracket inside quote when next char is ignore",
|
||||
key = [[{]],
|
||||
before = [[" |"]],
|
||||
after = [[" {|}"]]
|
||||
},
|
||||
{
|
||||
name = "20 move right on quote line ",
|
||||
key = [["]],
|
||||
before = [["|"]],
|
||||
after = [[""|]]
|
||||
},
|
||||
{
|
||||
name = "21 move right end line ",
|
||||
key = [["]],
|
||||
before = [[aaaa|"]],
|
||||
after = [[aaaa"|]]
|
||||
},
|
||||
{
|
||||
name = "22 move right when inside quote",
|
||||
key = [["]],
|
||||
before = [[("abcd|")]],
|
||||
after = [[("abcd"|)]]
|
||||
},
|
||||
|
||||
{
|
||||
name = "23 move right when inside quote",
|
||||
key = [["]],
|
||||
before = [[foo("|")]],
|
||||
after = [[foo(""|)]]
|
||||
},
|
||||
{
|
||||
name = "24 move right square bracket",
|
||||
key = [[)]],
|
||||
before = [[("abcd|) ]],
|
||||
after = [[("abcd)| ]]
|
||||
},
|
||||
{
|
||||
name = "25 move right bracket",
|
||||
key = [[}]],
|
||||
before = [[("abcd|}} ]],
|
||||
after = [[("abcd}|} ]]
|
||||
},
|
||||
{
|
||||
-- ref: issue #331
|
||||
name = "26 move right, should not move on non-end-pair char: `§|§` with (",
|
||||
setup_func = function()
|
||||
npairs.add_rule(Rule("§", "§"):with_move(cond.done()))
|
||||
end,
|
||||
key = [[(]],
|
||||
before = [[§|§]],
|
||||
after = [[§(|)§]]
|
||||
},
|
||||
{
|
||||
-- ref: issue #331
|
||||
name = "27 move right, should not move on non-end-pair char: `#|#` with \"",
|
||||
setup_func = function()
|
||||
npairs.add_rule(Rule("#", "#"):with_move(cond.done()))
|
||||
end,
|
||||
key = [["]],
|
||||
before = [[#|#]],
|
||||
after = [[#"|"#]]
|
||||
},
|
||||
{
|
||||
-- ref: issue #331 and #330
|
||||
name = "28 move right, should not move on non-end-pair char: `<|>` with (",
|
||||
setup_func = function()
|
||||
npairs.add_rule(Rule("<", ">"):with_move(cond.done()))
|
||||
end,
|
||||
key = [[(]],
|
||||
before = [[<|>]],
|
||||
after = [[<(|)>]],
|
||||
},
|
||||
{
|
||||
name = "29 move right when inside grave with special slash",
|
||||
key = [[`]],
|
||||
before = [[(`abcd\"|`)]],
|
||||
after = [[(`abcd\"`|)]]
|
||||
},
|
||||
{
|
||||
name = "30 move right when inside quote with special slash",
|
||||
key = [["]],
|
||||
before = [[("abcd\"|")]],
|
||||
after = [[("abcd\""|)]]
|
||||
},
|
||||
{
|
||||
filetype = 'rust',
|
||||
name = "31 move right double quote after single quote",
|
||||
key = [["]],
|
||||
before = [[ ('x').expect("|");]],
|
||||
after = [[ ('x').expect(""|);]],
|
||||
},
|
||||
{
|
||||
filetype = 'rust',
|
||||
name = "32 move right, should not move when bracket not closing",
|
||||
key = [[}]],
|
||||
before = [[{{ |} ]],
|
||||
after = [[{{ }|} ]]
|
||||
},
|
||||
|
||||
{
|
||||
filetype = 'rust',
|
||||
name = "33 move right, should move when bracket closing",
|
||||
key = [[}]],
|
||||
before = [[{ }|} ]],
|
||||
after = [[{ }}| ]]
|
||||
},
|
||||
{
|
||||
name = "34 delete bracket",
|
||||
filetype = "javascript",
|
||||
key = [[<bs>]],
|
||||
before = [[aaa(|) ]],
|
||||
after = [[aaa| ]]
|
||||
},
|
||||
{
|
||||
name = "35 breakline on {",
|
||||
filetype = "javascript",
|
||||
key = [[<cr>]],
|
||||
before = [[a{|}]],
|
||||
after = {
|
||||
"a{",
|
||||
"|",
|
||||
"}"
|
||||
}
|
||||
},
|
||||
{
|
||||
setup_func = function()
|
||||
vim.opt.indentexpr = "nvim_treesitter#indent()"
|
||||
end,
|
||||
name = "36 breakline on (",
|
||||
filetype = "javascript",
|
||||
key = [[<cr>]],
|
||||
before = [[function ab(|)]],
|
||||
after = {
|
||||
"function ab(",
|
||||
"|",
|
||||
")"
|
||||
}
|
||||
},
|
||||
{
|
||||
name = "37 breakline on ]",
|
||||
filetype = "javascript",
|
||||
key = [[<cr>]],
|
||||
before = [[a[|] ]],
|
||||
after = {
|
||||
"a[",
|
||||
"|",
|
||||
"]"
|
||||
}
|
||||
},
|
||||
{
|
||||
name = "38 move ) inside nested function call",
|
||||
filetype = "javascript",
|
||||
key = [[)]],
|
||||
before = {
|
||||
"fn(fn(|))",
|
||||
},
|
||||
after = {
|
||||
"fn(fn()|)",
|
||||
}
|
||||
},
|
||||
{
|
||||
name = "39 move } inside singleline function's params",
|
||||
filetype = "javascript",
|
||||
key = [[}]],
|
||||
before = {
|
||||
"({|}) => {}",
|
||||
},
|
||||
after = {
|
||||
"({}|) => {}",
|
||||
}
|
||||
},
|
||||
{
|
||||
name = "40 move } inside multiline function's params",
|
||||
filetype = "javascript",
|
||||
key = [[}]],
|
||||
before = {
|
||||
"({|}) => {",
|
||||
"",
|
||||
"}",
|
||||
},
|
||||
after = {
|
||||
"({}|) => {",
|
||||
"",
|
||||
"}",
|
||||
}
|
||||
},
|
||||
{
|
||||
name = "41 breakline on markdown ",
|
||||
filetype = "markdown",
|
||||
key = [[<cr>]],
|
||||
before = [[``` lua|```]],
|
||||
after = {
|
||||
[[``` lua]],
|
||||
[[|]],
|
||||
[[```]]
|
||||
}
|
||||
},
|
||||
{
|
||||
name = "42 breakline on < html",
|
||||
filetype = "html",
|
||||
key = [[<cr>]],
|
||||
before = [[<div>|</div>]],
|
||||
after = {
|
||||
[[<div>]],
|
||||
[[|]],
|
||||
[[</div>]]
|
||||
}
|
||||
},
|
||||
{
|
||||
name = "43 breakline on < html with text",
|
||||
filetype = "html",
|
||||
key = [[<cr>]],
|
||||
before = [[<div> ads |</div>]],
|
||||
after = {
|
||||
[[<div> ads]],
|
||||
[[|]],
|
||||
[[</div>]]
|
||||
},
|
||||
},
|
||||
{
|
||||
name = "44 breakline on < html with space after cursor",
|
||||
filetype = "html",
|
||||
key = [[<cr>]],
|
||||
before = [[<div> ads | </div>]],
|
||||
after = {
|
||||
[[<div> ads]],
|
||||
[[|]],
|
||||
[[</div>]]
|
||||
},
|
||||
},
|
||||
{
|
||||
name = "45 do not mapping on > html",
|
||||
filetype = "html",
|
||||
key = [[>]],
|
||||
before = [[<div| ]],
|
||||
after = [[<div>| ]]
|
||||
},
|
||||
{
|
||||
name = "46 press multiple key",
|
||||
filetype = "html",
|
||||
key = [[((((]],
|
||||
before = [[a| ]],
|
||||
after = [[a((((|)))) ]]
|
||||
},
|
||||
{
|
||||
setup_func = function()
|
||||
npairs.add_rules({
|
||||
Rule('u%d%d%d%d$', 'number', 'lua'):use_regex(true),
|
||||
})
|
||||
end,
|
||||
name = "47 text regex",
|
||||
filetype = "lua",
|
||||
key = "4",
|
||||
before = [[u123| ]],
|
||||
after = [[u1234|number ]]
|
||||
},
|
||||
{
|
||||
|
||||
setup_func = function()
|
||||
npairs.add_rules({
|
||||
Rule('x%d%d%d%d$', 'number', 'lua'):use_regex(true):replace_endpair(function(opts)
|
||||
return opts.prev_char:sub(#opts.prev_char - 3, #opts.prev_char)
|
||||
end),
|
||||
})
|
||||
end,
|
||||
name = "48 text regex with custom end_pair",
|
||||
filetype = "lua",
|
||||
key = "4",
|
||||
before = [[x123| ]],
|
||||
after = [[x1234|1234 ]]
|
||||
},
|
||||
{
|
||||
setup_func = function()
|
||||
npairs.add_rules({
|
||||
Rule('b%d%d%d%d%w$', '', 'vim'):use_regex(true, '<tab>'):replace_endpair(function(opts)
|
||||
return opts.prev_char:sub(#opts.prev_char - 4, #opts.prev_char) .. '<esc>viwUi'
|
||||
end),
|
||||
})
|
||||
end,
|
||||
name = "49 text regex with custom key",
|
||||
filetype = "vim",
|
||||
key = "<tab>",
|
||||
before = [[b1234s| ]],
|
||||
after = [[B|1234S1234S ]]
|
||||
|
||||
},
|
||||
{
|
||||
setup_func = function()
|
||||
npairs.add_rules({
|
||||
Rule('b%d%d%d%d%w$', '', 'vim'):use_regex(true, '<tab>'):replace_endpair(function(opts)
|
||||
return opts.prev_char:sub(#opts.prev_char - 4, #opts.prev_char) .. '<esc>viwUi'
|
||||
end),
|
||||
})
|
||||
end,
|
||||
name = "50 test move right custom char",
|
||||
filetype = "vim",
|
||||
key = "<tab>",
|
||||
before = [[b1234s| ]],
|
||||
after = [[B|1234S1234S ]]
|
||||
},
|
||||
{
|
||||
setup_func = function()
|
||||
npairs.add_rules({
|
||||
Rule("-", "+", "vim")
|
||||
:with_move(function(opt)
|
||||
return utils.get_prev_char(opt) == "x"
|
||||
end)
|
||||
:with_move(cond.done())
|
||||
})
|
||||
end,
|
||||
name = "51 test move right custom char plus",
|
||||
filetype = "vim",
|
||||
key = "+",
|
||||
before = [[x|+ ]],
|
||||
after = [[x+| ]]
|
||||
},
|
||||
{
|
||||
setup_func = function()
|
||||
npairs.add_rules({
|
||||
Rule("/**", "**/", "javascript")
|
||||
:with_move(cond.none())
|
||||
})
|
||||
end,
|
||||
name = "52 test javascript comment",
|
||||
filetype = "javascript",
|
||||
key = "*",
|
||||
before = [[/*| ]],
|
||||
after = [[/**|**/ ]]
|
||||
},
|
||||
{
|
||||
setup_func = function()
|
||||
npairs.add_rules({
|
||||
Rule("(", ")")
|
||||
:use_key("<c-h>")
|
||||
:replace_endpair(function() return "<bs><del>" end, true)
|
||||
})
|
||||
end,
|
||||
name = "53 test map custom key",
|
||||
filetype = "latex",
|
||||
key = [[<c-h>]],
|
||||
before = [[ abcde(|) ]],
|
||||
after = [[ abcde| ]],
|
||||
},
|
||||
{
|
||||
setup_func = function()
|
||||
npairs.add_rules {
|
||||
Rule(' ', ' '):with_pair(function(opts)
|
||||
local pair = opts.line:sub(opts.col, opts.col + 1)
|
||||
return vim.tbl_contains({ '()', '[]', '{}' }, pair)
|
||||
end),
|
||||
Rule('( ', ' )')
|
||||
:with_pair(function() return false end)
|
||||
:with_del(function() return false end)
|
||||
:with_move(function() return true end)
|
||||
:use_regex(false, ")")
|
||||
}
|
||||
end,
|
||||
name = "54 test multiple move right",
|
||||
filetype = "latex",
|
||||
key = [[)]],
|
||||
before = [[( | ) ]],
|
||||
after = [[( )| ]],
|
||||
},
|
||||
{
|
||||
setup_func = function()
|
||||
npairs.setup({
|
||||
enable_check_bracket_line = false
|
||||
})
|
||||
end,
|
||||
name = "55 test disable check bracket line",
|
||||
filetype = "latex",
|
||||
key = [[(]],
|
||||
before = [[(|))) ]],
|
||||
after = [[((|)))) ]],
|
||||
},
|
||||
{
|
||||
setup_func = function()
|
||||
npairs.add_rules({
|
||||
Rule("<", ">", { "rust" })
|
||||
:with_pair(cond.before_text("Vec"))
|
||||
})
|
||||
end,
|
||||
name = "56 test disable check bracket line",
|
||||
filetype = "rust",
|
||||
key = [[<]],
|
||||
before = [[Vec| ]],
|
||||
after = [[Vec<|> ]],
|
||||
},
|
||||
{
|
||||
setup_func = function()
|
||||
npairs.add_rule(Rule("!", "!"):with_pair(cond.not_filetypes({ "lua" })))
|
||||
end,
|
||||
name = "57 disable pairs in lua",
|
||||
filetype = "lua",
|
||||
key = "!",
|
||||
before = [[x| ]],
|
||||
after = [[x!| ]]
|
||||
},
|
||||
{
|
||||
setup_func = function()
|
||||
npairs.clear_rules()
|
||||
npairs.add_rules({
|
||||
Rule("%(.*%)%s*%=>", " { }", { "typescript", "typescriptreact", "javascript" })
|
||||
:use_regex(true)
|
||||
:set_end_pair_length(2)
|
||||
})
|
||||
end,
|
||||
name = "58 mapping regex with custom end_pair_length",
|
||||
filetype = "typescript",
|
||||
key = ">",
|
||||
before = [[(o)=| ]],
|
||||
after = [[(o)=> { | } ]]
|
||||
|
||||
},
|
||||
{
|
||||
setup_func = function()
|
||||
npairs.add_rules({
|
||||
Rule('(', ')'):use_key('<c-w>'):replace_endpair(function()
|
||||
return '<bs><del><del><del>'
|
||||
end, true),
|
||||
Rule('(', ')'):use_key('<c-h>'):replace_endpair(function()
|
||||
return '<bs><del>'
|
||||
end, true),
|
||||
})
|
||||
end,
|
||||
name = "59 mapping same pair with different key",
|
||||
filetype = "typescript",
|
||||
key = "(",
|
||||
before = [[(test|) ]],
|
||||
after = [[(test(|)) ]]
|
||||
|
||||
},
|
||||
{
|
||||
setup_func = function()
|
||||
npairs.clear_rules()
|
||||
npairs.add_rule(Rule("„", "”"))
|
||||
end,
|
||||
name = "60 multibyte character from custom keyboard",
|
||||
not_replace_term_code = true,
|
||||
key = "„",
|
||||
before = [[a | ]],
|
||||
after = [[a „|” ]],
|
||||
end_cursor = 3
|
||||
},
|
||||
{
|
||||
setup_func = function()
|
||||
npairs.clear_rules()
|
||||
npairs.add_rule(Rule("„", "”"):with_move(cond.done()))
|
||||
end,
|
||||
name = "61 multibyte character move_right",
|
||||
not_replace_term_code = true,
|
||||
key = "”",
|
||||
before = [[a „|”xx ]],
|
||||
after = [[a „”|xx ]],
|
||||
end_cursor = 6
|
||||
},
|
||||
{
|
||||
setup_func = function()
|
||||
npairs.clear_rules()
|
||||
npairs.add_rule(Rule("„", "”"):with_move(cond.done()))
|
||||
end,
|
||||
name = "62 multibyte character delete",
|
||||
key = "<bs>",
|
||||
before = [[a „|” ]],
|
||||
after = [[a | ]],
|
||||
},
|
||||
{
|
||||
setup_func = function()
|
||||
npairs.clear_rules()
|
||||
npairs.add_rule(Rule("a„", "”b"):with_move(cond.done()))
|
||||
end,
|
||||
not_replace_term_code = true,
|
||||
name = "63 multibyte character and multiple ",
|
||||
key = "„",
|
||||
before = [[a| ]],
|
||||
after = [[a„|”b ]],
|
||||
end_cursor = 2
|
||||
},
|
||||
{
|
||||
setup_func = function()
|
||||
npairs.setup({ map_c_h = true })
|
||||
end,
|
||||
name = "64 map <c-h>",
|
||||
key = "<c-h>",
|
||||
before = [[aa'|' ]],
|
||||
after = [[aa| ]],
|
||||
},
|
||||
{
|
||||
setup_func = function()
|
||||
npairs.setup({
|
||||
map_c_w = true
|
||||
})
|
||||
end,
|
||||
name = "65 map <c-w>",
|
||||
key = "<c-w>",
|
||||
before = [[aa'|' ]],
|
||||
after = [[aa| ]],
|
||||
},
|
||||
{
|
||||
setup_func = function()
|
||||
npairs.clear_rules()
|
||||
npairs.add_rule(Rule("x", "x", { '-vim', '-rust' }))
|
||||
end,
|
||||
filetype = 'vim',
|
||||
name = "66 disable filetype vim",
|
||||
key = [[x]],
|
||||
before = [[a | ]],
|
||||
after = [[a x| ]]
|
||||
},
|
||||
{
|
||||
filetype = 'vim',
|
||||
name = "67 undo on quote",
|
||||
key = [[{123<esc>u]],
|
||||
end_cursor = 12,
|
||||
before = [[local abc=| ]],
|
||||
after = [[local abc={|} ]]
|
||||
},
|
||||
{
|
||||
filetype = 'vim',
|
||||
name = "68 undo on bracket",
|
||||
key = [['123<esc>u]],
|
||||
end_cursor = 12,
|
||||
before = [[local abc=| ]],
|
||||
after = [[local abc='|' ]]
|
||||
},
|
||||
{
|
||||
filetype = 'vim',
|
||||
name = "69 double quote on vim after char",
|
||||
key = [["ab]],
|
||||
before = [[echo | ]],
|
||||
after = [[echo "ab|" ]]
|
||||
},
|
||||
{
|
||||
filetype = 'vim',
|
||||
name = "70 double quote on vim on begin",
|
||||
key = [["ab]],
|
||||
before = [[ | aaa]],
|
||||
after = [[ "ab| aaa]]
|
||||
},
|
||||
{
|
||||
setup_func = function()
|
||||
npairs.add_rule(
|
||||
Rule('struct%s[a-zA-Z]+%s?{$', '};')
|
||||
:use_regex(true, "{")
|
||||
)
|
||||
end,
|
||||
filetype = 'javascript',
|
||||
name = "71 custom endwise rule",
|
||||
key = [[{]],
|
||||
before = [[struct abc | ]],
|
||||
after = [[struct abc {|};]],
|
||||
},
|
||||
{
|
||||
setup_func = function()
|
||||
npairs.clear_rules()
|
||||
npairs.add_rule(Rule("{", "}"):end_wise())
|
||||
end,
|
||||
filetype = 'javascript',
|
||||
name = "72 custom endwise rule",
|
||||
key = [[<cr>]],
|
||||
before = [[function () {| ]],
|
||||
after = {
|
||||
[[function () {]],
|
||||
[[|]],
|
||||
[[}]],
|
||||
},
|
||||
},
|
||||
{
|
||||
setup_func = function()
|
||||
vim.opt.smartindent = true
|
||||
end,
|
||||
filetype = 'ps1',
|
||||
name = "73 indent on powershell",
|
||||
key = [[<cr>]],
|
||||
before = [[function () {|} ]],
|
||||
after = {
|
||||
[[function () {]],
|
||||
[[|]],
|
||||
[[}]],
|
||||
},
|
||||
},
|
||||
{
|
||||
setup_func = function()
|
||||
npairs.clear_rules()
|
||||
npairs.add_rule(
|
||||
Rule("{", "")
|
||||
:replace_endpair(function()
|
||||
return "}"
|
||||
end)
|
||||
:end_wise()
|
||||
)
|
||||
end,
|
||||
filetype = 'javascript',
|
||||
name = "74 custom endwise rule with custom end_pair",
|
||||
key = [[<cr>]],
|
||||
before = [[function () {| ]],
|
||||
after = {
|
||||
[[function () {]],
|
||||
[[|]],
|
||||
[[}]],
|
||||
},
|
||||
},
|
||||
{
|
||||
name = "75 open bracker on back tick",
|
||||
key = [[(]],
|
||||
before = [[ |`abcd`]],
|
||||
after = [[ (`abcd`) ]]
|
||||
},
|
||||
{
|
||||
name = "76 should not add bracket on line have bracket ",
|
||||
key = [[(]],
|
||||
before = [[ |(abcd))]],
|
||||
after = [[ ((abcd)) ]]
|
||||
},
|
||||
{
|
||||
name = "77 not add bracket on line have bracket ",
|
||||
key = [[(]],
|
||||
before = [[ |(abcd) ( visual)]],
|
||||
after = [[ ()(abcd) ( visual)]]
|
||||
},
|
||||
{
|
||||
name = "78 should add single quote when it have primes char",
|
||||
key = [[']],
|
||||
before = [[Ben's friends say: | ]],
|
||||
after = [[Ben's friends say: '|' ]]
|
||||
},
|
||||
{
|
||||
name = "79 a quote with single quote string",
|
||||
key = "'",
|
||||
before = [[{{("It doesn't name %s", ''), 'ErrorMsg'| }}, ]],
|
||||
after = [[{{("It doesn't name %s", ''), 'ErrorMsg''|' }}, ]],
|
||||
end_cursor = 41
|
||||
},
|
||||
{
|
||||
name = "80 add normal quote with '",
|
||||
key = [["]],
|
||||
before = [[aa| 'aa]],
|
||||
after = [[aa"|" 'aa]]
|
||||
},
|
||||
{
|
||||
name = "81 add closing single quote for python prefixed string",
|
||||
filetype = "python",
|
||||
key = [[']],
|
||||
before = [[print(f|)]],
|
||||
after = [[print(f'|')]]
|
||||
},
|
||||
{
|
||||
name = "82 add closing single quote for capital python prefixed string",
|
||||
filetype = "python",
|
||||
key = [[']],
|
||||
before = [[print(B|)]],
|
||||
after = [[print(B'|')]]
|
||||
},
|
||||
{
|
||||
name = "83 don't add closing single quote for random prefix string",
|
||||
filetype = "python",
|
||||
key = [[']],
|
||||
before = [[print(s|)]],
|
||||
after = [[print(s'|)]]
|
||||
},
|
||||
{
|
||||
name = "84 don't add closing single quote for other filetype prefixed string",
|
||||
filetype = "lua",
|
||||
key = [[']],
|
||||
before = [[print(f|)]],
|
||||
after = [[print(f'|)]]
|
||||
},
|
||||
{
|
||||
name = "85 allow brackets in prefixed python single quote string",
|
||||
filetype = "python",
|
||||
key = [[{]],
|
||||
before = [[print(f'|')]],
|
||||
after = [[print(f'{|}')]]
|
||||
},
|
||||
{
|
||||
name = "86 move ' is working on python",
|
||||
filetype = "python",
|
||||
key = [[']],
|
||||
before = [[('|') ]],
|
||||
after = [[(''|) ]]
|
||||
},
|
||||
{
|
||||
setup_func = function()
|
||||
npairs.add_rules({
|
||||
Rule('123456', '789'):with_pair(cond.before_regex('^12345$', 5)),
|
||||
})
|
||||
end,
|
||||
name = '87 test before_regex with a specific string length',
|
||||
key = [[123456]],
|
||||
before = [[ some text before| ]],
|
||||
after = [[ some text before123456|789 ]],
|
||||
},
|
||||
}
|
||||
|
||||
local run_data = _G.Test_filter(data)
|
||||
|
||||
describe('autopairs ', function()
|
||||
_G.Test_withfile(run_data, {
|
||||
cursor_add = 0,
|
||||
before_each = function(value)
|
||||
npairs.setup()
|
||||
vim.opt.indentexpr = ""
|
||||
if value.setup_func then
|
||||
value.setup_func()
|
||||
end
|
||||
end,
|
||||
})
|
||||
end)
|
||||
@ -0,0 +1,189 @@
|
||||
local utils = require('nvim-autopairs.utils')
|
||||
local log = require('nvim-autopairs._log')
|
||||
local api = vim.api
|
||||
local ts_get_node_text = vim.treesitter.get_node_text or vim.treesitter.query.get_node_text
|
||||
|
||||
local helpers = {}
|
||||
|
||||
function helpers.feed(text, feed_opts, is_replace)
|
||||
feed_opts = feed_opts or 'n'
|
||||
if not is_replace then
|
||||
text = vim.api.nvim_replace_termcodes(text, true, false, true)
|
||||
end
|
||||
vim.api.nvim_feedkeys(text, feed_opts, true)
|
||||
end
|
||||
|
||||
function helpers.insert(text, is_replace)
|
||||
helpers.feed('i' .. text, 'x', is_replace)
|
||||
end
|
||||
|
||||
utils.insert_char = function(text)
|
||||
api.nvim_put({ text }, 'c', true, true)
|
||||
end
|
||||
|
||||
utils.feed = function(text, num)
|
||||
local result = ''
|
||||
for _ = 1, num, 1 do
|
||||
result = result .. text
|
||||
end
|
||||
api.nvim_feedkeys(
|
||||
---@diagnostic disable-next-line: param-type-mismatch
|
||||
api.nvim_replace_termcodes(result, true, false, true),
|
||||
'x',
|
||||
true
|
||||
)
|
||||
end
|
||||
|
||||
_G.eq = assert.are.same
|
||||
|
||||
_G.Test_filter = function(data)
|
||||
local run_data = {}
|
||||
for _, value in pairs(data) do
|
||||
if value.only == true then
|
||||
table.insert(run_data, value)
|
||||
break
|
||||
end
|
||||
end
|
||||
if #run_data == 0 then
|
||||
run_data = data
|
||||
end
|
||||
return run_data
|
||||
end
|
||||
|
||||
local compare_text = function(linenr, text_after, name, cursor_add, end_cursor)
|
||||
cursor_add = cursor_add or 0
|
||||
local new_text = vim.api.nvim_buf_get_lines(
|
||||
0,
|
||||
linenr - 1,
|
||||
linenr + #text_after - 1,
|
||||
true
|
||||
)
|
||||
for i = 1, #text_after, 1 do
|
||||
local t = string.gsub(text_after[i], '%|', '')
|
||||
if t
|
||||
and new_text[i]
|
||||
and t:gsub('%s+$', '') ~= new_text[i]:gsub('%s+$', '')
|
||||
then
|
||||
eq(t, new_text[i], '\n\n text error: ' .. name .. '\n')
|
||||
end
|
||||
local p_after = string.find(text_after[i], '%|')
|
||||
if p_after then
|
||||
local row, col = utils.get_cursor()
|
||||
if end_cursor then
|
||||
eq(row, linenr + i - 2, '\n\n cursor row error: ' .. name .. '\n')
|
||||
eq(
|
||||
col + 1,
|
||||
end_cursor,
|
||||
'\n\n end cursor column error : ' .. name .. '\n'
|
||||
)
|
||||
else
|
||||
eq(row, linenr + i - 2, '\n\n cursor row error: ' .. name .. '\n')
|
||||
p_after = p_after + cursor_add
|
||||
eq(
|
||||
col,
|
||||
math.max(p_after - 2, 0),
|
||||
'\n\n cursor column error : ' .. name .. '\n'
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
_G.Test_withfile = function(test_data, cb)
|
||||
for _, value in pairs(test_data) do
|
||||
it('test ' .. value.name, function(_)
|
||||
local text_before = {}
|
||||
value.linenr = value.linenr or 1
|
||||
local pos_before = {
|
||||
linenr = value.linenr,
|
||||
colnr = 0,
|
||||
}
|
||||
if not vim.tbl_islist(value.before) then
|
||||
value.before = { value.before }
|
||||
end
|
||||
for index, text in pairs(value.before) do
|
||||
local txt = string.gsub(tostring(text), '%|', '')
|
||||
table.insert(text_before, txt)
|
||||
if string.match(tostring(text), '%|') then
|
||||
if string.find(tostring(text), '%|') then
|
||||
pos_before.colnr = string.find(tostring(text), '%|')
|
||||
pos_before.linenr = value.linenr + index - 1
|
||||
end
|
||||
end
|
||||
end
|
||||
if not vim.tbl_islist(value.after) then
|
||||
value.after = { value.after }
|
||||
end
|
||||
vim.bo.filetype = value.filetype or 'text'
|
||||
vim.cmd(':bd!')
|
||||
if cb.before_each then
|
||||
cb.before_each(value)
|
||||
end
|
||||
---@diagnostic disable-next-line: missing-parameter
|
||||
if vim.fn.filereadable(vim.fn.expand(value.filepath)) == 1 then
|
||||
vim.cmd(':e ' .. value.filepath)
|
||||
if value.filetype then
|
||||
vim.bo.filetype = value.filetype
|
||||
end
|
||||
vim.cmd(':e')
|
||||
else
|
||||
vim.cmd(':new')
|
||||
if value.filetype then
|
||||
vim.bo.filetype = value.filetype
|
||||
end
|
||||
end
|
||||
local status, parser = pcall(vim.treesitter.get_parser, 0)
|
||||
if status then
|
||||
parser:parse(true)
|
||||
end
|
||||
vim.api.nvim_buf_set_lines(
|
||||
0,
|
||||
value.linenr - 1,
|
||||
value.linenr + #text_before,
|
||||
false,
|
||||
text_before
|
||||
)
|
||||
vim.api.nvim_win_set_cursor(
|
||||
0,
|
||||
{ pos_before.linenr, pos_before.colnr - 1 }
|
||||
)
|
||||
if type(value.key) == "function" then
|
||||
log.debug("call key")
|
||||
value.key()
|
||||
else
|
||||
log.debug('insert:' .. value.key)
|
||||
helpers.insert(value.key, value.not_replace_term_code)
|
||||
vim.wait(2)
|
||||
helpers.feed('<esc>')
|
||||
end
|
||||
compare_text(
|
||||
value.linenr,
|
||||
value.after,
|
||||
value.name,
|
||||
cb.cursor_add,
|
||||
value.end_cursor
|
||||
)
|
||||
if cb.after_each then
|
||||
cb.after_each(value)
|
||||
end
|
||||
vim.cmd(':bd!')
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
_G.dump_node = function(node)
|
||||
local text = ts_get_node_text(node)
|
||||
for _, txt in pairs(text) do
|
||||
print(txt)
|
||||
end
|
||||
end
|
||||
|
||||
_G.dump_node_text = function(target)
|
||||
for node in target:iter_children() do
|
||||
local node_type = node:type()
|
||||
local text = ts_get_node_text(node)
|
||||
log.debug('type:' .. node_type .. ' ')
|
||||
log.debug(text)
|
||||
end
|
||||
end
|
||||
@ -0,0 +1,131 @@
|
||||
local npairs = require('nvim-autopairs')
|
||||
local ts = require('nvim-treesitter.configs')
|
||||
local log = require('nvim-autopairs._log')
|
||||
local Rule = require('nvim-autopairs.rule')
|
||||
local ts_conds = require('nvim-autopairs.ts-conds')
|
||||
|
||||
_G.npairs = npairs
|
||||
vim.api.nvim_set_keymap(
|
||||
'i',
|
||||
'<CR>',
|
||||
'v:lua.npairs.check_break_line_char()',
|
||||
{ expr = true, noremap = true }
|
||||
)
|
||||
|
||||
ts.setup({
|
||||
ensure_installed = { 'lua', 'javascript', 'rust', 'markdown', 'markdown_inline' },
|
||||
highlight = { enable = true },
|
||||
autopairs = { enable = true },
|
||||
})
|
||||
|
||||
local data = {
|
||||
{
|
||||
name = 'treesitter lua quote',
|
||||
filepath = './tests/endwise/init.lua',
|
||||
filetype = 'lua',
|
||||
linenr = 5,
|
||||
key = [["]],
|
||||
before = {
|
||||
[[ [[ aaa| ]],
|
||||
[[ ]],
|
||||
']]',
|
||||
},
|
||||
after = [[ [[ aaa"| ]],
|
||||
},
|
||||
|
||||
{
|
||||
setup_func = function()
|
||||
npairs.add_rules({
|
||||
Rule('%', '%', 'lua'):with_pair(
|
||||
ts_conds.is_ts_node({ 'string', 'comment', 'string_content' })
|
||||
),
|
||||
})
|
||||
end,
|
||||
name = 'ts_conds is_ts_node quote',
|
||||
filepath = './tests/endwise/init.lua',
|
||||
filetype = 'lua',
|
||||
linenr = 5,
|
||||
key = [[%]],
|
||||
before = {
|
||||
[[ [[ abcde | ]],
|
||||
[[ ]],
|
||||
']]',
|
||||
},
|
||||
after = [[ [[ abcde %|% ]],
|
||||
},
|
||||
{
|
||||
name = 'ts_conds is_ts_node failed',
|
||||
filepath = './tests/endwise/init.lua',
|
||||
linenr = 5,
|
||||
filetype = 'lua',
|
||||
key = '%',
|
||||
before = { [[local abcd| = ' visual ']] },
|
||||
after = [[local abcd%| = ' visual ']],
|
||||
},
|
||||
{
|
||||
setup_func = function()
|
||||
npairs.add_rules({
|
||||
Rule('<', '>', 'rust'):with_pair(ts_conds.is_ts_node({
|
||||
'type_identifier',
|
||||
'let_declaration',
|
||||
'parameters',
|
||||
})),
|
||||
})
|
||||
end,
|
||||
name = 'ts_conds is_ts_node failed',
|
||||
filepath = './tests/endwise/main.rs',
|
||||
linenr = 5,
|
||||
filetype = 'rust',
|
||||
key = '<',
|
||||
before = [[pub fn noop(_inp: Vec|) {]],
|
||||
after = [[pub fn noop(_inp: Vec<|>) {]],
|
||||
},
|
||||
{
|
||||
setup_func = function()
|
||||
npairs.add_rules({
|
||||
Rule('*', '*', { 'markdown', 'markdown_inline' })
|
||||
:with_pair(ts_conds.is_not_in_context()),
|
||||
})
|
||||
end,
|
||||
name = 'ts_context markdown `*` success md_context',
|
||||
filepath = './tests/endwise/sample.md',
|
||||
linenr = 2,
|
||||
filetype = 'markdown',
|
||||
key = '*',
|
||||
before = [[|]],
|
||||
after = [[*|*]],
|
||||
},
|
||||
{
|
||||
setup_func = function()
|
||||
npairs.add_rules({
|
||||
Rule('*', '*', { 'markdown', 'markdown_inline' })
|
||||
:with_pair(ts_conds.is_not_in_context()),
|
||||
})
|
||||
end,
|
||||
name = 'ts_context codeblock `*` fail js_context',
|
||||
filepath = './tests/endwise/sample.md',
|
||||
linenr = 6,
|
||||
filetype = 'markdown',
|
||||
key = '*',
|
||||
before = [[let calc = 1 |]],
|
||||
after = [[let calc = 1 *|]],
|
||||
},
|
||||
}
|
||||
|
||||
local run_data = _G.Test_filter(data)
|
||||
|
||||
describe('[treesitter check]', function()
|
||||
_G.Test_withfile(run_data, {
|
||||
before_each = function(value)
|
||||
npairs.setup({
|
||||
check_ts = true,
|
||||
ts_config = {
|
||||
javascript = { 'template_string', 'comment' },
|
||||
},
|
||||
})
|
||||
if value.setup_func then
|
||||
value.setup_func()
|
||||
end
|
||||
end,
|
||||
})
|
||||
end)
|
||||
@ -0,0 +1,65 @@
|
||||
local utils = require('nvim-autopairs.utils')
|
||||
local log = require('nvim-autopairs._log')
|
||||
|
||||
local eq = assert.are.same
|
||||
|
||||
local data = {
|
||||
{
|
||||
text = "add normal bracket",
|
||||
start = 2,
|
||||
num = 2,
|
||||
result = 'dd'
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
text = "iood",
|
||||
start = 1,
|
||||
num = 2,
|
||||
result = 'io'
|
||||
},
|
||||
{
|
||||
text = "add normal bracket",
|
||||
start = 0,
|
||||
num = -2,
|
||||
result = ''
|
||||
},
|
||||
|
||||
{
|
||||
text = "add normal bracket",
|
||||
start = 3,
|
||||
num = -2,
|
||||
result = 'dd'
|
||||
},
|
||||
{
|
||||
text = [["""]],
|
||||
start = 3,
|
||||
num = -3,
|
||||
result = '"""'
|
||||
},
|
||||
|
||||
{
|
||||
text = [["""]],
|
||||
start = 3,
|
||||
num = 3,
|
||||
result = '"'
|
||||
},
|
||||
|
||||
{
|
||||
text = [["""]],
|
||||
start = 2,
|
||||
num = 2,
|
||||
result = '""'
|
||||
},
|
||||
}
|
||||
|
||||
describe('utils test substring ', function()
|
||||
for _, value in pairs(data) do
|
||||
it('test sub: ' .. value.text, function()
|
||||
local result = utils.text_sub_char(value.text, value.start, value.num)
|
||||
eq(value.result, result, 'start ' .. value.start .. ' num' .. value.num)
|
||||
end)
|
||||
end
|
||||
end)
|
||||
|
||||
vim.wait(100)
|
||||
Reference in New Issue
Block a user