├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ ├── lint.yml │ ├── neovim.yml │ ├── neovim_treesitter.yml │ └── vim.yml ├── .gitignore ├── .gitlab-ci.yml ├── .luacheckrc ├── .projections.json ├── .vintrc.yml ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── after ├── ftplugin │ ├── c_matchup.vim │ ├── cpp_matchup.vim │ ├── fortran_matchup.vim │ ├── html_matchup.vim │ ├── janet_matchup.vim │ ├── javascript_matchup.vim │ ├── javascriptreact_matchup.vim │ ├── lua_matchup.vim │ ├── ocaml_matchup.vim │ ├── ruby_matchup.vim │ ├── tex_matchup.vim │ ├── typescriptreact_matchup.vim │ ├── vim_matchup.vim │ ├── vue_matchup.vim │ └── xml_matchup.vim ├── plugin │ └── matchit.vim └── queries │ ├── astro │ └── matchup.scm │ ├── bash │ └── matchup.scm │ ├── c │ └── matchup.scm │ ├── cpp │ └── matchup.scm │ ├── dockerfile │ └── matchup.scm │ ├── ecma │ └── matchup.scm │ ├── elm │ └── matchup.scm │ ├── fish │ └── matchup.scm │ ├── glimmer │ └── matchup.scm │ ├── go │ └── matchup.scm │ ├── haskell │ └── matchup.scm │ ├── html │ └── matchup.scm │ ├── javascript │ └── matchup.scm │ ├── jsx │ └── matchup.scm │ ├── julia │ └── matchup.scm │ ├── lua │ └── matchup.scm │ ├── nim │ └── matchup.scm │ ├── nix │ └── matchup.scm │ ├── perl │ └── matchup.scm │ ├── python │ └── matchup.scm │ ├── quote │ └── matchup.scm │ ├── ruby │ └── matchup.scm │ ├── rust │ └── matchup.scm │ ├── smali │ └── matchup.scm │ ├── svelte │ └── matchup.scm │ ├── templ │ └── matchup.scm │ ├── tsx │ └── matchup.scm │ ├── typescript │ └── matchup.scm │ ├── vim │ └── matchup.scm │ ├── vue │ └── matchup.scm │ └── zig │ └── matchup.scm ├── autoload ├── matchup.vim └── matchup │ ├── custom.vim │ ├── delim.vim │ ├── loader.vim │ ├── matchparen.vim │ ├── misc.vim │ ├── motion.vim │ ├── perf.vim │ ├── pos.vim │ ├── quirks.vim │ ├── re.vim │ ├── surround.vim │ ├── test.vim │ ├── text_obj.vim │ ├── transmute.vim │ ├── ts_engine.vim │ ├── ts_syntax.vim │ ├── unmatchit.vim │ ├── util.vim │ └── where.vim ├── doc └── matchup.txt ├── lua ├── match-up.lua ├── treesitter-matchup.lua └── treesitter-matchup │ ├── compat.lua │ ├── internal.lua │ ├── syntax.lua │ ├── third-party │ ├── hl-info.lua │ ├── lru.LICENSE-MIT │ ├── lru.lua │ ├── nvim-treesitter.LICENSE-APACHE-2.0 │ ├── plenary.LICENSE-MIT │ ├── query.lua │ ├── reload.lua │ └── utils.lua │ └── util.lua ├── plugin └── matchup.vim └── test ├── issues ├── 3 │ ├── hotfix.vim │ └── test.sql ├── 7 │ ├── augroup.vim │ ├── hotfix.vim │ └── hotfix2.vim ├── 8 │ ├── flex.html │ ├── flex2.html │ ├── hotfix.vim │ └── slash.html ├── 10 │ ├── legacy.vim │ └── string.vim ├── 14 │ └── example.tex ├── 15 │ ├── enhance-vimrc │ ├── gc.vim │ └── issue-vimrc ├── 16 │ ├── any.vim │ └── blocks.vim ├── 19 │ ├── hotfix.vim │ ├── option.vim │ └── test.html ├── 21 │ └── Matchup_Problem_File.txt ├── 26 │ └── example.rb ├── 30 │ ├── complex-hl.html │ ├── example.html │ ├── example.vue │ └── minvimrc ├── 33 │ ├── minvimrc │ └── test.rb ├── 34 │ └── endvar.vim ├── 36 │ └── image_uploader.rb ├── 46 │ ├── Sample.jsx │ ├── minvimrc1 │ └── minvimrc2 ├── 48 │ ├── minvimrc │ ├── new.xml │ ├── simple.xml │ └── vim-matchup-20181230.xml ├── 49 │ ├── example.vim │ └── test.sh ├── 51 │ └── test.f90 ├── 54 │ └── foo.vim ├── 59 │ └── rebind.vim ├── 63 │ └── test.f90 ├── 64 │ └── ast.cc ├── 69 │ ├── cpptemplate.vim │ └── template.cpp ├── 84 │ └── ex.tex ├── 88 │ └── ex.cs ├── 98 │ └── test.html └── 107 │ └── bug.sv ├── lang ├── lua │ └── tohtml.lua └── ruby │ └── next.rb ├── legacy ├── addrtp.vim ├── augment.matchuptest ├── bootstrap.vim ├── forwhile.vim ├── hlend.matchuptest ├── mwe.vim ├── parens.txt ├── parts.vim ├── rtp │ ├── ftdetect │ │ └── matchuptest.vim │ └── ftplugin │ │ └── matchuptest.vim ├── startup.sh ├── tabs.vim ├── test.html ├── textobjV.vim ├── transmute.html ├── transmute2.html ├── unicode.matchuptest ├── vimrc-startup └── zsze.matchuptest ├── minvimrc ├── new ├── .coveragerc ├── .gitignore ├── Makefile ├── common │ └── bootstrap.vim ├── requirements.txt ├── test-core │ ├── Makefile │ ├── test.txt │ ├── test_perf.vim │ └── test_pos.vim ├── test-delim │ ├── Makefile │ ├── test.tex │ └── test.vim ├── test-loader │ ├── Makefile │ ├── example.ext │ └── test.vim ├── test-syn │ ├── Makefile │ ├── example.rb │ └── test.vim ├── test-treesitter │ ├── Makefile │ ├── example.py │ ├── example.rb │ └── test.vim ├── test-vader │ └── Makefile └── test-where │ ├── LICENSE │ ├── Makefile │ ├── normal.c │ ├── test.vim │ ├── test1.good │ ├── test2.good │ └── test3.good ├── scripts └── style-check.sh └── vader ├── issue-66.vader ├── minvimrc ├── motion.vader ├── motion_force.vader ├── ruby.vader ├── run ├── syn.vader ├── text_obj.vader └── ts_py_motion.vader /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | labels: bug 5 | --- 6 | 7 | ### Explain the issue 8 | 9 | Most issues are related to bugs or problems. In these cases, you should 10 | include a minimal working example and a minimal vimrc file (see below), as 11 | well as: 12 | 13 | 1. What vim version are you using? If using neovim, Are you using 14 | tree-sitter or classic matching? 15 | 2. Steps to reproduce 16 | 3. Expected behavior 17 | 4. Observed behavior 18 | 19 | If your issue is instead a feature request or anything else, please 20 | consider if minimal examples and vimrc files might still be relevant. 21 | 22 | 23 | ### Minimal working example 24 | 25 | Please provide a minimal working example, e.g., 26 | 27 | ```vim 28 | if l:x == 1 29 | call one() 30 | elseif l:x == 2 31 | call two() 32 | else 33 | call three() 34 | endif 35 | ``` 36 | 37 | ### Minimal vimrc file 38 | 39 | Please provide a minimal vimrc file that reproduces the issue. The 40 | following should often suffice: 41 | 42 | ```vim 43 | set nocompatible 44 | 45 | " load match-up 46 | let &rtp = '~/.vim/bundle/vim-matchup,' . &rtp 47 | let &rtp .= ',~/.vim/bundle/vim-matchup/after' 48 | 49 | " load other plugins, if necessary 50 | " let &rtp = '~/path/to/other/plugin,' . &rtp 51 | 52 | filetype plugin indent on 53 | syntax enable 54 | 55 | " match-up options go here 56 | ``` 57 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | labels: enhancement 5 | --- 6 | 7 | **Is your feature request related to a problem? Please describe.** 8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 9 | 10 | **Describe the solution you'd like** 11 | A clear and concise description of what you want to happen. 12 | 13 | **Describe alternatives you've considered** 14 | A clear and concise description of any alternative solutions or features you've considered. 15 | 16 | **Additional context** 17 | Add any other context or screenshots about the feature request here. 18 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: Linting and style checking 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | luacheck: 7 | name: Luacheck 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v1 11 | 12 | - name: Prepare 13 | run: | 14 | sudo apt-get update 15 | sudo add-apt-repository universe 16 | sudo apt install luarocks -y 17 | sudo luarocks install luacheck 18 | 19 | - name: Run Luacheck 20 | run: sudo ./test/scripts/style-check.sh 21 | 22 | vint: 23 | name: Vint 24 | runs-on: ubuntu-latest 25 | steps: 26 | - uses: actions/checkout@v3 27 | 28 | - name: Install python 29 | uses: actions/setup-python@v4 30 | 31 | - name: Install vint 32 | run: | 33 | python -m pip install --upgrade pip 34 | pip install vim-vint 35 | 36 | - name: Lint with vint 37 | run: | 38 | vint plugin autoload 39 | -------------------------------------------------------------------------------- /.github/workflows/neovim.yml: -------------------------------------------------------------------------------- 1 | name: Neovim 2 | 3 | on: 4 | push: 5 | branches: 6 | - '*' 7 | pull_request: 8 | branches: 9 | - master 10 | 11 | jobs: 12 | build: 13 | strategy: 14 | matrix: 15 | neovim_version: 16 | - 'head' 17 | - 'v0.10.1' 18 | runs-on: ubuntu-latest 19 | steps: 20 | - uses: 'actions/checkout@v2' 21 | 22 | - name: Install vader.vim 23 | run: git clone --depth=1 https://github.com/junegunn/vader.vim.git test/vader/vader.vim 24 | 25 | - name: 'setup Neovim' 26 | uses: 'thinca/action-setup-vim@v2' 27 | with: 28 | vim_version: '${{ matrix.neovim_version }}' 29 | vim_type: 'Neovim' 30 | 31 | - name: 'Show version' 32 | run: nvim --version 33 | 34 | - name: 'Run test' 35 | run: | 36 | bash -c 'VIMCMD=nvim test/vader/run' 37 | 38 | - name: 'Run new tests' 39 | run: | 40 | cd ./test/new && make -j1 && make -j1 coverage 41 | -------------------------------------------------------------------------------- /.github/workflows/neovim_treesitter.yml: -------------------------------------------------------------------------------- 1 | name: Neovim with Tree-sitter 2 | 3 | on: 4 | push: 5 | branches: 6 | - '*' 7 | pull_request: 8 | branches: 9 | - master 10 | 11 | jobs: 12 | build: 13 | strategy: 14 | matrix: 15 | neovim_version: 16 | - 'head' 17 | - 'v0.10.1' 18 | runs-on: ubuntu-latest 19 | env: 20 | TESTS_ENABLE_TREESITTER: 1 21 | steps: 22 | - uses: 'actions/checkout@v2' 23 | 24 | - name: Install vader.vim 25 | run: git clone --depth=1 https://github.com/junegunn/vader.vim.git test/vader/vader.vim 26 | 27 | - name: 'setup Neovim' 28 | uses: 'thinca/action-setup-vim@v2' 29 | with: 30 | vim_version: '${{ matrix.neovim_version }}' 31 | vim_type: 'Neovim' 32 | 33 | - name: Install nvim-treesitter 34 | run: git clone --depth=1 https://github.com/nvim-treesitter/nvim-treesitter.git test/vader/plugged/nvim-treesitter 35 | 36 | - name: Install python treesitter module 37 | run: nvim --headless -Nu test/vader/minvimrc -c 'TSInstallSync python' -c 'q' 38 | 39 | - name: 'Show version' 40 | run: nvim --version 41 | 42 | - name: 'Run test' 43 | run: | 44 | bash -c 'VIMCMD=nvim test/vader/run' 45 | 46 | - name: Install ruby treesitter module 47 | run: nvim --headless -Nu test/vader/minvimrc -c 'TSInstallSync ruby' -c 'q' 48 | 49 | - name: 'Run new tests' 50 | run: | 51 | cd ./test/new && make -j1 && make -j1 coverage 52 | -------------------------------------------------------------------------------- /.github/workflows/vim.yml: -------------------------------------------------------------------------------- 1 | name: Vim 2 | 3 | on: 4 | push: 5 | branches: 6 | - '*' 7 | pull_request: 8 | branches: 9 | - master 10 | 11 | jobs: 12 | build: 13 | strategy: 14 | matrix: 15 | vim_version: 16 | - nightly 17 | - 'v8.0.1575' 18 | - 'v7.4.2273' 19 | runs-on: ubuntu-latest 20 | steps: 21 | - uses: 'actions/checkout@v4' 22 | 23 | - name: Install vader.vim 24 | run: git clone --depth=1 https://github.com/junegunn/vader.vim.git test/vader/vader.vim 25 | 26 | - name: 'setup Vim' 27 | uses: 'rhysd/action-setup-vim@v1' 28 | with: 29 | version: '${{ matrix.vim_version }}' 30 | 31 | - name: 'Show version' 32 | run: vim --version 33 | 34 | - name: 'Run test' 35 | run: | 36 | bash ./test/vader/run 37 | 38 | - name: 'Run new tests' 39 | env: 40 | MYVIM: vim -T dumb --not-a-term -n 41 | run: | 42 | cd ./test/new && make -j1 && make -j1 coverage 43 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | doc/tags 2 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | --- 2 | stages: 3 | - test 4 | - gen_coverage 5 | - deploy 6 | 7 | .setup: 8 | before_script: 9 | - apk update 10 | - apk add curl git bash make 11 | - apk add build-base neovim python3 12 | - curl -sSL https://bootstrap.pypa.io/pip/3.6/get-pip.py | python3 13 | - git clone --depth=1 https://github.com/junegunn/vader.vim.git ./test/vader/vader.vim 14 | 15 | test-latest: 16 | stage: test 17 | extends: .setup 18 | image: 19 | name: thinca/vim:latest-full 20 | entrypoint: [""] 21 | variables: 22 | MYVIM: vim -T dumb --not-a-term -n 23 | script: cd ./test/new && make -j1 24 | artifacts: 25 | paths: 26 | - ./test/new/cov.tmp/ 27 | 28 | test-8.0.1575: 29 | stage: test 30 | extends: .setup 31 | image: 32 | name: thinca/vim:v8.0.1575-full 33 | entrypoint: [""] 34 | variables: 35 | MYVIM: vim -T dumb --not-a-term -n 36 | script: cd ./test/new && make -j1 37 | artifacts: 38 | paths: 39 | - ./test/new/cov.tmp/ 40 | 41 | test-7.4.2273: 42 | stage: test 43 | extends: .setup 44 | image: 45 | name: thinca/vim:v7.4.2273-full 46 | entrypoint: [""] 47 | variables: 48 | MYVIM: vim -T dumb --not-a-term -n 49 | script: cd ./test/new && make -j1 50 | artifacts: 51 | paths: 52 | - ./test/new/cov.tmp/ 53 | 54 | test-neovim: 55 | stage: test 56 | extends: .setup 57 | image: alpine:latest 58 | script: cd ./test/new && make -j1 59 | artifacts: 60 | paths: 61 | - ./test/new/cov.tmp/ 62 | 63 | test-neovim-treesitter: 64 | stage: test 65 | extends: .setup 66 | image: alpine:edge 67 | variables: 68 | TESTS_ENABLE_TREESITTER: 1 69 | script: 70 | - git clone --depth=1 https://github.com/nvim-treesitter/nvim-treesitter.git test/vader/plugged/nvim-treesitter 71 | - cd ./test/new 72 | - nvim --headless -Nu common/bootstrap.vim -c 'TSInstallSync! python' -c 'TSInstallSync! ruby' -c 'q' 73 | - make -j1 74 | artifacts: 75 | paths: 76 | - ./test/new/cov.tmp/ 77 | 78 | coverage: 79 | stage: gen_coverage 80 | extends: .setup 81 | image: alpine:latest 82 | script: cd ./test/new && make -j1 coverage 83 | artifacts: 84 | reports: 85 | coverage_report: 86 | coverage_format: cobertura 87 | path: ./test/new/coverage.xml 88 | paths: 89 | - ./test/new/htmlcov 90 | 91 | pages: 92 | stage: deploy 93 | image: ruby:2.3 94 | script: 95 | - mkdir public 96 | - mv ./test/new/htmlcov public/ 97 | artifacts: 98 | paths: 99 | - public 100 | expire_in: 30 days 101 | dependencies: 102 | - coverage 103 | only: 104 | - master 105 | - dev-test-ts-split 106 | -------------------------------------------------------------------------------- /.luacheckrc: -------------------------------------------------------------------------------- 1 | -- Rerun tests only if their modification time changed. 2 | cache = true 3 | 4 | -- Glorious list of warnings: https://luacheck.readthedocs.io/en/stable/warnings.html 5 | ignore = { 6 | "212", -- Unused argument, In the case of callback function, _arg_name is easier to understand than _, so this option is set to off. 7 | "411", -- Redefining a local variable. 8 | "412", -- Redefining an argument. 9 | "422", -- Shadowing an argument 10 | "122", -- Indirectly setting a readonly global 11 | "331" -- Value assigned to variable is mutated but never accessed 12 | } 13 | 14 | -- Global objects defined by the C code 15 | read_globals = { 16 | "vim", 17 | } 18 | -------------------------------------------------------------------------------- /.projections.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugin/*.vim": {"type": "plugin"}, 3 | "autoload/*.vim": {"type": "autoload"}, 4 | "after/*.vim": {"type": "after"}, 5 | "doc/*.txt": {"type": "doc"}, 6 | "README.md": {"type": "readme"}, 7 | "test/*": {"type": "test"} 8 | } 9 | -------------------------------------------------------------------------------- /.vintrc.yml: -------------------------------------------------------------------------------- 1 | policies: 2 | ProhibitNoAbortFunction: 3 | enabled: false 4 | 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Issue descriptions 2 | 3 | Please see the [issue template](.github/ISSUE_TEMPLATE/bug_report.md) 4 | for how to write a good 5 | issue description. In short, it should contain the following: 6 | 7 | 1. Describe the issue in detail, include steps to reproduce the issue 8 | 2. Include a minimal working example 9 | 3. Include a minimal vimrc file 10 | 11 | # Guide for code contributions 12 | 13 | ## Branch model 14 | 15 | match-up is developed mainly through the master branch, and pull requests should 16 | be [fork based](https://help.github.com/articles/using-pull-requests/). 17 | 18 | ## Documentation style 19 | 20 | Vim help files have their own specific syntax. There is a Vim help section on 21 | how to write them, see [`:h 22 | help-writing`](http://vimdoc.sourceforge.net/htmldoc/helphelp.html#help-writing). 23 | 24 | The match-up documentation style should be relatively clear, and it should be 25 | easy to see from the existing documentation how to write it. Still, here are 26 | some pointers: 27 | 28 | - Max 80 columns per line 29 | - Use the help tag system for pointers to other parts of the Vim documentation 30 | - Use line of `=`s to separate sections 31 | - Use line of `-`s to separate subsections 32 | - The section tags should be right aligned at the 79th column 33 | - Sections should be included and linked to from the table of contents 34 | 35 | ## Code style 36 | 37 | When submitting code for match-up, please adhere to the following standards: 38 | 39 | - Use `shiftwidth=2` - no tabs! 40 | - Write readable code 41 | - Break lines for readability 42 | - Line should not be longer than 74 columns 43 | - Use comments: 44 | - For complex code that is difficult to understand 45 | - Simple code does not need comments 46 | - Use (single) empty lines to separate logical blocks of code 47 | - Use good variable names 48 | - The name should indicate what the variable is/does 49 | - Variable names should be lower case 50 | - Local function variables should be preceded with `l:` 51 | - Prefer single quoted strings 52 | - See also the [Google vimscript style 53 | guide](https://google.github.io/styleguide/vimscriptguide.xml) 54 | - Use markers for folding 55 | - I generally only fold functions, and I tend to group similar functions so 56 | that when folded, I get a nice structural overview of a file 57 | - See some of the files for examples of how I do this 58 | 59 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT license 2 | 3 | Copyright (c) 2020 Andy Massimino 4 | 5 | Copyright (c) 2016 Karl Yngve Lervåg 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | this software and associated documentation files (the "Software"), to deal in 9 | the Software without restriction, including without limitation the rights to 10 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 11 | of the Software, and to permit persons to whom the Software is furnished to do 12 | so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | -------------------------------------------------------------------------------- /after/ftplugin/c_matchup.vim: -------------------------------------------------------------------------------- 1 | " vim match-up - even better matching 2 | " 3 | " Maintainer: Andy Massimino 4 | " Email: a@normed.space 5 | " 6 | 7 | if !exists('g:loaded_matchup') || !exists('b:did_ftplugin') 8 | finish 9 | endif 10 | 11 | if matchup#util#check_match_words('bb2bcbee') 12 | call matchup#util#append_match_words('/\*:\*/') 13 | endif 14 | 15 | " vim: fdm=marker sw=2 16 | 17 | -------------------------------------------------------------------------------- /after/ftplugin/cpp_matchup.vim: -------------------------------------------------------------------------------- 1 | " vim match-up - even better matching 2 | " 3 | " Maintainer: Andy Massimino 4 | " Email: a@normed.space 5 | " 6 | 7 | if !exists('g:loaded_matchup') || !exists('b:did_ftplugin') 8 | finish 9 | endif 10 | 11 | let s:save_cpo = &cpo 12 | set cpo&vim 13 | 14 | if matchup#util#matchpref('template', 0) 15 | call matchup#util#append_match_words( 16 | \ '\%(\s\@\|>\s\@!\)=\@!') 17 | if stridx(&matchpairs, '<:>') 18 | setlocal matchpairs-=<:> 19 | endif 20 | endif 21 | 22 | let &cpo = s:save_cpo 23 | 24 | " vim: fdm=marker sw=2 25 | 26 | -------------------------------------------------------------------------------- /after/ftplugin/fortran_matchup.vim: -------------------------------------------------------------------------------- 1 | " vim match-up - even better matching 2 | " 3 | " Maintainer: Andy Massimino 4 | " Email: a@normed.space 5 | " 6 | 7 | if !exists('g:loaded_matchup') || !exists('b:did_ftplugin') 8 | finish 9 | endif 10 | 11 | let s:save_cpo = &cpo 12 | set cpo&vim 13 | 14 | call matchup#util#patch_match_words('\\g{hlend}') 15 | call matchup#util#patch_match_words( 16 | \ '\' 21 | \ . ':^\s*#\s*elif\>:^\s*#\s*else\>' 22 | \ . ':^\s*#\s*endif\>') 23 | 24 | let &cpo = s:save_cpo 25 | 26 | " vim: fdm=marker sw=2 27 | 28 | -------------------------------------------------------------------------------- /after/ftplugin/html_matchup.vim: -------------------------------------------------------------------------------- 1 | " vim match-up - even better matching 2 | " 3 | " Maintainer: Andy Massimino 4 | " Email: a@normed.space 5 | " 6 | 7 | if !exists('g:loaded_matchup') || !exists('b:did_ftplugin') 8 | finish 9 | endif 10 | 11 | let s:save_cpo = &cpo 12 | set cpo&vim 13 | 14 | call matchup#util#patch_match_words( 15 | \ '[^ \t>]*\)[^>]*\%(>\|$\):<\@<=/\1>', 16 | \ '[^ \t>]*\)\%(>\|$\|[ \t][^>]*\%(>\|$\)\):<\@<=/\1>' 17 | \) 18 | 19 | if matchup#util#matchpref('nolists', 20 | \ get(g:, 'matchup_matchpref_html_nolists', 0)) 21 | call matchup#util#patch_match_words( 22 | \ '<\@<=[ou]l\>[^>]*\%(>\|$\):<\@<=li\>:<\@<=/[ou]l>', 23 | \ '') 24 | call matchup#util#patch_match_words( 25 | \ '<\@<=dl\>[^>]*\%(>\|$\):<\@<=d[td]\>:<\@<=/dl>', 26 | \ '') 27 | endif 28 | 29 | if matchup#util#matchpref('tagnameonly', 0) 30 | call matchup#util#patch_match_words( 31 | \ '\)\%(', 32 | \ '\)\g{hlend}\%(') 33 | call matchup#util#patch_match_words( 34 | \ ']l\>[', 35 | \ ']l\>\g{hlend}[') 36 | call matchup#util#patch_match_words( 37 | \ 'dl\>', 38 | \ 'dl\>\g{hlend}') 39 | call matchup#util#patch_match_words( 40 | \ '1>', 41 | \ '1\g{hlend}>') 42 | call matchup#util#patch_match_words( 43 | \ ']l>', 44 | \ ']l\g{hlend}>') 45 | call matchup#util#patch_match_words( 46 | \ 'dl>', 47 | \ 'dl\g{hlend}>') 48 | endif 49 | 50 | let &cpo = s:save_cpo 51 | 52 | " vim: fdm=marker sw=2 53 | 54 | -------------------------------------------------------------------------------- /after/ftplugin/janet_matchup.vim: -------------------------------------------------------------------------------- 1 | " vim match-up - even better matching 2 | " 3 | " Maintainer: Andy Massimino 4 | " Email: a@normed.space 5 | " 6 | 7 | if !exists('g:loaded_matchup') || !exists('b:did_ftplugin') 8 | finish 9 | endif 10 | 11 | let s:save_cpo = &cpo 12 | set cpo&vim 13 | 14 | call matchup#util#append_match_words('``:``\g{syn;!JanetString}') 15 | 16 | let &cpo = s:save_cpo 17 | 18 | " vim: fdm=marker sw=2 19 | -------------------------------------------------------------------------------- /after/ftplugin/javascript_matchup.vim: -------------------------------------------------------------------------------- 1 | " vim match-up - even better matching 2 | " 3 | " Maintainer: Andy Massimino 4 | " Email: a@normed.space 5 | " 6 | 7 | if !exists('g:loaded_matchup') || !exists('b:did_ftplugin') 8 | finish 9 | endif 10 | 11 | if matchup#util#check_match_words('802f71c1') 12 | call matchup#util#append_match_words('/\*:\*/') 13 | endif 14 | 15 | " vim: fdm=marker sw=2 16 | -------------------------------------------------------------------------------- /after/ftplugin/javascriptreact_matchup.vim: -------------------------------------------------------------------------------- 1 | " vim match-up - even better matching 2 | " 3 | " Maintainer: Andy Massimino 4 | " Email: a@normed.space 5 | " 6 | 7 | if !exists('g:loaded_matchup') || !exists('b:did_ftplugin') 8 | finish 9 | endif 10 | 11 | let s:save_cpo = &cpo 12 | set cpo&vim 13 | 14 | let b:match_skip = 's:\%(comment\|string\)\%(jsxCloseString\)\@', '1\g{hlend}>') 20 | call matchup#util#patch_match_words(':/>', ':/\g{hlend}>') 21 | endif 22 | 23 | let &cpo = s:save_cpo 24 | 25 | " vim: sw=2 26 | -------------------------------------------------------------------------------- /after/ftplugin/lua_matchup.vim: -------------------------------------------------------------------------------- 1 | " vim match-up - even better matching 2 | " 3 | " Maintainer: Andy Massimino 4 | " Email: a@normed.space 5 | " 6 | 7 | if !exists('g:loaded_matchup') || !exists('b:did_ftplugin') 8 | finish 9 | endif 10 | 11 | let s:save_cpo = &cpo 12 | set cpo&vim 13 | 14 | let b:match_midmap = [ 15 | \ ['luaFunction', 'return'], 16 | \] 17 | let b:undo_ftplugin .= '| unlet! b:match_midmap' 18 | 19 | call matchup#util#append_match_words('--\[\(=*\)\[:]\1]') 20 | 21 | let &cpo = s:save_cpo 22 | 23 | " vim: fdm=marker sw=2 24 | 25 | -------------------------------------------------------------------------------- /after/ftplugin/ocaml_matchup.vim: -------------------------------------------------------------------------------- 1 | " vim match-up - even better matching 2 | " 3 | " Maintainer: Andy Massimino 4 | " Email: a@normed.space 5 | " 6 | 7 | if !exists('g:loaded_matchup') || !exists('b:did_ftplugin') 8 | finish 9 | endif 10 | 11 | let b:matchup_matchparen_timeout=100 12 | let b:undo_ftplugin .= ' | unlet! b:matchup_matchparen_timeout' 13 | 14 | " vim: fdm=marker sw=2 15 | 16 | -------------------------------------------------------------------------------- /after/ftplugin/ruby_matchup.vim: -------------------------------------------------------------------------------- 1 | " vim match-up - even better matching 2 | " 3 | " Maintainer: Andy Massimino 4 | " Email: a@normed.space 5 | " 6 | 7 | if !exists('g:loaded_matchup') || !exists('b:did_ftplugin') 8 | finish 9 | endif 10 | 11 | let s:save_cpo = &cpo 12 | set cpo&vim 13 | 14 | call matchup#util#patch_match_words('retry', 'retry\|return') 15 | 16 | let b:match_midmap = [ 17 | \ ['rubyRepeat', 'next'], 18 | \ ['rubyDefine', 'return'], 19 | \] 20 | if exists('b:undo_ftplugin') 21 | let b:undo_ftplugin .= '|unlet! b:match_midmap' 22 | endif 23 | 24 | let &cpo = s:save_cpo 25 | 26 | " vim: fdm=marker sw=2 27 | -------------------------------------------------------------------------------- /after/ftplugin/tex_matchup.vim: -------------------------------------------------------------------------------- 1 | " vim match-up - even better matching 2 | " 3 | " Maintainer: Andy Massimino 4 | " Email: a@normed.space 5 | " 6 | 7 | if !exists('g:loaded_matchup') || !exists('b:did_ftplugin') 8 | finish 9 | endif 10 | 11 | let s:save_cpo = &cpo 12 | set cpo&vim 13 | 14 | function! s:has_plugin(plug) 15 | return !empty(filter(split(&rtp,','), 'v:val =~? ''\<'.a:plug.'\>''')) 16 | endfunction 17 | 18 | let s:not_bslash = '\v%(\\@\|\\[|{}]\|.\)' 23 | let l:match_words = '\\left\>'.l:delim 24 | \ .':\\middle\>'.l:delim 25 | \ .':\\right\>'.l:delim 26 | let l:match_words .= ',\(\\[bB]igg\?\)l\>'.l:delim 27 | \ . ':\1m\>'.l:delim 28 | \ . ':\1r\>'.l:delim 29 | 30 | " un-sided sized, left and right delimiters 31 | let l:mod = '\(\\[bB]igg\?\)' 32 | let l:wdelim = '\%(angle\|floor\|ceil\|[vV]ert\|brace\)\>' 33 | let l:ldelim = '\%(\\l'.l:wdelim.'\|\\[lu]lcorner\>\|(\|\[\|\\{\)' 34 | let l:mdelim = '\%(\\vert\>\||\|\\|\)' 35 | let l:rdelim = '\%(\\r'.l:wdelim.'\|\\[lu]rcorner\>\|)\|]\|\\}\)' 36 | let l:mtopt = '\%(\%(\w\[\)\@2' 50 | 51 | " the curly braces 52 | let l:match_words .= ',{:}' 53 | 54 | " latex equation markers 55 | let l:match_words .= ',\\(:\\),'.s:not_bslash.'\\\[:\\]' 56 | 57 | " latex3 file i/o 58 | let l:match_words .= ',\\ior_open\:NnT\?F\?\s*\\\([^\s]*\):\\ior_close\:N\s*\\\1' 59 | let l:match_words .= ',\\ior_open\:cnT\?F\?\s*{\s*\([^\s\\}]*\)\s*}:\\ior_close\:c\s*{\s*\1\s*}' 60 | let l:match_words .= ',\\iow_open\:Nn\s*\\\([^\s]*\):\\iow_close\:N\s*\\\1' 61 | let l:match_words .= ',\\iow_open\:cn\s*{\s*\([^\s\\}]*\)\s*}:\\iow_close\:c\s*{\s*\1\s*}' 62 | 63 | " simple blocks 64 | let l:match_words .= ',\\if\%(\:w\|\%(\w\|@\)*\)\>:\\else\:\?\>:\\fi\:\?\>' 65 | let l:match_words .= ',\\if_\%(true\|false\)\::\\else\::\\fi\:' 66 | let l:match_words .= ',\\if_mode_\%(horizontal\|vertical\|math\|inner\)\::\\else\::\\fi\:' 67 | let l:match_words .= ',\\if_\%(charcode\|catcode\|dim\)\:w:\\else\::\\fi\:' 68 | let l:match_words .= ',\\if_cs_exist\:w:\\cs_end\::\\else\::\\fi\:' 69 | let l:match_words .= ',\\if_cs_exist\:N:\\else\::\\fi\:' 70 | let l:match_words .= ',\\if_[hv]box\:N:\\else\::\\fi\:' 71 | let l:match_words .= ',\\if_box_empty\:N:\\else\::\\fi\:' 72 | let l:match_words .= ',\\cs\:w:\\cs_end\:' 73 | let l:match_words .= ',\\makeatletter:\\makeatother' 74 | let l:match_words .= ',\\ExplSyntaxOn:\\ExplSyntaxOff' 75 | let l:match_words .= ',\\debug_suspend\::\\debug_resume\:' 76 | let l:match_words .= ',\\begingroup:\\endgroup,\\bgroup:\\egroup' 77 | let l:match_words .= ',\\group_begin\::\\group_end\:' 78 | let l:match_words .= ',\\group_align_safe_begin\::\\group_align_safe_end\:' 79 | let l:match_words .= ',\\color_group_begin\::\\color_group_end\:' 80 | let l:match_words .= ',\\cctab_begin\:[Nc]:\\cctab_end\:' 81 | let l:match_words .= ',\\exp\:w:\\exp_end\(_continue_f\:n\?w\|\:\)' 82 | 83 | " environments 84 | let l:match_words .= ',\\begin{tabular}' 85 | \ . ':\\toprule\>:\\midrule\>:\\bottomrule\>' 86 | \ . ':\\end{tabular}' 87 | 88 | " enumerate, itemize 89 | let l:match_words .= ',\\begin\s*{\(enumerate\*\=\|itemize\*\=\)}' 90 | \ . ':\\item\>:\\end\s*{\1}' 91 | 92 | " generic environment 93 | if matchup#util#matchpref('relax_env', 0) 94 | let l:match_words .= ',\\begin\s*{\([^}]*\)}:\\end\s*{\([^}]*\)}' 95 | else 96 | let l:match_words .= ',\\begin\s*{\([^}]*\)}:\\end\s*{\1}' 97 | endif 98 | 99 | " dollar sign math 100 | if exists('b:vimtex') 101 | let l:match_words .= ',\$:\$\g{syn;!texMathZoneTI}' 102 | else 103 | let l:match_words .= ',\$:\$\g{syn;!texMathZoneX}' 104 | endif 105 | 106 | return l:match_words 107 | endfunction 108 | 109 | function! s:setup_match_words() 110 | setlocal matchpairs=(:),{:},[:] 111 | let b:matchup_delim_nomatchpairs = 1 112 | let b:match_words = s:get_match_words() 113 | 114 | " the syntax method is too slow for latex 115 | let b:match_skip = 'r:\\\@ % 130 | silent! xunmap % 131 | silent! ounmap % 132 | 133 | " lervag/vimtex/issues/1051 134 | let g:vimtex_matchparen_enabled = 0 135 | silent! call vimtex#matchparen#disable() 136 | 137 | call s:setup_match_words() 138 | else 139 | let b:matchup_matchparen_enabled = 0 140 | let b:matchup_matchparen_fallback = 0 141 | endif 142 | else 143 | call s:setup_match_words() 144 | endif 145 | 146 | let &cpo = s:save_cpo 147 | 148 | " vim: fdm=marker sw=2 149 | 150 | -------------------------------------------------------------------------------- /after/ftplugin/typescriptreact_matchup.vim: -------------------------------------------------------------------------------- 1 | " vim match-up - even better matching 2 | " 3 | " Maintainer: Andy Massimino 4 | " Email: a@normed.space 5 | " 6 | 7 | if !exists('g:loaded_matchup') || !exists('b:did_ftplugin') 8 | finish 9 | endif 10 | 11 | let s:save_cpo = &cpo 12 | set cpo&vim 13 | 14 | let b:match_skip = 's:\%(comment\|string\)\%(tsxCloseString\)\@', '1\g{hlend}>') 20 | call matchup#util#patch_match_words(':/>', ':/\g{hlend}>') 21 | endif 22 | 23 | let &cpo = s:save_cpo 24 | 25 | " vim: sw=2 26 | -------------------------------------------------------------------------------- /after/ftplugin/vim_matchup.vim: -------------------------------------------------------------------------------- 1 | " vim match-up - even better matching 2 | " 3 | " Maintainer: Andy Massimino 4 | " Email: a@normed.space 5 | " 6 | 7 | if !exists('g:loaded_matchup') || !exists('b:did_ftplugin') 8 | finish 9 | endif 10 | 11 | let s:save_cpo = &cpo 12 | set cpo&vim 13 | 14 | let b:match_skip = 's:comment\|string\|vimSynReg' 15 | \ . '\|vimSet\|vimFuncName\|vimNotPatSep' 16 | \ . '\|vimVar\|vimFuncVar\|vimFBVar\|vimOperParen' 17 | \ . '\|vimUserFunc' 18 | 19 | call matchup#util#patch_match_words( 20 | \ '\\)\@!\S:', 21 | \ '\\)\@!\S:' 22 | \) 23 | 24 | call matchup#util#patch_match_words( 25 | \ '\|def\)!\=\s\+', 26 | \ '\|\%(export\s\+\)\@', '1\g{hlend}>') 18 | call matchup#util#patch_match_words(':/>', ':/\g{hlend}>') 19 | endif 20 | 21 | call matchup#util#patch_match_words('[^/>]*', '[^>]*[^/>]') 22 | 23 | let &cpo = s:save_cpo 24 | 25 | " vim: fdm=marker sw=2 26 | -------------------------------------------------------------------------------- /after/plugin/matchit.vim: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymass/vim-matchup/56c714495ec7f40cf2c7e92fb124067c7951e650/after/plugin/matchit.vim -------------------------------------------------------------------------------- /after/queries/astro/matchup.scm: -------------------------------------------------------------------------------- 1 | ; inherits: html 2 | -------------------------------------------------------------------------------- /after/queries/bash/matchup.scm: -------------------------------------------------------------------------------- 1 | (if_statement 2 | "if" @open.if 3 | "fi" @close.if) @scope.if 4 | 5 | (else_clause 6 | "else" @mid.if.1) 7 | 8 | (elif_clause 9 | "elif" @mid.if.2) 10 | 11 | (while_statement 12 | ("while")? @open.loop 13 | ("until")? @open.loop 14 | (do_group 15 | "done" @close.loop)) @scope.loop 16 | 17 | (for_statement 18 | ("for")? @open.loop 19 | ("select")? @open.loop 20 | (do_group 21 | "done" @close.loop)) @scope.loop 22 | 23 | ((word) @mid.loop.1 (#eq? @mid.loop.1 "break")) 24 | ((word) @mid.loop.2 (#eq? @mid.loop.2 "continue")) 25 | 26 | (case_statement 27 | "case" @open.case 28 | (case_item) @mid.case.1 29 | "esac" @close.case) @scope.case 30 | 31 | (heredoc_redirect 32 | (heredoc_start) @open.rhrd 33 | (heredoc_end ) @close.rhrd) @scope.rhrd 34 | -------------------------------------------------------------------------------- /after/queries/c/matchup.scm: -------------------------------------------------------------------------------- 1 | ; inherits: quote 2 | 3 | (preproc_ifdef 4 | ["#ifdef" "#ifndef"] @open.def 5 | "#endif" @close.def) @scope.def 6 | 7 | (preproc_if 8 | "#if" @open.def 9 | "#endif" @close.def) @scope.def 10 | 11 | (preproc_elif "#elif" @mid.def.1) 12 | (preproc_else "#else" @mid.def.2) 13 | 14 | (switch_statement 15 | "switch" @open.switch 16 | body: (compound_statement 17 | (case_statement "case" @mid.switch.1)? 18 | (case_statement "default" @mid.switch.2)?)) @scope.switch 19 | 20 | ; 'else' and 'else if' 21 | (else_clause 22 | "else" @_start (if_statement "if" @_end)? 23 | (#make-range! "mid.if.1" @_start @_end)) 24 | 25 | ; if 26 | ((if_statement 27 | "if" @open.if) @scope.if 28 | (#not-has-parent? @scope.if else_clause)) 29 | 30 | 31 | ; if 32 | (compound_statement 33 | (if_statement 34 | "if" @open.if) @scope.if) 35 | 36 | ; Functions 37 | (function_definition) @scope.function 38 | (function_declarator declarator: (identifier) @open.function) 39 | (return_statement "return" @mid.function.1) 40 | 41 | ; Loops 42 | (for_statement "for" @open.loop) @scope.loop 43 | (while_statement "while" @open.loop) @scope.loop 44 | (do_statement "do" @open.loop "while" @close.loop) @scope.loop 45 | (break_statement "break" @mid.loop.1) 46 | -------------------------------------------------------------------------------- /after/queries/cpp/matchup.scm: -------------------------------------------------------------------------------- 1 | ; inherits: c 2 | 3 | (template_parameter_list 4 | "<" @open.template 5 | ">" @close.template) @scope.template 6 | 7 | (template_argument_list 8 | "<" @open.template_arg 9 | ">" @close.template_arg) @scope.template_arg 10 | -------------------------------------------------------------------------------- /after/queries/dockerfile/matchup.scm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymass/vim-matchup/56c714495ec7f40cf2c7e92fb124067c7951e650/after/queries/dockerfile/matchup.scm -------------------------------------------------------------------------------- /after/queries/ecma/matchup.scm: -------------------------------------------------------------------------------- 1 | ; inherits: quote 2 | 3 | ; functions 4 | [ 5 | (arrow_function "=>" @open.function) 6 | (function_expression "function" @open.function) 7 | (function_declaration "function" @open.function) 8 | (method_definition body: (statement_block "{" @open.function "}" @close.function)) 9 | ] @scope.function 10 | 11 | (return_statement "return" @mid.function.1) 12 | 13 | ; switch case 14 | (switch_statement "switch" @open.switch) @scope.switch 15 | (switch_case "case" @mid.switch.1) 16 | (switch_default "default" @mid.switch.2) 17 | 18 | ; 'else' and 'else if' 19 | (else_clause 20 | "else" @_start (if_statement "if" @_end)? 21 | (#make-range! "mid.if.1" @_start @_end)) 22 | 23 | ; if 24 | ((if_statement 25 | "if" @open.if) @scope.if 26 | (#not-has-parent? @scope.if else_clause)) 27 | 28 | ; try 29 | (try_statement "try" @open.try) @scope.try 30 | (catch_clause "catch" @mid.try.1) 31 | (finally_clause "finally" @mid.try.2) 32 | 33 | ; template strings 34 | (template_string 35 | "`" @open.tmpl_str 36 | "`" @close.tmpl_str) @scope.tmpl_str 37 | -------------------------------------------------------------------------------- /after/queries/elm/matchup.scm: -------------------------------------------------------------------------------- 1 | (if_else_expr 2 | . "if" @open.if) @scope.if 3 | 4 | (if_else_expr 5 | "else" @_else 6 | "if"? @_if 7 | (#make-range! "mid.if.1" @_else @_if)) 8 | 9 | (let_in_expr 10 | "let" @open.let 11 | "in" @mid.let.1) @scope.let 12 | 13 | (case_of_expr 14 | (case) @open.case 15 | (case_of_branch 16 | (arrow) @mid.case.1)) @scope.case 17 | -------------------------------------------------------------------------------- /after/queries/fish/matchup.scm: -------------------------------------------------------------------------------- 1 | (if_statement 2 | "if" @open.if 3 | (else_if_clause ("else" "if") @mid.if.1)? 4 | (else_clause "else" @mid.if.2)? 5 | "end" @close.if 6 | ) @scope.if 7 | 8 | (switch_statement 9 | "switch" @open.switch 10 | (case_clause "case" @mid.switch.1)? 11 | "end" @close.switch 12 | ) @scope.switch 13 | 14 | (for_statement 15 | "for" @open.loop 16 | "in" @mid.loop.1 17 | "end" @close.loop) @scope.loop 18 | ((break) @mid.loop.2)? 19 | ((continue) @mid.loop.3)? 20 | 21 | (while_statement 22 | "while" @open.loop 23 | "end" @close.loop) @scope.loop 24 | 25 | (begin_statement 26 | "begin" @open.block 27 | "end" @close.block) @scope.block 28 | 29 | (function_definition 30 | "function" @open.func 31 | "end" @close.func) @scope.func 32 | (return "return" @mid.func.1) 33 | -------------------------------------------------------------------------------- /after/queries/glimmer/matchup.scm: -------------------------------------------------------------------------------- 1 | ; inherits: quote 2 | 3 | (element_node) @scope.tag 4 | 5 | (element_node_start (tag_name) @open.tag) 6 | (element_node_end 7 | (tag_name) @close.tag 8 | (#offset! @close.tag 0 -1 0 0)) 9 | 10 | (block_statement 11 | (block_statement_start) @open.block 12 | (block_statement_end) @close.block 13 | ) @scope.block 14 | ; {{else if ...}} 15 | (mustache_statement 16 | (helper_invocation helper: (identifier) @mid.block.1 (#lua-match? @mid.block.1 "else")) 17 | ) 18 | ; {{else}} 19 | (mustache_statement ((identifier) @mid.block.2 (#lua-match? @mid.block.2 "else"))) 20 | 21 | (element_node_void 22 | (tag_name) @open.selftag 23 | "/>" @close.selftag 24 | ) @scope.selftag 25 | 26 | (mustache_statement 27 | [(helper_invocation) "{{"] @open.mustache 28 | "}}" @close.mustache 29 | ) @scope.mustache 30 | 31 | (sub_expression 32 | [(helper_invocation) "("] @open.subexpr 33 | ")" @close.subexpr 34 | ) @scope.subexpr 35 | -------------------------------------------------------------------------------- /after/queries/go/matchup.scm: -------------------------------------------------------------------------------- 1 | (function_declaration "func" @open.func) @scope.func 2 | (method_declaration "func" @open.func) @scope.func 3 | (func_literal "func" @open.func) @scope.func 4 | 5 | (return_statement "return" @mid.func.1) 6 | 7 | ; 'else' and 'else if' 8 | (if_statement 9 | "else" @_start (if_statement "if" @_end)? 10 | (#make-range! "mid.if.1" @_start @_end)) 11 | 12 | ; if 13 | (block (if_statement "if" @open.if) @scope.if) 14 | 15 | ; switch 16 | (expression_switch_statement "switch" @open.switch 17 | (expression_case "case" @mid.switch.1) 18 | (default_case "default" @mid.switch.2)) @scope.switch 19 | 20 | (_ 21 | "\"" @open.quote_double 22 | "\"" @close.quote_double) @scope.quote_double 23 | -------------------------------------------------------------------------------- /after/queries/haskell/matchup.scm: -------------------------------------------------------------------------------- 1 | ; --------------- module/where --------------- 2 | (header ( 3 | ("module" @open.module (module)) 4 | ("where" @mid.module.1) 5 | )) @scope.module 6 | 7 | ; ----------------- case/of ------------------ 8 | (expression/case 9 | "case" @open.case (_) 10 | "of" @mid.case.1 11 | (alternatives 12 | (alternative) @mid.case.2 13 | ) 14 | ) @scope.case 15 | 16 | ; --------------- lambda case ---------------- 17 | (expression/lambda_case 18 | "\case" @open.case 19 | (alternatives 20 | (alternative) @mid.case.1 21 | ) 22 | ) @scope.case 23 | 24 | ; -------------- if/then/else ---------------- 25 | (expression/conditional 26 | "if" @open.if (_) 27 | "then" @mid.if.1 (_) 28 | "else" @mid.if.2 (_) 29 | ) @scope.if 30 | 31 | ;------------------ let/in ------------------- 32 | (expression/let_in 33 | ("let" @open.let (local_binds)) 34 | ("in" @mid.let.1 (_)) 35 | ) @scope.let 36 | 37 | ; -------- ADT data/constructors ------------- 38 | (data_type 39 | "data" @open.adt (_) 40 | constructors: (data_constructors 41 | (data_constructor 42 | constructor: (_) @mid.adt.2 43 | )) 44 | ) @scope.adt 45 | 46 | ; --------------- ADT record ------------------ 47 | (data_type 48 | "data" @open.rec (_) 49 | constructors: (data_constructors 50 | constructor: (data_constructor 51 | (record 52 | fields: (fields 53 | "{" @mid.rec.1 (_) 54 | "}" @mid.rec.2 55 | ) 56 | ) 57 | ) 58 | ) 59 | ) @scope.rec 60 | 61 | ; ------------- GADT data/where --------------- 62 | (data_type 63 | "data" @open.gadt (_) 64 | "where" @mid.gadt.1 65 | constructors: (gadt_constructors 66 | constructor: (gadt_constructor 67 | name: (constructor) @mid.gadt.2 68 | ) 69 | ) 70 | ) @scope.gadt 71 | 72 | ; --------------- class/where ----------------- 73 | (class 74 | "class" @open.class 75 | "where" @mid.class.1 76 | declarations: (class_declarations 77 | declaration: (_ 78 | name: (variable) @mid.class.2 79 | ) 80 | ) 81 | ) @scope.class 82 | -------------------------------------------------------------------------------- /after/queries/html/matchup.scm: -------------------------------------------------------------------------------- 1 | ; inherits: quote 2 | 3 | [ 4 | (element) 5 | (script_element) 6 | (style_element) 7 | ] @scope.tag 8 | 9 | (start_tag (tag_name) @open.tag) 10 | (end_tag 11 | (tag_name) @close.tag 12 | (#offset! @close.tag 0 -1 0 0)) 13 | 14 | (self_closing_tag 15 | (tag_name) @open.selftag 16 | "/>" @close.selftag) @scope.selftag 17 | -------------------------------------------------------------------------------- /after/queries/javascript/matchup.scm: -------------------------------------------------------------------------------- 1 | ; inherits: ecma,jsx 2 | -------------------------------------------------------------------------------- /after/queries/jsx/matchup.scm: -------------------------------------------------------------------------------- 1 | (jsx_element) @scope.tag 2 | (jsx_opening_element (identifier) @open.tag) 3 | (jsx_closing_element 4 | (identifier) @close.tag 5 | (#offset! @close.tag 0 -1 0 0)) 6 | 7 | (jsx_self_closing_element 8 | name: (identifier) @open.selftag 9 | "/>" @close.selftag) @scope.selftag 10 | -------------------------------------------------------------------------------- /after/queries/julia/matchup.scm: -------------------------------------------------------------------------------- 1 | (function_definition 2 | "function" @open.function 3 | "end" @close.function) @scope.function 4 | (return_statement 5 | "return" @mid.function.1) 6 | 7 | (if_statement 8 | "if" @open.if 9 | "end" @close.if) @scope.if 10 | (else_clause "else" @mid.if.1) 11 | (elseif_clause "elseif" @mid.if.2) 12 | 13 | (for_statement 14 | "for" @open.loop 15 | "end" @close.loop) @scope.loop 16 | (while_statement 17 | "while" @open.loop 18 | "end" @close.loop) @scope.loop 19 | (break_statement) @mid.loop.1 20 | (continue_statement) @mid.loop.2 21 | 22 | (try_statement 23 | "try" @open.try 24 | "end" @close.try) @scope.try 25 | (catch_clause 26 | "catch" @mid.try.2) 27 | (finally_clause 28 | "finally" @mid.try.1) 29 | 30 | (compound_statement 31 | "begin" @open.block 32 | "end" @close.block) @scope.block 33 | (do_clause 34 | "do" @open.block 35 | "end" @close.block) @scope.block 36 | 37 | (let_statement 38 | "let" @open.let 39 | "end" @close.let) @scope.let 40 | (module_definition 41 | "module" @open.module 42 | "end" @close.module) @scope.module 43 | -------------------------------------------------------------------------------- /after/queries/lua/matchup.scm: -------------------------------------------------------------------------------- 1 | ; inherits: quote 2 | 3 | (for_statement 4 | "do" @open.loop 5 | "end" @close.loop) @scope.loop 6 | 7 | (while_statement 8 | "do" @open.loop 9 | "end" @close.loop) @scope.loop 10 | 11 | (break_statement) @mid.loop.1 12 | 13 | (if_statement 14 | "if" @open.if 15 | "end" @close.if) @scope.if 16 | (else_statement "else" @mid.if.1) 17 | (elseif_statement "elseif" @mid.if.2) 18 | 19 | (function_declaration 20 | "function" @open.function 21 | "end" @close.function) @scope.function 22 | (function_definition 23 | "function" @open.function 24 | "end" @close.function) @scope.function 25 | 26 | (return_statement 27 | "return" @mid.function.1) 28 | 29 | (do_statement 30 | "do" @open.block 31 | "end" @close.block) @scope.block 32 | -------------------------------------------------------------------------------- /after/queries/nim/matchup.scm: -------------------------------------------------------------------------------- 1 | (for "for" @open.loop "in" @mid.loop.3) @scope.loop 2 | (while "while" @open.loop) @scope.loop 3 | (block "block" @open.loop) @scope.loop 4 | (break_statement "break" @mid.loop.1) 5 | (continue_statement "continue" @mid.loop.2) 6 | 7 | (if "if" @open.conditional) @scope.conditional 8 | (when "when" @open.conditional) @scope.conditional 9 | (elif_branch "elif" @mid.conditional.1) 10 | (else_branch "else" @mid.conditional.2) 11 | 12 | (case "case" @open.conditional) @scope.conditional 13 | (of_branch "of" @mid.conditional.3) 14 | 15 | (variant_declaration "case" @open.conditional) @scope.conditional 16 | (conditional_declaration "when" @open.conditional) @scope.conditional 17 | 18 | (try "try" @open.try) @scope.try 19 | (except_branch "except" @mid.try.1 ) 20 | (finally_branch "finally" @mid.try.2) 21 | 22 | (proc_declaration "proc" @open.routine) @scope.routine 23 | (func_declaration "func" @open.routine) @scope.routine 24 | (method_declaration "method" @open.routine) @scope.routine 25 | (converter_declaration "converter" @open.routine) @scope.routine 26 | (template_declaration "template" @open.routine) @scope.routine 27 | (macro_declaration "macro" @open.routine) @scope.routine 28 | 29 | (proc_expression "proc" @open.routine) @scope.routine 30 | (func_expression "func" @open.routine) @scope.routine 31 | 32 | (return_statement "return" @mid.routine.1) 33 | 34 | (iterator_declaration "iterator" @open.iterator) @scope.iterator 35 | (iterator_expression "iterator" @open.iterator) @scope.iterator 36 | 37 | (yield_statement "yield" @mid.iterator.1) 38 | 39 | (import_statement 40 | "import" @open.import 41 | (except_clause 42 | "except" @mid.import.1)) @scope.import 43 | 44 | (import_from_statement 45 | "from" @open.from 46 | "import" @mid.from.1) @scope.from 47 | 48 | (char_literal 49 | . "'" @open.char 50 | "'" @close.char .) @scope.char 51 | 52 | (interpreted_string_literal 53 | . "\"" @open.string 54 | "\"" @close.string .) @scope.string 55 | 56 | (raw_string_literal 57 | . ["r\"" "R\""] @open.string 58 | "\"" @close.string .) @scope.string 59 | 60 | (long_string_literal 61 | . ["\"\"\"" "r\"\"\"" "R\"\"\""] @open.multistring 62 | "\"\"\"" @close.multistring .) @scope.multistring 63 | 64 | (generalized_string 65 | function: (_) 66 | . ["\"" "\"\"\""] @open.multistring 67 | ["\"" "\"\"\""] @close.multistring .) @scope.multistring 68 | 69 | (accent_quoted 70 | . "`" @open.accent 71 | "`" @close.accent .) @scope.accent 72 | 73 | (block_documentation_comment 74 | . "##[" @open.doc_comment 75 | "]##" @close.doc_comment .) @scope.doc_comment 76 | 77 | (block_comment 78 | . "#[" @open.comment 79 | "]#" @close.comment .) @scope.comment 80 | 81 | (pragma_list 82 | . "{." @open.pragma 83 | ["}" ".}"] @close.pragma .) @scope.pragma 84 | -------------------------------------------------------------------------------- /after/queries/nix/matchup.scm: -------------------------------------------------------------------------------- 1 | ; --------------- let/in --------------- 2 | (let_expression 3 | "let" @open.let (binding_set) 4 | "in" @mid.let.1 (_)) @scope.let 5 | ; --------------- binding -------------- 6 | ; (binding (_)+ (function_exppression) ";") tend to be many lines long 7 | (binding 8 | (attrpath) @open.binding (function_expression) 9 | ";" @close.binding) @scope.binding 10 | -------------------------------------------------------------------------------- /after/queries/perl/matchup.scm: -------------------------------------------------------------------------------- 1 | ; matches any conditional -> else type block -> end of final block 2 | (conditional_statement 3 | ["if" "unless"] @open.if 4 | "elsif"? @mid.if.1 5 | "else"? @mid.if.2 6 | (block "}" @close.if) . 7 | ) @scope.if 8 | 9 | ; matches any loop construct -> loop control (last, next) -> end of final block 10 | (_ 11 | ["for" "foreach" "while" "unless"] @open.loop 12 | (block "}" @close.loop) . 13 | ) @scope.loop 14 | (loopex_expression) @mid.loop.1 15 | 16 | ; matches sub -> return -> end of block 17 | (_ 18 | "sub" @open.fun 19 | (block "}" @close.fun) . 20 | ) @scope.fun 21 | (return_expression "return" @mid.fun.1) 22 | 23 | ; handling for all the different quote types; multi part quotes cycle through 24 | [ 25 | (_ "'" @open.quotelike (string_content) "'" @close.quotelike) 26 | (quoted_regexp "'" @open.quotelike "'" @close.quotelike) 27 | (_ "'" @open.quotelike (_) "'"+ @mid.quotelike.1 (replacement) "'" @close.quotelike) 28 | ] @scope.quotelike 29 | 30 | (try_statement 31 | "try" @open.try 32 | "catch"? @mid.try.1 33 | "finally"? @close.try 34 | ) @scope.try 35 | -------------------------------------------------------------------------------- /after/queries/python/matchup.scm: -------------------------------------------------------------------------------- 1 | (if_statement 2 | "if" @open.if 3 | alternative: (elif_clause "elif" @mid.if.1)? 4 | alternative: (else_clause "else" @mid.if.2)?) @scope.if 5 | 6 | (function_definition 7 | "def" @open.function) @scope.function 8 | (return_statement 9 | "return" @mid.function.1) 10 | (yield 11 | "yield" @mid.function.2) 12 | 13 | (for_statement 14 | ("for" @open.loop) 15 | alternative: (else_clause "else" @mid.loop.1)?) @scope.loop 16 | (while_statement 17 | ("while" @open.loop) 18 | alternative: (else_clause "else" @mid.loop.1)?) @scope.loop 19 | (break_statement 20 | "break" @mid.loop.2) 21 | (continue_statement 22 | "continue" @mid.loop.3) 23 | 24 | (try_statement 25 | ("try" @open.try) 26 | (finally_clause "finally" @mid.try.1)? 27 | (except_clause "except" @mid.try.2)? 28 | (else_clause "else" @mid.try.3)?) @scope.try 29 | 30 | (string 31 | (string_start) @open.quote_all 32 | (string_end) @close.quote_all) @scope.quote_all 33 | -------------------------------------------------------------------------------- /after/queries/quote/matchup.scm: -------------------------------------------------------------------------------- 1 | (_ 2 | "\"" @open.quote_double 3 | "\"" @close.quote_double) @scope.quote_double 4 | 5 | (_ 6 | "'" @open.quote_single 7 | "'" @close.quote_single) @scope.quote_single 8 | -------------------------------------------------------------------------------- /after/queries/ruby/matchup.scm: -------------------------------------------------------------------------------- 1 | (method 2 | "def" @open.def 3 | "end" @close.def) @scope.def 4 | (singleton_method 5 | "def" @open.def 6 | "end" @close.def) @scope.def 7 | (return 8 | "return" @mid.def.1) 9 | (yield 10 | "yield" @mid.def.2) 11 | (body_statement 12 | (rescue "rescue" @mid.def.1)) 13 | (body_statement 14 | (ensure "ensure" @mid.def.2)) 15 | 16 | (class 17 | "class" @open.class 18 | "end" @close.class) @scope.class 19 | (singleton_class 20 | "class" @open.class 21 | "end" @close.class) @scope.class 22 | 23 | (if 24 | "if" @open.if 25 | (else "else" @mid.if.2)? 26 | "end" @close.if) @scope.if 27 | (elsif (else "else" @mid.if.2)) 28 | (elsif "elsif" @mid.if.1) 29 | 30 | (unless 31 | "unless" @open.unless 32 | (else "else" @mid.unless.2)? 33 | "end" @close.unless) @scope.unless 34 | 35 | (while 36 | "while" @open.loop 37 | body: (do 38 | "end" @close.loop)) @scope.loop 39 | 40 | (for 41 | "for" @open.loop 42 | body: (do 43 | "end" @close.loop)) @scope.loop 44 | 45 | (next 46 | "next" @mid.loop.1)? 47 | (break 48 | "break" @mid.loop.2)? 49 | 50 | (case 51 | "case" @open.case 52 | (when 53 | "when" @mid.case.1)? 54 | (else 55 | "else" @mid.case.2)? 56 | "end" @close.case) @scope.case 57 | 58 | (begin 59 | "begin" @open.begin 60 | (rescue 61 | "rescue" @mid.begin.1)? 62 | (ensure 63 | "ensure" @mid.begin.2)? 64 | "end" @close.begin) @scope.begin 65 | 66 | (module 67 | "module" @open.module 68 | "end" @close.module) @scope.module 69 | 70 | (do_block 71 | "do" @open.do 72 | "end" @close.do) @scope.do 73 | 74 | (if_modifier) @skip 75 | (unless_modifier) @skip 76 | (while_modifier) @skip 77 | (until_modifier) @skip 78 | 79 | (block_parameters 80 | ("|") @open.block_param 81 | (_) 82 | ("|") @close.block_param 83 | ) @scope.block_param 84 | -------------------------------------------------------------------------------- /after/queries/rust/matchup.scm: -------------------------------------------------------------------------------- 1 | ; inherits: quote 2 | 3 | ; --------------- types --------------- 4 | (type_arguments 5 | "<" @open.typeargs 6 | ">" @close.typeargs) @scope.typeargs 7 | 8 | (type_parameters 9 | "<" @open.typeparams 10 | ">" @open.typeparams) @scope.typeparams 11 | 12 | ; --------------- if/else --------------- 13 | (block (if_expression "if" @open.if_) @scope.if_) 14 | (expression_statement (if_expression "if" @open.if_) @scope.if_) 15 | (let_declaration (if_expression "if" @open.if_) @scope.if_) 16 | 17 | (else_clause "else" @mid.if_.1 (block)) 18 | (else_clause 19 | "else" @_start (if_expression "if" @_end) 20 | (#make-range! "mid.if_.2" @_start @_end)) 21 | 22 | ; --------------- async/await --------------- 23 | (function_item (function_modifiers "async" @open.async)) @scope.async 24 | (async_block "async" @open.async) @scope.async 25 | (await_expression "await" @mid.async.1) 26 | 27 | ; --------------- fn/return --------------- 28 | (function_item 29 | "fn" @open.function) @scope.function 30 | (closure_expression) @scope.function 31 | (return_expression 32 | "return" @mid.function.1) 33 | 34 | ; --------------- closures --------------- 35 | (closure_parameters 36 | "|" @open.closureparams 37 | "|" @close.closureparams) @scope.closureparams 38 | 39 | ; --------------- while/loop/for + break/continue --------------- 40 | (for_expression . "for" @open.loop) @scope.loop 41 | (while_expression . "while" @open.loop) @scope.loop 42 | (loop_expression . "loop" @open.loop) @scope.loop 43 | 44 | (break_expression "break" @mid.loop.1 .) 45 | (break_expression "break" @mid.loop.1 .) 46 | (continue_expression "continue" @mid.loop.1 .) 47 | -------------------------------------------------------------------------------- /after/queries/smali/matchup.scm: -------------------------------------------------------------------------------- 1 | ; inherits: quote 2 | 3 | (method_definition 4 | ".method" @open.function 5 | ".end method" @close.function) @scope.function 6 | 7 | (parameter_directive 8 | ".parameter" @open.parameter 9 | ".end parameter" @close.parameter) @scope.parameter 10 | 11 | (param_directive 12 | ".param" @open.parameter 13 | ".end param" @close.parameter) @scope.parameter 14 | 15 | ((opcode) @mid.function.1 16 | (#lua-match? @mid.function.1 "^return")) 17 | 18 | (annotation_directive 19 | ".annotation" @open.annotation 20 | ".end annotation" @close.annotation) @scope.annotation 21 | 22 | (subannotation_directive 23 | ".subannotation" @open.subannotation 24 | ".end subannotation" @close.subannotation) @scope.subannotation 25 | 26 | (array_data_directive 27 | ".array-data" @open.array-data 28 | ".end array-data" @close.array-data) @scope.array-data 29 | 30 | (field_definition 31 | ".field" @open.field 32 | ".end field" @close.field) @scope.field 33 | 34 | (sparse_switch_directive 35 | ".sparse-switch" @open.sparse-switch 36 | ".end sparse-switch" @close.sparse-switch) @scope.sparse-switch 37 | 38 | (packed_switch_directive 39 | ".packed-switch" @open.packed-switch 40 | ".end packed-switch" @close.packed-switch) @scope.packed-switch 41 | -------------------------------------------------------------------------------- /after/queries/svelte/matchup.scm: -------------------------------------------------------------------------------- 1 | ; inherits: quote 2 | 3 | [ 4 | (element) 5 | (script_element) 6 | (style_element) 7 | ] @scope.tag 8 | 9 | (start_tag (tag_name) @open.tag) 10 | 11 | (end_tag 12 | (tag_name) @close.tag 13 | (#offset! @close.tag 0 -1 0 0)) 14 | 15 | (self_closing_tag 16 | (tag_name) @open.selftag 17 | "/>" @close.selftag) @scope.selftag 18 | 19 | ; await 20 | 21 | (await_statement 22 | (await_start 23 | (block_start_tag 24 | "await" @open.await 25 | (#offset! @open.await 0 -1 0 0)))) @scope.await 26 | 27 | (await_end 28 | (block_end_tag 29 | "await" @close.await 30 | (#offset! @close.await 0 -1 0 0))) 31 | 32 | ("then" @mid.await.1 33 | (#offset! @mid.await.1 0 -1 0 0)) 34 | 35 | ("catch" @mid.await.2 36 | (#offset! @mid.await.2 0 -1 0 0)) 37 | 38 | ; each 39 | 40 | (each_statement 41 | (each_start 42 | (block_start_tag 43 | "each" @open.each 44 | (#offset! @open.each 0 -1 0 0)))) @scope.each 45 | 46 | (each_end 47 | (block_end_tag 48 | "each" @close.each 49 | (#offset! @close.each 0 -1 0 0))) 50 | 51 | ; if 52 | 53 | (if_statement 54 | (if_start 55 | (block_start_tag 56 | "if" @open.if 57 | (#offset! @open.if 0 -1 0 0)))) @scope.if 58 | 59 | (else_if_start 60 | (block_tag 61 | "else if" @mid.if.1 62 | (#offset! @mid.if.1 0 -1 0 0))) 63 | 64 | (else_start 65 | (block_tag 66 | "else" @mid.if.2 67 | (#offset! @mid.if.2 0 -1 0 0))) 68 | 69 | (if_end 70 | (block_end_tag 71 | "if" @close.if 72 | (#offset! @close.if 0 -1 0 0))) 73 | 74 | ; key 75 | 76 | (key_statement 77 | (key_start 78 | (block_start_tag 79 | "key" @open.key 80 | (#offset! @open.key 0 -1 0 0)))) @scope.key 81 | 82 | (key_end 83 | (block_end_tag 84 | "key" @close.key 85 | (#offset! @close.key 0 -1 0 0))) 86 | 87 | ; snippet 88 | 89 | (snippet_statement 90 | (snippet_start 91 | (block_start_tag 92 | "snippet" @open.snippet 93 | (#offset! @open.snippet 0 -1 0 0)))) @scope.snippet 94 | 95 | (snippet_end 96 | (block_end_tag 97 | "snippet" @close.snippet 98 | (#offset! @close.snippet 0 -1 0 0))) 99 | -------------------------------------------------------------------------------- /after/queries/templ/matchup.scm: -------------------------------------------------------------------------------- 1 | ; inherits: quote 2 | 3 | [ 4 | (component_if_statement) 5 | (conditional_attribute_if_statement) 6 | ] @scope.if 7 | 8 | ; 'else' 9 | ("else" @mid.if.1) 10 | 11 | ; if 12 | ("if" @open.if) 13 | 14 | ; switch 15 | (component_switch_statement "switch" @open.switch 16 | (component_switch_expression_case "case" @mid.switch.1) 17 | (component_switch_default_case "default" @mid.switch.2)) @scope.switch 18 | 19 | [ 20 | (element) 21 | (script_element) 22 | ] @scope.tag 23 | 24 | (tag_start (element_identifier) @open.tag) 25 | (tag_end 26 | (element_identifier) @close.tag 27 | (#offset! @close.tag 0 -1 0 0)) 28 | 29 | (style_element 30 | (style_tag_start) @open.style 31 | (#offset! @open.style 0 1 0 -1) 32 | (style_tag_end) @close.style 33 | (#offset! @close.style 0 1 0 -1) 34 | ) @scope.style 35 | 36 | (self_closing_tag 37 | (element_identifier) @open.selftag 38 | "/>" @close.selftag) @scope.selftag 39 | -------------------------------------------------------------------------------- /after/queries/tsx/matchup.scm: -------------------------------------------------------------------------------- 1 | ; inherits: typescript,jsx 2 | -------------------------------------------------------------------------------- /after/queries/typescript/matchup.scm: -------------------------------------------------------------------------------- 1 | ; inherits: ecma 2 | 3 | (type_arguments) @scope.typeargs 4 | (type_arguments) "<" @open.typeargs 5 | (type_arguments) ">" @close.typeargs 6 | 7 | (type_parameters) @scope.typeparams 8 | (type_parameters) "<" @open.typeparams 9 | (type_parameters) ">" @close.typeparams 10 | -------------------------------------------------------------------------------- /after/queries/vim/matchup.scm: -------------------------------------------------------------------------------- 1 | (function_definition 2 | "function" @open.function 3 | "endfunction" @close.function) @scope.function 4 | (return_statement 5 | "return" @mid.function.1) 6 | 7 | (if_statement 8 | "if" @open.if 9 | "endif" @close.if) @scope.if 10 | (elseif_statement 11 | "elseif" @mid.if.1) 12 | (else_statement 13 | "else" @mid.if.2) 14 | 15 | (for_loop 16 | "for" @open.loop 17 | "endfor" @close.loop) @scope.loop 18 | (while_loop 19 | "while" @open.loop 20 | "endwhile" @close.loop) @scope.loop 21 | (continue_statement "continue" @mid.loop.1) 22 | (break_statement "break" @mid.loop.2) 23 | -------------------------------------------------------------------------------- /after/queries/vue/matchup.scm: -------------------------------------------------------------------------------- 1 | ; inherits: quote 2 | 3 | [ 4 | (element) 5 | (script_element) 6 | (style_element) 7 | (template_element) 8 | ] @scope.tag 9 | 10 | (start_tag (tag_name) @open.tag) 11 | (end_tag 12 | (tag_name) @close.tag 13 | (#offset! @close.tag 0 -1 0 0)) 14 | 15 | (self_closing_tag 16 | (tag_name) @open.selftag 17 | "/>" @close.selftag) @scope.selftag 18 | -------------------------------------------------------------------------------- /after/queries/zig/matchup.scm: -------------------------------------------------------------------------------- 1 | ; inherits: quote 2 | 3 | (function_declaration 4 | "fn" @open.function) @scope.function 5 | (return_expression 6 | "return" @mid.function.1) 7 | 8 | ; 'else' and 'else if' 9 | (else_clause 10 | "else" @_start (if_statement "if" @_end)? 11 | (#make-range! "mid.if.1" @_start @_end)) 12 | 13 | ; if 14 | ((if_statement 15 | "if" @open.if) @scope.if 16 | (#not-has-parent? @scope.if else_clause)) 17 | 18 | ; Loops 19 | (while_statement "while" @open.loop) @scope.loop 20 | (break_expression "break" @mid.loop.1) 21 | (continue_expression "continue" @mid.loop.2) 22 | -------------------------------------------------------------------------------- /autoload/matchup/custom.vim: -------------------------------------------------------------------------------- 1 | " vim match-up - even better matching 2 | " 3 | " Maintainer: Andy Massimino 4 | " Email: a@normed.space 5 | " 6 | 7 | let s:save_cpo = &cpo 8 | set cpo&vim 9 | 10 | "" 11 | " example motion as described in issues/49: 12 | " - if on a delim, go to {count} next matching delim, up or down 13 | " - if not on a delim, go to {count} local surrounding, up or down 14 | " 15 | " {info} dict with the following fields: 16 | " visual : 1 if visual or operator mode 17 | " count/count1: v:count/v:count1 for this map 18 | " operator : if non-empty, the operator in op mode 19 | " motion_force: forced operator mode, e.g, for 'dvx' this is 'v' 20 | " {opts} user data dict from motion definition 21 | function! matchup#custom#example_motion(info, opts) abort 22 | let l:delim = matchup#delim#get_current('all', 'both_all') 23 | if !empty(l:delim) 24 | let l:matches = matchup#delim#get_matching(l:delim, 1) 25 | if len(l:matches) 26 | for _ in range(a:info.count1) 27 | let l:delim = l:delim.links[a:opts.down ? 'next': 'prev'] 28 | endfor 29 | return matchup#custom#suggest_pos(l:delim, a:opts) 30 | endif 31 | endif 32 | 33 | let [l:open_, l:close_] = matchup#delim#get_surrounding( 34 | \ 'delim_all', v:count1, {}) 35 | if empty(l:open_) || empty(l:close_) 36 | return [] 37 | endif 38 | let [l:open, l:close] = matchup#delim#get_surround_nearest(l:open_) 39 | if empty(l:open) 40 | let [l:open, l:close] = [l:open_, l:open_.links.next] 41 | endif 42 | let l:delim = a:opts.down ? l:close : l:open 43 | 44 | " exclude delim in operators unless v is given 45 | if !empty(a:info.operator) && a:info.motion_force !=# 'v' 46 | if a:opts.down 47 | return matchup#pos#prev(l:delim) 48 | else 49 | return matchup#pos#next(matchup#delim#end_pos(l:delim)) 50 | endif 51 | else 52 | return matchup#custom#suggest_pos(l:delim, a:opts) 53 | endif 54 | endfunction 55 | 56 | "" 57 | " api function: get the preferred cursor location for delim 58 | " {delim} delimiter object 59 | " {opts} field 'down' denotes motion direction 60 | function! matchup#custom#suggest_pos(delim, opts) abort 61 | if g:matchup_motion_cursor_end && (a:delim.side ==# 'close' 62 | \ || a:delim.side ==# 'mid' && get(a:opts, 'down', 0)) 63 | return [a:delim.lnum, matchup#delim#jump_target(a:delim)] 64 | endif 65 | return matchup#pos#(a:delim) 66 | endfunction 67 | 68 | "" 69 | " define a custom motion 70 | " {modes} specify which modes modes of {n,o,x} the mapping is active in 71 | " {keys} key sequence for map 72 | " {fcn} function to call, must take two arguments 73 | " [@opts] user data dict passed to function 74 | function! matchup#custom#define_motion(modes, keys, fcn, ...) abort 75 | if a:modes !~# '^[nox]\+$' 76 | echoerr 'invalid modes' 77 | endif 78 | 79 | let s:custom_counter += 1 80 | let l:k = s:custom_counter 81 | let l:opts = a:0 ? deepcopy(a:1) : {} 82 | call extend(l:opts, { 'fcn': a:fcn, 'keys': a:keys }) 83 | let s:custom_opts[l:k] = l:opts 84 | 85 | if a:modes =~# 'n' 86 | execute 'nnoremap (matchup-custom-'.a:keys.')' 87 | \ ':call matchup#custom#wrap(0, '.l:k.')' 88 | execute 'nmap' a:keys '(matchup-custom-'.a:keys.')' 89 | endif 90 | 91 | if a:modes =~# '[xo]' 92 | let l:sid = substitute(matchup#motion_sid(), "\", '', '') 93 | execute 'xnoremap ' l:sid.'(matchup-custom-'.l:k.')' 94 | \ ':call matchup#custom#wrap(1, '.l:k.')' 95 | endif 96 | 97 | if a:modes =~# 'x' 98 | execute 'xmap (matchup-custom-'.a:keys.')' 99 | \ l:sid.'(matchup-custom-'.l:k.')' 100 | execute 'xmap ' a:keys '(matchup-custom-'.a:keys.')' 101 | endif 102 | 103 | if a:modes =~# 'o' 104 | execute 'onoremap (matchup-custom-'.a:keys.')' 105 | \ ':call matchup#motion#op(' 106 | \ . string('custom-'.l:k).')' 107 | if !call(matchup#motion_sid().'make_oldstyle_omaps', 108 | \ [a:keys, 'custom-'.a:keys]) 109 | execute 'omap' a:keys '(matchup-custom-'.a:keys.')' 110 | endif 111 | endif 112 | endfunction 113 | 114 | if !exists('s:custom_opts') 115 | let s:custom_opts = {} 116 | let s:custom_counter = 0 117 | endif 118 | 119 | " motion wrapper 120 | function! matchup#custom#wrap(visual, id) abort 121 | " default to 1 second (can override in custom motion) 122 | call matchup#perf#timeout_start(1000) 123 | 124 | let l:info = { 125 | \ 'visual': a:visual, 126 | \ 'count': v:count, 127 | \ 'count1': v:count1, 128 | \ 'operator': matchup#motion#getoper(), 129 | \ 'motion_force': g:v_motion_force, 130 | \} 131 | let l:is_oper = !empty(l:info.operator) 132 | let l:opts = s:custom_opts[a:id] 133 | 134 | if a:visual 135 | normal! gv 136 | endif 137 | 138 | let l:ret = call(l:opts.fcn, [l:info, l:opts]) 139 | 140 | if type(l:ret) != type([]) || empty(l:ret) 141 | if !a:visual || l:is_oper 142 | execute "normal! \" 143 | endif 144 | elseif type(l:ret) == type([]) && len(l:ret) >= 2 145 | call matchup#pos#set_cursor(l:ret) 146 | endif 147 | endfunction 148 | 149 | let &cpo = s:save_cpo 150 | 151 | " vim: fdm=marker sw=2 152 | 153 | -------------------------------------------------------------------------------- /autoload/matchup/misc.vim: -------------------------------------------------------------------------------- 1 | " vim match-up - even better matching 2 | " 3 | " Maintainer: Andy Massimino 4 | " Email: a@normed.space 5 | " 6 | 7 | " {{{1 function! matchup#misc#reload() 8 | if get(s:, 'reload_guard', 1) 9 | function! matchup#misc#reload() abort 10 | let s:reload_guard = 0 11 | 12 | for l:file in glob(fnamemodify(s:file, ':h') . '/../**/*.vim', 0, 1) 13 | execute 'source' l:file 14 | endfor 15 | 16 | call matchup#init() 17 | 18 | if has('nvim-0.5.0') 19 | silent! lua require('treesitter-matchup.third-party.reload') 20 | \ .reload_module('treesitter-matchup') 21 | endif 22 | 23 | unlet s:reload_guard 24 | endfunction 25 | endif 26 | 27 | " }}}1 28 | 29 | let s:file = expand('') 30 | 31 | " vim: fdm=marker sw=2 32 | 33 | -------------------------------------------------------------------------------- /autoload/matchup/perf.vim: -------------------------------------------------------------------------------- 1 | " vim match-up - even better matching 2 | " 3 | " Maintainer: Andy Massimino 4 | " Email: a@normed.space 5 | " 6 | 7 | let s:save_cpo = &cpo 8 | set cpo&vim 9 | 10 | let s:time_start = {} 11 | let s:alpha = 2.0/(10+1) 12 | 13 | let g:matchup#perf#times = {} 14 | 15 | function! matchup#perf#tic(context) 16 | let s:time_start[a:context] = reltime() 17 | endfunction 18 | 19 | function! matchup#perf#toc(context, state) 20 | let l:elapsed = s:Reltimefloat(reltime(s:time_start[a:context])) 21 | 22 | let l:key = a:context.'#'.a:state 23 | if has_key(g:matchup#perf#times, l:key) 24 | if l:elapsed > g:matchup#perf#times[l:key].maximum 25 | let g:matchup#perf#times[l:key].maximum = l:elapsed 26 | endif 27 | let g:matchup#perf#times[l:key].last = l:elapsed 28 | let g:matchup#perf#times[l:key].emavg = s:alpha*l:elapsed 29 | \ + (1-s:alpha)*g:matchup#perf#times[l:key].emavg 30 | else 31 | let g:matchup#perf#times[l:key] = { 32 | \ 'maximum' : l:elapsed, 33 | \ 'emavg' : l:elapsed, 34 | \ 'last' : l:elapsed, 35 | \} 36 | endif 37 | endfunction 38 | 39 | function! s:sort_by_last(a, b) 40 | let l:a = g:matchup#perf#times[a:a].last 41 | let l:b = g:matchup#perf#times[a:b].last 42 | return l:a == l:b ? 0 : l:a > l:b ? 1 : -1 43 | endfunction 44 | 45 | function! matchup#perf#show_times() 46 | let l:keys = keys(g:matchup#perf#times) 47 | let l:contexts = uniq(sort(map(copy(l:keys), 'split(v:val, "#")[0]'))) 48 | if empty(l:contexts) 49 | echo 'no times' 50 | return 51 | end 52 | 53 | echohl Title 54 | echo printf('%42s%11s%17s', 'average', 'last', 'maximum') 55 | echohl None 56 | for l:c in l:contexts 57 | echohl Special 58 | echo '['.l:c.']' 59 | echohl None 60 | let l:states = filter(copy(l:keys), 'v:val =~# "^\\V'.l:c.'#"') 61 | call sort(l:states, 's:sort_by_last') 62 | for l:s in l:states 63 | echo printf(' %-25s%12.2gms%12.2gms%12.2gms', 64 | \ join(split(l:s,'#')[1:],'#'), 65 | \ 1000*g:matchup#perf#times[l:s].emavg, 66 | \ 1000*g:matchup#perf#times[l:s].last, 67 | \ 1000*g:matchup#perf#times[l:s].maximum) 68 | endfor 69 | endfor 70 | endfunction 71 | 72 | command! MatchupShowTimes call matchup#perf#show_times() 73 | command! MatchupClearTimes let g:matchup#perf#times = {} 74 | 75 | let s:timeout = 0 76 | let s:timeout_enabled = 0 77 | let s:timeout_pulse_time = reltime() 78 | 79 | function! matchup#perf#timeout() " {{{1 80 | return float2nr(s:timeout) 81 | endfunction 82 | 83 | "}}}1 84 | function! matchup#perf#timeout_start(timeout) " {{{1 85 | let s:timeout = a:timeout 86 | let s:timeout_enabled = (a:timeout == 0) ? 0 : 1 87 | let s:timeout_pulse_time = reltime() 88 | endfunction 89 | 90 | " }}}1 91 | function! matchup#perf#timeout_check() " {{{1 92 | if !s:timeout_enabled | return 0 | endif 93 | let l:elapsed = 1000.0 * s:Reltimefloat(reltime(s:timeout_pulse_time)) 94 | let s:timeout -= l:elapsed 95 | let s:timeout_pulse_time = reltime() 96 | return s:timeout <= 0.0 97 | endfunction 98 | 99 | " }}}1 100 | 101 | " function! s:reltimefloat(time) {{{1 102 | if exists('*reltimefloat') 103 | let s:Reltimefloat = function('reltimefloat') 104 | else 105 | function! s:Reltimefloat(time) 106 | return str2float(reltimestr(a:time)) 107 | endfunction 108 | endif 109 | 110 | " }}}1 111 | 112 | let &cpo = s:save_cpo 113 | 114 | " vim: fdm=marker sw=2 115 | 116 | -------------------------------------------------------------------------------- /autoload/matchup/pos.vim: -------------------------------------------------------------------------------- 1 | " vim match-up - even better matching 2 | " 3 | " Maintainer: Andy Massimino 4 | " Email: a@normed.space 5 | " 6 | 7 | let s:save_cpo = &cpo 8 | set cpo&vim 9 | 10 | function! matchup#pos#set_cursor(...) abort " {{{1 11 | call cursor(s:parse_args(a:000)) 12 | endfunction 13 | 14 | " }}}1 15 | " function! matchup#pos#get_cursor() {{{1 16 | if exists('*getcurpos') 17 | function! matchup#pos#get_cursor() abort 18 | return getcurpos() 19 | endfunction 20 | else 21 | function! matchup#pos#get_cursor() abort 22 | return getpos('.') 23 | endfunction 24 | endif 25 | 26 | " }}}1 27 | 28 | " }}}1 29 | function! matchup#pos#get_cursor_line() abort " {{{1 30 | let l:pos = matchup#pos#get_cursor() 31 | return l:pos[1] 32 | endfunction 33 | 34 | " }}}1 35 | 36 | function! matchup#pos#(...) abort " {{{1 37 | let [l:lnum, l:cnum; l:rest] = s:parse_args(a:000) 38 | return [l:lnum, l:cnum] 39 | endfunction 40 | 41 | " }}}1 42 | function! matchup#pos#val(...) " {{{1 43 | let [l:lnum, l:cnum; l:rest] = s:parse_args(a:000) 44 | 45 | return 100000*l:lnum + min([l:cnum, 90000]) 46 | endfunction 47 | 48 | " }}}1 49 | function! matchup#pos#next_eol(...) abort " {{{1 50 | let [l:lnum, l:cnum; l:rest] = s:parse_args(a:000) 51 | 52 | if l:cnum > strlen(getline(l:lnum)) 53 | return [0, l:lnum+1, 1, 0] 54 | endif 55 | 56 | let l:next = matchup#pos#next(l:lnum, l:cnum) 57 | if l:next[1] > l:lnum 58 | return [0, l:lnum, l:cnum+1, 0] 59 | endif 60 | return l:next 61 | endfunction 62 | 63 | " }}}1 64 | function! matchup#pos#next(...) abort " {{{1 65 | let [l:lnum, l:cnum; l:rest] = s:parse_args(a:000) 66 | 67 | let l:line = getline(l:lnum) 68 | let l:charlen = matchend(l:line[l:cnum-1:], '.') 69 | if l:charlen >= 0 && l:cnum + l:charlen <= strlen(l:line) 70 | return [0, l:lnum, l:cnum + l:charlen, 0] 71 | else 72 | return [0, l:lnum+1, 1, 0] 73 | endif 74 | endfunction 75 | 76 | " }}}1 77 | function! matchup#pos#prev_eol(...) abort " {{{1 78 | let [l:lnum, l:cnum; l:rest] = s:parse_args(a:000) 79 | 80 | if l:cnum <= 1 && l:lnum > 1 81 | return [0, l:lnum - 1, strlen(getline(l:lnum - 1)) + 1, 0] 82 | else 83 | return matchup#pos#prev(l:lnum, l:cnum) 84 | endif 85 | endfunction 86 | 87 | " }}}1 88 | function! matchup#pos#prev(...) abort " {{{1 89 | let [l:lnum, l:cnum; l:rest] = s:parse_args(a:000) 90 | 91 | if l:cnum > 1 92 | return [0, l:lnum, match(getline(l:lnum)[0:l:cnum-2], '.$') + 1, 0] 93 | else 94 | return [0, max([l:lnum-1, 1]), 95 | \ max([strlen(getline(l:lnum-1)), 1]), 0] 96 | endif 97 | endfunction 98 | 99 | " }}}1 100 | 101 | function! matchup#pos#larger(pos1, pos2) abort " {{{1 102 | return matchup#pos#val(a:pos1) > matchup#pos#val(a:pos2) 103 | endfunction 104 | 105 | " }}}1 106 | function! matchup#pos#equal(p1, p2) abort " {{{1 107 | let l:pos1 = s:parse_args(a:p1) 108 | let l:pos2 = s:parse_args(a:p2) 109 | return l:pos1[:1] == l:pos2[:1] 110 | endfunction 111 | 112 | " }}}1 113 | function! matchup#pos#smaller(pos1, pos2) abort " {{{1 114 | return matchup#pos#val(a:pos1) < matchup#pos#val(a:pos2) 115 | endfunction 116 | 117 | " }}}1 118 | function! matchup#pos#smaller_or_equal(pos1, pos2) abort " {{{1 119 | return matchup#pos#smaller(a:pos1, a:pos2) 120 | \ || matchup#pos#equal(a:pos1, a:pos2) 121 | endfunction 122 | 123 | " }}}1 124 | function! s:parse_args(args) abort " {{{1 125 | " 126 | " The arguments should be in one of the following forms (when unpacked): 127 | " 128 | " [lnum, cnum] 129 | " [bufnum, lnum, cnum, ...] 130 | " {'lnum' : lnum, 'cnum' : cnum} 131 | " 132 | 133 | if len(a:args) > 1 134 | return s:parse_args([a:args]) 135 | elseif len(a:args) == 1 136 | if type(a:args[0]) == type({}) 137 | return [get(a:args[0], 'lnum'), get(a:args[0], 'cnum')] 138 | else 139 | if len(a:args[0]) == 2 140 | return a:args[0] 141 | else 142 | return a:args[0][1:] 143 | endif 144 | endif 145 | else 146 | return a:args 147 | endif 148 | endfunction 149 | 150 | " }}}1 151 | 152 | let &cpo = s:save_cpo 153 | 154 | " vim: fdm=marker sw=2 155 | -------------------------------------------------------------------------------- /autoload/matchup/quirks.vim: -------------------------------------------------------------------------------- 1 | " vim match-up - even better matching 2 | " 3 | " Maintainer: Andy Massimino 4 | " Email: a@normed.space 5 | " 6 | 7 | let s:save_cpo = &cpo 8 | set cpo&vim 9 | 10 | function! s:ftcheck(fts) abort " {{{1 11 | let l:ft = get(split(&filetype, '\.'), 0, '') 12 | return index(a:fts, l:ft) > -1 13 | endfunction 14 | 15 | " }}}1 16 | function! matchup#quirks#isclike() abort " {{{1 17 | return s:ftcheck(s:clikeft) 18 | endfunction 19 | 20 | let s:clikeft = [ 21 | \ 'arduino', 'c', 'cpp', 'cuda', 'ld', 'php', 'go', 22 | \ 'javascript', 'typescript', 23 | \ 'javascriptreact', 'typescriptreact', 24 | \] 25 | 26 | " }}}1 27 | function! matchup#quirks#ishtmllike() abort " {{{1 28 | return s:ftcheck(s:htmllikeft) 29 | endfunction 30 | 31 | let s:htmllikeft = [ 32 | \ 'tidy', 'php', 'liquid', 'haml', 'tt2html', 33 | \ 'html', 'xhtml', 'xml', 'jsp', 'htmldjango', 34 | \ 'aspvbs', 'rmd', 'markdown', 'eruby', 'vue', 35 | \ 'javascriptreact', 'typescriptreact', 'svelte', 36 | \ 'templ' 37 | \] 38 | 39 | " }}}1 40 | 41 | function! matchup#quirks#status_adjust(offscreen) abort " {{{1 42 | if a:offscreen.match ==# '{' && matchup#quirks#isclike() 43 | let [l:a, l:b] = [indent(a:offscreen.lnum), 44 | \ indent(a:offscreen.links.close.lnum)] 45 | if strpart(getline(a:offscreen.lnum), 46 | \ 0, a:offscreen.cnum-1) =~# '^\s*$' 47 | let l:target = l:a 48 | elseif l:a != l:b 49 | let l:target = l:b 50 | else 51 | return 0 52 | endif 53 | " go up to next line with same indent (up to s:adjust_max) 54 | for l:adjust in range(-1, -s:adjust_max, -1) 55 | let l:lnum = a:offscreen.lnum + l:adjust 56 | if getline(l:lnum) =~? '^\s*$' 57 | break 58 | endif 59 | if indent(l:lnum) == l:target 60 | \ && getline(l:lnum) !~? '^\s*\%(#\|/\*\|//\)' 61 | return l:adjust 62 | endif 63 | endfor 64 | endif 65 | 66 | return 0 67 | endfunction 68 | 69 | let s:adjust_max = 9 70 | 71 | " }}}1 72 | 73 | let &cpo = s:save_cpo 74 | 75 | " vim: fdm=marker sw=2 76 | -------------------------------------------------------------------------------- /autoload/matchup/re.vim: -------------------------------------------------------------------------------- 1 | " vim match-up - even better matching 2 | " 3 | " Maintainer: Andy Massimino 4 | " Email: a@normed.space 5 | " 6 | 7 | let s:nbsl = '\v%(\\@","\"], l:char) >= 0 24 | return 25 | endif 26 | endif 27 | let l:tpope = !empty(maparg('VSurround', 'x')) 28 | 29 | let [l:l1, l:c11, l:c12] = [l:open.lnum, l:open.cnum, 30 | \ l:open.cnum + strlen(l:open.match) - 1] 31 | let [l:l2, l:c21, l:c22] = [l:close.lnum, l:close.cnum, 32 | \ l:close.cnum + strlen(l:close.match) - 1] 33 | 34 | if a:op ==# 'd' || a:op ==# 'c' 35 | call matchup#pos#set_cursor(l1, c12+1) 36 | 37 | let [l:insl, l:insr] = ['', ''] 38 | if a:op ==# 'c' && !l:tpope 39 | let l:idx = index(s:pairtrans, l:char) 40 | let l:insl = l:idx < 0 ? l:char : s:pairtrans[l:idx/2*2] 41 | let l:insr = l:idx < 0 ? l:char : s:pairtrans[l:idx/2*2+1] 42 | endif 43 | 44 | let l:line = getline(l:l2) 45 | call setline(l:l2, strpart(l:line, 0, l:c21-1) 46 | \ . l:insr . strpart(l:line, l:c22)) 47 | let l:regtext = strpart(l:line, l:c21-1, l:c22-l:c21+1) 48 | 49 | let l:line = getline(l:l1) 50 | call setline(l:l1, strpart(l:line, 0, l:c11-1) 51 | \ . l:insl . strpart(l:line, l:c12)) 52 | 53 | call setreg(v:register, strpart(l:line, l:c11-1, l:c12-l:c11+1) 54 | \ . ' ' . l:regtext) 55 | 56 | let l:epos = l:c21-1 - (l:l1 == l:l2 57 | \ ? (l:c12-l:c11+1-strlen(l:insl)-strlen(l:insr)) : 0) 58 | call setpos("']", [0, l:l2, l:epos, 0]) 59 | call setpos("'[", [0, l:l1, l:c11, 0]) 60 | endif 61 | 62 | if a:op ==# 'd' || a:op ==# 'c' && empty(l:char) 63 | silent! call repeat#set("\(matchup-ds%)", v:count) 64 | elseif a:op ==# 'c' && l:tpope 65 | normal! `[v`] 66 | undojoin 67 | execute "normal \VSurround".l:char 68 | silent! call repeat#set("\(matchup-cs%)" 69 | \ . matchstr(g:repeat_sequence, 'SSurroundRepeat\zs.\+'), 70 | \ v:count) 71 | endif 72 | 73 | call matchup#pos#set_cursor(l1, c11) 74 | endfunction 75 | 76 | let s:pairtrans = split('()<>[]{}«»“”', '\ze') 77 | 78 | " }}}1 79 | 80 | let &cpo = s:save_cpo 81 | 82 | " vim: fdm=marker sw=2 83 | 84 | -------------------------------------------------------------------------------- /autoload/matchup/test.vim: -------------------------------------------------------------------------------- 1 | " vim match-up - even better matching 2 | " 3 | " Maintainer: Andy Massimino 4 | " Email: a@normed.space 5 | " 6 | 7 | function! matchup#test#finished() abort " {{{1 8 | for l:error in v:errors 9 | let l:match = matchlist(l:error, '\(.*\) line \(\d\+\): \(.*\)') 10 | let l:file = fnamemodify(l:match[1], ':.') 11 | let l:lnum = l:match[2] 12 | let l:msg = l:match[3] 13 | echo printf("%s:%d: %s\n", l:file, l:lnum, l:msg) 14 | endfor 15 | 16 | if len(v:errors) > 0 17 | cquit 18 | else 19 | quitall! 20 | endif 21 | endfunction 22 | 23 | " }}}1 24 | 25 | function! matchup#test#assert(condition) abort " {{{1 26 | if a:condition | return 1 | endif 27 | 28 | call s:fail() 29 | endfunction 30 | 31 | " }}}1 32 | function! matchup#test#assert_equal(expect, observe) abort " {{{1 33 | if a:expect ==# a:observe | return 1 | endif 34 | 35 | call s:fail([ 36 | \ 'expect: ' . string(a:expect), 37 | \ 'observe: ' . string(a:observe), 38 | \]) 39 | endfunction 40 | 41 | " }}}1 42 | function! matchup#test#assert_match(x, regex) abort " {{{1 43 | if a:x =~# a:regex | return 1 | endif 44 | 45 | call s:fail([ 46 | \ 'x = ' . string(a:x), 47 | \ 'regex = ' . a:regex, 48 | \]) 49 | endfunction 50 | 51 | " }}}1 52 | 53 | function! s:fail(...) abort " {{{1 54 | echo 'Assertion failed!' 55 | 56 | if a:0 > 0 && !empty(a:1) 57 | if type(a:1) == v:t_string 58 | echo a:1 59 | else 60 | for line in a:1 61 | echo line 62 | endfor 63 | endif 64 | endif 65 | echon "\n" 66 | 67 | cquit 68 | endfunction 69 | 70 | " }}}1 71 | -------------------------------------------------------------------------------- /autoload/matchup/text_obj.vim: -------------------------------------------------------------------------------- 1 | " vim match-up - even better matching 2 | " 3 | " Maintainer: Andy Massimino 4 | " Email: a@normed.space 5 | " 6 | 7 | let s:save_cpo = &cpo 8 | set cpo&vim 9 | 10 | function! matchup#text_obj#delimited(is_inner, visual, type) abort " {{{1 11 | let l:v_motion_force = matchup#motion_force() 12 | 13 | " get the current selection, move to the _start_ the of range 14 | if a:visual 15 | let l:selection = getpos("'<")[1:2] + getpos("'>")[1:2] 16 | call matchup#pos#set_cursor(getpos("'<")) 17 | endif 18 | 19 | " motion forcing 20 | let l:forced = a:visual ? '' : l:v_motion_force 21 | 22 | " determine if operator is able to act line-wise (i.e., for inner) 23 | let l:linewise_op = index(g:matchup_text_obj_linewise_operators, 24 | \ v:operator) >= 0 25 | 26 | if v:operator ==# 'g@' 27 | let l:save_reg = v:register 28 | let l:spec = matchlist(g:matchup_text_obj_linewise_operators, 29 | \ '^g@\%(,\(.\+\)\)\?') 30 | if !empty(l:spec) 31 | if empty(l:spec[1]) 32 | let l:linewise_op = 1 33 | else 34 | execute 'let l:linewise_op =' l:spec[1] 35 | endif 36 | endif 37 | elseif v:operator ==# ':' 38 | \ && index(g:matchup_text_obj_linewise_operators, 39 | \ visualmode()) >= 0 40 | let l:linewise_op = 1 41 | endif 42 | 43 | " set the timeout fairly high 44 | call matchup#perf#timeout_start(725) 45 | 46 | " try up to six times 47 | for [l:local, l:try_again] in (v:count == 1 48 | \ || v:count > g:matchup_delim_count_max) 49 | \ ? a:is_inner ? [[0, 0], [0, 1], [0, 2], [0, 3]] 50 | \ : [[0, 0], [0, 1], [0, 2]] 51 | \ : a:is_inner ? [[1, 0], [0, 0], [1, 1], [0, 1], [1, 2], [0, 2]] 52 | \ : [[1, 0], [0, 0], [1, 1], [0, 1]] 53 | 54 | let l:count = v:count1 + l:try_again 55 | 56 | " we use v:count1 on the first try and increment each successive time 57 | " find the open-close block then narrow down to local after 58 | let [l:open_, l:close_] = matchup#delim#get_surrounding( 59 | \ a:type, l:count, { 'local': 0 }) 60 | 61 | if empty(l:open_) 62 | if a:visual 63 | normal! gv 64 | else 65 | " TODO: can this be simplified by making omaps ? 66 | " invalid text object, try to do nothing 67 | " cause a drop into normal mode 68 | call feedkeys("\\\", 'n') 69 | 70 | " and undo the text vim enters if necessary 71 | " vint: -ProhibitUnnecessaryDoubleQuote 72 | call feedkeys(":call matchup#text_obj#undo(" 73 | \ .undotree().seq_cur.")\:\", 'n') 74 | " vint: +ProhibitUnnecessaryDoubleQuote 75 | endif 76 | return 77 | endif 78 | 79 | if l:local 80 | let [l:open, l:close] = matchup#delim#get_surround_nearest(l:open_) 81 | if empty(l:open) 82 | let [l:open, l:close] = [l:open_, l:open_.links.next] 83 | endif 84 | else 85 | let [l:open, l:close] = [l:open_, l:open_.links.close] 86 | endif 87 | 88 | " no way to specify an empty region so we need to use some tricks 89 | let l:epos = [l:open.lnum, l:open.cnum] 90 | let l:epos[1] += matchup#delim#end_offset(l:open) 91 | if !a:visual && a:is_inner 92 | \ && matchup#pos#equal(l:close, matchup#pos#next(l:epos)) 93 | 94 | " TODO: cpo-E 95 | if v:operator ==# 'c' 96 | " this is apparently the most reliable way to handle 97 | " the 'c' operator, although it raises a TextChangedI 98 | " and fills registers with a space (from targets.vim) 99 | call matchup#pos#set_cursor(l:close) 100 | silent! execute "normal! i \v" 101 | elseif stridx('<>', v:operator) < 0 102 | let l:byte = line2byte(l:close.lnum) + l:close.cnum - 1 103 | call feedkeys(l:byte.'go', 'n') 104 | endif 105 | 106 | return 107 | endif 108 | 109 | let [l:l1, l:c1, l:l2, l:c2] = [l:open.lnum, l:open.cnum, 110 | \ l:close.lnum, l:close.cnum] 111 | 112 | " whether the pair has at least one line in between them 113 | let l:line_count = l:l2 - l:l1 + 1 114 | 115 | " special case: if inner and the current selection coincides 116 | " with the open and close positions, try for a second time 117 | " this allows vi% in [[ ]] to work 118 | if a:visual && a:is_inner && l:selection == [l:l1, l:c1, l:l2, l:c2] 119 | continue 120 | endif 121 | 122 | " adjust the borders of the selection 123 | if a:is_inner 124 | let l:c1 += matchup#delim#end_offset(l:open) 125 | let [l:l1, l:c1] = matchup#pos#next(l:l1, l:c1)[1:2] 126 | let l:sol = (l:c2 <= 1) 127 | let [l:l2, l:c2] = matchup#pos#prev(l:l2, l:c2)[1:2] 128 | 129 | " make *i% more like *it for html 130 | " don't include next < 131 | if l:line_count < 2 && matchup#quirks#ishtmllike() 132 | \ && !matchup#util#matchpref('classic_textobj', 0) 133 | \ && l:close.match =~? '^/\w\+\s*>\=$' 134 | \ && !(a:visual 135 | \ && matchup#pos#equal([l:l1, l:c1], [l:l2, l:c2])) 136 | let [l:l2, l:c2] = matchup#pos#prev(l:l2, l:c2)[1:2] 137 | if l:open.match !~? '>$' 138 | let [l:l1, l:c1] = matchup#pos#next(l:l1, l:c1)[1:2] 139 | endif 140 | endif 141 | 142 | " don't select only indent at close 143 | while matchup#util#in_indent(l:l2, l:c2) 144 | let l:c2 = 1 145 | let [l:l2, l:c2] = matchup#pos#prev(l:l2, l:c2)[1:2] 146 | let l:sol = 1 147 | endwhile 148 | 149 | " include the line break if we had wrapped around 150 | if a:visual && l:sol 151 | let l:c2 = strlen(getline(l:l2))+1 152 | endif 153 | 154 | if !a:visual 155 | " otherwise adjust end pos 156 | if l:sol 157 | let [l:l2, l:c2] = matchup#pos#next(l:l2, l:c2)[1:2] 158 | endif 159 | 160 | " toggle exclusive: difference between di% and dvi% 161 | let l:inclusive = 0 162 | if !l:sol && matchup#pos#smaller_or_equal( 163 | \ [l:l1, l:c1], [l:l2, l:c2]) 164 | let l:inclusive = 1 165 | endif 166 | if l:forced ==# 'v' 167 | let l:inclusive = !l:inclusive 168 | endif 169 | 170 | " sometimes operate in visual line motion (re-purpose force) 171 | " cf src/normal.c:1824 172 | if empty(l:v_motion_force) 173 | \ && l:c2 <= 1 && l:line_count > 1 && !l:inclusive 174 | let l:l2 -= 1 175 | if l:c1 <= 1 || matchup#util#in_indent(l:l1, l:c1-1) 176 | let l:forced = 'V' 177 | let l:inclusive = 1 178 | else 179 | " end_adjusted 180 | let l:c2 = strlen(getline(l:l2)) + 1 181 | if l:c2 > 1 182 | let l:c2 -= 1 183 | let l:inclusive = 1 184 | endif 185 | endif 186 | endif 187 | 188 | if !l:inclusive 189 | let [l:l2, l:c2] = matchup#pos#prev(l:l2, l:c2)[1:2] 190 | endif 191 | endif 192 | 193 | " check for the line-wise special case 194 | if l:line_count > 2 && l:linewise_op && strlen(l:close.match) > 1 195 | if l:c1 != 1 196 | let l:l1 += 1 197 | let l:c1 = 1 198 | endif 199 | let l:l2 = l:close.lnum - 1 200 | let l:c2 = strlen(getline(l:l2))+1 201 | endif 202 | 203 | " if this would be an empty selection.. 204 | if !a:visual && (l:l2 < l:l1 || l:l1 == l:l2 && l:c1 > l:c2) 205 | if v:operator ==# 'c' 206 | call matchup#pos#set_cursor(l:l1, l:c1) 207 | silent! execute "normal! i \v" 208 | elseif stridx('<>', v:operator) < 0 209 | let l:byte = line2byte(l:l1) + l:c1 - 1 210 | call feedkeys(l:byte.'go', 'n') 211 | endif 212 | return 213 | endif 214 | else 215 | let l:c2 += matchup#delim#end_offset(l:close) 216 | 217 | " make *a% more like *at for html 218 | " capture starting < 219 | if matchup#quirks#ishtmllike() 220 | \ && !matchup#util#matchpref('classic_textobj', 0) 221 | \ && l:close.match =~? '^/\w\+\s*>\=$' 222 | let l:c1 -= 1 223 | if l:close.match !~? '>$' 224 | let l:c2 += 1 225 | endif 226 | endif 227 | 228 | " special case for delete operator 229 | if !a:visual && v:operator ==# 'd' 230 | \ && l:line_count > 1 231 | \ && strpart(getline(l:l2), l:c2) =~# '^\s*$' 232 | \ && strpart(getline(l:l2), 0, l:c1-1) =~# '^\s*$' 233 | let l:c1 = 1 234 | let l:c2 = strlen(getline(l:l2))+1 235 | endif 236 | endif 237 | 238 | " in visual line mode, force new selection to not be smaller 239 | " (only check line numbers) 240 | if a:visual && visualmode() ==# 'V' 241 | \ && (l:l1 > l:selection[0] || l:l2 < l:selection[2]) 242 | continue 243 | endif 244 | 245 | " in other visual modes, try again if we didn't reach a bigger range 246 | if a:visual && visualmode() !=# 'V' 247 | \ && !matchup#pos#equal(l:selection[0:1], l:selection[2:3]) 248 | \ && (l:selection == [l:l1, l:c1, l:l2, l:c2] 249 | \ || matchup#pos#larger([l:l1, l:c1], l:selection[0:1]) 250 | \ || matchup#pos#larger(l:selection[2:3], [l:l2, l:c2])) 251 | continue 252 | endif 253 | 254 | break 255 | endfor 256 | 257 | " set the proper visual mode for this selection 258 | let l:select_mode = (v:operator ==# ':') 259 | \ ? visualmode() 260 | \ : (l:forced !=# '') 261 | \ ? l:forced 262 | \ : 'v' 263 | 264 | if &selection ==# 'exclusive' 265 | let [l:l2, l:c2] = matchup#pos#next_eol(l:l2, l:c2)[1:2] 266 | endif 267 | 268 | " apply selection 269 | execute 'normal!' l:select_mode 270 | normal! o 271 | call matchup#pos#set_cursor(l:l1, l:c1) 272 | normal! o 273 | call matchup#pos#set_cursor(l:l2, l:c2) 274 | if exists('l:save_reg') 275 | execute 'normal! "' . l:save_reg 276 | endif 277 | endfunction 278 | 279 | function! matchup#text_obj#undo(seq) 280 | if undotree().seq_cur > a:seq 281 | silent! undo 282 | endif 283 | endfunction 284 | 285 | " }}}1 286 | function! matchup#text_obj#double_click() abort " {{{1 287 | let [l:open, l:close] = [{}, {}] 288 | 289 | call matchup#perf#timeout_start(0) 290 | let l:delim = matchup#delim#get_current('all', 'both_all') 291 | if !empty(l:delim) 292 | let l:matches = matchup#delim#get_matching(l:delim, 1) 293 | if len(l:matches) > 1 && has_key(l:delim, 'links') 294 | let [l:open, l:close] = [l:delim.links.open, l:delim.links.close] 295 | endif 296 | endif 297 | 298 | if empty(l:open) || empty(l:close) 299 | call feedkeys("\<2-LeftMouse>", 'nt') 300 | return 301 | endif 302 | 303 | let [l:lnum, l:cnum] = [l:close.lnum, l:close.cnum] 304 | let l:cnum += matchup#delim#end_offset(l:close) 305 | 306 | if &selection ==# 'exclusive' 307 | let [l:lnum, l:cnum] = matchup#pos#next_eol(l:lnum, l:cnum)[1:2] 308 | endif 309 | 310 | call matchup#pos#set_cursor(l:open) 311 | normal! v 312 | call matchup#pos#set_cursor(l:lnum, l:cnum) 313 | if l:delim.side ==# 'close' 314 | normal! o 315 | endif 316 | endfunction 317 | 318 | " }}}1 319 | 320 | let &cpo = s:save_cpo 321 | 322 | " vim: fdm=marker sw=2 323 | 324 | -------------------------------------------------------------------------------- /autoload/matchup/transmute.vim: -------------------------------------------------------------------------------- 1 | " vim match-up - even better matching 2 | " 3 | " Maintainer: Andy Massimino 4 | " Email: a@normed.space 5 | " 6 | 7 | let s:save_cpo = &cpo 8 | set cpo&vim 9 | 10 | function! matchup#transmute#init_module() " {{{1 11 | if !g:matchup_transmute_enabled | return | endif 12 | 13 | call matchup#transmute#enable() 14 | endfunction 15 | 16 | " }}}1 17 | 18 | function! matchup#transmute#enable() " {{{1 19 | " TODO: add insert mode map 20 | " TODO: add g:matchup_transmute_auto 21 | endfunction 22 | 23 | " }}}1 24 | function! matchup#transmute#disable() " {{{1 25 | 26 | endfunction 27 | 28 | " }}}1 29 | 30 | function! matchup#transmute#tick(insertmode) abort " {{{1 31 | if !g:matchup_transmute_enabled | return 0 | endif 32 | 33 | if a:insertmode 34 | return 0 35 | endif 36 | 37 | if changenr() > get(w:, 'matchup_transmute_last_changenr', -1) 38 | \ && !empty('w:matchup_matchparen_context.prior') 39 | let w:matchup_transmute_last_changenr = changenr() 40 | 41 | return matchup#transmute#dochange( 42 | \ w:matchup_matchparen_context.prior.corrlist, 43 | \ w:matchup_matchparen_context.prior.current, 44 | \ w:matchup_matchparen_context.normal.current) 45 | endif 46 | 47 | return 0 48 | endfunction 49 | 50 | " }}}1 51 | function! matchup#transmute#reset() abort " {{{1 52 | if !g:matchup_transmute_enabled | return 0 | endif 53 | let w:matchup_transmute_last_changenr = changenr() 54 | endfunction 55 | 56 | " }}}1 57 | function! matchup#transmute#dochange(list, pri, cur) abort " {{{1 58 | if empty(a:pri) || a:cur.type !=# a:pri.type 59 | return 0 60 | endif 61 | if !has_key(s:dochange, a:cur.type) 62 | return 0 63 | endif 64 | return s:dochange[a:cur.type](a:list, a:pri, a:cur) 65 | endfunction 66 | 67 | " }}}1 68 | 69 | let s:dochange = {} 70 | 71 | function! s:dochange.delim_py(list, pri, cur) abort " {{{1 72 | return 0 73 | endfunction 74 | 75 | " }}}1 76 | function! s:dochange.delim_tex(list, pri, cur) abort " {{{1 77 | if empty(a:list) || empty(a:pri) || empty(a:cur) | return 0 | endif 78 | 79 | let l:cur = a:cur 80 | 81 | " check back one 82 | if a:pri.class[0] != l:cur.class[0] 83 | let l:cur = matchup#delim#get_current('all', a:pri.side, 84 | \ {'insertmode': 1}) 85 | if empty(l:cur) | return 0 | endif 86 | endif 87 | 88 | " right now, only same-class changes are supported 89 | if a:pri.class[0] != l:cur.class[0] 90 | return 0 91 | endif 92 | if a:pri.side =~# '^open\|close$' && a:pri.side isnot l:cur.side 93 | return 0 94 | endif 95 | if !matchup#pos#equal(a:pri, l:cur) 96 | return 0 97 | endif 98 | 99 | let l:num_changes = 0 100 | 101 | let l:delta = strdisplaywidth(l:cur.match) 102 | \ - strdisplaywidth(a:pri.match) 103 | 104 | for l:i in range(len(a:list)) 105 | if l:i == a:pri.match_index | continue | endif 106 | 107 | let l:corr = a:list[l:i] 108 | let l:line = getline(l:corr.lnum) 109 | 110 | let l:column = l:corr.cnum 111 | if l:corr.lnum == l:cur.lnum && l:i > a:pri.match_index 112 | let l:column += l:delta 113 | endif 114 | 115 | let l:re_anchored = '\%'.(l:column).'c' 116 | \ . '\%('.(l:corr.regexone[l:corr.side]).'\)' 117 | 118 | let l:groups = copy(l:corr.groups) 119 | for l:grp in keys(l:groups) 120 | let l:count = len(split(l:re_anchored, 121 | \ g:matchup#re#not_bslash.'\\'.l:grp))-1 122 | if l:count == 0 | continue | endif 123 | 124 | if l:cur.groups[l:grp] ==# l:groups[l:grp] 125 | continue 126 | endif 127 | 128 | for l:dummy in range(len(l:count)) 129 | " create a pattern which isolates the old group text 130 | let l:prevtext = s:qescape(l:groups[l:grp]) 131 | let l:pattern = substitute(l:re_anchored, 132 | \ g:matchup#re#not_bslash.'\\'.l:grp, 133 | \ '\=''\zs\V'.l:prevtext.'\m\ze''', '') 134 | let l:pattern = matchup#delim#fill_backrefs(l:pattern, 135 | \ l:groups, 0) 136 | let l:string = l:cur.groups[l:grp] 137 | let l:line = substitute(l:line, l:pattern, 138 | \ '\='''.s:qescape(l:string)."'", '') 139 | endfor 140 | 141 | let l:groups[l:grp] = l:cur.groups[l:grp] 142 | endfor 143 | 144 | if getline(l:corr.lnum) !=# l:line 145 | if g:matchup_transmute_breakundo && l:num_changes == 0 146 | execute "normal! a\u" 147 | endif 148 | call setline(l:corr.lnum, l:line) 149 | let l:num_changes += 1 150 | endif 151 | endfor 152 | 153 | return l:num_changes 154 | endfunction 155 | 156 | function! s:qescape(str) 157 | return escape(substitute(a:str, "'", "''", 'g'), '\') 158 | endfunction 159 | 160 | " }}}1 161 | 162 | let &cpo = s:save_cpo 163 | 164 | " vim: fdm=marker sw=2 165 | -------------------------------------------------------------------------------- /autoload/matchup/ts_engine.vim: -------------------------------------------------------------------------------- 1 | " vim match-up - even better matching 2 | " 3 | " Maintainer: Andy Massimino 4 | " Email: a@normed.space 5 | " 6 | 7 | let s:save_cpo = &cpo 8 | set cpo&vim 9 | 10 | function! s:forward(fn, ...) 11 | let l:ret = luaeval( 12 | \ 'require"treesitter-matchup.internal".' . a:fn . '(unpack(_A))', 13 | \ a:000) 14 | return l:ret 15 | endfunction 16 | 17 | function! matchup#ts_engine#is_enabled(bufnr) abort 18 | if !has('nvim-0.5.0') 19 | return 0 20 | endif 21 | return +s:forward('is_enabled', a:bufnr) 22 | endfunction 23 | 24 | function! matchup#ts_engine#is_hl_enabled(bufnr) abort 25 | if !has('nvim-0.5.0') 26 | return 0 27 | endif 28 | return +s:forward('is_hl_enabled', a:bufnr) 29 | endfunction 30 | 31 | function! matchup#ts_engine#get_option(bufnr, opt_name) abort 32 | return s:forward('get_option', a:bufnr, a:opt_name) 33 | endfunction 34 | 35 | let s:attached = {} 36 | 37 | function! matchup#ts_engine#attach(bufnr, lang) abort 38 | let s:attached[a:bufnr] = a:lang 39 | endfunction 40 | 41 | function! matchup#ts_engine#detach(bufnr) abort 42 | unlet s:attached[a:bufnr] 43 | endfunction 44 | 45 | function! matchup#ts_engine#get_delim(opts) abort 46 | call matchup#perf#tic('ts_engine.get_delim') 47 | 48 | let l:res = s:forward('get_delim', bufnr('%'), a:opts) 49 | if empty(l:res) 50 | call matchup#perf#toc('ts_engine.get_delim', 'fail') 51 | return {} 52 | endif 53 | 54 | let l:res.get_matching = function('matchup#ts_engine#get_matching') 55 | 56 | call matchup#perf#toc('ts_engine.get_delim', 'done') 57 | 58 | return l:res 59 | endfunction 60 | 61 | function! matchup#ts_engine#get_matching(down, _) dict abort 62 | call matchup#perf#tic('ts_engine.get_matching') 63 | 64 | let l:list = s:forward('get_matching', self, a:down, bufnr('%')) 65 | 66 | call matchup#perf#toc('ts_engine.get_matching', 'done') 67 | 68 | return l:list 69 | endfunction 70 | 71 | let &cpo = s:save_cpo 72 | 73 | " vim: fdm=marker sw=2 74 | -------------------------------------------------------------------------------- /autoload/matchup/ts_syntax.vim: -------------------------------------------------------------------------------- 1 | " vim match-up - even better matching 2 | " 3 | " Maintainer: Andy Massimino 4 | " Email: a@normed.space 5 | " 6 | 7 | let s:save_cpo = &cpo 8 | set cpo&vim 9 | 10 | function! s:forward(fn, ...) abort 11 | let l:ret = luaeval( 12 | \ 'require"treesitter-matchup.syntax".' . a:fn . '(unpack(_A))', 13 | \ a:000) 14 | return l:ret 15 | endfunction 16 | 17 | function! matchup#ts_syntax#synID(lnum, col, trans) abort 18 | return s:forward('synID', a:lnum, a:col, a:trans) 19 | endfunction 20 | 21 | function! matchup#ts_syntax#lang_skip(lnum, col) abort 22 | return s:forward('lang_skip', a:lnum, a:col) 23 | endfunction 24 | 25 | function! matchup#ts_syntax#skip_expr(lnum, col) abort 26 | if matchup#ts_syntax#lang_skip(a:lnum, a:col) 27 | return 1 28 | endif 29 | 30 | let l:syn = synIDattr(matchup#ts_syntax#synID( 31 | \ a:lnum, a:col, 1), 'name') 32 | return l:syn =~? '\%(String\|Comment\|Character\)' 33 | endfunction 34 | 35 | let &cpo = s:save_cpo 36 | 37 | " vim: fdm=marker sw=2 38 | -------------------------------------------------------------------------------- /autoload/matchup/unmatchit.vim: -------------------------------------------------------------------------------- 1 | " vim match-up - even better matching 2 | " 3 | " Maintainer: Andy Massimino 4 | " Email: a@normed.space 5 | " 6 | 7 | " this file is loaded only from plugin/matchup.vim 8 | 9 | if !exists('g:loaded_matchup') 10 | \ || !exists('g:loaded_matchit') 11 | \ || !exists(':MatchDebug') 12 | finish 13 | endif 14 | 15 | function! matchup#unmatchit#() 16 | endfunction 17 | 18 | unlet g:loaded_matchit 19 | 20 | delcommand MatchDebug 21 | 22 | silent! unmap % 23 | silent! unmap [% 24 | silent! unmap ]% 25 | silent! unmap a% 26 | silent! unmap g% 27 | 28 | " vim: fdm=marker sw=2 29 | -------------------------------------------------------------------------------- /autoload/matchup/util.vim: -------------------------------------------------------------------------------- 1 | " vim match-up - even better matching 2 | " 3 | " Maintainer: Andy Massimino 4 | " Email: a@normed.space 5 | " 6 | 7 | let s:save_cpo = &cpo 8 | set cpo&vim 9 | 10 | function! matchup#util#command(cmd) " {{{1 11 | let l:lines = '' 12 | try 13 | execute 'silent! redir => l:lines' 14 | silent! execute a:cmd 15 | redir END 16 | finally 17 | return split(l:lines, '\n') 18 | endtry 19 | endfunction 20 | 21 | " }}}1 22 | 23 | function! matchup#util#in_comment(...) " {{{1 24 | return call('matchup#util#in_syntax', ['^Comment$'] + a:000) 25 | endfunction 26 | 27 | " }}}1 28 | function! matchup#util#in_string(...) " {{{1 29 | return call('matchup#util#in_syntax', ['^String$'] + a:000) 30 | endfunction 31 | 32 | " }}}1 33 | function! matchup#util#in_comment_or_string(...) " {{{1 34 | return call('matchup#util#in_syntax', 35 | \ ['\%(String\|Comment\)'] + a:000) 36 | endfunction 37 | 38 | " }}}1 39 | function! matchup#util#in_syntax(name, ...) " {{{1 40 | " usage: matchup#util#in_syntax(name, [line, col]) 41 | let l:pos = a:0 > 0 ? [a:1, a:2] : [line('.'), col('.')] 42 | 43 | " check syntax at position (same as matchit's s: method) 44 | let l:syn = synIDattr(synID(l:pos[0], l:pos[1], 1), 'name') 45 | return l:syn =~? a:name 46 | endfunction 47 | 48 | " }}}1 49 | function! matchup#util#in_synstack(name, ...) abort " {{{1 50 | let l:pos = a:0 > 0 ? [a:1, a:2] : [line('.'), col('.')] 51 | let l:syn = map(synstack(l:pos[0], l:pos[1]), 52 | \ "synIDattr(v:val, 'name')") 53 | return match(l:syn, '^' . a:name . '$') >= 0 54 | endfunction 55 | 56 | " }}}1 57 | 58 | function! matchup#util#in_whitespace(...) " {{{1 59 | let l:pos = a:0 > 0 ? [a:1, a:2] : [line('.'), col('.')] 60 | return matchstr(getline(l:pos[0]), '\%'.l:pos[1].'c.') =~# '\s' 61 | endfunction 62 | 63 | " }}}1 64 | function! matchup#util#in_indent(...) " {{{1 65 | let l:pos = a:0 > 0 ? [a:1, a:2] : [line('.'), col('.')] 66 | return l:pos[1] > 0 && getline(l:pos[0]) =~# '^\s*\%'.(l:pos[1]+1).'c' 67 | endfunction 68 | 69 | " }}}1 70 | 71 | function! matchup#util#has_duplicate_str(list) " {{{1 72 | if len(a:list) <= 1 | return 0 | endif 73 | let l:seen = {} 74 | for l:elem in a:list 75 | if has_key(l:seen, l:elem) 76 | return 1 77 | endif 78 | let l:seen[l:elem] = 1 79 | endfor 80 | return 0 81 | endfunction 82 | 83 | " }}}1 84 | 85 | function! matchup#util#patch_match_words(from, to, ...) abort " {{{1 86 | if !exists('b:match_words') | return | endif 87 | 88 | " if extra argument is given, give diagnostic information 89 | if a:0 90 | let l:first = stridx(b:match_words, a:from) 91 | if l:first < 0 92 | echoerr 'match-up: patch_match_words:' a:from 'not found' 93 | return 94 | elseif stridx(b:match_words, a:from, l:first+1) > -1 95 | echoerr 'match-up: patch_match_words: multiple occurences of' a:from 96 | return 97 | endif 98 | endif 99 | 100 | let b:match_words = substitute(b:match_words, 101 | \ '\V'.escape(a:from, '\'), 102 | \ escape(a:to, '\'), 103 | \ '') 104 | endfunction 105 | 106 | " }}}1 107 | function! matchup#util#check_match_words(sha256) abort " {{{1 108 | if !exists('b:match_words') | return 0 | endif 109 | return sha256(b:match_words) =~# '^'.a:sha256 110 | endfunction 111 | 112 | " }}}1 113 | function! matchup#util#append_match_words(str) abort " {{{1 114 | if !exists('b:match_words') 115 | let b:match_words = '' 116 | endif 117 | 118 | if len(b:match_words) && b:match_words[-1] !=# ',' && a:str[0] !=# ',' 119 | let b:match_words .= ',' 120 | endif 121 | let b:match_words .= a:str 122 | endfunction 123 | 124 | " }}}1 125 | 126 | function! matchup#util#matchpref(id, default) abort " {{{1 127 | return get(get(g:matchup_matchpref, &filetype, {}), a:id, a:default) 128 | endfunction 129 | 130 | " }}}1 131 | 132 | function! matchup#util#standard_html(...) abort " {{{1 133 | let l:prefs = a:0 ? a:1 : {} 134 | let l:variant = get(l:prefs, 'variant', 'html') 135 | 136 | let l:words = '<:>,<\@<=!--:-->' 137 | 138 | if l:variant ==# 'html' && get(l:prefs, 'lists', 0) 139 | let l:words .= ',<\@<=[ou]l\>\g{hlend}[^>]*\%(>\|$\)' 140 | \ . ':<\@<=li\>' 141 | \ . ':<\@<=/[ou]l\g{hlend}>' 142 | let l:words .= ',<\@<=dl\>\g{hlend}[^>]*\%(>\|$\)' 143 | \ . ':<\@<=d[td]\>' 144 | \ . ':<\@<=/dl\g{hlend}>' 145 | endif 146 | 147 | if l:variant ==# 'html' 148 | let l:words .= ',<\@<=\([^/!][^ \t>]*\)\g{hlend}' 149 | \ . '\%(>\|$\|[ \t][^>]*\%(>\|$\)\)' 150 | \ . ':<\@<=/\1\g{hlend}>' 151 | elseif l:variant ==# 'xml' 152 | let l:words .= ',<\@<=!\[CDATA\[:]]>' 153 | let l:words .= ',<\@<=?\k\+:?>' 154 | let l:words .= ',<\@<=\([^ \t>/]\+\)\g{hlend}' 155 | \ . '\%(\s\+[^>]*\%([^/]>\|$\)\|>\|$\)' 156 | \ . ':<\@<=/\1\g{hlend}>' 157 | let l:words .= ',<\@<=\%([^ \t>/]\+\)\g{hlend}' 158 | \ . '\%(\s\+[^>]*[^/>]\|$\)' 159 | \ . ':/>' 160 | else 161 | echoerr 'match-up: invalid variant' l:variant 162 | endif 163 | 164 | if !get(l:prefs, 'tagnameonly', 1) 165 | let l:words = substitute(l:words, '\\g{hlend}', '', 'g') 166 | endif 167 | 168 | return l:words 169 | endfunction 170 | 171 | " }}}1 172 | function! matchup#util#standard_xml(...) abort " {{{1 173 | let l:prefs = a:0 ? copy(a:1) : {} 174 | let l:prefs['variant'] = 'xml' 175 | return matchup#util#standard_html(l:prefs) 176 | endfunction 177 | 178 | " }}}1 179 | 180 | let &cpo = s:save_cpo 181 | 182 | " vim: fdm=marker sw=2 183 | -------------------------------------------------------------------------------- /autoload/matchup/where.vim: -------------------------------------------------------------------------------- 1 | " vim match-up - even better matching 2 | " 3 | " Maintainer: Andy Massimino 4 | " Email: a@normed.space 5 | " 6 | 7 | scriptencoding utf8 8 | 9 | let s:save_cpo = &cpo 10 | set cpo&vim 11 | 12 | let s:curpos = [] 13 | 14 | function! matchup#where#get(timeout) abort " {{{1 15 | let l:save_view = winsaveview() 16 | let l:trail = [] 17 | 18 | let l:prev = [matchup#pos#get_cursor_line(), 1] 19 | call matchup#pos#set_cursor(l:prev) 20 | for l:dummy in range(15) 21 | " TODO make this into an api 22 | " TODO replace with a faster version with searchpairpos/return value? 23 | let l:opts_io = { 24 | \ '__where_impl__': 1, 25 | \ 'timeout': a:timeout, 26 | \} 27 | call matchup#motion#find_unmatched(0, 0, l:opts_io) 28 | 29 | if matchup#pos#get_cursor()[1:2] == l:prev 30 | break 31 | endif 32 | 33 | let l:prev = matchup#pos#get_cursor()[1:2] 34 | call add(l:trail, l:prev + [l:opts_io.delim]) 35 | endfor 36 | 37 | call winrestview(l:save_view) 38 | return reverse(l:trail) 39 | endfunction 40 | 41 | " }}}1 42 | 43 | function! s:print_verbose() " {{{1 44 | echohl Title | echon 'match-up:' | echohl None 45 | echon ' loading...' 46 | let l:trail = matchup#where#get(500) 47 | redraw! 48 | if empty(l:trail) 49 | echohl Title | echon 'match-up:' | echohl None 50 | echon ' no context found' 51 | return 52 | endif 53 | let l:last = -1 54 | for l:t in l:trail 55 | let l:opts = { 56 | \ 'noshowdir': 1, 57 | \ 'width': &columns - 1, 58 | \} 59 | let [l:str, l:adj] = matchup#matchparen#status_str(l:t[2], l:opts) 60 | if l:adj == l:last 61 | continue 62 | endif 63 | if l:last != -1 64 | echon "\n" 65 | endif 66 | call s:EchoHLString(l:str) 67 | let l:last = l:adj 68 | endfor 69 | endfunction 70 | 71 | " }}}1 72 | function! s:print_short() " {{{1 73 | echohl Title | echon 'match-up:' | echohl None 74 | echon ' loading...' 75 | let l:trail = matchup#where#get(200) 76 | redraw! 77 | if empty(l:trail) 78 | echohl Title | echon 'match-up:' | echohl None 79 | echon ' no context found' 80 | return 81 | endif 82 | " TODO len(trail) is not quite right here 83 | let l:width = (&columns - 3*(len(l:trail)-1)) / len(l:trail) 84 | let l:fullstr = '' 85 | let l:prev = -1 86 | for l:t in l:trail 87 | let l:opts = { 88 | \ 'noshowdir': 1, 89 | \ 'compact': l:prev != -1, 90 | \ 'width': l:width, 91 | \} 92 | let [l:str, l:adj] = matchup#matchparen#status_str(l:t[2], l:opts) 93 | if l:adj == l:prev 94 | continue 95 | endif 96 | if l:prev != -1 97 | let l:fullstr .= ' %#Title#' . s:arrow() . '%#Normal# ' 98 | endif 99 | let l:fullstr .= l:str 100 | let l:prev = l:adj 101 | endfor 102 | call matchup#perf#tic('where') 103 | call s:EchoHLString(l:fullstr) 104 | call matchup#perf#toc('where', 'echohlstring') 105 | endfunction 106 | 107 | function! s:arrow() 108 | if empty(g:matchup_where_separator) 109 | return g:matchup_matchparen_start_sign 110 | endif 111 | return g:matchup_where_separator 112 | endfunction 113 | 114 | " }}}1 115 | 116 | function! matchup#where#print(args) 117 | let l:verbose = 0 118 | if a:args =~? '!' || len(a:args) >= 2 119 | \ || a:args =~? '?' && s:curpos == getcurpos() 120 | let l:verbose = 1 121 | endif 122 | let s:curpos = getcurpos() 123 | 124 | if l:verbose 125 | call s:print_verbose() 126 | else 127 | call s:print_short() 128 | endif 129 | endfunction 130 | 131 | function! s:EchoHLString(str) 132 | let l:str = '%<' . substitute(a:str, '%{[^}]\+}', '', 'g') 133 | let l:pat = '\%(%\(<\)\|%#\([0-9A-Za-z_@.]*\)#\)' 134 | let l:components = split(l:str, l:pat.'\&') 135 | call map(l:components, 'matchlist(v:val, "^".l:pat."\\(.*\\)")') 136 | 137 | for l:c in l:components 138 | let l:m = matchlist(l:c, '^'.l:pat.'\(.*\)') 139 | if empty(l:m) 140 | let l:str = l:c 141 | elseif !empty(l:m[1]) 142 | let l:str = l:m[3] 143 | echon l:m[2] 144 | elseif !empty(l:m[2]) 145 | let l:str = l:m[3] 146 | execute 'echohl' l:m[2] 147 | endif 148 | echon l:str 149 | endfor 150 | echohl NONE 151 | endfunction 152 | 153 | let &cpo = s:save_cpo 154 | 155 | " vim: fdm=marker sw=2 156 | 157 | -------------------------------------------------------------------------------- /lua/match-up.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | local function do_setup(opts, validate) 4 | for mod, elem in pairs(opts) do 5 | for key, val in pairs(type(elem) == 'table' and elem or {}) do 6 | local opt = 'matchup_'..mod..'_'..key 7 | if validate and vim.g[opt] == nil then 8 | error(string.format('invalid option name %s.%s', mod, key)) 9 | end 10 | vim.g[opt] = val 11 | end 12 | end 13 | end 14 | 15 | function M.setup(opts) 16 | local sync = opts.sync 17 | if sync then 18 | vim.cmd[[runtime! plugin/matchup.vim]] 19 | end 20 | 21 | do_setup(opts, sync) 22 | end 23 | 24 | return M 25 | -------------------------------------------------------------------------------- /lua/treesitter-matchup.lua: -------------------------------------------------------------------------------- 1 | if not pcall(require, 'nvim-treesitter') then 2 | return {init = function() end} 3 | end 4 | 5 | local treesitter = require 'nvim-treesitter' 6 | local queries = require 'nvim-treesitter.query' 7 | 8 | local M = {} 9 | 10 | function M.init() 11 | treesitter.define_modules { 12 | matchup = { 13 | module_path = 'treesitter-matchup.internal', 14 | is_supported = function(lang) 15 | return queries.has_query_files(lang, 'matchup') 16 | end 17 | } 18 | } 19 | end 20 | 21 | return M 22 | -------------------------------------------------------------------------------- /lua/treesitter-matchup/compat.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | 3 | local ts = vim.treesitter 4 | local tsq = vim.treesitter.query 5 | 6 | M.get_node_text = function(node, source, opts) 7 | return (ts.get_node_text or tsq.get_node_text)(node, source, opts) 8 | end 9 | 10 | M.get_query = function(lang, query_name) 11 | return (tsq.get or tsq.get_query)(lang, query_name) 12 | end 13 | 14 | return M 15 | -------------------------------------------------------------------------------- /lua/treesitter-matchup/syntax.lua: -------------------------------------------------------------------------------- 1 | if not pcall(require, 'nvim-treesitter') then 2 | return { 3 | is_active = function() return false end, 4 | synID = function(lnum, col, transparent) 5 | return vim.fn.synID(lnum, col, transparent) 6 | end 7 | } 8 | end 9 | 10 | local api = vim.api 11 | local hl_info = require'treesitter-matchup.third-party.hl-info' 12 | local queries = require'treesitter-matchup.third-party.query' 13 | local ts_utils = require'nvim-treesitter.ts_utils' 14 | local parsers = require'nvim-treesitter.parsers' 15 | 16 | local M = {} 17 | 18 | function M.is_active(bufnr) 19 | bufnr = bufnr or api.nvim_get_current_buf() 20 | return (hl_info.active() 21 | and api.nvim_buf_get_option(bufnr, 'syntax') == '') 22 | end 23 | 24 | --- Get all nodes that are marked as skip 25 | function M.get_skips(bufnr) 26 | local matches = queries.get_matches(bufnr, 'matchup') 27 | 28 | local skips = {} 29 | 30 | for _, match in ipairs(matches) do 31 | if match.skip then 32 | skips[match.skip.node:id()] = 1 33 | end 34 | end 35 | 36 | return skips 37 | end 38 | 39 | local function get_node_at_pos(cursor) 40 | local cursor_range = { cursor[1] - 1, cursor[2] } 41 | 42 | local buf = vim.api.nvim_win_get_buf(0) 43 | local root_lang_tree = parsers.get_parser(buf) 44 | if not root_lang_tree then 45 | return 46 | end 47 | local root = ts_utils.get_root_for_position( 48 | cursor_range[1], cursor_range[2], root_lang_tree) 49 | 50 | if not root then 51 | return 52 | end 53 | 54 | return root:named_descendant_for_range( 55 | cursor_range[1], cursor_range[2], cursor_range[1], cursor_range[2]) 56 | end 57 | 58 | function M.lang_skip(lnum, col) 59 | local bufnr = api.nvim_get_current_buf() 60 | local skips = M.get_skips(bufnr) 61 | 62 | if vim.tbl_isempty(skips) then 63 | return false 64 | end 65 | 66 | local node = get_node_at_pos({lnum, col - 1}) 67 | if not node then 68 | return false 69 | end 70 | if skips[node:id()] then 71 | return true 72 | end 73 | 74 | return false 75 | end 76 | 77 | function M.synID(lnum, col, transparent) 78 | if not M.is_active() then 79 | return vim.fn.synID(lnum, col, transparent) 80 | end 81 | 82 | local cursor = { lnum, col - 1 } 83 | local matches = hl_info.get_treesitter_hl(cursor) 84 | if #matches < 1 then 85 | return 0 86 | end 87 | 88 | -- heuristically get the last group with any hl definitions 89 | for i = 1, #matches do 90 | local group = matches[#matches + 1 - i] 91 | group = group[#group] 92 | 93 | local id = vim.fn.hlID(group) 94 | local trans_id = vim.fn.synIDtrans(id) 95 | if vim.fn.synIDattr(trans_id, 'fg') ~= '' 96 | or vim.fn.synIDattr(trans_id, 'fg') ~= '' then 97 | return id 98 | end 99 | end 100 | 101 | return 0 102 | end 103 | 104 | return M 105 | -------------------------------------------------------------------------------- /lua/treesitter-matchup/third-party/hl-info.lua: -------------------------------------------------------------------------------- 1 | -- From https://github.com/nvim-treesitter/playground 2 | -- Copyright 2021 3 | -- licensed under the Apache License 2.0 4 | -- See nvim-treesitter.LICENSE-APACHE-2.0 5 | 6 | local ts = vim.treesitter 7 | local utils = require "treesitter-matchup.third-party.utils" 8 | local highlighter = require "vim.treesitter.highlighter" 9 | 10 | local M = {} 11 | 12 | if vim.treesitter.highlighter.hl_map and vim.fn.has('nvim-0.9.0') == 0 then 13 | function M.get_treesitter_hl(cursor) 14 | local buf = vim.api.nvim_get_current_buf() 15 | local row, col = unpack(cursor or vim.api.nvim_win_get_cursor(0)) 16 | row = row - 1 17 | 18 | local self = highlighter.active[buf] 19 | 20 | if not self then 21 | return {} 22 | end 23 | 24 | local matches = {} 25 | 26 | self.tree:for_each_tree(function(tstree, tree) 27 | if not tstree then 28 | return 29 | end 30 | 31 | local root = tstree:root() 32 | local root_start_row, _, root_end_row, _ = root:range() 33 | 34 | -- Only worry about trees within the line range 35 | if root_start_row > row or root_end_row < row then 36 | return 37 | end 38 | 39 | local query = self:get_query(tree:lang()) 40 | 41 | -- Some injected languages may not have highlight queries. 42 | if not query:query() then 43 | return 44 | end 45 | 46 | local iter = query:query():iter_captures(root, self.bufnr, row, row + 1) 47 | 48 | for capture, node, _ in iter do 49 | if ts.is_in_node_range(node, row, col) then 50 | local c = query._query.captures[capture] -- name of the capture in the query 51 | if c ~= nil then 52 | local general_hl, is_vim_hl = query:_get_hl_from_capture(capture) 53 | local local_hl = not is_vim_hl and (tree:lang() .. general_hl) 54 | local line = { c } 55 | if local_hl then 56 | table.insert(line, local_hl) 57 | end 58 | if general_hl and general_hl ~= local_hl then 59 | table.insert(line, general_hl) 60 | end 61 | table.insert(matches, line) 62 | end 63 | end 64 | end 65 | end, true) 66 | return matches 67 | end 68 | else 69 | function M.get_treesitter_hl(cursor) 70 | local bufnr = vim.api.nvim_get_current_buf() 71 | local row, col = unpack(cursor or vim.api.nvim_win_get_cursor(0)) 72 | row = row - 1 73 | 74 | local results = utils.get_hl_groups_at_position(bufnr, row, col) 75 | local highlights = {} 76 | for _, hl in pairs(results) do 77 | local line = { "@" .. hl.capture } 78 | if hl.priority then 79 | table.insert(line, hl.priority) 80 | end 81 | table.insert(highlights, line) 82 | end 83 | return highlights 84 | end 85 | end 86 | 87 | function M.active() 88 | local buf = vim.api.nvim_get_current_buf() 89 | if highlighter.active[buf] then 90 | return true 91 | end 92 | return false 93 | end 94 | 95 | return M 96 | -------------------------------------------------------------------------------- /lua/treesitter-matchup/third-party/lru.LICENSE-MIT: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Boris Nagaev 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /lua/treesitter-matchup/third-party/lru.lua: -------------------------------------------------------------------------------- 1 | -- lua-lru, LRU cache in Lua 2 | -- Copyright (c) 2015 Boris Nagaev 3 | -- See the LICENSE file for terms of use. 4 | 5 | local lru = {} 6 | 7 | function lru.new(max_size, max_bytes) 8 | 9 | assert(max_size >= 1, "max_size must be >= 1") 10 | assert(not max_bytes or max_bytes >= 1, 11 | "max_bytes must be >= 1") 12 | 13 | -- current size 14 | local size = 0 15 | local bytes_used = 0 16 | 17 | -- map is a hash map from keys to tuples 18 | -- tuple: value, prev, next, key 19 | -- prev and next are pointers to tuples 20 | local map = {} 21 | 22 | -- indices of tuple 23 | local VALUE = 1 24 | local PREV = 2 25 | local NEXT = 3 26 | local KEY = 4 27 | local BYTES = 5 28 | 29 | -- newest and oldest are ends of double-linked list 30 | local newest = nil -- first 31 | local oldest = nil -- last 32 | 33 | local removed_tuple -- created in del(), removed in set() 34 | 35 | -- remove a tuple from linked list 36 | local function cut(tuple) 37 | local tuple_prev = tuple[PREV] 38 | local tuple_next = tuple[NEXT] 39 | tuple[PREV] = nil 40 | tuple[NEXT] = nil 41 | if tuple_prev and tuple_next then 42 | tuple_prev[NEXT] = tuple_next 43 | tuple_next[PREV] = tuple_prev 44 | elseif tuple_prev then 45 | -- tuple is the oldest element 46 | tuple_prev[NEXT] = nil 47 | oldest = tuple_prev 48 | elseif tuple_next then 49 | -- tuple is the newest element 50 | tuple_next[PREV] = nil 51 | newest = tuple_next 52 | else 53 | -- tuple is the only element 54 | newest = nil 55 | oldest = nil 56 | end 57 | end 58 | 59 | -- insert a tuple to the newest end 60 | local function setNewest(tuple) 61 | if not newest then 62 | newest = tuple 63 | oldest = tuple 64 | else 65 | tuple[NEXT] = newest 66 | newest[PREV] = tuple 67 | newest = tuple 68 | end 69 | end 70 | 71 | local function del(key, tuple) 72 | map[key] = nil 73 | cut(tuple) 74 | size = size - 1 75 | bytes_used = bytes_used - (tuple[BYTES] or 0) 76 | removed_tuple = tuple 77 | end 78 | 79 | -- removes elemenets to provide enough memory 80 | -- returns last removed element or nil 81 | local function makeFreeSpace(bytes) 82 | while size + 1 > max_size or 83 | (max_bytes and bytes_used + bytes > max_bytes) 84 | do 85 | assert(oldest, "not enough storage for cache") 86 | del(oldest[KEY], oldest) 87 | end 88 | end 89 | 90 | local function get(_, key) 91 | local tuple = map[key] 92 | if not tuple then 93 | return nil 94 | end 95 | cut(tuple) 96 | setNewest(tuple) 97 | return tuple[VALUE] 98 | end 99 | 100 | local function set(_, key, value, bytes) 101 | local tuple = map[key] 102 | if tuple then 103 | del(key, tuple) 104 | end 105 | if value ~= nil then 106 | -- the value is not removed 107 | bytes = max_bytes and (bytes or #value) or 0 108 | makeFreeSpace(bytes) 109 | local tuple1 = removed_tuple or {} 110 | map[key] = tuple1 111 | tuple1[VALUE] = value 112 | tuple1[KEY] = key 113 | tuple1[BYTES] = max_bytes and bytes 114 | size = size + 1 115 | bytes_used = bytes_used + bytes 116 | setNewest(tuple1) 117 | else 118 | assert(key ~= nil, "Key may not be nil") 119 | end 120 | removed_tuple = nil 121 | end 122 | 123 | local function delete(_, key) 124 | return set(_, key, nil) 125 | end 126 | 127 | local function mynext(_, prev_key) 128 | local tuple 129 | if prev_key then 130 | tuple = map[prev_key][NEXT] 131 | else 132 | tuple = newest 133 | end 134 | if tuple then 135 | return tuple[KEY], tuple[VALUE] 136 | else 137 | return nil 138 | end 139 | end 140 | 141 | -- returns iterator for keys and values 142 | local function lru_pairs() 143 | return mynext, nil, nil 144 | end 145 | 146 | local mt = { 147 | __index = { 148 | get = get, 149 | set = set, 150 | delete = delete, 151 | pairs = lru_pairs, 152 | }, 153 | __pairs = lru_pairs, 154 | } 155 | 156 | return setmetatable({}, mt) 157 | end 158 | 159 | return lru 160 | -------------------------------------------------------------------------------- /lua/treesitter-matchup/third-party/plenary.LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 TJ DeVries 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /lua/treesitter-matchup/third-party/reload.lua: -------------------------------------------------------------------------------- 1 | -- From https://github.com/nvim-lua/plenary.nvim 2 | -- MIT License 3 | -- Copyright (c) 2020 TJ DeVries 4 | -- See plenary.LICENSE-MIT 5 | 6 | local reload = {} 7 | 8 | reload.reload_module = function(module_name, starts_with_only) 9 | -- TODO: Might need to handle cpath / compiled lua packages? Not sure. 10 | local matcher 11 | if not starts_with_only then 12 | matcher = function(pack) 13 | return string.find(pack, module_name, 1, true) 14 | end 15 | else 16 | matcher = function(pack) 17 | return string.find(pack, '^' .. module_name) 18 | end 19 | end 20 | 21 | for pack, _ in pairs(package.loaded) do 22 | if matcher(pack) then 23 | package.loaded[pack] = nil 24 | end 25 | end 26 | end 27 | 28 | return reload 29 | -------------------------------------------------------------------------------- /lua/treesitter-matchup/third-party/utils.lua: -------------------------------------------------------------------------------- 1 | -- From https://github.com/nvim-treesitter/playground 2 | -- Copyright 2021 3 | -- licensed under the Apache License 2.0 4 | -- See nvim-treesitter.LICENSE-APACHE-2.0 5 | 6 | local api = vim.api 7 | local ts = vim.treesitter 8 | local highlighter = require "vim.treesitter.highlighter" 9 | 10 | local M = {} 11 | 12 | function M.debounce(fn, debounce_time) 13 | local timer = vim.loop.new_timer() 14 | local is_debounce_fn = type(debounce_time) == "function" 15 | 16 | return function(...) 17 | timer:stop() 18 | 19 | local time = debounce_time 20 | local args = { ... } 21 | 22 | if is_debounce_fn then 23 | time = debounce_time() 24 | end 25 | 26 | timer:start( 27 | time, 28 | 0, 29 | vim.schedule_wrap(function() 30 | fn(unpack(args)) 31 | end) 32 | ) 33 | end 34 | end 35 | 36 | function M.get_hl_groups_at_position(bufnr, row, col) 37 | local buf_highlighter = highlighter.active[bufnr] 38 | 39 | if not buf_highlighter then 40 | return {} 41 | end 42 | 43 | local matches = {} 44 | 45 | buf_highlighter.tree:for_each_tree(function(tstree, tree) 46 | if not tstree then 47 | return 48 | end 49 | 50 | local root = tstree:root() 51 | local root_start_row, _, root_end_row, _ = root:range() 52 | 53 | -- Only worry about trees within the line range 54 | if root_start_row > row or root_end_row < row then 55 | return 56 | end 57 | 58 | local query = buf_highlighter:get_query(tree:lang()) 59 | 60 | -- Some injected languages may not have highlight queries. 61 | if not query:query() then 62 | return 63 | end 64 | 65 | local iter = query:query():iter_captures(root, buf_highlighter.bufnr, row, row + 1) 66 | 67 | for capture, node, metadata in iter do 68 | local hl = query.hl_cache[capture] 69 | 70 | if hl and ts.is_in_node_range(node, row, col) then 71 | local c = query._query.captures[capture] -- name of the capture in the query 72 | if c ~= nil then 73 | table.insert(matches, { capture = c, priority = metadata.priority }) 74 | end 75 | end 76 | end 77 | end, true) 78 | return matches 79 | end 80 | 81 | function M.for_each_buf_window(bufnr, fn) 82 | if not api.nvim_buf_is_loaded(bufnr) then 83 | return 84 | end 85 | 86 | for _, window in ipairs(vim.fn.win_findbuf(bufnr)) do 87 | fn(window) 88 | end 89 | end 90 | 91 | function M.to_lookup_table(list, key_mapper) 92 | local result = {} 93 | 94 | for i, v in ipairs(list) do 95 | local key = v 96 | 97 | if key_mapper then 98 | key = key_mapper(v, i) 99 | end 100 | 101 | result[key] = v 102 | end 103 | 104 | return result 105 | end 106 | 107 | function M.node_contains(node, range) 108 | local start_row, start_col, end_row, end_col = node:range() 109 | local start_fits = start_row < range[1] or (start_row == range[1] and start_col <= range[2]) 110 | local end_fits = end_row > range[3] or (end_row == range[3] and end_col >= range[4]) 111 | 112 | return start_fits and end_fits 113 | end 114 | 115 | function M.is_in_node_range(node, line, col) 116 | local start_line, start_col, end_line, end_col = ts.get_node_range(node) 117 | if line >= start_line and line <= end_line then 118 | if line == start_line and line == end_line then 119 | return col >= start_col and col < end_col 120 | elseif line == start_line then 121 | return col >= start_col 122 | elseif line == end_line then 123 | return col < end_col 124 | else 125 | return true 126 | end 127 | else 128 | return false 129 | end 130 | end 131 | 132 | --- Returns a tuple with the position of the last line and last column (0-indexed). 133 | function M.get_end_pos(bufnr) 134 | local bufnr = bufnr or api.nvim_get_current_buf() 135 | local last_row = api.nvim_buf_line_count(bufnr) - 1 136 | local last_line = api.nvim_buf_get_lines(bufnr, last_row, last_row + 1, true)[1] 137 | local last_col = last_line and #last_line or 0 138 | return last_row, last_col 139 | end 140 | 141 | return M 142 | -------------------------------------------------------------------------------- /lua/treesitter-matchup/util.lua: -------------------------------------------------------------------------------- 1 | local random = math.random 2 | 3 | local M = {} 4 | 5 | function M.uuid4() 6 | local template ='xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx' 7 | return string.gsub(template, '[xy]', function (c) 8 | local v = (c == 'x') and random(0, 0xf) or random(8, 0xb) 9 | return string.format('%x', v) 10 | end) 11 | end 12 | 13 | return M 14 | -------------------------------------------------------------------------------- /plugin/matchup.vim: -------------------------------------------------------------------------------- 1 | " vim match-up - even better matching 2 | " 3 | " Maintainer: Andy Massimino 4 | " Email: a@normed.space 5 | " 6 | 7 | if !get(g:, 'matchup_enabled', 1) || &cp 8 | finish 9 | endif 10 | 11 | if !get(g:, 'matchup_no_version_check', 0) 12 | \ && !(v:version >= 704 || has('nvim-0.1.7')) 13 | echoerr 'match-up does not support this version of vim' 14 | finish 15 | endif 16 | 17 | if !has('reltime') 18 | echoerr 'match-up requires reltime()' 19 | finish 20 | endif 21 | 22 | if exists('g:loaded_matchup') 23 | finish 24 | endif 25 | let g:loaded_matchup = 1 26 | 27 | if exists('g:loaded_matchit') && exists(':MatchDebug') 28 | call matchup#unmatchit#() 29 | endif 30 | let g:loaded_matchit = 1 31 | 32 | " ensure pi_paren is loaded but deactivated 33 | try 34 | runtime plugin/matchparen.vim 35 | au! matchparen 36 | catch /^Vim\%((\a\+)\)\=:E216/ 37 | unlet! g:loaded_matchparen 38 | runtime plugin/matchparen.vim 39 | silent! au! matchparen 40 | let g:loaded_matchparen = 1 41 | endtry 42 | command! NoMatchParen call matchup#matchparen#toggle(0) 43 | command! DoMatchParen call matchup#matchparen#toggle(1) 44 | 45 | hi def link MatchParenCur MatchParen 46 | hi def link MatchWord MatchParen 47 | " hi def link MatchWordCur MatchParenCur 48 | hi def link MatchBackground ColorColumn 49 | 50 | if get(g:, 'matchup_override_vimtex', 0) 51 | let g:vimtex_matchparen_enabled = 0 52 | endif 53 | 54 | call matchup#init() 55 | 56 | " vim: fdm=marker sw=2 57 | 58 | -------------------------------------------------------------------------------- /test/issues/10/legacy.vim: -------------------------------------------------------------------------------- 1 | 2 | if "(foo)" 3 | 4 | let x = "(foo)" 5 | 6 | endif 7 | 8 | ( ) 9 | 10 | let x = ( "( )" ) 11 | 12 | let y = "(" 13 | \ . ")" 14 | 15 | "(" 16 | ) 17 | \ . ")" 18 | 19 | let z = ( '( ' ) . ' )' 20 | 21 | let a = " if endif " 22 | *cpo-M* 23 | M When excluded, "%" matching will take backslashes into 24 | account. Thus in "( \( )" and "\( ( \)" the outer 25 | parenthesis match. When included "%" ignores 26 | backslashes, which is Vi compatible. 27 | 28 | let b = '\( \)' 29 | let c = "\\( \\)" 30 | 31 | let d = "( \\( )" . "\\( " . '\( \)' . "\\)" 32 | 33 | -------------------------------------------------------------------------------- /test/issues/10/string.vim: -------------------------------------------------------------------------------- 1 | 2 | function String() 3 | 4 | let output = filter(list, "matchstr(v:val, '^\s*\zsfoo\ze\\(bar\\|baz\\)')") 5 | let output = filter(list, 'matchstr(v:val, ''^\s*\zsfoo\ze\(bar\|baz\)'')') 6 | 7 | endfunction 8 | 9 | -------------------------------------------------------------------------------- /test/issues/107/bug.sv: -------------------------------------------------------------------------------- 1 | module somemodule 2 | always@( * ) begin 3 | //begin 4 | end 5 | 6 | ///end 7 | endmodule 8 | -------------------------------------------------------------------------------- /test/issues/14/example.tex: -------------------------------------------------------------------------------- 1 | 2 | \begin{equation} 3 | \left\{ 4 | \begin{aligned} 5 | lhs1 &= rhs1 \\ 6 | lhs2 &= rhs2 \\ 7 | \end{aligned} 8 | \right. 9 | \end{equation} 10 | 11 | \left]a,b\right[ 12 | \bigl]a,b\bigr] 13 | \Bigl]a,b\Bigr] 14 | \biggl]a,b\biggr] 15 | \Biggl]a,b\Biggr] 16 | 17 | \left( \frac{a}{b} \middle| q \right) 18 | 19 | \begin{tabular}{@{} lr @{}} 20 | \toprule 21 | City & Population\\ 22 | \midrule 23 | Mexico City & 20,116,842\\ 24 | Shanghai & 19,210,000\\ 25 | Peking & 15,796,450\\ 26 | Istanbul & 14,160,467\\ 27 | \bottomrule 28 | \end{tabular} 29 | 30 | \begin{itemize} 31 | \item 32 | ... 33 | \item 34 | \end{itemize} 35 | 36 | \ifpdf 37 | \DeclareGraphicsExtensions{.pdf,.jpg,.png} 38 | \else 39 | \DeclareGraphicsExtensions{.eps,.jpg,.png} 40 | \fi 41 | 42 | \makeatletter 43 | \makeatother 44 | \begingroup ...\endgroup 45 | 46 | -------------------------------------------------------------------------------- /test/issues/15/enhance-vimrc: -------------------------------------------------------------------------------- 1 | set nocompatible 2 | 3 | " load match-up (and commentary) 4 | for s:loc in ['bundle', 'plugged'] 5 | let &rtp = '~/.vim/'.s:loc.'/vim-matchup,' . &rtp 6 | let &rtp .= ',~/.vim/'.s:loc.'/vim-matchup/after' 7 | let &rtp = '~/.vim/'.s:loc.'/vim-commentary,' . &rtp 8 | let &rtp .= ',~/.vim/'.s:loc.'/vim-commentary/after' 9 | endfor 10 | 11 | " load other plugins, if necessary 12 | " let &rtp = '~/path/to/other/plugin,' . &rtp 13 | 14 | filetype plugin indent on 15 | syntax enable 16 | 17 | " match-up options go here 18 | function! IsCommentaryOpFunc() 19 | return &operatorfunc ==? matchstr(maparg('Commentary', 'n'), 20 | \ '\cset op\%(erator\)\?func=\zs.\{-\}\ze') 21 | endfunction 22 | 23 | let g:matchup_text_obj_linewise_operators = ['d', 'y', 24 | \ 'g@,IsCommentaryOpFunc()', 'V'] 25 | 26 | -------------------------------------------------------------------------------- /test/issues/15/gc.vim: -------------------------------------------------------------------------------- 1 | function! s:test() 2 | 3 | let l:str = "hello" 4 | 5 | return l:str 6 | 7 | endfunction 8 | 9 | if condition 10 | █call one() 11 | call two() 12 | endif 13 | 14 | -------------------------------------------------------------------------------- /test/issues/15/issue-vimrc: -------------------------------------------------------------------------------- 1 | set nocompatible 2 | 3 | " load match-up (and commentary) 4 | for s:loc in ['bundle', 'plugged'] 5 | let &rtp = '~/.vim/'.s:loc.'/vim-matchup,' . &rtp 6 | let &rtp .= ',~/.vim/'.s:loc.'/vim-matchup/after' 7 | let &rtp = '~/.vim/'.s:loc.'/vim-commentary,' . &rtp 8 | let &rtp .= ',~/.vim/'.s:loc.'/vim-commentary/after' 9 | endfor 10 | 11 | " load other plugins, if necessary 12 | " let &rtp = '~/path/to/other/plugin,' . &rtp 13 | 14 | filetype plugin indent on 15 | syntax enable 16 | 17 | " match-up options go here 18 | let g:matchup_text_obj_linewise_operators = ['d', 'y', 'g@', ':'] 19 | 20 | -------------------------------------------------------------------------------- /test/issues/16/any.vim: -------------------------------------------------------------------------------- 1 | function! s:test() 2 | 3 | if l:x == 1 4 | if l:y == "hello andy" 5 | echom "hello andy" " CURSOR 6 | endif 7 | call one() 8 | else 9 | call two() 10 | elseif 11 | call three() 12 | endif 13 | 14 | let l:str = "hello" 15 | 16 | return l:str 17 | 18 | endfunction 19 | 20 | 21 | -------------------------------------------------------------------------------- /test/issues/16/blocks.vim: -------------------------------------------------------------------------------- 1 | 2 | function! Fcn() 3 | " cursor 1 4 | if 0 5 | " cursor 2 6 | return 7 | " cursor 3 8 | else 9 | " cursor 4 10 | return 11 | " cursor 5 12 | endif 13 | " cursor 6 14 | endfunction 15 | 16 | -------------------------------------------------------------------------------- /test/issues/19/hotfix.vim: -------------------------------------------------------------------------------- 1 | 2 | function! HtmlListHotfix() 3 | call matchup#util#patch_match_words( 4 | \ '<\@<=[ou]l\>[^>]*\%(>\|$\):<\@<=li\>:<\@<=/[ou]l>', 5 | \ '') 6 | endfunction 7 | 8 | let g:matchup_hotfix_html = 'HtmlListHotfix' 9 | 10 | -------------------------------------------------------------------------------- /test/issues/19/option.vim: -------------------------------------------------------------------------------- 1 | 2 | let g:matchup_matchpref_html_nolists = 1 3 | 4 | -------------------------------------------------------------------------------- /test/issues/19/test.html: -------------------------------------------------------------------------------- 1 | 2 |
    3 |
  • 4 |
  • 5 |
6 | 7 | -------------------------------------------------------------------------------- /test/issues/21/Matchup_Problem_File.txt: -------------------------------------------------------------------------------- 1 | { 2 | { 3 | { 4 | { 5 | a 6 | a 7 | a 8 | a 9 | a 10 | a 11 | { 12 | } 13 | } 14 | { 15 | a 16 | a 17 | } 18 | { 19 | } 20 | } 21 | { 22 | { 23 | a 24 | { 25 | } 26 | } 27 | { 28 | a 29 | a 30 | } 31 | { 32 | } 33 | } 34 | { 35 | a 36 | { 37 | a 38 | a 39 | a 40 | a 41 | a 42 | a 43 | { 44 | a 45 | a 46 | a 47 | a 48 | a 49 | a 50 | a 51 | a 52 | a 53 | a 54 | } 55 | } 56 | { 57 | a 58 | a 59 | a 60 | a 61 | a 62 | a 63 | a 64 | a 65 | a 66 | a 67 | } 68 | { 69 | { 70 | a 71 | a 72 | a 73 | { 74 | } 75 | } 76 | } 77 | { 78 | { 79 | a 80 | a 81 | a 82 | { 83 | } 84 | } 85 | } 86 | } 87 | { 88 | { 89 | a 90 | a 91 | a 92 | a 93 | { 94 | } 95 | } 96 | { 97 | a 98 | a 99 | } 100 | { 101 | } 102 | } 103 | { 104 | { 105 | { 106 | a 107 | a 108 | } 109 | a 110 | a 111 | a 112 | a 113 | a 114 | a 115 | a 116 | a 117 | a 118 | a 119 | a 120 | a 121 | a 122 | a 123 | a 124 | a 125 | { 126 | } 127 | } 128 | { 129 | a 130 | a 131 | a 132 | a 133 | a 134 | a 135 | } 136 | } 137 | { 138 | { 139 | a 140 | a 141 | a 142 | { 143 | } 144 | } 145 | { 146 | a 147 | a 148 | } 149 | } 150 | { 151 | { 152 | a 153 | a 154 | a 155 | a 156 | a 157 | a 158 | { 159 | a 160 | } 161 | } 162 | { 163 | a 164 | a 165 | a 166 | a 167 | a 168 | a 169 | { 170 | a 171 | } 172 | { 173 | a 174 | a 175 | a 176 | a 177 | } 178 | } 179 | { 180 | a 181 | a 182 | a 183 | a 184 | } 185 | } 186 | { 187 | { 188 | a 189 | a 190 | } 191 | { 192 | { 193 | a 194 | } 195 | a 196 | a 197 | } 198 | { 199 | a 200 | a 201 | a 202 | { 203 | a 204 | } 205 | { 206 | a 207 | a 208 | a 209 | a 210 | } 211 | { 212 | } 213 | } 214 | { 215 | a 216 | a 217 | } 218 | } 219 | { 220 | { 221 | a 222 | { 223 | } 224 | } 225 | { 226 | a 227 | a 228 | } 229 | { 230 | } 231 | } 232 | { 233 | { 234 | a 235 | { 236 | } 237 | } 238 | { 239 | a 240 | a 241 | } 242 | } 243 | { 244 | { 245 | a 246 | { 247 | } 248 | } 249 | { 250 | a 251 | a 252 | } 253 | } 254 | { 255 | { 256 | a 257 | a 258 | a 259 | a 260 | a 261 | a 262 | a 263 | a 264 | a 265 | a 266 | a 267 | a 268 | a 269 | { 270 | a 271 | a 272 | a 273 | a 274 | a 275 | a 276 | a 277 | a 278 | a 279 | a 280 | a 281 | a 282 | } 283 | { 284 | } 285 | } 286 | { 287 | a 288 | a 289 | a 290 | a 291 | } 292 | } 293 | { 294 | a 295 | a 296 | a 297 | a 298 | { 299 | a 300 | a 301 | a 302 | { 303 | } 304 | } 305 | { 306 | a 307 | a 308 | } 309 | { 310 | } 311 | { 312 | { 313 | a 314 | a 315 | a 316 | a 317 | a 318 | a 319 | a 320 | a 321 | a 322 | } 323 | { 324 | a 325 | a 326 | } 327 | { 328 | { 329 | a 330 | a 331 | a 332 | } 333 | { 334 | a 335 | a 336 | } 337 | } 338 | } 339 | } 340 | { 341 | { 342 | a 343 | a 344 | a 345 | a 346 | a 347 | { 348 | } 349 | } 350 | { 351 | a 352 | a 353 | } 354 | { 355 | } 356 | } 357 | { 358 | { 359 | a 360 | a 361 | { 362 | } 363 | } 364 | { 365 | a 366 | a 367 | } 368 | { 369 | } 370 | } 371 | { 372 | { 373 | a 374 | } 375 | { 376 | a 377 | b 378 | b 379 | b 380 | b 381 | b 382 | b 383 | b 384 | b 385 | { 386 | } 387 | } 388 | { 389 | a 390 | a 391 | a 392 | a 393 | a 394 | a 395 | a 396 | a 397 | } 398 | { 399 | } 400 | } 401 | } 402 | } 403 | -------------------------------------------------------------------------------- /test/issues/26/example.rb: -------------------------------------------------------------------------------- 1 | 2 | class Example 3 | def initialize 4 | @text = 'for text' 5 | @text2 = 'end text2' 6 | @text3 = '( text )' 7 | end 8 | end 9 | 10 | -------------------------------------------------------------------------------- /test/issues/3/hotfix.vim: -------------------------------------------------------------------------------- 1 | 2 | function! SQLHotFix() 3 | call matchup#util#patch_match_words( 4 | \ '\%(\', 7 | \ '\%(\' 10 | \ . ':\' 11 | \ . ':\\ze\%(\s\+next\)\@!\%(.\|$\)' 12 | \) 13 | endfunction 14 | 15 | let g:matchup_hotfix_sql = 'SQLHotFix' 16 | 17 | -------------------------------------------------------------------------------- /test/issues/3/test.sql: -------------------------------------------------------------------------------- 1 | drop function if exists dummy; 2 | 3 | create or replace function dummy() 4 | returns setof text as 5 | $$ 6 | begin 7 | return next 'something'; 8 | return; 9 | end 10 | $$ language 'plpgsql'; 11 | 12 | CREATE FUNCTION dbo.median (@score int) 13 | RETURNS NUMERIC(20,2) 14 | AS BEGIN 15 | DECLARE @MedianScore as NUMERIC(20,2); 16 | SELECT @MedianScore= 17 | ( 18 | (SELECT MAX(@score) FROM 19 | (SELECT TOP 50 PERCENT Score FROM t ORDER BY Score) AS BottomHalf) 20 | + 21 | (SELECT MIN(@score) FROM 22 | (SELECT TOP 50 PERCENT Score FROM t ORDER BY Score DESC) AS TopHalf) 23 | ) / 2 ; 24 | RETURN(@MedianScore); 25 | END; 26 | 27 | drop function if exists another_function; 28 | create or replace function another_function() 29 | returns setof text as 30 | $$ 31 | begin 32 | if 1=0 then 33 | return 'impossible!'; 34 | end if; 35 | return next 'something'; 36 | return; 37 | end 38 | $$ language 'plpgsql'; 39 | 40 | -------------------------------------------------------------------------------- /test/issues/30/complex-hl.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /test/issues/30/example.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | item 4 | 5 | 6 | 7 | item 8 | 9 | 10 |
    11 |
  • text
  • 12 |
13 | 14 |
    15 |
  • text
  • 17 |
18 | 19 |
20 |
Question 1
21 |
22 | 23 | -------------------------------------------------------------------------------- /test/issues/30/example.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | item 4 | 5 | 6 | 7 | item 8 | 9 | 10 |
    11 |
  • text
  • 12 |
13 | 14 |
    15 |
  • text
  • 17 |
18 | 19 |
20 |
Question 1
21 |
22 | 23 | -------------------------------------------------------------------------------- /test/issues/30/minvimrc: -------------------------------------------------------------------------------- 1 | set nocompatible 2 | 3 | " load match-up 4 | let s:path = simplify(expand(':h').'/../../..') 5 | let &rtp = s:path.',' . &rtp 6 | let &rtp .= ','.s:path.'/after' 7 | 8 | filetype plugin indent on 9 | syntax enable 10 | 11 | " match-up options go here 12 | let g:matchup_matchpref = { 13 | \ 'html': { 'tagnameonly': 1, }, 14 | \ 'vue': { 'tagnameonly': 1, }, 15 | \} 16 | 17 | -------------------------------------------------------------------------------- /test/issues/33/minvimrc: -------------------------------------------------------------------------------- 1 | set nocompatible 2 | 3 | " load match-up 4 | let &rtp = '~/.vim/bundle/vim-matchup,' . &rtp 5 | let &rtp .= ',~/.vim/bundle/vim-matchup/after' 6 | 7 | " load other plugins, if necessary 8 | " let &rtp = '~/path/to/other/plugin,' . &rtp 9 | 10 | set ignorecase " Case insensitive search 11 | set hlsearch " Highlight search results 12 | 13 | filetype plugin indent on 14 | syntax enable 15 | 16 | " match-up options go here 17 | 18 | -------------------------------------------------------------------------------- /test/issues/33/test.rb: -------------------------------------------------------------------------------- 1 | require 'yaml' 2 | require 'aws-sdk' 3 | 4 | class Time 5 | COMMON_YEAR_DAYS_IN_MONTH = [nil, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31].freeze 6 | 7 | class << self 8 | def days_in_month(month, year) 9 | if month == 2 && ::Date.gregorian_leap?(year) 10 | 29 11 | else 12 | COMMON_YEAR_DAYS_IN_MONTH[month] 13 | end 14 | end 15 | end 16 | end 17 | 18 | module LoremIpsum 19 | class Lorem < Ipsum 20 | def test 21 | lorem_ipsum = Aws::Credentials.new(@config[:lorem_ipsum][:dolor_sit], @config[:amet][:consectetur]) 22 | @adipiscing = @config[:elit][:sed] 23 | @do = Aws::S3::Client.new(:region => @config[:eiusmod][:tempor], :credentials => lorem_ipsum) 24 | @incididunt = Aws::S3::Bucket.new(@adipiscing , client: @do) 25 | @ut = @config[:labore][:et] 26 | @dolore = /#{@config[:magna]}/ 27 | @aliqua = /#{@config[:ut]}/ 28 | @enim = @config[:ad] || false 29 | @minim = @config[:veniam].nil? ? :quis: @config[:nostrud].to_sym 30 | @exercitation = @config[:ullamco] 31 | @laboris = (@config[:nisi] || 0) * 60 32 | @ut = @config[:aliquip] || false 33 | @ex = @config[:ea] || false 34 | 35 | dolor = {:region => @config[:ex][:ea], 36 | :access_key_id => @config[:commodo][:consequat], 37 | :secret_access_key => @config[:duis][:aute]} 38 | @irure = Aws::S3::Client.new(dolor) 39 | 40 | @reprehenderit = @config[:in][:voluptate] 41 | @velit = Aws::S3::Bucket.new(@esse, client: @cillum) 42 | @dolore = @config[:eu][:fugiat] 43 | @nulla = @config[:pariatur] 44 | 45 | @excepteur = @config[:velit][:esse] 46 | @cillum = Aws::S3::Bucket.new(@dolore, client: @eu) 47 | @fugiat = @config[:nulla][:pariatur] 48 | 49 | if (@config[:excepteur]) 50 | sint(@config[:occaecat]) 51 | elsif (@config[:cupidatat]) 52 | non(@config[:proident]) 53 | else 54 | throw "sunt" 55 | end 56 | 57 | @in = Aws::EMR::Client.new(culpa) 58 | 59 | @qui = @config[:officia][:deserunt] 60 | 61 | @mollit = @config[:anim] 62 | 63 | @id = @config[:est][:laborum] 64 | end 65 | end 66 | end 67 | 68 | LoremIpsum::Lorem.test if __FILE__ == $0 69 | 70 | -------------------------------------------------------------------------------- /test/issues/34/endvar.vim: -------------------------------------------------------------------------------- 1 | 2 | function! s:InNumber() abort 3 | let l:line = getline('.') 4 | let l:col = col('.') - 1 5 | " virtcol for start of number 6 | let l:start = l:col 7 | " virtcol for last character in number 8 | let l:end = l:col 9 | if (l:line[l:col:] !~# '\d') 10 | return 11 | endif 12 | if (l:line[l:col] !~# '\d') 13 | " number in rest of line (not under cursor) 14 | let l:curCol = l:col + 1 " current column in for loop 15 | " while this might be confusing, it should work. Temporarily store the 16 | " length of l:line into l:end. Use this for the break condition for the 17 | " loop below. If th 18 | let l:end = len(l:line) 19 | " find the first number in rest of line 20 | " for l:ch in l:line[l:curCol:] 21 | while l:curCol < l:end 22 | let l:ch = l:line[l:curCol] 23 | if (l:ch =~# '\d') 24 | if (l:start !=# l:col) 25 | " l:start was not set yet, and current char is a number 26 | let l:start = l:curCol 27 | endif 28 | else 29 | if (l:start !=# l:col) 30 | " l:start was changed, and current char is not a number; 31 | " if this condition is never true, then l:start and l:end 32 | " were both already set to the correct values 33 | let l:end = l:curCol - 1 34 | break 35 | endif 36 | endif 37 | endwhile 38 | let l:curCol += 1 39 | else 40 | " number is under cursor 41 | " iterate backwards over all characters from 0 to l:curCol-1 in order to 42 | " find l:start 43 | let l:start = 0 44 | let l:curCol = l:col - 1 45 | " for l:ch in join(reverse(split(l:line[:l:curCol], '.\zs'))) 46 | while (l:curCol >= 0) 47 | let l:ch = l:line[l:curCol] 48 | if (l:ch !~# '\d') 49 | " current char is not a number; 50 | " if this condition is never true, then l:start was set to the 51 | " correct value anyway 52 | let l:start = l:curCol + 1 53 | break 54 | endif 55 | let l:curCol -= 1 56 | endwhile 57 | " iterate forwards over all characters from l:curCol+1 to $ in order to 58 | " find l:end 59 | let l:end = len(l:line) 60 | let l:curCol = l:col + 1 61 | " for l:ch in l:line[l:curCol:] 62 | while l:curCol < l:end 63 | let l:ch = l:line[l:curCol] 64 | if (l:ch !~# '\d') 65 | " current char is not a number; 66 | " if this condition is never true, then l:end was set to the 67 | " correct value anyway 68 | let l:end = l:curCol - 1 69 | break 70 | endif 71 | endwhile 72 | endif 73 | " finally, just select the appropriate region on the line 74 | execute 'normal! '.l:start.'|v'.l:end.'|' 75 | endfunction 76 | 77 | -------------------------------------------------------------------------------- /test/issues/36/image_uploader.rb: -------------------------------------------------------------------------------- 1 | return unless original_filename 2 | 3 | if model && model.read_attribute(mounted_as).present? 4 | model.read_attribute(mounted_as) 5 | else 6 | "#{SecureRandom.hex(5)}.#{file.extension}" 7 | end 8 | end 9 | 10 | def store_dir 11 | "u/#{model.user_id}/#{model.id}" 12 | end 13 | 14 | def extension_whitelist 15 | %w[jpg jpeg png] 16 | end 17 | 18 | version :thumb do 19 | process resize_to_fit: [150, 150] 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /test/issues/46/Sample.jsx: -------------------------------------------------------------------------------- 1 | 2 | const Sample = 3 | some body 4 | ; 5 | 6 | -------------------------------------------------------------------------------- /test/issues/46/minvimrc1: -------------------------------------------------------------------------------- 1 | set nocompatible 2 | 3 | " load match-up 4 | let s:path = simplify(expand(':h').'/../../..') 5 | let &rtp = s:path.',' . &rtp 6 | let &rtp .= ','.s:path.'/after' 7 | 8 | autocmd FileType * echo &ft | sleep 1 9 | 10 | call plug#begin('~/.vim/plugged') 11 | Plug 'mxw/vim-jsx' 12 | Plug 'othree/yajs.vim' 13 | Plug 'othree/es.next.syntax.vim' 14 | call plug#end() 15 | 16 | filetype plugin indent on 17 | syntax enable 18 | 19 | " match-up options go here 20 | function! JsxHotfix() 21 | echo 'JsxHotfix' 22 | setlocal matchpairs=(:),{:},[:],<:> 23 | let b:match_words = '<\@<=\([^/][^ \t>]*\)\g{hlend}[^>]*\%(/\@\|$\):<\@<=/\1>' 24 | endfunction 25 | let g:matchup_hotfix = { 'javascript.jsx': 'JsxHotfix' } 26 | 27 | -------------------------------------------------------------------------------- /test/issues/46/minvimrc2: -------------------------------------------------------------------------------- 1 | set nocompatible 2 | 3 | " load match-up 4 | let s:path = simplify(expand(':h').'/../../..') 5 | let &rtp = s:path.',' . &rtp 6 | let &rtp .= ','.s:path.'/after' 7 | 8 | autocmd FileType * echo &ft | sleep 1 9 | 10 | call plug#begin('~/.vim/plugged') 11 | Plug 'mxw/vim-jsx' 12 | Plug 'othree/yajs.vim' 13 | Plug 'othree/es.next.syntax.vim' 14 | call plug#end() 15 | 16 | filetype plugin indent on 17 | syntax enable 18 | 19 | " match-up options go here 20 | function! JsxHotfix() 21 | echo 'JsxHotfix' 22 | setlocal matchpairs=(:),{:},[:],<:> 23 | let b:match_words = '<\@<=\([^/][^ \t>]*\)\g{hlend}[^>]*\%(/\@\|$\):<\@<=/\1>' 24 | endfunction 25 | autocmd FileType javascript.jsx let b:matchup_hotfix = 'JsxHotfix' 26 | 27 | -------------------------------------------------------------------------------- /test/issues/48/minvimrc: -------------------------------------------------------------------------------- 1 | set nocompatible 2 | 3 | " load match-up 4 | let s:path = simplify(expand(':h').'/../../..') 5 | let &rtp = s:path.',' . &rtp 6 | let &rtp .= ','.s:path.'/after' 7 | 8 | " rtp for testing files 9 | let &rtp = s:path.'/test/rtp,' . &rtp 10 | 11 | " load other plugins, if necessary 12 | " let &rtp = '~/path/to/other/plugin,' . &rtp 13 | 14 | filetype plugin indent on 15 | syntax enable 16 | 17 | " match-up options go here 18 | hi MatchParen ctermfg=blue ctermbg=NONE 19 | let g:matchup_transmute_enabled = 1 20 | 21 | -------------------------------------------------------------------------------- /test/issues/48/new.xml: -------------------------------------------------------------------------------- 1 | x 2 | 3 | a '' 4 | -------------------------------------------------------------------------------- /test/issues/48/simple.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /test/issues/48/vim-matchup-20181230.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | $CHECK_FZF 10 | CHECK_FZF 11 | awk $0~"^"N"="{$0=N"="V;f=1}{a[++n]=$0}END{if(!f)a[++n]=N"="V;++n;for(i=1;i!=n;i++)print a[i]>ARGV[ARGC-1]} N=CHECK_FZF V=\$CHECK_FZF /root/.apprc 12 | 13 | 14 | 15 | 16 | 17 | 20 | 23 | 24 | 25 | 26 | CHECK_FZF_WINDOW 27 | closewindow:CHECK_FZF_WINDOW 28 | 29 | -------------------------------------------------------------------------------- /test/issues/49/example.vim: -------------------------------------------------------------------------------- 1 | source ../../bootstrap.vim 2 | 3 | call matchup#custom#define_motion('nox', '%', 4 | \ 'matchup#custom#example_motion', { 'down': 1 }) 5 | call matchup#custom#define_motion('nox', 'g%', 6 | \ 'matchup#custom#example_motion', { 'down': 0 }) 7 | 8 | -------------------------------------------------------------------------------- /test/issues/49/test.sh: -------------------------------------------------------------------------------- 1 | # `%` jumps to fi 2 | if test -z ""; then 3 | echo "cursor_position" 4 | else 5 | true 6 | fi 7 | 8 | -------------------------------------------------------------------------------- /test/issues/51/test.f90: -------------------------------------------------------------------------------- 1 | program ifElseIfElseProg 2 | implicit none 3 | 4 | integer :: a = 100 5 | 6 | if( a == 10 ) then 7 | 8 | a = a + 1 9 | #ifdef three_d 10 | + 3 11 | #endif 12 | 13 | else if( a == 20 ) 14 | & then 15 | print*, "Value of a is 20" 16 | 17 | else if( a == 30 ) then 18 | 19 | print*, "Value of a is 30" 20 | 21 | else 22 | 23 | print*, "None of the values is matching" 24 | 25 | end if 26 | 27 | print*, "exact value of a is ", a 28 | 29 | end program ifElseIfElseProg 30 | -------------------------------------------------------------------------------- /test/issues/54/foo.vim: -------------------------------------------------------------------------------- 1 | 2 | function! Foo(var, func) 3 | return a:func(a:var) 4 | endfunction 5 | 6 | function! Foo(list, var) 7 | return sort(a:list, s:function('a:var')) 8 | endfunction 9 | 10 | -------------------------------------------------------------------------------- /test/issues/59/rebind.vim: -------------------------------------------------------------------------------- 1 | 2 | source ../../bootstrap.vim 3 | 4 | xmap u% (matchup-i%) 5 | omap u% (matchup-i%) 6 | 7 | " optional, for use without patch 8.1.0648 8 | call call(matchup#motion_sid().'make_oldstyle_omaps', ['u%', 'i%']) 9 | 10 | -------------------------------------------------------------------------------- /test/issues/63/test.f90: -------------------------------------------------------------------------------- 1 | program matchup_parsing 2 | real :: x = 1.0, y = 2.0, a 3 | 4 | 5 | if (x < y) then 6 | if (x == 0) stop 7 | a = y / x 8 | else 9 | if (y == 0) stop ! matchup sees corresponding `if - end if` pairs from HERE 10 | a = x / y 11 | end if ! to HERE 12 | 13 | write(*, *) a 14 | 15 | end program 16 | 17 | -------------------------------------------------------------------------------- /test/issues/64/ast.cc: -------------------------------------------------------------------------------- 1 | Error ASTNodeImporter::ImportFunctionDeclBody(FunctionDecl *FromFD, 2 | FunctionDecl *ToFD) { 3 | if (Stmt *FromBody = FromFD->getBody()) { 4 | if (ExpectedStmt ToBodyOrErr = import(FromBody)) 5 | ToFD->setBody(*ToBodyOrErr); 6 | else 7 | return ToBodyOrErr.takeError(); 8 | } 9 | return Error::success(); 10 | } 11 | 12 | -------------------------------------------------------------------------------- /test/issues/69/cpptemplate.vim: -------------------------------------------------------------------------------- 1 | 2 | function! CppTemplate() 3 | call matchup#util#append_match_words( 4 | \ '\%(\s\@\|>\s\@!\)=\@!') 5 | endfunction 6 | if !exists('g:matchup_hotfix') 7 | let g:matchup_hotfix = {} 8 | endif 9 | let g:matchup_hotfix.cpp = 'CppTemplate' 10 | set matchpairs-=<:> 11 | 12 | -------------------------------------------------------------------------------- /test/issues/69/template.cpp: -------------------------------------------------------------------------------- 1 | typedef BOOST_DEDUCED_TYPENAME boost::conditional< 2 | boost::is_signed::value, 3 | boost::make_signed, 4 | boost::type_identity 5 | >::type no_cvr_prefinal_lazy_t; 6 | 7 | -------------------------------------------------------------------------------- /test/issues/7/augroup.vim: -------------------------------------------------------------------------------- 1 | 2 | augroup nomatchparen 3 | autocmd! 4 | autocmd VimEnter * NoMatchParen 5 | augroup END 6 | 7 | -------------------------------------------------------------------------------- /test/issues/7/hotfix.vim: -------------------------------------------------------------------------------- 1 | 2 | function! AugroupHotfix() 3 | call matchup#util#patch_match_words( 4 | \ '\\)\@!\S:', 5 | \ '\\)\@!\S\+:') 6 | endfunction 7 | 8 | let g:matchup_hotfix_vim = 'AugroupHotfix' 9 | 10 | -------------------------------------------------------------------------------- /test/issues/7/hotfix2.vim: -------------------------------------------------------------------------------- 1 | 2 | function! AugroupHotfix() 3 | call matchup#util#patch_match_words( 4 | \ '\\)\@!\S:', 5 | \ '\\)\@!\S\@=:') 6 | endfunction 7 | 8 | let g:matchup_hotfix_vim = 'AugroupHotfix' 9 | 10 | -------------------------------------------------------------------------------- /test/issues/8/flex.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 数据加载中。。。 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /test/issues/8/flex2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /test/issues/8/hotfix.vim: -------------------------------------------------------------------------------- 1 | 2 | function! HTMLHotFix() 3 | let b:match_words = '<:>,' . 4 | \ '<\@<=[ou]l\>[^>]*\%(>\|$\):<\@<=li\>:<\@<=/[ou]l>,' . 5 | \ '<\@<=dl\>[^>]*\%(>\|$\):<\@<=d[td]\>:<\@<=/dl>,' . 6 | \ '<\@<=\([^/][^ \t>]*\)[^>]*\%(>\|$\):<\@<=/\1>' 7 | 8 | call matchup#util#patch_match_words( 9 | \ '<\@<=\([^/][^ \t>]*\)[^>]*\%(>\|$\):<\@<=/\1>', 10 | \ '<\@<=\([^/][^ \t>]*\)\%(/\@\|$\|[ \t][^>]*\%(/\@\|$\)\):<\@<=/\1>' 11 | \) 12 | 13 | " call matchup#util#patch_match_words( 14 | " \ '<\@<=\([^/][^ \t>]*\)[^>]*\%(>\|$\):<\@<=/\1>', 15 | " \ '<\@<=\([^/][^ \t>]*\)\%(>\|$\|[ \t][^>]*\%(>\|$\)\):<\@<=/\1>' 16 | " \) 17 | 18 | endfunction 19 | 20 | 21 | let g:matchup_hotfix_html = 'HTMLHotFix' 22 | 23 | -------------------------------------------------------------------------------- /test/issues/8/slash.html: -------------------------------------------------------------------------------- 1 | 2 |
hello world
3 |
hello world
4 | 5 | -------------------------------------------------------------------------------- /test/issues/84/ex.tex: -------------------------------------------------------------------------------- 1 | \[ 2 | \begin{gathered} 3 | First equation \\ 4 | Second equation \\[1ex] 5 | Third and last equation 6 | \end{gathered} 7 | \] 8 | -------------------------------------------------------------------------------- /test/issues/88/ex.cs: -------------------------------------------------------------------------------- 1 | this is some longer text 2 | short {0} 3 | -------------------------------------------------------------------------------- /test/issues/98/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 |
7 |
    8 |
  • 9 |
10 | 11 | -------------------------------------------------------------------------------- /test/lang/lua/tohtml.lua: -------------------------------------------------------------------------------- 1 | -- Converts Lua table to HTML output in table.html file 2 | function tohtml(x) 3 | ret = tohtml_table(x,1) 4 | writefile("table.html", ret) 5 | os.execute("table.html") 6 | return(ret) 7 | end 8 | 9 | -- Saves a string to file 10 | function writefile(filename, value) 11 | if (value) then 12 | local file = io.open(filename,"w+") 13 | file:write(value) 14 | file:close() 15 | end 16 | end 17 | 18 | function tohtml_table(x, table_level) 19 | local k, s, tcolor 20 | local html_colors = { 21 | "#339900","#33CC00","#669900","#666600","#FF3300", 22 | "#FFCC00","#FFFF00","#CCFFCC","#CCCCFF","#CC66FF", 23 | "#339900","#33CC00","#669900","#666600","#FF3300", 24 | "#FFCC00","#FFFF00","#CCFFCC","#CCCCFF","#CC66FF" 25 | } 26 | local lineout = {} 27 | local tablefound = false 28 | if type(x) == "table" then 29 | s = "" 30 | k = 1 31 | local i, v = next(x) 32 | while i do 33 | if (type(v) == "table") then 34 | if (table_level<10) then 35 | lineout[k] = "" .. flat(i) .. "".. tohtml_table(v, table_level + 1) 36 | else 37 | lineout[k] = "MAXIMUM LEVEL BREACHED" 38 | end 39 | tablefound = true 40 | else 41 | lineout[k] = flat(i) .. "=" .. tohtml_table(v) 42 | end 43 | k = k + 1 44 | i, v = next(x, i) 45 | end 46 | 47 | for k,line in ipairs(lineout) do 48 | if (tablefound) then 49 | s = s .. "" .. line .. "\n" 50 | else 51 | s = s .. "" .. line .. "\n" 52 | end 53 | end 54 | if not (tablefound) then 55 | s = "" .. 56 | "" .. s .. "
\n" 57 | else 58 | tcolor = html_colors[table_level] 59 | s = "" .. 60 | s .. "
\n" 61 | end 62 | 63 | return s 64 | end 65 | if type(x) == "function" then 66 | return "FUNC" 67 | end 68 | if type(x) == "file" then 69 | return "FILE" 70 | end 71 | 72 | return tostring(x) 73 | end 74 | -------------------------------------------------------------------------------- /test/lang/ruby/next.rb: -------------------------------------------------------------------------------- 1 | for i in 0..5 2 | if i < 2 then 3 | next 4 | else 5 | end 6 | puts "Value of local variable is #{i}" 7 | end 8 | 9 | -------------------------------------------------------------------------------- /test/legacy/addrtp.vim: -------------------------------------------------------------------------------- 1 | 2 | " rtp for testing files 3 | 4 | let s:path = expand(':h') 5 | let &rtp = s:path.'/rtp,' . &rtp 6 | 7 | runtime! ftdetect/matchuptest.vim 8 | 9 | -------------------------------------------------------------------------------- /test/legacy/augment.matchuptest: -------------------------------------------------------------------------------- 1 | 2 | foobar 3 | 4 | barfoo 5 | 6 | endfoobar 7 | 8 | " \<\(\(foo\)\(bar\)\):\3\2:end\1 9 | 10 | " vim: set ft=matchuptest : 11 | -------------------------------------------------------------------------------- /test/legacy/bootstrap.vim: -------------------------------------------------------------------------------- 1 | set nocompatible 2 | 3 | " load match-up 4 | let s:path = simplify(expand(':h').'/..') 5 | let &rtp = s:path.',' . &rtp 6 | let &rtp .= ','.s:path.'/after' 7 | 8 | " rtp for testing files 9 | let &rtp = s:path.'/test/rtp,' . &rtp 10 | 11 | " load other plugins, if necessary 12 | " let &rtp = '~/path/to/other/plugin,' . &rtp 13 | 14 | filetype plugin indent on 15 | syntax enable 16 | 17 | " match-up options go here 18 | 19 | -------------------------------------------------------------------------------- /test/legacy/forwhile.vim: -------------------------------------------------------------------------------- 1 | if a:findstart 2 | if exists('s:completer') | unlet s:completer | endif 3 | 4 | let l:pos = col('.') - 1 5 | let l:line = getline('.')[:l:pos-1] 6 | for l:completer in s:completers 7 | if !get(l:completer, 'enabled', 1) | continue | endif 8 | 9 | for l:pattern in l:completer.patterns 10 | if l:line =~# l:pattern 11 | let s:completer = l:completer 12 | while l:pos > 0 13 | if l:line[l:pos - 1] =~# '{\|,\|\[\|\\' 14 | \ || l:line[l:pos-2:l:pos-1] ==# ', ' 15 | let s:completer.context = matchstr(l:line, '\S*$') 16 | return l:pos 17 | else 18 | let l:pos -= 1 19 | endif 20 | endwhile 21 | return -2 22 | endif 23 | endfor 24 | endfor 25 | return -3 26 | else 27 | if !exists('s:completer') | return [] | endif 28 | 29 | return g:matchup_complete_close_braces && get(s:completer, 'inside_braces', 1) 30 | \ ? s:close_braces(s:completer.complete(a:base)) 31 | \ : s:completer.complete(a:base) 32 | endif 33 | 34 | -------------------------------------------------------------------------------- /test/legacy/hlend.matchuptest: -------------------------------------------------------------------------------- 1 | 2 | < highlight this | but not this > no cursor 3 | 4 | < mid this | not > no 5 | 6 | < end this | not > no 7 | 8 | -------------------------------------------------------------------------------- /test/legacy/mwe.vim: -------------------------------------------------------------------------------- 1 | 2 | if l:x == 1 3 | call one() 4 | else 5 | call two() 6 | elseif 7 | call three() 8 | endif 9 | 10 | -------------------------------------------------------------------------------- /test/legacy/parens.txt: -------------------------------------------------------------------------------- 1 | ( 2 | dib 3 | dvib 4 | dVib 5 | ) 6 | ---- 7 | 8 | { 9 | 10 | { 11 | 12 | a nested 13 | block 14 | 15 | } 16 | 17 | } 18 | 19 | ( 20 | 21 | ( 22 | 23 | another nested block 24 | L 25 | ) 26 | L 27 | ) 28 | 29 | ( 30 | 31 | 32 | 33 | ) 34 | 35 | ( hello 36 | 37 | 38 | 39 | 40 | 41 | 42 | ) 43 | 44 | (vibd) 45 | (dvib) 46 | (dib) 47 | () 48 | 49 | ---- 50 | ( 51 | something 52 | 53 | | ) 54 | ---- 55 | 56 | block = ( 1, 57 | 2, 58 | 3, ); 59 | 60 | ( (( ) )) 61 | 62 | ( 63 | hello 64 | 65 | ) | 66 | 67 | ( 68 | ( empty 69 | 70 | 71 | ) 72 | ) 73 | ( 74 | 75 | bye ) 76 | 77 | { { hello 78 | 79 | 80 | } } | 81 | 82 | 83 | ---- 84 | ( ( (( )) ) ) 85 | ---- 86 | 87 | ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( 88 | ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( 89 | ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( 90 | ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( 91 | ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( 92 | ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( 93 | ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( 94 | ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( 95 | ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( 96 | ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) 97 | ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) 98 | ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) 99 | ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) 100 | ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) 101 | ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) 102 | ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) 103 | ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) 104 | ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) 105 | 106 | 107 | -------------------------------------------------------------------------------- /test/legacy/parts.vim: -------------------------------------------------------------------------------- 1 | 2 | 3 | function 4 | return 5 | 6 | break 7 | endwhile 8 | 9 | 10 | -------------------------------------------------------------------------------- /test/legacy/rtp/ftdetect/matchuptest.vim: -------------------------------------------------------------------------------- 1 | autocmd BufNewFile,BufRead *.matchuptest setlocal filetype=matchuptest 2 | 3 | -------------------------------------------------------------------------------- /test/legacy/rtp/ftplugin/matchuptest.vim: -------------------------------------------------------------------------------- 1 | 2 | " Only do this when not done yet for this buffer 3 | if exists("b:did_ftplugin") 4 | finish 5 | endif 6 | 7 | " Don't load another plugin for this buffer 8 | let b:did_ftplugin = 1 9 | 10 | let s:cpo_save = &cpo 11 | set cpo-=C 12 | 13 | " Let the matchit plugin know what items can be matched. 14 | if exists("loaded_matchit") 15 | let b:match_ignorecase = 0 16 | " let b:match_words = 17 | " \ '\:\:\,' . 18 | " \ '\<\(wh\%[ile]\|for\)\>:\:\:\,' . 19 | " \ '\:\:\,' . 20 | " \ '\:\:\:\,' . 21 | " \ '\\)\@!\S:\,' . 22 | " \ '(:)' 23 | 24 | " very tricky examples: 25 | " bad: let b:match_words = '\(foo\)\(bar\):more\1:and\2:end\1\2' 26 | " good: 27 | let b:match_words = '\<\(\(foo\)\(bar\)\):\3\2:end\1' 28 | let b:match_words .= ',\:\' 29 | let b:match_words .= ',\:\' 30 | let b:match_words .= ',\:\' 31 | let b:match_words .= ',\%(end\)\@\ze no cursor:< mid \1\g{hlend} | not >\ze no:< end \1\g{hlend} | not >\ze no' 39 | let b:match_words .= ',\\word{\(.\{-}\)}:\\endword{\1}' 40 | 41 | let b:match_skip = 'synIDattr(synID(line("."),col("."),1),"name") 42 | \ =~? "comment\\|string\\|vimSynReg\\|vimSet"' 43 | endif 44 | 45 | let &cpo = s:cpo_save 46 | unlet s:cpo_save 47 | 48 | -------------------------------------------------------------------------------- /test/legacy/startup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | VISUAL=${VISUAL:-vim} 4 | 5 | cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd 6 | 7 | dir='profile' 8 | mkdir -vp "$dir" 9 | 10 | file="$dir/startup-$(date +%Y-%m-%d.%H:%M:%S)" 11 | file1="$file-1.log" 12 | file2="$file-2.log" 13 | 14 | "$VISUAL" -u vimrc-startup --startuptime "$file1" 15 | 16 | echo 'g:matchup_delim_start_plaintext=0' 17 | grep matchup "$file1" 18 | 19 | export TEST_PLAIN=1 20 | "$VISUAL" -u vimrc-startup --startuptime "$file2" 21 | 22 | echo 'g:matchup_delim_start_plaintext=1' 23 | grep matchup "$file2" 24 | 25 | -------------------------------------------------------------------------------- /test/legacy/tabs.vim: -------------------------------------------------------------------------------- 1 | 2 | for l:pattern in l:completer.patterns 3 | if l:line =~# l:pattern 4 | let s:completer = l:completer 5 | while l:pos > 0 6 | if l:line[l:pos - 1] =~# '{\|,\|\[\|\\' 7 | \ || l:line[l:pos-2:l:pos-1] ==# ', ' 8 | let s:completer.context = matchstr(l:line, '\S*$') 9 | return l:pos 10 | else 11 | let l:pos -= 1 12 | endif 13 | endwhile 14 | return -2 15 | endif 16 | endfor 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /test/legacy/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title of the document 6 | 7 | 8 | 9 | Content of the document...... 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /test/legacy/textobjV.vim: -------------------------------------------------------------------------------- 1 | 2 | while 1 3 | if l:x == 1 4 | echo 'one' 5 | else 6 | echo 'two' 7 | elseif 8 | echo 'three' 9 | endif 10 | endwhile 11 | 12 | if l:x == 1 13 | echo 'one' 14 | else 15 | echo 'two' 16 | elseif 17 | echo 'three' 18 | endif 19 | 20 | -------------------------------------------------------------------------------- /test/legacy/transmute.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /test/legacy/transmute2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title of the document 6 | 7 | 8 | 9 | 10 | 11 | 12 | Content of the document...... 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /test/legacy/unicode.matchuptest: -------------------------------------------------------------------------------- 1 | ぽ 2 | 3 | もぎ | 4 | 5 | ぽ 6 | 7 | も ぎ 8 | 9 | ぽ 10 | むめ 11 | 12 | endむめも 13 | 14 | むめ 15 | 16 | ぽendむめも 17 | 18 | ぽむめ 19 | 20 | endむめも 21 | 22 | \begin{🍩🍩🍩} 23 | 24 | \end{🍩🍩🍩} 25 | 26 | one😀🐑one 27 | two😐🐑two 28 | three🙁🐑foo 29 | 30 | hi MatchParen cterm=strikethrough 31 | 32 | " vim: set ft=matchuptest : 33 | -------------------------------------------------------------------------------- /test/legacy/vimrc-startup: -------------------------------------------------------------------------------- 1 | set nocompatible 2 | 3 | let &rtp = '~/.vim/bundle/vim-matchup,' . &rtp 4 | let &rtp .= ',~/.vim/bundle/vim-matchup/after' 5 | 6 | let g:matchup_delim_start_plaintext = !!$TEST_PLAIN 7 | " let g:matchup_matchparen_enabled = 0 8 | 9 | filetype plugin indent on 10 | syntax enable 11 | 12 | autocmd VimEnter * put!=execute('MatchupShowTimes')|set nomodified 13 | nnoremap q :quit 14 | 15 | -------------------------------------------------------------------------------- /test/legacy/zsze.matchuptest: -------------------------------------------------------------------------------- 1 | 2 | bazbar 3 | 4 | barbaz 5 | 6 | zabrab 7 | 8 | rabzab 9 | 10 | where 11 | 12 | when 13 | 14 | " vim: set ft=matchuptest : 15 | -------------------------------------------------------------------------------- /test/minvimrc: -------------------------------------------------------------------------------- 1 | set nocompatible 2 | 3 | " load match-up 4 | let &rtp = '~/.vim/bundle/vim-matchup,' . &rtp 5 | let &rtp .= ',~/.vim/bundle/vim-matchup/after' 6 | 7 | " rtp for testing files 8 | let &rtp = '~/.vim/bundle/vim-matchup/test/rtp,' . &rtp 9 | 10 | " load other plugins, if necessary 11 | " let &rtp = '~/path/to/other/plugin,' . &rtp 12 | 13 | filetype plugin indent on 14 | syntax enable 15 | 16 | " match-up options go here 17 | 18 | -------------------------------------------------------------------------------- /test/new/.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | plugins = covimerage 3 | data_file = cov.tmp/coverage_covimerage 4 | -------------------------------------------------------------------------------- /test/new/.gitignore: -------------------------------------------------------------------------------- 1 | .coverage 2 | .coverage_covimerage 3 | coverage.xml 4 | env 5 | -------------------------------------------------------------------------------- /test/new/Makefile: -------------------------------------------------------------------------------- 1 | RANDOM := $(shell bash -c 'echo $$RANDOM') 2 | COVER = covimerage -q run --append --no-report \ 3 | --data-file $(CURDIR)/cov.tmp/_$(RANDOM)_coverage_covimerage_$@ \ 4 | --source $(CURDIR)/../../autoload \ 5 | --source $(CURDIR)/../../plugin 6 | MYVIM ?= nvim --headless 7 | MAKEFLAGS += --no-print-directory 8 | 9 | TESTS := $(wildcard test-*) 10 | 11 | .PHONY: test $(TESTS) 12 | 13 | test: $(TESTS) 14 | 15 | sysinfo: 16 | @echo "**** SYSTEM INFORMATION ****" 17 | @-git log -1 18 | @-$(MYVIM) --version 19 | @echo "**** SYSTEM INFORMATION ****" 20 | 21 | $(TESTS): env 22 | @. env/bin/activate 23 | mkdir -p cov.tmp 24 | MYVIM="$(COVER) $(MYVIM)" $(MAKE) -C $@ 25 | 26 | coverage: coverage.xml 27 | 28 | cov.tmp/coverage_covimerage: $(wildcard cov.tmp/_*) 29 | coverage combine $^ 30 | 31 | coverage.xml: env cov.tmp/coverage_covimerage 32 | . env/bin/activate 33 | coverage report -m 34 | coverage html 35 | coverage xml 36 | 37 | env: env/pyvenv.cfg 38 | 39 | env/pyvenv.cfg: 40 | python3 -m venv env 41 | . env/bin/activate 42 | pip install -r requirements.txt 43 | 44 | ifndef MAKECMDGOALS 45 | test: sysinfo 46 | $(TESTS): sysinfo 47 | endif 48 | -------------------------------------------------------------------------------- /test/new/common/bootstrap.vim: -------------------------------------------------------------------------------- 1 | set packpath-=~/.vim packpath-=~/.vim/after 2 | set packpath-=~/.config/nvim packpath-=~/.config/nvim/after 3 | let &rtp = '../../..,' . &rtp 4 | let &rtp = &rtp . ',../../../after' 5 | 6 | if $TESTS_ENABLE_TREESITTER 7 | let s:path = simplify(expand(':h').'/../../..') 8 | let &rtp = s:path.'/test/vader/plugged/nvim-treesitter,' . &rtp 9 | let &rtp .= ','.s:path.'/test/vader/plugged/nvim-treesitter/after' 10 | 11 | runtime! plugin/nvim-treesitter.vim 12 | runtime! plugin/nvim-treesitter.lua 13 | 14 | lua < 33 | -------------------------------------------------------------------------------- /test/new/requirements.txt: -------------------------------------------------------------------------------- 1 | setuptools 2 | wheel 3 | click<8.0.0 4 | coverage==4.5.4 5 | covimerage==0.2.1 6 | -------------------------------------------------------------------------------- /test/new/test-core/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: test 2 | 3 | MYVIM ?= nvim --headless 4 | 5 | INMAKE := 1 6 | export INMAKE 7 | 8 | test: 9 | @$(MYVIM) -u test_pos.vim 10 | @$(MYVIM) -u test_perf.vim 11 | -------------------------------------------------------------------------------- /test/new/test-core/test.txt: -------------------------------------------------------------------------------- 1 | example 2 | 3 | 4 | -------------------------------------------------------------------------------- /test/new/test-core/test_perf.vim: -------------------------------------------------------------------------------- 1 | set nocompatible 2 | source ../common/bootstrap.vim 3 | 4 | function! s:isclose(a, b, rtol) 5 | return abs(a:a - a:b) <= a:rtol * abs(a:b) 6 | endfunction 7 | 8 | silent edit test.txt 9 | 10 | call matchup#perf#tic('testing') 11 | 12 | call matchup#perf#timeout_start(100) 13 | sleep 90m 14 | call assert_equal(0, matchup#perf#timeout_check()) 15 | call assert_true(s:isclose(matchup#perf#timeout(), 10, 0.20)) 16 | sleep 11m 17 | call assert_equal(1, matchup#perf#timeout_check()) 18 | 19 | call matchup#perf#toc('testing', 'checkpoint1') 20 | 21 | call matchup#perf#tic('testing') 22 | sleep 10m 23 | call matchup#perf#toc('testing', 'checkpoint1') 24 | 25 | " [testing] 26 | " checkpoint1 101.63ms 101.63ms 101.63ms% 27 | let out = matchup#util#command('MatchupShowTimes') 28 | let out = join(out, '\n') 29 | let p = '\s\+\([0-9.]\+\)ms' 30 | let out = matchlist(out, '\[testing]\_.\{-}checkpoint1' . p . p . p) 31 | 32 | call assert_true(s:isclose(out[1], 80, 0.20)) 33 | call assert_true(s:isclose(out[2], 10, 0.20)) 34 | call assert_true(s:isclose(out[3], 100, 0.20)) 35 | 36 | call matchup#test#finished() 37 | -------------------------------------------------------------------------------- /test/new/test-core/test_pos.vim: -------------------------------------------------------------------------------- 1 | set nocompatible 2 | source ../common/bootstrap.vim 3 | 4 | silent edit test.txt 5 | 6 | call matchup#perf#timeout_start(0) 7 | 8 | normal! gg_ 9 | call assert_equal([0, 1, 1, 0, 1], matchup#pos#get_cursor()) 10 | 11 | normal! $ 12 | call assert_equal([0, 1, 7, 0, 2147483647], matchup#pos#get_cursor()) 13 | 14 | let [l, c] = matchup#pos#get_cursor()[1:2] 15 | call assert_equal([0, 2, 1, 0], matchup#pos#next(l, c)) 16 | call assert_equal([0, 1, 8, 0], matchup#pos#next_eol(l, c)) 17 | 18 | let pos = matchup#pos#(l, c) 19 | let pos = matchup#pos#next_eol(matchup#pos#next_eol(pos)) 20 | call assert_equal([0, 2, 1, 0], pos) 21 | call assert_equal([2, 1], matchup#pos#(pos)) 22 | 23 | call assert_equal(1, matchup#pos#smaller_or_equal([2, 10], [3, 1])) 24 | call assert_equal(1, matchup#pos#larger([3, 1], [1, 3])) 25 | 26 | call matchup#test#finished() 27 | -------------------------------------------------------------------------------- /test/new/test-delim/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: test 2 | 3 | MYVIM ?= nvim --headless 4 | 5 | INMAKE := 1 6 | export INMAKE 7 | 8 | test: 9 | @$(MYVIM) -u test.vim 10 | -------------------------------------------------------------------------------- /test/new/test-delim/test.tex: -------------------------------------------------------------------------------- 1 | \[ 2 | \begin{gathered} 3 | First equation \\ 4 | Second equation \\[1ex] 5 | Third and last equation 6 | \end{gathered} 7 | \] 8 | 9 | \begin{a} 10 | \begin{b} 11 | \end{c} 12 | \end{d} 13 | -------------------------------------------------------------------------------- /test/new/test-delim/test.vim: -------------------------------------------------------------------------------- 1 | set nocompatible 2 | source ../common/bootstrap.vim 3 | 4 | let g:tex_flavor = "latex" 5 | 6 | silent edit test.tex 7 | 8 | call matchup#perf#timeout_start(0) 9 | 10 | normal! 7G 11 | let s:current = matchup#delim#get_current('all', 'both') 12 | let s:corresponding = matchup#delim#get_matching(s:current) 13 | call matchup#test#assert_equal(1, s:corresponding[0].lnum) 14 | 15 | normal! 9G 16 | let s:current = matchup#delim#get_current('all', 'both') 17 | let s:corresponding = matchup#delim#get_matching(s:current) 18 | call matchup#test#assert_equal(9, s:current.lnum) 19 | call matchup#test#assert_equal(1, len(s:corresponding)) 20 | 21 | call matchup#test#finished() 22 | -------------------------------------------------------------------------------- /test/new/test-loader/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: test 2 | 3 | MYVIM ?= nvim --headless 4 | 5 | INMAKE := 1 6 | export INMAKE 7 | 8 | test: 9 | @$(MYVIM) -u test.vim 10 | -------------------------------------------------------------------------------- /test/new/test-loader/example.ext: -------------------------------------------------------------------------------- 1 | foobar 2 | barfoo 3 | endfoobar 4 | -------------------------------------------------------------------------------- /test/new/test-loader/test.vim: -------------------------------------------------------------------------------- 1 | set nocompatible 2 | source ../common/bootstrap.vim 3 | 4 | autocmd BufNewFile,BufRead *.ext let b:match_words = '\<\(\(foo\)\(bar\)\):\3\2:end\1'|set mps= 5 | " setlocal filetype=matchuptest 6 | 7 | silent edit example.ext 8 | 9 | " result of successively replacing (in reverse) capture groups in the open 10 | " pattern, '\(\(foo\)\(bar\)\)', with their corresponding backrefs 11 | call matchup#test#assert_equal({ 12 | \ '0': '\<\(\(foo\)\(bar\)\)', 13 | \ '1': '\<\1', 14 | \ '2': '\<\(\2\3\)', 15 | \ '3': '\<\(\(foo\)\3\)' 16 | \}, 17 | \ b:matchup_delim_lists.delim_tex.regex[0].augments) 18 | 19 | let s:cap = b:matchup_delim_lists.delim_tex.regex_capture[0] 20 | 21 | " for match_words \3\2, we get the following capture pattern 22 | call matchup#test#assert_equal('\(bar\)\(foo\)', s:cap.mid_list[0]) 23 | 24 | " for example, from text 'barfoo', we build string \(foobar\) by mapping 25 | " group 1 (bar) -> group 3 26 | " group 2 (foo) -> group 2 27 | " finally, str group 1 -> open group 1 28 | " 29 | call matchup#test#assert_equal([{ 30 | \ 'str': '\<\(\2\3\)', 31 | \ 'inputmap': {'1': '3', '2': '2'}, 32 | \ 'outputmap': {'1': '1'} 33 | \}], 34 | \ s:cap.aug_comp[1]) 35 | 36 | " for match_words end\1 we get the following capture pattern 37 | call matchup#test#assert_equal('end\(\(foo\)\(bar\)\)', s:cap.close) 38 | 39 | " for example, from text 'endfoobar', we build two possible strings 40 | " 1. \1 where 41 | " group 1 (foobar) -> group 1 42 | " group 2 (foo) -> group 2 (actually ignored) 43 | " group 3 (bar) -> group 3 (actually ignored) 44 | " 2. \(\2\3\) where 45 | " group 2 (foo) -> group 2 46 | " group 3 (bar) -> group 3 47 | " and str group 1 -> open group 1 48 | " 49 | call matchup#test#assert_equal([{ 50 | \ 'str': '\<\1', 51 | \ 'inputmap': {'1': '1', '2': '2', '3': '3'}, 52 | \ 'outputmap': {} 53 | \},{ 54 | \ 'str': '\<\(\2\3\)', 55 | \ 'inputmap': {'2': '2', '3': '3'}, 56 | \ 'outputmap': {'1': '1'} 57 | \}], 58 | \ s:cap.aug_comp[2]) 59 | 60 | " test captured groups and augment 61 | call matchup#perf#timeout_start(0) 62 | 63 | normal! 1G 64 | let s:cur = matchup#delim#get_current('all', 'both') 65 | 66 | call matchup#test#assert_equal('foobar', s:cur.match) 67 | call matchup#test#assert_equal({'1': 'foobar', '2': 'foo', '3': 'bar'}, s:cur.groups) 68 | call matchup#test#assert_equal({}, s:cur.augment) 69 | 70 | normal! 2G 71 | let s:cur = matchup#delim#get_current('all', 'both_all') 72 | 73 | " in this case, group 1 cannot be captured and is unresolved 74 | call matchup#test#assert_equal('barfoo', s:cur.match) 75 | call matchup#test#assert_equal({'2': 'foo', '3': 'bar'}, s:cur.groups) 76 | call matchup#test#assert_equal( 77 | \ {'str': '\<\(\Vfoo\m\Vbar\m\)', 'unresolved': {'1': '1'}}, 78 | \ s:cur.augment) 79 | 80 | let s:matching = matchup#delim#get_matching(s:cur) 81 | 82 | normal! 3G 83 | let s:cur = matchup#delim#get_current('all', 'both') 84 | 85 | call matchup#test#assert_equal('endfoobar', s:cur.match) 86 | call matchup#test#assert_equal({'1': 'foobar', '2': 'foo', '3': 'bar'}, s:cur.groups) 87 | call matchup#test#assert_equal( 88 | \ {'str': '\<\Vfoobar\m', 'unresolved': {}}, 89 | \ s:cur.augment) 90 | 91 | call matchup#test#finished() 92 | -------------------------------------------------------------------------------- /test/new/test-syn/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: test 2 | 3 | MYVIM ?= nvim --headless 4 | 5 | INMAKE := 1 6 | export INMAKE 7 | 8 | test: 9 | MODE=0 $(MYVIM) -u test.vim 10 | MODE=1 $(MYVIM) -u test.vim 11 | MODE=2 $(MYVIM) -u test.vim 12 | MODE=3 $(MYVIM) -u test.vim 13 | -------------------------------------------------------------------------------- /test/new/test-syn/example.rb: -------------------------------------------------------------------------------- 1 | describe '#foo' do 2 | context 'when foo' do 3 | it 'bars' do 4 | expect(1).to eq(1) 5 | end 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /test/new/test-syn/test.vim: -------------------------------------------------------------------------------- 1 | set nocompatible 2 | source ../common/bootstrap.vim 3 | 4 | if !$TESTS_ENABLE_TREESITTER && $MODE > 0 5 | call matchup#test#finished() 6 | endif 7 | 8 | let s:expect_ts_engine = +$TESTS_ENABLE_TREESITTER 9 | 10 | if $MODE == 1 11 | lua < -1) 11 | endfunction 12 | 13 | " python 14 | silent edit example.py 15 | 16 | call s:assert_ts_active() 17 | 18 | 0go 19 | norm % 20 | call assert_equal([3, 10], getcurpos()[1:2]) 21 | norm 2% 22 | call assert_equal([10, 12], getcurpos()[1:2]) 23 | 24 | " ruby 25 | silent edit example.rb 26 | 27 | call s:assert_ts_active() 28 | 29 | 0go 30 | norm % 31 | call assert_equal([3, 4], getcurpos()[1:2]) 32 | norm 2% 33 | call assert_equal([1, 1], getcurpos()[1:2]) 34 | 35 | call matchup#test#finished() 36 | -------------------------------------------------------------------------------- /test/new/test-vader/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: test 2 | 3 | MYVIM ?= nvim --headless 4 | 5 | INMAKE := 1 6 | export INMAKE 7 | 8 | VADER_DIR := ../../vader 9 | TESTS := $(wildcard $(VADER_DIR)/*.vader) 10 | TESTS := $(TESTS:.vader=) 11 | 12 | test: $(TESTS) 13 | 14 | $(VADER_DIR)/%: $(VADER_DIR)/%.vader 15 | $(MYVIM) -u $(VADER_DIR)/minvimrc +Vader! $< 16 | -------------------------------------------------------------------------------- /test/new/test-where/LICENSE: -------------------------------------------------------------------------------- 1 | VIM LICENSE 2 | 3 | I) There are no restrictions on distributing unmodified copies of Vim except 4 | that they must include this license text. You can also distribute 5 | unmodified parts of Vim, likewise unrestricted except that they must 6 | include this license text. You are also allowed to include executables 7 | that you made from the unmodified Vim sources, plus your own usage 8 | examples and Vim scripts. 9 | 10 | II) It is allowed to distribute a modified (or extended) version of Vim, 11 | including executables and/or source code, when the following four 12 | conditions are met: 13 | 1) This license text must be included unmodified. 14 | 2) The modified Vim must be distributed in one of the following five ways: 15 | a) If you make changes to Vim yourself, you must clearly describe in 16 | the distribution how to contact you. When the maintainer asks you 17 | (in any way) for a copy of the modified Vim you distributed, you 18 | must make your changes, including source code, available to the 19 | maintainer without fee. The maintainer reserves the right to 20 | include your changes in the official version of Vim. What the 21 | maintainer will do with your changes and under what license they 22 | will be distributed is negotiable. If there has been no negotiation 23 | then this license, or a later version, also applies to your changes. 24 | The current maintainer is Bram Moolenaar . If this 25 | changes it will be announced in appropriate places (most likely 26 | vim.sf.net, www.vim.org and/or comp.editors). When it is completely 27 | impossible to contact the maintainer, the obligation to send him 28 | your changes ceases. Once the maintainer has confirmed that he has 29 | received your changes they will not have to be sent again. 30 | b) If you have received a modified Vim that was distributed as 31 | mentioned under a) you are allowed to further distribute it 32 | unmodified, as mentioned at I). If you make additional changes the 33 | text under a) applies to those changes. 34 | c) Provide all the changes, including source code, with every copy of 35 | the modified Vim you distribute. This may be done in the form of a 36 | context diff. You can choose what license to use for new code you 37 | add. The changes and their license must not restrict others from 38 | making their own changes to the official version of Vim. 39 | d) When you have a modified Vim which includes changes as mentioned 40 | under c), you can distribute it without the source code for the 41 | changes if the following three conditions are met: 42 | - The license that applies to the changes permits you to distribute 43 | the changes to the Vim maintainer without fee or restriction, and 44 | permits the Vim maintainer to include the changes in the official 45 | version of Vim without fee or restriction. 46 | - You keep the changes for at least three years after last 47 | distributing the corresponding modified Vim. When the maintainer 48 | or someone who you distributed the modified Vim to asks you (in 49 | any way) for the changes within this period, you must make them 50 | available to him. 51 | - You clearly describe in the distribution how to contact you. This 52 | contact information must remain valid for at least three years 53 | after last distributing the corresponding modified Vim, or as long 54 | as possible. 55 | e) When the GNU General Public License (GPL) applies to the changes, 56 | you can distribute the modified Vim under the GNU GPL version 2 or 57 | any later version. 58 | 3) A message must be added, at least in the output of the ":version" 59 | command and in the intro screen, such that the user of the modified Vim 60 | is able to see that it was modified. When distributing as mentioned 61 | under 2)e) adding the message is only required for as far as this does 62 | not conflict with the license used for the changes. 63 | 4) The contact information as required under 2)a) and 2)d) must not be 64 | removed or changed, except that the person himself can make 65 | corrections. 66 | 67 | III) If you distribute a modified version of Vim, you are encouraged to use 68 | the Vim license for your changes and make them available to the 69 | maintainer, including the source code. The preferred way to do this is 70 | by e-mail or by uploading the files to a server and e-mailing the URL. 71 | If the number of changes is small (e.g., a modified Makefile) e-mailing a 72 | context diff will do. The e-mail address to be used is 73 | 74 | 75 | IV) It is not allowed to remove this license from the distribution of the Vim 76 | sources, parts of it or from a modified version. You may use this 77 | license for previous Vim releases instead of the license that they came 78 | with, at your option. 79 | -------------------------------------------------------------------------------- /test/new/test-where/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: test 2 | 3 | MYVIM ?= nvim --headless 4 | 5 | INMAKE := 1 6 | export INMAKE 7 | 8 | test: 9 | echo "test skipped" 10 | # $(MYVIM) -u test.vim 11 | -------------------------------------------------------------------------------- /test/new/test-where/test.vim: -------------------------------------------------------------------------------- 1 | set nocompatible 2 | source ../common/bootstrap.vim 3 | 4 | if !has('nvim') 5 | echo 'skipping test-where for vim' 6 | call matchup#test#finished() 7 | endif 8 | 9 | set encoding=utf-8 columns=120 10 | NoMatchParen 11 | 12 | edit +161 normal.c 13 | 14 | if matchup#ts_engine#is_enabled(bufnr('.')) 15 | " TODO: matchparen.vim: if empty(a:offscreen.links.close.match) 16 | echo 'skipping test-where for tree_sitter' 17 | call matchup#test#finished() 18 | endif 19 | 20 | redir! > test1.out 21 | sil MatchupWhereAmI? 22 | sleep 50m 23 | redir END 24 | 25 | normal! j 26 | redir! > test2.out 27 | sil MatchupWhereAmI? 28 | sleep 50m 29 | redir END 30 | 31 | normal! k 32 | redir! > test3.out 33 | sil MatchupWhereAmI?? 34 | sleep 50m 35 | redir END 36 | 37 | call assert_equal(readfile('test1.good'), readfile('test1.out')) 38 | call assert_equal(readfile('test2.good'), readfile('test2.out')) 39 | call assert_equal(readfile('test3.good'), readfile('test3.out')) 40 | 41 | call matchup#test#finished() 42 | -------------------------------------------------------------------------------- /test/new/test-where/test1.good: -------------------------------------------------------------------------------- 1 | match-up: loading...normal_cmd( … { ▶ if (!(VIsual_active && … { ▶ while ( (c >= '1' & … { ▶ if (ctrl_w) … { -------------------------------------------------------------------------------- /test/new/test-where/test2.good: -------------------------------------------------------------------------------- 1 | match-up: loading...normal_cmd( … { ▶ if (!(VIsual_active && … { ▶ while ( (c >= '1' & … { ▶ if (ctrl_w) … { -------------------------------------------------------------------------------- /test/new/test-where/test3.good: -------------------------------------------------------------------------------- 1 | match-up: loading...normal_cmd( … { 2 | if (!(VIsual_active && VIsual_select)) … { 3 | while ( (c >= '1' && c <= '9') … { 4 | if (ctrl_w) … { -------------------------------------------------------------------------------- /test/scripts/style-check.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | luacheck `find ./lua -name "*.lua"` --codes 4 | -------------------------------------------------------------------------------- /test/vader/issue-66.vader: -------------------------------------------------------------------------------- 1 | Given vim (Parentheses): 2 | if l:x == 1 3 | call one() 4 | elseif l:x == 2 5 | call two() 6 | elseif l:x == 3 7 | call three() 8 | elseif l:x == 4 9 | call four() 10 | elseif l:x == 5 11 | call five() 12 | elseif l:x == 6 13 | call six() 14 | elseif l:x == 7 15 | call seven() 16 | elseif l:x == 8 17 | call eight() 18 | else 19 | call none() 20 | endif 21 | 22 | Do (Delete 3 inner %): 23 | 7gg 24 | d3i% 25 | 26 | Expect vim (Verify): 27 | if l:x == 1 28 | call one() 29 | elseif l:x == 2 30 | call two() 31 | elseif l:x == 3 32 | call three() 33 | elseif l:x == 4 34 | call four() 35 | elseif l:x == 5 36 | call five() 37 | elseif l:x == 6 38 | call six() 39 | elseif l:x == 7 40 | call seven() 41 | elseif l:x == 8 42 | call eight() 43 | else 44 | call none() 45 | endif 46 | 47 | Do (Delete 3 inner %, with blank first line): 48 | ggO\ 49 | 7gg 50 | d3i% 51 | 52 | Expect vim (Verify): 53 | 54 | if l:x == 1 55 | call one() 56 | elseif l:x == 2 57 | call two() 58 | elseif l:x == 3 59 | call three() 60 | elseif l:x == 4 61 | call four() 62 | elseif l:x == 5 63 | call five() 64 | elseif l:x == 6 65 | call six() 66 | elseif l:x == 7 67 | call seven() 68 | elseif l:x == 8 69 | call eight() 70 | else 71 | call none() 72 | endif 73 | 74 | Do (Delete inner %): 75 | 7gg 76 | di% 77 | 78 | Expect vim (Verify): 79 | if l:x == 1 80 | call one() 81 | elseif l:x == 2 82 | call two() 83 | elseif l:x == 3 84 | elseif l:x == 4 85 | call four() 86 | elseif l:x == 5 87 | call five() 88 | elseif l:x == 6 89 | call six() 90 | elseif l:x == 7 91 | call seven() 92 | elseif l:x == 8 93 | call eight() 94 | else 95 | call none() 96 | endif 97 | 98 | Do (Delete 1 inner %): 99 | 7gg 100 | d1i% 101 | 102 | Expect vim (Verify): 103 | if l:x == 1 104 | endif 105 | -------------------------------------------------------------------------------- /test/vader/minvimrc: -------------------------------------------------------------------------------- 1 | set nocompatible 2 | 3 | " load match-up 4 | let s:path = simplify(expand(':h').'/../..') 5 | let &rtp = s:path.',' . &rtp 6 | let &rtp .= ','.s:path.'/test/vader/vader.vim' 7 | let &rtp .= ','.s:path.'/after' 8 | 9 | " rtp for testing files 10 | let &rtp = s:path.'/test/rtp,' . &rtp 11 | 12 | " load other plugins, if necessary 13 | " let &rtp = '~/path/to/other/plugin,' . &rtp 14 | 15 | if $TESTS_ENABLE_TREESITTER 16 | let &rtp = s:path.'/test/vader/plugged/nvim-treesitter,' . &rtp 17 | let &rtp .= ','.s:path.'/test/vader/plugged/nvim-treesitter/after' 18 | 19 | runtime! plugin/nvim-treesitter.vim 20 | runtime! plugin/nvim-treesitter.lua 21 | 22 | lua <%): 20 | d% 21 | Expect (Verify): 22 | | 23 | 24 | -------------------------------------------------------------------------------- /test/vader/ruby.vader: -------------------------------------------------------------------------------- 1 | Given ruby (Ruby for if): 2 | for i in 0..5 3 | if i < 2 then 4 | next 5 | end 6 | puts "Value of local variable is #{i}" 7 | end 8 | 9 | Do (Motion %): 10 | go 11 | % 12 | 13 | Then (Verify): 14 | Log b:match_words 15 | Log b:match_midmap 16 | AssertEqual 'next', expand('') 17 | 18 | Given ruby (Ruby do end): 19 | context 'webhooks' do 20 | before { allow_any_instance_of(described_class).to receive(:webhook_endpoint_active?).and_return(true) } 21 | 22 | it 'runs webhooks' do 23 | expect(Webhook::Runner).to receive(:deliver) 24 | subject 25 | end 26 | end 27 | 28 | Do (Motion %): 29 | go2W 30 | % 31 | 32 | Then (Verify): 33 | AssertEqual 'end', getline('.') 34 | 35 | Do (Motion %): 36 | 2ggee 37 | % 38 | % 39 | 40 | Then (Verify): 41 | AssertEqual '{', getline('.')[col('.')-1] 42 | 43 | -------------------------------------------------------------------------------- /test/vader/run: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | cd "$(dirname "${BASH_SOURCE[0]}")" 4 | ${VIMCMD:-vim} -Nu minvimrc +"Vader! ${1:-*}" 5 | 6 | -------------------------------------------------------------------------------- /test/vader/syn.vader: -------------------------------------------------------------------------------- 1 | Execute (opts): 2 | let matchup_matchparen_offscreen = {} 3 | let matchup_delim_noskips = 2 4 | 5 | Given scheme (Syntax): 6 | (define procname ; ) in comment isn't matched as expected 7 | ") in string is however matched" 8 | body) 9 | 10 | Before (): 11 | 2normal! f) 12 | Log getcurpos() 13 | Log synIDattr(synID(line('.'), col('.'), 1), 'name') 14 | 15 | Do (%): 16 | % 17 | Then (Verify line): 18 | Log getcurpos() 19 | AssertEqual 1, line('.') 20 | 21 | -------------------------------------------------------------------------------- /test/vader/text_obj.vader: -------------------------------------------------------------------------------- 1 | Given (Parentheses): 2 | ( 3 | 4 | 5 | 6 | ) 7 | 8 | ( hello 9 | 10 | 11 | 12 | ) 13 | 14 | (vibd) 15 | (dvib) 16 | (dib) 17 | () 18 | 19 | Do (Delete inner %): 20 | 16gg0 21 | di% 22 | kdi% 23 | kdvi% 24 | kvi%d 25 | 3kdi% 26 | 4kdi% 27 | 28 | Expect (Verify): 29 | ( 30 | ) 31 | 32 | ( 33 | 34 | ) 35 | 36 | () 37 | (b) 38 | () 39 | () 40 | 41 | -------------------------------------------------------------------------------- /test/vader/ts_py_motion.vader: -------------------------------------------------------------------------------- 1 | Execute (Helper): 2 | function! TSActive() 3 | return exists(':TSInstall') 4 | endfunction 5 | 6 | if TSActive() 7 | Log 'nvim-treesitter active' 8 | else 9 | Log 'nvim-treesitter not active' 10 | endif 11 | 12 | Given python (A python script): 13 | def F(x, y): 14 | if x == 1: 15 | return 1 16 | elif x == 2: 17 | if y == 5: 18 | pass 19 | elif y == 7: 20 | return 9 21 | else: 22 | return x 23 | else: 24 | return 3 25 | return 2 26 | 27 | Execute (Logs): 28 | Log b:matchup_active_engines 29 | 30 | # ----- outer if/elif/else ----- 31 | 32 | Before (Cursor): 33 | normal! 2gg^ 34 | 35 | Do (Move %): 36 | % 37 | Then (Verify line): 38 | AssertEqual (TSActive() ? 4 : 2), line('.') 39 | 40 | Do (Move % twice): 41 | %% 42 | Then (Verify line): 43 | AssertEqual (TSActive() ? 11 : 2), line('.') 44 | 45 | Do (Move % 3 times): 46 | %%% 47 | Then (Verify line): 48 | AssertEqual (TSActive() ? 2 : 2), line('.') 49 | 50 | Do (Move % 4 times): 51 | %%%% 52 | Then (Verify line): 53 | AssertEqual (TSActive() ? 4 : 2), line('.') 54 | 55 | # ----- inner if/elif/else ----- 56 | 57 | Before (Cursor): 58 | normal! 5gg^ 59 | 60 | Do (Inner: Move %): 61 | % 62 | Then (Verify line): 63 | AssertEqual (TSActive() ? 7 : 5), line('.') 64 | 65 | Do (Inner: % 2 times): 66 | %% 67 | Then (Verify line): 68 | AssertEqual (TSActive() ? 9 : 5), line('.') 69 | 70 | Do (Inner: % 3 times): 71 | %%% 72 | Then (Verify line): 73 | AssertEqual (TSActive() ? 5 : 5), line('.') 74 | 75 | Do (Inner: % 4 times): 76 | %%%% 77 | Then (Verify line): 78 | AssertEqual (TSActive() ? 7 : 5), line('.') 79 | --------------------------------------------------------------------------------