pax_global_header00006660000000000000000000000064145617215000014513gustar00rootroot0000000000000052 comment=11fec7442de5cd63d07563ae64767fcee7a594a2 auto-pairs-4.0.2/000077500000000000000000000000001456172150000136025ustar00rootroot00000000000000auto-pairs-4.0.2/.github/000077500000000000000000000000001456172150000151425ustar00rootroot00000000000000auto-pairs-4.0.2/.github/CODE_OF_CONDUCT.md000066400000000000000000000064261456172150000177510ustar00rootroot00000000000000# Contributor Covenant Code of Conduct ## Our Pledge In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. ## Our Standards Examples of behavior that contributes to creating a positive environment include: * Using welcoming and inclusive language * Being respectful of differing viewpoints and experiences * Gracefully accepting constructive criticism * Focusing on what is best for the community * Showing empathy towards other community members Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery and unwelcome sexual attention or advances * Trolling, insulting/derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or electronic address, without explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Our Responsibilities Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. ## Scope This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at zoe.i2k1@gmail.com. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html [homepage]: https://www.contributor-covenant.org For answers to common questions about this code of conduct, see https://www.contributor-covenant.org/faq auto-pairs-4.0.2/.github/CONTRIBUTING.md000066400000000000000000000050531456172150000173760ustar00rootroot00000000000000# Contributing ## Basic expectations The project has a [code of conduct](https://github.com/LunarWatcher/auto-pairs/blob/master/.github/CODE_OF_CONDUCT.md) you're expected to follow. ## Asking questions, reporting bugs, posting feature requests, etc. This repo has enabled both discussions and issues, and the general distribution is: * Bugs and feature requests go into issues * Questions on usage go in discussions This distribution is largely because discussions center around answerability, and there's not really that many proper answers to a feature request or a bug. Aside votes potentially indicating usefulness, but that's beside the point. That said, it's not always obvious what goes where. Something could be a bug, but could also just be a bad configuration. It's therefore expected that you make an attempt at figuring out where it's best suited, but there's no consequences for posting in the wrong category. At worst, it can just be converted, no harm done. ## Pull requests We welcome pull requests, but as this project has been getting more complex, there's a few meta guidelines surrounding these. ### Versioning There's a variable that keeps track of versions. Simply put, if you're making the first PR after a version has been tagged, you have to increment the number by one. If commits have been made since the previous tag, skip this step. And again, this only applies to the number in `autoload/`. I'll take care of the more semantic side of versioning. This step is largely to make sure `g:AutoPairsVersion` doesn't indicate an old version with features that aren't a part of the tagged version. ### Changelog The project has a changelog. As evidenced by the already existing content of the changelog, it doesn't have to be completely exhaustive or detailed, but a line or two describing any applicable changes should be a part of your PR. The changelog loosely uses the [keepachangelog](https://keepachangelog.com/en/1.0.0/) 1.0.0 standard, though with a few variations. You can largely just base it off the existing entries if nothing for the current version exists. ### Testing GitHub automatically builds tests when you commit in a PR (though new contributors need to have the run manually approved in order to start, because GitHub said so). The tests always have to pass. If some core functionality was changed that means the failing test(s) need changes, these must be made for the PR to be approved. Adding tests is highly encouraged, and only required for bug fixes. Regression tests are extremely important for ensuring bugs don't happen again later. auto-pairs-4.0.2/.github/ISSUE_TEMPLATE/000077500000000000000000000000001456172150000173255ustar00rootroot00000000000000auto-pairs-4.0.2/.github/ISSUE_TEMPLATE/bug_report.yml000066400000000000000000000027531456172150000222270ustar00rootroot00000000000000name: Report a bug description: File a bug report labels: ["bug"] body: - type: markdown attributes: value: | ## Before reporting Make sure you've tested on the latest version of auto-pairs, and that you've read the trouble-shooting guide (AutoPairsTrouble.txt, `:h autopairs-troubleshooting`) to see if your issue is already well-known. Searching existing issues is also recommended. ## Environment information - type: input validations: required: true attributes: label: OS version placeholder: Linux Mint 20, Windows 10, etc. - type: input validations: required: true attributes: label: Vim version (and distribution) placeholder: Vim 9.0.1234, nvim v0.7, ... - type: textarea validations: required: false attributes: label: Autopairs config - type: markdown attributes: value: | ## Describe the bug Remember to be detailed. - type: textarea validations: required: true attributes: label: Describe the bug description: Desribe the bug here - type: textarea validations: required: true attributes: label: Steps to reproduce description: Describe what you did to trigger the bug, and the steps required to reproduce it. - type: textarea validations: required: false attributes: label: Other information description: Anything else important not covered by the other fields can go here. auto-pairs-4.0.2/.github/ISSUE_TEMPLATE/config.yml000066400000000000000000000002551456172150000213170ustar00rootroot00000000000000blank_issues_enabled: true contact_links: - name: General support url: https://github.com/lunarwatcher/auto-pairs/discussions about: Ask the community for support auto-pairs-4.0.2/.github/ISSUE_TEMPLATE/feature_request.md000066400000000000000000000003751456172150000230570ustar00rootroot00000000000000--- name: Feature request about: Got a new feature you wanna see? title: 'Add a short description of your feature request here' labels: feature-request assignees: '' --- auto-pairs-4.0.2/.github/workflows/000077500000000000000000000000001456172150000171775ustar00rootroot00000000000000auto-pairs-4.0.2/.github/workflows/tests.yml000066400000000000000000000033421456172150000210660ustar00rootroot00000000000000name: Tests on: push: branches: [ master, develop, develop-4.0.0 ] pull_request: branches: [ master, develop, develop-4.0.0 ] jobs: test-ubuntu: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Versions run: vim --version - name: Run tests run: | git clone https://github.com/thinca/vim-themis ./vim-themis/bin/themis test-mac: runs-on: macos-latest steps: - uses: actions/checkout@v2 - name: Versions run: vim --version - name: Run tests run: | git clone https://github.com/thinca/vim-themis ./vim-themis/bin/themis test-windows: runs-on: windows-latest steps: - uses: actions/checkout@v2 - name: Versions run: vim --version - name: Run tests shell: cmd run: | git clone https://github.com/thinca/vim-themis bash -c "./vim-themis/bin/themis" test-docs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Versions run: vim --version - name: Run tests run: | # TL;DR: # Run helptags doc # If an error happens, the try-catch catches it. Echoerr v:exception then logs it # and aborts the rest of that command. If it doesn't error, the `qa` is executed, # and vim exits normally, resulting in the last -c not being executed. # The last -c is only executed if an error occurs, and cq is exiting vim with an error, # which causes the CI to observe teh error as well, and causing a proper CI failure. # Stonks! vim -c "try | helptags doc | catch | echoerr v:exception | endtry | qa" -c "cq" auto-pairs-4.0.2/.gitignore000066400000000000000000000000301456172150000155630ustar00rootroot00000000000000doc/tags .lvimrc *.log auto-pairs-4.0.2/.themisrc000066400000000000000000000022551456172150000154250ustar00rootroot00000000000000let s:expect = themis#helper('expect') let g:CachePairs = autopairs#AutoPairsDefine({}) let g:AutoPairsForceDefine = 69420 let g:Assert = themis#helper("assert") " Some plugin apparently changes the tex filetype " to plaintex, which breaks stuff:tm: " This ensures it doesn't let g:tex_flavor = 'latex' syntax on filetype plugin indent on set noswapfile " We have to set this to make sure indent-sensitive checks work as expected. " This is largely just to make sure indent changes don't break working tests set expandtab set sw=2 " Not sure why I have to use a function to forward, but okay fun! Expect(input) return s:expect(a:input) endfun fun! CheckBuffImpl(input, output) return join(getline(1, '$'), '\n') ==# a:output endfun fun! ToMatchImpl(input, output) %d " Clear the file execute 'normal i' . a:input return join(getline(1, '$'), '\n') ==# a:output endfun call themis#helper#expect#define_matcher('CheckBuff', function('CheckBuffImpl'), '"Expected:\n" . a:2 . "\nActual:\n". join(getline(1, ''$''), ''\n'')') call themis#helper#expect#define_matcher('ToMatch', function('ToMatchImpl'), '"Expected:\n" . a:2 . "\nActual:\n". join(getline(1, ''$''), ''\n'')') auto-pairs-4.0.2/CHANGELOG.md000066400000000000000000000433011456172150000154140ustar00rootroot00000000000000# 4.0.2 `g:AutoPairsVersion = 40002` ## Fixed * Made sure the AutoPairsJump keybind in insert mode ends up after the cursor ([upstream/#367](https://github.com/jiangmiao/auto-pairs/issues/367) (comment)) ## Changed * Setting `mapclose = 0` now makes `alwaysmapdefaultclose` default to 0 instead of 1 * The LaTeX pairs no longer jump by default ## Added * `g:AutoPairsSpaceCompletionRegex` ([#75 followups](https://github.com/LunarWatcher/auto-pairs/issues/75#issuecomment-1403772146)) * `g:AutoPairsDefaultDisableKeybinds` ([upstream/#367](https://github.com/jiangmiao/auto-pairs/issues/367) (comment)) for default-blanking the various keybind variables ## Docs * Described the exact reason for [#66](https://github.com/LunarWatcher/auto-pairs/issues/66) in `:h autopairs-autocomplete-cr` * Documented variable initialisation and function call order issues ([#84](https://github.com/LunarWatcher/auto-pairs/issues/84)) # 4.0.1 `g:AutoPairsVersion = 40001` ## Fixed * Missing escape ([#74](https://github.com/LunarWatcher/auto-pairs/issues/74)) # 4.0.0 `g:AutoPairsVersion = 40000` ## Changed * `g:AutoPairsCompatibleMaps` is now 0 by default. * Added enforcement of scriptversion 4 to all files ## Documentation * Added docs for `` incompatibilities * Documentation with some basic how-to guides for auto-pairs features. These can technically be figured out by just reading the documentation, but it's easier to compress it into concrete guides. * Documentation for Krasjet's space-only completion exceptions, and first-class support for it. * Documentation and first-class support for Krasjet's balance blacklist ## Fixed * Minimum Vim version is now correctly listed as 8.1 patch 1114; I severely misread the minimum required version before. * Missing `...` specifier prevented argument forwarding for IgnoreInsertEnter * Missing period for string concatenation seems to have broken the move feature * Switched to a variable for universal event ignoring, without overwriting the variable unrecoverably (`exists('##InsertLeavePre')` <3) * [parallel-fixed in an unversioned 3.0.x-version] Fixed bad regex management for multibyte pairs ([#71](https://github.com/LunarWatcher/auto-pairs/issues/71)) ## Added * Tests for both the character whitelist for only completing on space, and the balance check blacklist. * Added `g:AutoPairsAutoBreakBefore` and `g:AutoPairsSyncAutoBreakOptions` ([#57](https://github.com/LunarWatcher/auto-pairs/issues/57)) * `InsertLeavePre` is now ignored * Regex pairs are now disabled and made opt-in only ([#53](https://github.com/LunarWatcher/auto-pairs/issues/53)) * `g:AutoPairsPrefix`, used for switching the default prefix in incompatible map mode. * The LaTeX pairs `\[\]` and `\(\)` are supported out of the box for the `tex` filetype * **Breaking:** regex is now disabled by default, and requires a manual parameter. See `:h autopairs-pair-object`. * The auto-pairs compatible maps prefix can now be adjusted with `g:AutoPairsPrefix` ([#48](https://github.com/LunarWatcher/auto-pairs/discussions/48), [#70](https://github.com/LunarWatcher/auto-pairs/issues/70)) ## Meta * Removed pre-commit * Added a test to catch duplicate helptags # 3.0.4 `g:AutoPairsVersion = 30063` ## Changed * Renamed `autopairs#Variables#_InitVariables` to `autopairs#Variables#InitVariables`, as the API is now more intended for public use * `g:AutoPairsFiletypeBlacklist` now contains `"registers"` by default, and fully prevents loading in the buffer ## Documentation * Documented `autopairs#Variables#InitVariables()` # 3.0.3 `g:AutoPairsVersion = 30062` ## Changed * Enabled experimental autocmd by default; preparing for the eventual deprecation of it # 3.0.2 `g:AutoPairsVersion = 30061` ## Meta * Cleaned up the help documents to, hopefully, be easier to navigate. ## Removed * `g:AutoPairsBackwardsCompat`, as it doesn't appear to have any uses at this time. ## Added * `g:AutoPairsBSIn` * `g:AutoPairsBSAfter` * Troubleshooting docs for Rust ## Fixed * Duplicate tags in help docs ([#59](https://github.com/LunarWatcher/auto-pairs/pull/59)) # 3.0.1 `g:AutoPairsVersion = 30060` ## Fixed * Annoying escape problem ([#52](https://github.com/LunarWatcher/auto-pairs/discussions/52)) * Open == close-pairs struggled to verify balance. ([#40](https://github.com/LunarWatcher/auto-pairs/discussions/40) (discussion) and its associated issue ([#41](https://github.com/LunarWatcher/auto-pairs/issues/41))) * Bug preventing `open: 'not empty', close: ''` from clearing output inserted by other pairs * Typo in offset potentially breaking balancing (not sure if this was a problem before 3.0.1 or if the changes made here made it painfully obvious, but it's fixed now nonetheless) * Add a lookahead to the regex group for single quotes in vim files. Just using `\ze` doesn't actually prevent it from matching the rest of the quote, causing weird quote insertion behavior with the changes made as a part of 3.0.1. # 3.0.0 No changes; Purely a symbolic packaging for 3.0.0-beta13. # 3.0.0-beta13 `g:AutoPairsVersion = 30058` ## Meta * Code cleanup * Vimscript standard update #1 ## Added * Skip single completion ([jiangmiao#335](https://github.com/jiangmiao/auto-pairs/issues/335)) * More tests (including tests to cover single skip) # 3.0.0-beta12 `g:AutoPairsVersion = 30057` ## Fixed * Better escape handing ([jiangmiao#325](https://github.com/jiangmiao/auto-pairs/issues/325)) * Typos in the help document * Update variable list in the help document * Add a help document covering plugin interop for specific plugins * Bug from beta11 breaking the autopairs toggle shortcut ## Added * `g:AutoPairsSearchEscape` ## Removed * `g:AutoPairsShortcutMultilineClose` # 3.0.0-beta11 `g:AutoPairsVersion = 30056` ## Fixed * Close pair balance checks weren't up to date with new balance systems * `g:AutoPairsStringHandlingMode` shouldn't prevent skipping characters * Add buffer variables for keybinds ([#35](https://github.com/LunarWatcher/auto-pairs/issues/35)) ## Changed * Cleaned up the implementation of the beta9 hotpatch (AKA properly fix #30) * Moved variable (global + buffer) declaration to a separate file to reduce clutter in `autoload/autopairs.vim` * Tweaks to the close balance logic making it more jump-happy than previously * Reordered method calls to reduce unnecessary synstack calls for people who don't want it * Rolled back the change to multiline close ([#32](https://github.com/LunarWatcher/auto-pairs/issues/32)) * `g:AutoPairsMultilineClose` is back ## Added * Tests to reduce the chances [#30](https://github.com/LunarWatcher/auto-pairs/issues/30) occurs again * `balancebyclose` added to pair objects ([#31](https://github.com/LunarWatcher/auto-pairs/issues/31)) to aid balancing. Also helps towards #30 * CI to auto-run tests on the three major operating systems (doesn't affect the plugin itself; only the dev process) * `g:AutoPairsShortcutToggleMultilineClose` * `g:AutoPairsPreferClose` ## Removed * `autopairs#AutoPairsScriptInit()` # Deprecated * `g:AutoPairsShortcutMultilineClose` # 3.0.0-beta10 `g:AutoPairsVersion = 30055` * Some docs * Accidental debug logging # 3.0.0-beta9 `g:AutoPairsVersion = 30054` ## Fixed * Broken open == close balance check ([#30](https://github.com/LunarWatcher/auto-pairs/issues/30)) * Fix single-quote edge case for balance checks * Fix no ft edge-case for syntax checking # 3.0.0-beta8 `g:AutoPairsVersion = 30053` ## Added * [Meta] Testing * `autopairs#AutoPairsAddPair()` * `autopairs#AutoPairsAddPairs()` * Lots of customization functionality through `:h autopairs-pair-object`. Highlights: * `g:AutoPairs` and `autopairs#AutoPairsAddPair` (+ `autopairs#AutoPairsAddPairs` by extension) support a `language` tag, meaning there's now a way to make all your pairs work by modifying a single variable. The language tag also takes a single language as well as a list of languages, meaning it's easy to apply a single pair to several languages. * The option to disable delete for individual pairs * The option to map a related or unrelated key to explicitly jump through the pair. * `g:AutoPairsShortcutMultilineClose` ([#19](https://github.com/lunarwatcher/auto-pairs/issues/19), [#21](https://github.com/lunarwatcher/auto-pairs/issues/21)) * Added `g:AutoPairsExperimentalAutocmd` * Added `g:AutoPairsStringHandlingMode` * Added `:AutoPairsToggle`, `:AutoPairsDisable`, and `:AutoPairsEnable` (upstream [#278](https://github.com/jiangmiao/auto-pairs/issues/278), missed in the initial ticket crunch) * Added `g:AutoPairsMoveExpression` (fixes [#25](https://github.com/LunarWatcher/auto-pairs/issues/25); an issue introduced by a fix to [#317](https://github.com/jiangmiao/auto-pairs/issues/317) that remapped from `` to `` (which doesn't work because input processing artifacts)). * Explicit support for vim-visual-multi (Completely fixes [#12](https://github.com/LunarWatcher/auto-pairs/issues/12)) * Added `g:AutoPairsMultilineBackspace` ([#29](https://github.com/LunarWatcher/auto-pairs/issues/29)) ## Changed * Made `autopairs#AutoPairsDefine` accept a list as well. The list contains a different type of more powerful objects; see the documentation (autopairs-pair-object) * Made explicit jump keys map themselves if no mappings are defined. The explicit meaning of the map may change, but it's designed not to conflict with other keys (and as such, it's designed to maintain backwards-compatibility, without breaking stuff) * Internal: moved open pair balancing to a separate function * Prevent an explicit close key from preventing close when it's also desired to close by the normal key * Documentation cleanup of the troubleshooting section (copy editing, general updates, remove bad advice) * Made `g:AutoPairsBackwardsCompat` default to 0 instead of a conditional ## Removed * An API that gave some minor customization access to pairs. The API has been replaced with a substantially more flexible API (see `:h autopairs-pair-object` for more details; **potentially breaking**) * `g:AutoPairsWildClosedPair` (has been unused for a long time) ## Deprecated * `autopairs#AutoPairsScriptInit` * `g:AutoPairsEnableMove` (deprecated in favor of `let g:AutoPairsMoveExpression = ""`) ## Fixed * Multibyte fast wrap around vim pairs (`%`-able built-in (and manually specified) pairs) * Make multiline reverse pair deletion opt-in (`g:AutoPairsMultilineBackspace`) # 3.0.0-beta7 `g:AutoPairsVersion = 30052` ## Fixed * Bug in backspace triggered by empty close not being ignored ([#22](https://github.com/LunarWatcher/auto-pairs/issues/22)) * Bug in backspace triggered by a bad comparison (causing bad `` when not deleting actual pairs, but i.e. half a pair * Add `g:AutoPairsReturnOnEmptyOnly` # 3.0.0-beta6 `g:AutoPairsVersion = 30051` ## Changed * All the keybinds ([#18](https://github.com/LunarWatcher/auto-pairs/issues/18)) - The new scheme uses largely compound keybinds: `` as a prefix (ctrl-auto**p**airs), followed by some semi-representative ctrl keybind. `` for jump (ctrl skip), `` for back insert, `` for toggling auto-pairs. `` is for fast wrap, but note that `` is not used for this keybind at all. - `let g:AutoPairsCompatibleMaps` added ([#20](https://github.com/LunarWatcher/auto-pairs/issues/20); defaults to 1 for the near foreseeable future) * Re-disable `g:AutoPairsMultilineClose` # 3.0.0-beta5 `g:AutoPairsVersion = 30050` ## Fixed * Bad fast wrap when open == close and there isn't a space before open ([#17](https://github.com/LunarWatcher/auto-pairs/issues/17)) * Bad balance check caused by `if index(...)` rather than `if index(...) != -1` * Fixed broken `foo[]|`-check (early return, bugged since the start) * Make `foo[]|` run a multiline check in reverse ## Changed * `g:AutoPairsVersion` no longer has a semantic meaning # 3.0.0-beta4 ## Added * `b:AutoPairsJumpRegex` ## Fixed * Balance checks where the open bracket is regex ([#15](https://github.com/LunarWatcher/auto-pairs/issues/15)) (`count(whatever, open) => s:regexCount(whatever, open)`) * Manual jump now includes custom pairs ([#16](https://github.com/LunarWatcher/auto-pairs/issues/16)) # 3.0.0-beta3 ## Added * `g:AutoPairsMultilineCloseDeleteSpace` * `g:AutoPairsMultibyteFastWrap` -- fast wrap now supports multibyte pairs * `g:AutoPairsFiletypeBlacklist` ## Fixed * Made the vim comment regex less awful * `AutoPairsMultilineClose` didn't work * `g:AutoPairsCompleteOnlyOnSpace` regex: \S is enough. Newlines appear to be stripped anyway, so EOL is fine * Revert `g:AutoPairsMultilineClose` to 0; not sure when it changed to 1 * Corrected multiline pair regex (`'^\V'.close` -> `'\v^\s*\zs\V'.close`); not sure why it was changed in the first place, doesn't appear to be relevant for space-only autoinsert. (Objections are welcome on this one; open an issue if you disagree or if this breaks your use of the plugin) * Slightly saner check for escaped characters ## Changed * Made `g:AutoPairsOpenBalanceBlacklist` empty by default. Can't remember the rationale behind adding them in the first place * [Meta] Removed old, outdated comments and add new confused ones # 3.0.0-beta2 ## Added * Added `g:AutoPairsVersion` * Added `g:AutoPairsBackwardsCompat` * Backwards compat documentation * Added `g:AutoPairsMultilineFastWrap`; also means minor, optional changes to the fast wrap system * Added `g:AutoPairsFlyModeList` * Added `g:AutoPairsJumpBlacklist` ([jiangmiao/313](https://github.com/jiangmiao/auto-pairs/issues/313)) ## Fixed * Incompatibility with vim-visual-multi * Fixed weird fast wrap behavior when the closer is identical to the opener ([jiangmiao/296](https://github.com/jiangmiao/auto-pairs/issues/296)) * Try to fix issue where brackets are imbalanced on the line, but that isn't indicative of bad balancing. Primarily an issue in multiline if-else blocks, or try-catch blocks in languages like C, C++, and Java. (fix has since been fixed) * Some function calls were not renamed (bad refactoring; [#13](https://github.com/LunarWatcher/auto-pairs/issues/13)) * Handle strgetchar() returning -1 ([#14](https://github.com/LunarWatcher/auto-pairs/issues/14)) * `g:AutoPairsCRKey` looking for expansions on `` when `g:AutoPairsCRKey` isn't `` (should look for keybinds to `g:AutoPairsCRKey` rather than just ``) * Update to flymode pairs that unescaped values unescaped ], which _has_ to be escaped. * Make sure g/b:AutoPairsNoJump = 1 doesn't interfere with balancing logic. ## Changed * `autopairs#AutoPairsFastWrap` argument movement changed from a required argument to a vararg to make it optional; defaults to `e` when not supplied # 3.0.0-beta1 ## Added * `autopairs#AutoPairsScriptInit` (dummy function for autoload; see the docs) * `g:AutoPairsLanguagePairs` (exposed previously private API) * `g:AutoPairsAutoLineBreak` * `g:AutoPairsCarefulStringExpansion`, `g:AutoPairsQuotes` ## Fixed * Load autopairs functions properly (switch primary script to autoload) * Jump keybind and backticks ([jiangmiao/299](https://github.com/jiangmiao/auto-pairs/issues/299)) * Moved variables from the wrong section of the help document to the right section. Whoops! * Make `g:AutoPairsOpenBalanceBlacklist` work (+ add docs) ## Changed * Merged `b:AutoPairs` help into `g:AutoPairs` * Added notice of the existence of a buffer variable for (hopefully) all the variables that have a buffer variant. * Moved the movement logic in `autopairs#AutoPairReturn()` to a separate function to enable `g:AutoPairsAutoLineBreak` # 3.0.0-alpha4 ## Added * `g:AutoPairsSearchCloseAfterSpace` * `g:AutoPairsSingleQuoteMode` * `g:AutoPairsSingleQuoteExpandFor` ## Fixed * `g:AutoPairsNoJump` didn't work as intended; this has now been fixed. An if-statement in the wrong place prevented it from doing what it was meant to do; avoid jumping. * Typo in AutoPairsDelete causing backspace errors * Bad backslash use in character group ([#10](https://github.com/LunarWatcher/auto-pairs/pull/10)) ## Changed * Corrected documentation of AutoPairsDefine to include the optional second argument. # 3.0.0-alpha3 ## Changes * AutoPairsFastWrap now has a parameter that decides the movement. The one mapped by default is `e`, but due to how Vim works, the argument has to be passed explicitly. (Vim 8.1 patch 1310 supports default arguments in functions, but anything before that as well as neovim would lose support). ([#8](https://github.com/LunarWatcher/auto-pairs/pull/8)) ## Fixed * `AutoPairsDefine` called `AutoPairsDefaultPairs` without `autopairs#` (missed part of the breaking change from 3.0.0-alpha2) * Prevent issues when removing a key that doesn't exist in `AutoPairsDefine` ([#9](https://github.com/LunarWatcher/auto-pairs/pull/9)) * Fix comment regex for vimscript files ([#7](https://github.com/LunarWatcher/auto-pairs/pull/7)) # 3.0.0-alpha2 ## Added * `g:AutoPairsNoJump` * `g:AutoPairsDirectoryBlacklist` * `g:AutoPairsCompleteOnSpace` * `g:AutoPairsInitHook` * Added function documentation * Added multibyte pair documentation * Document `b:autopairs_enabled` * Add more buffer variants of variables ## Changes * [Breaking] Moved all autopair functions to have an `autopairs#` prefix ## Fixes * Clarified the addition of pairs * Cleaned up the define cascades with a function (3 lines -> 1 line) * Fixed pair regex in vimscripts to better detect when quotes are likely to be comments. Largely [#7](https://github.com/LunarWatcher/auto-pairs/pull/7) (thanks to [lemeb](https://github.com/lemeb)!), but with a minor change to ignore Plug, Plugin, echo, and echoerr (where you can use double-quotes for strings, but these commands cannot have a comment on the same line -- Vimscript is weird). The changes ignoring those four commands are hackish -- improvements are welcome. # 3.0.0-alpha1 Initial release of this fork; primarily fixes a few bugs, contains documentation updates, and merges a few pull requests of varying sizes. The changelog wasn't added until 3.0.0-alpha2, which means the changes here weren't properly tracked. auto-pairs-4.0.2/LICENSE.md000066400000000000000000000021711456172150000152070ustar00rootroot00000000000000MIT license Copyright (C) 2011-2013 Miao Jiang Copyright (C) 2020 Krasjet Copyright (C) 2021-2024 Olivia (LunarWatcher) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. auto-pairs-4.0.2/README.md000066400000000000000000000137321456172150000150670ustar00rootroot00000000000000# Auto Pairs [![Tests](https://github.com/LunarWatcher/auto-pairs/actions/workflows/tests.yml/badge.svg)](https://github.com/LunarWatcher/auto-pairs/actions/workflows/tests.yml) [![Minimum Vim version 8.1 patch 1114](https://img.shields.io/badge/Vim-8.1%201--1114%20or%20newer-%23FFC0CB?logo=vim&labelColor=019833)](//github.com/vim/vim) Insert or delete brackets, parens, and quotes in pair: a maintained fork of [jiangmiao/auto-pairs](https://github.com/jiangmiao/auto-pairs) ## Note to migrating users If you're migrating from jiangmiao's version, it's highly recommended that you read `:h autopairs-migrating` after installing. There have been a number of breaking changes made in this fork, as well as changes to default behavior. See the migration guide for important differences that are may affect your workflow. ## Installation **NOTE:** Auto-pairs currently requires at least vim 8.1 with patch 1114. See [#37](https://github.com/LunarWatcher/auto-pairs/discussions/37) There's several installation methods, and you're free to use whatever you want, but I personally cannot recommend [vim-plug](https://github.com/junegunn/vim-plug) enough, in part because of the previous line of text. Installation, if you expect a more or less working variant, should be done with: ```vim Plug 'LunarWatcher/auto-pairs' ``` You can also specify a tag, but this is no longer needed as of the release of 3.0.0. To use experimental changes before they're deployed, use: ```vim Plug 'LunarWatcher/auto-pairs', {'branch': 'develop'} ``` **Note:** As of 4.0.0, `let g:AutoPairsCompatibleMaps = 0` is the default. Set the variable to 1 to use jiangmiao-compatible keybinds. ## Running tests (not required) Auto-pairs comes with a few tests aimed at making sure nothing accidentally regresses without manually testing everything. Tests are in the test folder, and are in the vimspec format (using [themis.vim](https://github.com/thinca/vim-themis)); follow its instructions to run the tests. Some plugins may interfere with the tests and cause erroneous failures, but the CI is generally indicative of the general state of auto-pairs. If it fails locally, that may be an indication of a plugin incompatibility (though these are often possible to fix) ### Versioning system (meta) This project roughly uses [semantic versioning](https://semver.org/spec/v2.0.0.html), with the minor exception that major version bumps may not be breaking in the sense that everything breaks, but introduces a set of features that significantly changes auto-pairs' functionality. Breaking API changes that affect code compatibility will never happen outside major version bumps (looking aside bugs). Additionally, the master branch is the main development branch and may therefore periodically break. While I do as many tests as I can before I push, there may still be bugs introduced on the main branch. If you want a stable (ish) experience, stick to tags. If you want updates when they're released, stick to the master branch. ## Differences from jiangmiao At this point, there's far too many differences to list all of them. Aside removing some variables (such as remapping ``), and tweaking defaults, many additional variables have been added. Including changes by Krasjet, here's a short list of some of the things this fork does that upstream doesn't: * Option for inserting pairs only if there's whitespace * Option for automatic linebreaks for some openers * Built-in support for language-specific pairs * Option for searching for closers after space (jiangmiao always did this, Krasjet never did this) * Option for entirely disabling jump * Option for a pre-init hook * Option for disabling in some directories * Options for single-quote handling around text * QOL improvements for matching * Balance checks with advanced modes (See `:h g:AutoPairsStringHandlingMode`) * ... Lots of bugfixes and general improvements * Better standards * Support and continued development :) The entire list is too long to place in its entirety here -- the documentation should cover all the variables, so reading it should give you a complete idea of the changes. ### Compatibility Quite a lot of code compatibility was thrown out the window with a massive change that moved the plugin to be partially autoloaded. This mainly leads to improvements in terms of making it easier to customize (i.e. `autopairs#AutoPairsDefine` is available without an autocmd now). Additionally, it makes sure to reduce the chance of a conflict between functions. Functionally, however, it's meant to resemble upstream as much as possible, partly to make migration less annoying for people with lots of customization. ## Goals * Improving on jiangmiao's original code * Updating the plugin with long-requested features * ... and with new ones. * Increased customizability ## Non-goals * Being a drop-in snippet replacement -- use UltiSnips or lexima.vim instead. * Supporting very old versions of Vim * HTML support: hardcoding HTML tags works, but writing a tag autoinserter requires substantial rewrites to the core engine. Instead, may I introduce you to [Tim Pope](https://github.com/tpope/vim-ragtag)? Or alternatively [alvan](https://github.com/alvan/vim-closetag)? ## Features * Obviously, the insertion and deletion of pairs (note that deletion is disabled by default. See `:h g:AutoPairsMapBS`) * An enter mapping for pair expansion * Quote handling aimed at avoiding accidental expansions * The ability to ignore pair insertion unless there's a whitespace (`:h autopairs-howto-whitespace-only`) * Extended balance checks * Fast pair wrapping * Several customisable features for various personal preferences For more features, as well as documentation, [see doc/AutoPairs.txt](https://github.com/LunarWatcher/auto-pairs/blob/master/doc/AutoPairs.txt) ## Contributors See [Contributors](https://github.com/lunarwatcher/auto-pairs/graphs/contributors) ## License The code is licensed under the MIT license. See [LICENSE.md](https://github.com/LunarWatcher/auto-pairs/blob/master/LICENSE.md) for the full license text. auto-pairs-4.0.2/autoload/000077500000000000000000000000001456172150000154125ustar00rootroot00000000000000auto-pairs-4.0.2/autoload/autopairs.vim000066400000000000000000000532711456172150000201460ustar00rootroot00000000000000" Insert or delete brackets, parens, quotes in pairs. " Fork Maintainer: Olivia " Version: See g:AutoPairsVersion, or the git tag " Fork Repository: https://github.com/LunarWatcher/auto-pairs " License: MIT scriptencoding utf-8 if !has('nvim') && has('vimscript-4') " We'll enforce the new version for versions of Vim that support the " fantastic |scriptversion|. The rest are gonna have to sort themselves " out. " This also lets me make sure I write better Vimscript scriptversion 4 endif " Current version; not representative of tags or real versions, but purely " meant as a number associated with the version. Semantic meaning on the first " digit will take place. See the documentation for more details. let g:AutoPairsVersion = 40002 let s:save_cpo = &cpoptions set cpoptions&vim call autopairs#Variables#InitVariables() fun! autopairs#AutoPairsAddLanguagePair(pair, language) if !has_key(a:pair, "open") || !has_key(a:pair, "close") echoerr "Invalid pair: missing open and/or close" return endif let open = get(a:pair, 'open') let close = get(a:pair, 'close') if (!has_key(g:AutoPairsLanguagePairs, a:language)) let g:AutoPairsLanguagePairs[a:language] = {} endif " As usual, make simple open:close pairs just that, and ditch objects. if (len(a:pair) == 2) let g:AutoPairsLanguagePairs[a:language][open] = close else " Make sure we don't have redundant information unlet a:pair["open"] let g:AutoPairsLanguagePairs[a:language][open] = a:pair endif endfun fun! autopairs#AutoPairsAddPairs(pairs, ...) let PairsObject = get(a:, '1', g:AutoPairs) for pair in a:pairs call autopairs#AutoPairsAddPair(pair, PairsObject) endfor endfun " @param pair A object containing a pair and other metadata fun! autopairs#AutoPairsAddPair(pair, ...) if !has_key(a:pair, "open") || !has_key(a:pair, "close") echoerr "Invalid pair: missing open and/or close" return endif let PairsObject = get(a:, '1', g:AutoPairs) let open = get(a:pair, 'open') let close = get(a:pair, 'close') " Prevent empty open " Empty close is fine, but empty open isn't. if (open == "") echoerr "Open cannot be empty. Discarding invalid pair" return endif " We know close is defined (and well-defined) " Meta-optimization; pairs consisting of close and open " are plain and not objects if len(a:pair) == 2 && has_key(a:pair, "close") let PairsObject[open] = close else " Now, that was clearly not a basic pair, which means it may have a " language attribute. " Let's check: if has_key(a:pair, "filetype") let filetypes = a:pair["filetype"] unlet a:pair["filetype"] if type(filetypes) == v:t_string call autopairs#AutoPairsAddLanguagePair(a:pair, filetypes) return elseif type(filetypes) == v:t_list for ft in filetypes call autopairs#AutoPairsAddLanguagePair(a:pair, ft) endfor return else echoerr "Invalid filetype: " .. filetypes .. " - must be string or list. Discarding pair" return endif endif " Prevent information duplication unlet a:pair["open"] " Otherwise, we inject the entire pair let PairsObject[open] = a:pair endif endfun " Returns the default set of pairs given the current buffer's filetype func! autopairs#AutoPairsDefaultPairs() let r = copy(g:AutoPairs) if has_key(g:AutoPairsLanguagePairs, &ft) for [open, close] in items(g:AutoPairsLanguagePairs[&ft]) let r[open] = close endfor endif return r endf " add or delete pairs base on g:AutoPairs " AutoPairsDefine(addPairs:dict[, removeOpenPairList:list]) " " eg: " au FileType html let b:AutoPairs = autopairs#AutoPairsDefine({''}, ['{']) " add pair and remove '{' for html file func! autopairs#AutoPairsDefine(pairs, ...) let r = autopairs#AutoPairsDefaultPairs() if a:0 > 0 for open in a:1 if has_key(r, open) unlet r[open] endif endfor end " Dict: iterate as normal if type(a:pairs) == v:t_dict for [open, close] in items(a:pairs) let r[open] = close endfor else call autopairs#AutoPairsAddPairs(a:pairs, r) endif return r endf func! autopairs#AutoPairsInsert(key, ...) if !b:autopairs_enabled || b:AutoPairsIgnoreSingle let b:AutoPairsIgnoreSingle = 0 return a:key end let balanced = -3 let l:multiline = get(a:, '1', b:AutoPairsMultilineClose) let b:autopairs_saved_pair = [a:key, getpos('.')] let [before, after, afterline] = autopairs#Strings#getline(l:multiline) " Check open pairs {{{ " TODO: maybe move this to another file? for [open, close, opt] in b:AutoPairsList let ms = autopairs#Strings#matchend(before .. a:key, open, opt) let m = matchstr(afterline, '^\v\s*\zs' .. autopairs#Utils#escape(close, opt)) "if (close == '''') "echom open close opt "echom "Line: " before .. a:key "endif if len(ms) > 0 let target = ms[1] " Contains the real pair, as opposed to the potential regex `open` " contains. This really needs some cleanup let openPair = ms[2] " To compensate for multibyte pairs, " we need to search for escaping after we find a match. " Since b:AutoPairsList is sorted by pair size, we can assume that " if we find \[ and it's matched, it's because there's a pair that " matches \[, and not that we have [ escaped. if b:AutoPairsSearchEscape " Intermediate length let pLen = len(openPair) " First check the character prior to the character of the " current pair. Take \[ in LaTeX: " 0 0 \ [ " -1 0 1 2 " ^ pair match found starting here -- that's why we're " referencing the length of the found pair. " Because of potentially varying width, we need to figure " out how long the match we wanna search is. " ^ Look for backslash here. If one is found, " ^ Look for one here. Essentially, this is to make sure we " don't trigger a false positive on, among other things, " '\\|', type ' at |. Essentially, if the backslash is " escaped, we assume that the pair character isn't. " This doesn't take into account '\\\|', ' at |, " because it only checks the last two backslashes. " There's no good way to check for correct escaping without " doing an obnoxious amount of checks, which is overkill " for a case like this. " (0 is a reference to null, meaning there's no string at that " position) " " TL;DR: if we find a backslash in front of the pair, we then know " it's escaped, and we don't want to insert the close. " If there's another backslash in front of the backslash in " front of the pair, we assume the backslash is escaped and " insert the pair anyway. if before[-pLen:-pLen] == '\' && before[-pLen - 1:-pLen - 1] != '\' return a:key endif endif " Krasjet: only insert the closing pair if the next character is a space " or a non-quote closing pair, or a whitelisted character (string) " Olivia: that ^ if and only if it's desired. if b:AutoPairsCompleteOnlyOnSpace == 1 && afterline[0] =~? '^\v' .. b:AutoPairsSpaceCompletionRegex && afterline[0] !~# b:autopairs_whitespace_exceptions break end let balanced = autopairs#Insert#checkBalance(open, close, opt, before, after, afterline, \ {"openPair": openPair, "m": m}, 0) if balanced <= 0 break endif return autopairs#Balancing#doInsert(open, close, openPair, before, afterline, target) end endfor " }}} let checkClose = autopairs#Insert#checkClose(a:key, before, after, afterline) if checkClose != "" " If we end up with checkClose != "", we know the close returned " something. That means the check was successful, and we wanna return " it return checkClose endif " Fly Mode, and the key is closed-pairs, search closed-pair and jump if g:AutoPairsFlyMode && a:key =~ '\v[' .. b:AutoPairsFlyModeList .. ']' if search(a:key, 'We') return "\" endif endif " As a final fallback, if we end up at the end, just return the key to " minimize distruption. return a:key endf func! autopairs#AutoPairsDelete() if !b:autopairs_enabled || b:AutoPairsIgnoreSingle let b:AutoPairsIgnoreSingle = 0 return "\" end let [before, after, ig] = autopairs#Strings#getline(b:AutoPairsMultilineBackspace) if b:AutoPairsBSIn == 1 for [open, close, opt] in b:AutoPairsList if !opt["delete"] || close == '' " Non-deletable pairs? Skip 'em continue endif let rest_of_line = opt['multiline'] ? after : ig let b = matchstr(before, autopairs#Utils#escape(open, opt) .. '\v\s?$') let a = matchstr(rest_of_line, '^\v\s*' .. autopairs#Utils#escape(close, opt)) if b != '' && a != '' if b[-1:-1] == ' ' if a[0] == ' ' return "\\" else return "\" end end return autopairs#Strings#backspace(b) .. autopairs#Strings#delete(a) end endfor endif if b:AutoPairsBSAfter == 1 " delete the pair foo[]| to foo for [open, close, opt] in b:AutoPairsList if !opt["delete"] continue endif if (close == '') continue endif let m = autopairs#Strings#matchend(before, autopairs#Utils#escape(open, opt) .. '\v\s*' .. autopairs#Utils#escape(close, opt) .. '\v$', 0) if len(m) > 0 return autopairs#Strings#backspace(m[2]) elseif opt["multiline"] && b:AutoPairsMultilineBackspace let m = matchstr(before, '^\v\s*' .. autopairs#Utils#escape(close, opt)) if m != '' let b = "" let offset = 1 " a = m while getline(line('.') - offset) =~ "^\s*$" let b ..= getline(line('.') - offset) .. ' ' let offset += 1 if (line('.') - offset <= 0) return "\" endif endwhile let a = matchstr(getline(line('.') - offset), autopairs#Utils#escape(open, opt) .. '\v\s*$') .. ' ' if a != ' ' return autopairs#Strings#backspace(a) .. autopairs#Strings#backspace(b) .. autopairs#Strings#backspace(m) endif endif end endfor endif return "\" endf " Fast wrap the word in brackets " Note to self: default arguments aren't supported until " 8.1 patch 1310, and doesn't support neovim. Implementing it here at this " time would break the plugin for a lot of people. " This being a fork, that isn't desired. func! autopairs#AutoPairsFastWrap(...) let movement = get(a:, 1, 'e') let c = @" if b:AutoPairsMultibyteFastWrap let [before, after, ig] = autopairs#Strings#getline() " At this point, after refers to the bit after the cursor. " We haven't cut anything yet. if after == '' " While we do have multiline fast wrap, we actually do need " something to wrap. return '' endif let length = 1 for [open, close, opt] in b:AutoPairsList if close == '' continue endif let match = [] let esc = substitute(close, "'", "''", "g") let esc = autopairs#Utils#escape(esc, opt) " TODO: Wtf is this for? let res = substitute(after, '^\V' .. esc, '\=add(match, submatch(0))', '') if len(match) > 0 && len(match[0]) > length let length = len(match[0]) endif endfor exec "normal!" length .. "x" let cursorOffset = length - 1 else let cursorOffset = 0 normal! x endi " Note regarding the previous note: an after == "" check doesn't make " sense here, because we've already cut at this point. We may want " multiline wrapping. " I think xd This has always been a bit weird. Might be better to " outsource the above check to outside the if-check to prevent weird " moves let [before, after, ig] = autopairs#Strings#getline() if after[0] =~ '\v[{[(<]' normal! % normal! p else for [open, close, opt] in b:AutoPairsList if close == '' continue end if after =~ '\v^\s*' .. autopairs#Utils#escape(open, opt) if open == close && count(before, open) % 2 != 0 \ && before =~ autopairs#Utils#escape(open, opt) .. '\v.*$' && after =~ '^' .. autopairs#Utils#escape(close, opt) break endif call search(close, 'We') " Search goes for the first one rather than the logical option " -- the last one. This is only a problem when open == close, " which means in the case of quotes. if open == close && after =~ '^\v\s+' .. autopairs#Utils#escape(close, opt) call search(close, 'We') endif normal! p if cursorOffset > 0 exec "normal!" cursorOffset .. 'h' endif let @" = c return "" endif endfor let g:AutoPairsDebug = after if after[1:1] =~ '\v' .. (g:AutoPairsMultilineFastWrap ? '(\w|$)' : '\w') exec "normal! " .. movement endif normal! p endif if cursorOffset > 0 exec "normal!" cursorOffset .. 'h' endif let @" = c return "" endfun " Contains manual jumping func! autopairs#AutoPairsJump() if len(b:AutoPairs) == 0 || b:autopairs_enabled == 0 return endif " Cache to prevent regenerating the regex if !exists('b:AutoPairsJumpRegex') " Defines the start of a regex group let b:AutoPairsJumpRegex = '\(' " We then iterate all the pairs... for [open, close, _] in b:AutoPairsList if close == '' continue endif " ... and do some quick substitutions let res = substitute(close, "'", "''", 'g') let res = substitute(res, '\', '\\\\', 'g') " Append the element let b:AutoPairsJumpRegex ..= (len(b:AutoPairsJumpRegex) > 2 ? '\|' : '') .. res endfor " End the regex group and finalize the variable let b:AutoPairsJumpRegex ..= '\)' endif " Use the variable (either freshly generated or cached) call search('\V' .. b:AutoPairsJumpRegex, 'W') endf func! autopairs#AutoPairsMoveCharacter(key) let c = getline(".")[col(".")-1] let escaped_key = substitute(a:key, "'", "''", 'g') return "\\:call search(" .. "'" .. escaped_key .. "'" .. ")\a" .. c .. "\" endf " Back insert for flymode. " setpos() makes this method unfit to be used as a backup for anything using " mutation. If the code changes, the position to jump back to is unreliable " and may be completely wrong. func! autopairs#AutoPairsBackInsert() let pair = b:autopairs_saved_pair[0] let pos = b:autopairs_saved_pair[1] call setpos('.', pos) return pair endf " Helper function. Determines what movement to do when is pushed. " It's modularized to also enable g:AutoPairsAutoLineBreak. fun! autopairs#AutoPairsDetermineCRMovement() let cmd = '' if g:AutoPairsCenterLine && winline() * 3 >= winheight(0) * 2 " Recenter before adding new line to avoid replacing line content let cmd = "zz" end " If equalprg has been set, then avoid call " https://github.com/jiangmiao/auto-pairs/issues/24 " This is essentially custom balancing beyond what Vim does. if &equalprg != '' return "\" .. cmd .. "O" endif " Note: for indent issues, see :h autopairs-diagnose-indent " conflict with javascript and coffee " javascript need indent new line " coffeescript forbid indent new line if &filetype == 'coffeescript' || &filetype == 'coffee' return "\" .. cmd .. "k==o" else return "\" .. cmd .. "=ko" endif endfun func! autopairs#AutoPairsReturn() if b:autopairs_enabled == 0 || b:AutoPairsIgnoreSingle let b:AutoPairsIgnoreSingle = 0 return '' end let b:autopairs_return_pos = 0 let before = getline(line('.') - 1) let [ig, ig, afterline] = autopairs#Strings#getline() for [open, close, opt] in b:AutoPairsList if close == '' continue end " \V\v is basically escaping. Makes sure ( isn't considered the " start of a group, which would yield incorrect results. " Used to prevent fuckups if before =~ autopairs#Utils#escape(open, opt) .. '\v' .. (b:AutoPairsReturnOnEmptyOnly ? '\s*' : '.*') .. '$' && afterline =~ '^\s*' .. autopairs#Utils#escape(close, opt) if b:AutoPairsCarefulStringExpansion && index(b:AutoPairsQuotes, open) != -1 && count(before, open) % 2 == 0 return "" endif let b:autopairs_return_pos = line('.') " Determining the exact movement has been moved to a separate " function when autobreak was added as an option. return autopairs#AutoPairsDetermineCRMovement() end endfor return '' endf func! autopairs#AutoPairsSpace() if !b:autopairs_enabled || b:AutoPairsIgnoreSingle let b:AutoPairsIgnoreSingle = 0 return "\" end let [before, after, ig] = autopairs#Strings#getline() for [open, close, opt] in b:AutoPairsList if close == '' continue end if before =~ autopairs#Utils#escape(open, opt) .. '\v$' && after =~ '^' .. autopairs#Utils#escape(close, opt) if close =~ '\v^[''"`]$' return "\" else return "\\" .. g:autopairs#Strings#Left end end endfor return "\" endf func! autopairs#AutoPairsMap(key, ...) " | is special key which separate map command from text let l:explicit = get(a:, '1', 0) let key = a:key if key == '|' let key = '' end let escaped_key = substitute(key, "'", "''", 'g') " use expr will cause search() doesn't work if l:explicit && len(maparg(key, "i")) != 0 return endif execute 'inoremap ' key "=autopairs#AutoPairsInsert('" .. escaped_key .. "')" endf func! autopairs#AutoPairsToggle() let b:autopairs_enabled = !b:autopairs_enabled echo 'AutoPairs' (b:autopairs_enabled ? 'enabled' : 'disabled') return '' endf func! autopairs#AutoPairsIgnore() let b:AutoPairsIgnoreSingle = !b:AutoPairsIgnoreSingle echo (b:AutoPairsIgnoreSingle ? "Skipping" : "Not skipping") "next pair" return '' endfunc fun! autopairs#AutoPairsToggleMultilineClose() let b:AutoPairsMultilineClose = !b:AutoPairsMultilineClose echo (b:AutoPairsMultilineClose ? "Enabled" : "Disabled") "multiline close" return '' endfun func! autopairs#AutoPairsInit() " Why can't we be consistent about capitalization? Ugh let b:autopairs_loaded = 1 " Buffer definitions let b:autopairs_return_pos = 0 let b:autopairs_saved_pair = [0, 0] " Krasjet: only auto-complete if the next character, or characters, is one of " these let b:autopairs_whitespace_exceptions = [] let b:AutoPairsList = [] " Deal with mappings associated with specific pairs call autopairs#Keybinds#mapPairKeybinds() " Map keys associated with various functions call autopairs#Keybinds#mapKeys() " TODO: Is this really necessary? if &keymap != '' let l:imsearch = &imsearch let l:iminsert = &iminsert let l:imdisable = &imdisable execute 'setlocal keymap=' .. &keymap execute 'setlocal imsearch=' .. l:imsearch execute 'setlocal iminsert=' .. l:iminsert if l:imdisable execute 'setlocal imdisable' else execute 'setlocal noimdisable' end end endf func! autopairs#AutoPairsTryInit() if exists('b:autopairs_loaded') return endif if type(g:AutoPairsInitHook) == 2 call g:AutoPairsInitHook() endif if index(g:AutoPairsDirectoryBlacklist, getcwd()) >= 0 || index(g:AutoPairsFiletypeBlacklist, &ft) != -1 return endif call autopairs#Variables#_InitBufferVariables() call autopairs#AutoPairsInit() endf let &cpoptions = s:save_cpo unlet s:save_cpo auto-pairs-4.0.2/autoload/autopairs/000077500000000000000000000000001456172150000174215ustar00rootroot00000000000000auto-pairs-4.0.2/autoload/autopairs/Balancing.vim000066400000000000000000000041731456172150000220210ustar00rootroot00000000000000if !has('nvim') && has('vimscript-4') scriptversion 4 endif fun! autopairs#Balancing#doInsert(open, close, openPair, before, afterline, target) let open = a:open let close = a:close let openPair = a:openPair let before = a:before let afterline = a:afterline let target = a:target " This first block makes sure we remove old insertions. This is " exclusively used for multibyte pairs. " " For an instance, if we have a pair <: > and <%: %], in the lack " of a better, real-world example (but the point being that one char is a " pair, multiple isn't), we'll want to clear the > from the previous pair " entirely when the % is inserted. " " Strictly speaking, this just does a bunch of calculations on " deletion numbers let bs = '' let del = '' while len(before) > len(target) let found = 0 " delete pair for [o, c, opt] in b:AutoPairsList let os = autopairs#Strings#matchend(before, o, opt) if len(os) && len(os[1]) < len(target) " any text before openPair should not be deleted continue end let cs = autopairs#Strings#matchbegin(afterline, c, opt) if len(os) && len(cs) let found = 1 let before = os[1] let afterline = cs[2] let bs = bs .. autopairs#Strings#backspace(os[2]) let del = del .. autopairs#Strings#delete(cs[1]) break end endfor if !found " delete character let ms = autopairs#Strings#matchend(before, '\v.', 0) if len(ms) let before = ms[1] let bs = bs .. autopairs#Strings#backspace(ms[2]) end end endwhile return bs .. del .. (index(b:AutoPairsAutoBreakBefore, open) != -1 ? "\" : '') .. openPair \ .. close .. autopairs#Strings#left(close) \ .. (index(b:AutoPairsAutoLineBreak, open) != -1 ? \ "\" .. autopairs#AutoPairsDetermineCRMovement() \ : '') endfun auto-pairs-4.0.2/autoload/autopairs/Insert.vim000066400000000000000000000165511456172150000214120ustar00rootroot00000000000000" Checks whether or not the open-close pair is balanced " Returns: " 1 if balanced " 0 if not " -1 if not balanced, but b:AutoPairsStringHandlingMode indicates this is " fine in this context, and should jump if possible fun! autopairs#Insert#checkBalance(open, close, opt, before, after, afterline, openArgs, checkingClose) " TODO: do more caching here to avoid unnecessary calls to the balance " checker. It's potentially an expensive operation if a:close == "" return 1 endif let checkingClose = a:checkingClose let inString = autopairs#Strings#isInString() if b:AutoPairsStringHandlingMode == 2 && inString return autopairs#Strings#GetFirstUnicodeChar(getline('.')[col('.') - 1:]) \ != autopairs#Strings#GetFirstUnicodeChar(a:close) ? 0 : -1 endif let [closePre, openPre, closePost, openPost, strClose, strOpen, totClose, totOpen] = autopairs#Strings#countHighlightMatches(a:open, a:close, a:opt, 'string') "echom "Matches for " a:open a:close ":" closePre openPre closePost openPost strClose strOpen totClose totOpen " Explanation, because this is a complex expression. " " First of all, this should only run if we're " checking for open pairs. This exists to forward open == close to close " checking for balancing and jumping. " " Secondly, we check for overall balance: if it's not balanced after the " cursor, we can skip and let closure handle balancing or skipping. " " The rest of this is fairly self-explanatory, and is a part of " jiangmiao's original code, but now without an initial pain in the ass of " a bug (#41) that got substantially worse in this fork due to active " balance checking. " " It simply checks if the open pair is after the cursor, which someone (I " assume) manages to check if open == close, but I'm honestly not entirely " sure how the intial handling in m and ms really works. " " The variable names are trash, and it's undocumented code that isn't " mine, and I've never bothered figuring out what their purpose is. if (checkingClose == 0 && (openPost % 2 != 0 || inString && strOpen % 2 != 1) \ && len(a:openArgs["openPair"]) == 1 && a:openArgs["openPair"] == a:openArgs["m"]) return 0 endif " Krasjet: do not complete the closing pair until pairs are balanced if a:open !~# b:autopairs_balance_blacklist if b:AutoPairsStringHandlingMode == 1 && autopairs#Strings#isInString() " We only need to address mode == 1 here. return strClose <= strOpen \ || ((a:open == a:close || a:opt["balancebyclose"]) && (strOpen + strClose) % 2 == 0) else if a:open == a:close || (b:AutoPairsSingleQuoteBalanceCheck && a:close ==# "'") || a:opt["balancebyclose"] if (totOpen % 2 != 0) return 0 end " The first check is the standard check: if open < close, there's " an imbalance " The second check is if there are any close characters after the " cursor " The third check checks if everything is balanced after the " cursor. elseif ((!checkingClose || g:AutoPairsPreferClose) \ && totOpen < totClose \ && closePost > 0 \ && openPost < closePost \ ) " Olivia: aside making sure there's an overall imbalance " in the line, only balance the brackets if there's an " imbalance after the cursor (we can disregard anything " before the cursor), and make sure there's actually a " close character to close after the cursor return 0 elseif checkingClose \ && totOpen > totClose \ && (!g:AutoPairsPreferClose && openPre > closePost \ || openPost < closePost \ ) return 0 endif endif endif return 1 endfun " Like checkClose, but for scripts that don't already have before, after, and " afterline easily available. fun! autopairs#Insert#checkCloseScript(key, ...) let l:multilineClose = get(a:, '1', 0) let [before, after, afterline] = s:getline() return autopairs#Insert#checkClose(key, before, after, afterline) endfun fun! autopairs#Insert#checkClose(key, before, after, afterline) " Whether or not to use a multiline close. " This functionality is disabled by default and requires an explicit " argument turning it on. for [open, close, opt] in b:AutoPairsList if close == '' continue end " This contains jump and close logic " The first if statement is to make sure the key pressed matches " either an explicit map close, an implicit mapped close, or both if " both are enabled. if opt['mapclose'] && opt['key'] == a:key || opt["alwaysmapdefaultclose"] == 1 && a:key == autopairs#Strings#GetFirstUnicodeChar(close) " the close pair is in the same line " ... but it's possible to enable only looking for the close pair let searchRegex = b:AutoPairsSearchCloseAfterSpace == 1 ? '^\v\s*\V' : '^\V' " Krasjet: do not search for the closing pair if spaces are in between " Olivia: Add override for people who want this (like me) " Note: this only checks the current line let m = matchstr(a:afterline, searchRegex .. autopairs#Utils#escape(close, opt)) if m != '' " Krasjet: only jump across the closing pair if pairs are balanced let balance = autopairs#Insert#checkBalance(open, close, opt, a:before, a:after, a:afterline, {}, 1) if balance == 0 return a:key endif " Olivia: return the key if we aren't jumping. if b:AutoPairsNoJump == 1 || index(b:AutoPairsJumpBlacklist, close) != -1 return a:key endif if a:before =~ '\V' .. autopairs#Utils#escape(open, opt) .. '\v\s*$' && m[0] =~ '\v\s' " remove the space we inserted if the text in pairs is blank return "\" .. autopairs#Strings#right(m[1:]) else return autopairs#Strings#right(m) endif end " Olivia: return the key if we aren't jumping. if b:AutoPairsNoJump == 1 || index(b:AutoPairsJumpBlacklist, close) != -1 return a:key endif " This may check multiline depending on something. " Still not entirely sure what this brings to the table that the " other clause doesn't let m = matchstr(a:after, '\v^\s*\zs\V' .. autopairs#Utils#escape(close, opt)) if m != '' if opt['multiline'] if b:AutoPairsMultilineCloseDeleteSpace && b:autopairs_return_pos == line('.') && getline('.') =~ '\v^\s*$' exec 'normal! ddk$' end call search(m, 'We') return "\" else break end end end endfor return "" endfun auto-pairs-4.0.2/autoload/autopairs/Keybinds.vim000066400000000000000000000336071456172150000217170ustar00rootroot00000000000000if !has('nvim') && has('vimscript-4') scriptversion 4 endif function! autopairs#Keybinds#IgnoreInsertEnter(f, ...) abort " TODO: Change this to use when support for vim 8.2.19xx is dropped let l:pre = "\=autopairs#Keybinds#SetEventignore()\" let l:val = call(function(a:f), a:000) let l:post = "\=autopairs#Keybinds#ResetEventignore()\" return l:pre .. l:val .. l:post endfunction function! autopairs#Keybinds#IgnoreInsertEnterCmd(cmd) abort call autopairs#Keybinds#SetEventignore() exec a:cmd call autopairs#Keybinds#ResetEventignore() return '' endfunction function! autopairs#Keybinds#SetEventignore() " TODO: Add InsertLeavePre when we know how to check version correctly on nvim " or when support for vim 8.2.1873 and below is dropped let b:autopairs_eventignore = &eventignore set eventignore+=InsertEnter,InsertLeave if exists('##InsertLeavePre') set eventignore+=InsertLeavePre endif return '' endfunction function! autopairs#Keybinds#ResetEventignore() let &eventignore = b:autopairs_eventignore return '' endfunction " Always silent the command inoremap AutoPairsReturn =autopairs#Keybinds#IgnoreInsertEnter('autopairs#AutoPairsReturn') imap AutoPairsReturn AutoPairsReturn func! autopairs#Keybinds#ExpandMap(map) let map = a:map let map = substitute(map, '\(\w\+\)', '\=maparg(submatch(1), "i")', 'g') let map = substitute(map, '\(([^)]*)\)', '\=maparg(submatch(1), "i")', 'g') return map endf fun! autopairs#Keybinds#mapPairKeybinds() for [open, close] in items(b:AutoPairs) let o = autopairs#Strings#GetLastUnicodeChar(open) " We wanna proxy the string value of close so we can start converting " to a different format. There's _way_ too many formats, admittedly, " but this means we can sort shit into opt instead, which is already " present in the system. This also means close gets a canonical " meaning, and we don't need to rewrite other bits of the code to " add a proxy for something we already have. let stringClose = "" if type(close) == v:t_dict if !has_key(close, "close") " Let's silently make sure we have a close. let close["close"] = "" endif " Objects store it in a key let stringClose = close["close"] else " Strings store it in itself, for obvious reasons. let stringClose = close endif " This line right here is part of why we filter it out this early. let c = autopairs#Strings#GetFirstUnicodeChar(stringClose) " TODO: link some global options against (some of) these let opt = {'mapclose': 1, \ 'alwaysmapdefaultclose': 1, \ 'delete': 1, 'multiline': 1, \ 'passiveclose': 1, \ 'balancebyclose': 0, \ 'regex': 0} " Default: set key = c let opt['key'] = c if o == c || len(c) == 0 let opt['multiline'] = 0 elseif type(close) == v:t_dict && has_key(close, 'multiline') let opt['multiline'] = close['multiline'] endif if type(close) == v:t_dict " We have a brand fucking new object! " Let's handle mappings first let mapDefaultClose = 1 if (has_key(close, "mapclose")) let mc = close["mapclose"] if type(mc) == v:t_number let opt["mapclose"] = mc let mapDefaultClose = 0 else let opt["key"] = mc " This is largely a compat util; if the key is empty, it's " equivalent to setting it to 0 if (mc != "") let opt["mapclose"] = 1 else let opt["mapclose"] = 0 endif endif endif " We've handled multiline earlier, so we only need to handle " delete. " Filetype is only handled in intialization methods (and is purely " syntactic sugar for using a different variable), and therefore " isn't used here. if has_key(close, "delete") let opt["delete"] = close["delete"] endif let opt["alwaysmapdefaultclose"] = get(close, 'alwaysmapdefaultclose', mapDefaultClose) let opt["passiveclose"] = get(close, "passiveclose", 1) let opt["balancebyclose"] = get(close, "balancebyclose", 0) let opt["regex"] = get(close, "regex", 0) endif call autopairs#AutoPairsMap(o) if o != c && c != '' && opt['mapclose'] if opt["key"] != c && opt["alwaysmapdefaultclose"] call autopairs#AutoPairsMap(c) endif call autopairs#AutoPairsMap(opt["key"], opt["key"] != c && opt["passiveclose"]) end " Krasjet: add any non-string closing characters to a list let b:AutoPairsList += [[open, stringClose, opt]] " Inserts all non-string close characters into a regex for matching " whitelisted characters for the following character if b:AutoPairsAutoBuildSpaceWhitelist && \ stringClose !=? '' && stringClose !~# '\V\[' .. escape(join(b:AutoPairsQuoteClosingChar, ''), '\') .. ']' let b:autopairs_whitespace_exceptions += [escape(stringClose, '\')] end endfor " sort pairs by length, longer pair should have higher priority let b:AutoPairsList = sort(b:AutoPairsList, "autopairs#Strings#sortByLength") " Krasjet: add whitelisted strings to the list for str in b:AutoPairsNextCharWhitelist let b:autopairs_whitespace_exceptions += [escape(str,'\')] endfor " Krasjet: construct a regex for whitelisted strings if empty(b:autopairs_whitespace_exceptions) let b:autopairs_whitespace_exceptions = '^$' else let b:autopairs_whitespace_exceptions = '^\V\(' .. join(b:autopairs_whitespace_exceptions, '\|') .. '\)' endif " Krasjet: add blacklisted open strings to the list let b:autopairs_balance_blacklist = [] for str in b:AutoPairsOpenBalanceBlacklist let b:autopairs_balance_blacklist += [escape(str,'\')] endfor if empty(b:autopairs_balance_blacklist) let b:autopairs_balance_blacklist = '^$' else let b:autopairs_balance_blacklist = '\V\('..join(b:autopairs_balance_blacklist, '\|') .. '\)' endif for item in b:AutoPairsList let [open, close, opt] = item " Note to self: this is the bit that's responsible for checking " whether a single-quote is in a word or not. " Olivia: altered to allow three different modes, to prevent issues " with things like string types in some languages (Python) " where the programmers either can't use anything but single " quotes, or (ew) decide to use single-quotes when " double-quotes are possible if open == "'" && open == close if b:AutoPairsSingleQuoteMode == -1 let item[0] = '\zs''' elseif b:AutoPairsSingleQuoteMode == 0 let item[0] = '(' .. b:AutoPairsSingleQuotePrefixGroup .. ')\zs''' elseif b:AutoPairsSingleQuoteMode == 1 let item[0] = '(' .. b:AutoPairsSingleQuotePrefixGroup .. ')\w?\zs''' elseif b:AutoPairsSingleQuoteMode == 2 " Note that g:AutoPairsSingleQuoteExpandFor is a separate " group to make sure prefix conditions still hold. This means " it still works for normal characters, and shouldn't expand " for i.e. blahf' " Largely quality of life; can be worked around with " |b:AutoPairsSingleQuotePrefixGroup| and mode == 0 if other " behavior is desired. let item[0] = '(' .. b:AutoPairsSingleQuotePrefixGroup .. ')[' .. b:AutoPairsSingleQuoteExpandFor .. ']?\zs''' else echoerr 'Invalid b:AutoPairsSingleQuoteMode: ' .. b:AutoPairsSingleQuoteMode \ .. ". Only -1, 0, 1, and 2 are allowed values.." endif let item[2]["balancebyclose"] = 1 let item[2]["regex"] = 1 end endfor endfun fun! autopairs#Keybinds#mapKeys() " This bit of code attempts to be compatible with other plugins. " It isn't always successful (:h autopairs-bad-cr), which is " overwhelmingly caused by other plugins doing weird shit with their " functions, in a way that often expects dedicated `` access. " " This leads to incompatibilities, some of which were previously listed in " a comment here, but have been moved to :h autopairs-incompatible-cr, at " least for plugins that have a confirmed incompatibility if b:AutoPairsMapCR " VIM 7.3 supports the advanced maparg, which can get info let info = maparg(g:AutoPairsCRKey, 'i', 0, 1) if empty(info) " Not _entirely_ sure if this should be or " g:AutoPairsCRKey. let old_cr = '' let is_expr = 0 else if (!has_key(info, "rhs")) " Incompatible nvim Lua map; abort. " Setting old_cr to AutoPairsReturn ensures the next step " ignores it let old_cr = "AutoPairsReturn" " Toggling this switch ensures this message is produced once " per session. let g:AutoPairsMapCR = 0 echoerr "You're using a version of nvim where maparg is broken. Due to this bug (or intentional move, we're yet to see which it is)," \ "auto-pairs will now disable g:AutoPairsMapCR, as this conflict cannot be fixed due to the Lua-centric approach taken" \ "by Neovim's developers. See :h autopairs-autocomplete-cr for workarounds. Note that the exact instructions may vary depending" \ "on which plugins are involved." \ "See https://github.com/neovim/neovim/issues/23666 for the current status on fixing this bug. `let g:AutoPairsMapCR = 0` to disable this error," \ "or reconfigure the other plugin attempting to map `` to use another key (or not to map it at all)." else let old_cr = info['rhs'] let old_cr = autopairs#Keybinds#ExpandMap(old_cr) let old_cr = substitute(old_cr, '', '' .. info['sid'] .. '_', 'g') let is_expr = info['expr'] let wrapper_name = 'AutoPairsOldCRWrapper73' endif endif if old_cr !~ 'AutoPairsReturn' if is_expr " remap to `name` to avoid mix expr and non-expr mode execute 'inoremap