]> git.madduck.net Git - etc/vim.git/commitdiff

madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

All patches and comments are welcome. Please squash your changes to logical commits before using git-format-patch and git-send-email to patches@git.madduck.net. If you'd read over the Git project's submission guidelines and adhered to them, I'd be especially grateful.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

Merge commit '56df844d3c39ec494dacc69eae34272b27db185a' as '.vim/bundle/asyncomplete'
authormartin f. krafft <madduck@madduck.net>
Tue, 8 Apr 2025 15:44:49 +0000 (17:44 +0200)
committermartin f. krafft <madduck@madduck.net>
Tue, 8 Apr 2025 15:44:49 +0000 (17:44 +0200)
22 files changed:
.vim/bundle/asyncomplete/.gitattributes [new file with mode: 0644]
.vim/bundle/asyncomplete/.github/FUNDING.yml [new file with mode: 0644]
.vim/bundle/asyncomplete/.github/stale.yml [new file with mode: 0644]
.vim/bundle/asyncomplete/.github/workflows/linux_neovim.yml [new file with mode: 0644]
.vim/bundle/asyncomplete/.github/workflows/linux_vim.yml [new file with mode: 0644]
.vim/bundle/asyncomplete/.github/workflows/mac_neovim.yml [new file with mode: 0644]
.vim/bundle/asyncomplete/.github/workflows/reviewdog.yml [new file with mode: 0644]
.vim/bundle/asyncomplete/.github/workflows/windows_neovim.yml [new file with mode: 0644]
.vim/bundle/asyncomplete/.github/workflows/windows_vim.yml [new file with mode: 0644]
.vim/bundle/asyncomplete/.gitignore [new file with mode: 0644]
.vim/bundle/asyncomplete/.vintrc.yaml [new file with mode: 0644]
.vim/bundle/asyncomplete/LICENSE [new file with mode: 0644]
.vim/bundle/asyncomplete/README.md [new file with mode: 0644]
.vim/bundle/asyncomplete/autoload/asyncomplete.vim [new file with mode: 0644]
.vim/bundle/asyncomplete/autoload/asyncomplete/utils.vim [new file with mode: 0644]
.vim/bundle/asyncomplete/autoload/asyncomplete/utils/_on_change/textchangedp.vim [new file with mode: 0644]
.vim/bundle/asyncomplete/autoload/asyncomplete/utils/_on_change/timer.vim [new file with mode: 0644]
.vim/bundle/asyncomplete/doc/asyncomplete.txt [new file with mode: 0644]
.vim/bundle/asyncomplete/plugin/asyncomplete.vim [new file with mode: 0644]
.vim/bundle/asyncomplete/renovate.json [new file with mode: 0644]
.vim/bundle/asyncomplete/test/.themisrc [new file with mode: 0644]
.vim/bundle/asyncomplete/test/asyncomplete.vimspec [new file with mode: 0644]

diff --git a/.vim/bundle/asyncomplete/.gitattributes b/.vim/bundle/asyncomplete/.gitattributes
new file mode 100644 (file)
index 0000000..176a458
--- /dev/null
@@ -0,0 +1 @@
+* text=auto
diff --git a/.vim/bundle/asyncomplete/.github/FUNDING.yml b/.vim/bundle/asyncomplete/.github/FUNDING.yml
new file mode 100644 (file)
index 0000000..eaf41dd
--- /dev/null
@@ -0,0 +1,12 @@
+# These are supported funding model platforms
+
+github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
+patreon: # Replace with a single Patreon username
+open_collective: asyncomplete
+ko_fi: # Replace with a single Ko-fi username
+tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
+community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
+liberapay: # Replace with a single Liberapay username
+issuehunt: # Replace with a single IssueHunt username
+otechie: # Replace with a single Otechie username
+custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
diff --git a/.vim/bundle/asyncomplete/.github/stale.yml b/.vim/bundle/asyncomplete/.github/stale.yml
new file mode 100644 (file)
index 0000000..dc90e5a
--- /dev/null
@@ -0,0 +1,17 @@
+# Number of days of inactivity before an issue becomes stale
+daysUntilStale: 60
+# Number of days of inactivity before a stale issue is closed
+daysUntilClose: 7
+# Issues with these labels will never be considered stale
+exemptLabels:
+  - pinned
+  - security
+# Label to use when marking an issue as stale
+staleLabel: wontfix
+# Comment to post when marking an issue as stale. Set to `false` to disable
+markComment: >
+  This issue has been automatically marked as stale because it has not had
+  recent activity. It will be closed if no further activity occurs. Thank you
+  for your contributions.
+# Comment to post when closing a stale issue. Set to `false` to disable
+closeComment: false
diff --git a/.vim/bundle/asyncomplete/.github/workflows/linux_neovim.yml b/.vim/bundle/asyncomplete/.github/workflows/linux_neovim.yml
new file mode 100644 (file)
index 0000000..3d902a8
--- /dev/null
@@ -0,0 +1,44 @@
+name: linux_neovim
+
+on:
+  push:
+    branches:
+      - master
+  pull_request:
+    branches:
+      - master
+
+jobs:
+  build:
+    strategy:
+      fail-fast: false
+      matrix:
+        os: [ubuntu-latest]
+        name: [neovim-v04-x64,neovim-nightly-x64]
+        include:
+          - name: neovim-v04-x64
+            os: ubuntu-latest
+            neovim_version: v0.4.3
+          - name: neovim-nightly-x64
+            os: ubuntu-latest
+            neovim_version: nightly
+    runs-on: ${{matrix.os}}
+    steps:
+      - uses: actions/checkout@v4
+      - name: Download neovim
+        shell: bash
+        run: |
+          mkdir -p ~/nvim/bin
+          curl -L https://github.com/neovim/neovim/releases/download/${{matrix.neovim_version}}/nvim.appimage -o ~/nvim/bin/nvim
+          chmod u+x ~/nvim/bin/nvim
+      - name: Download test runner
+        shell: bash
+        run: git clone --depth 1 --branch v1.5.4 --single-branch https://github.com/thinca/vim-themis ~/themis
+      - name: Run tests
+        shell: bash
+        run: |
+          export PATH=~/nvim/bin:$PATH
+          export PATH=~/themis/bin:$PATH
+          export THEMIS_VIM=nvim
+          nvim --version
+          themis --reporter spec
diff --git a/.vim/bundle/asyncomplete/.github/workflows/linux_vim.yml b/.vim/bundle/asyncomplete/.github/workflows/linux_vim.yml
new file mode 100644 (file)
index 0000000..e50e66c
--- /dev/null
@@ -0,0 +1,46 @@
+name: linux_vim
+
+on:
+  push:
+    branches:
+      - master
+  pull_request:
+    branches:
+      - master
+
+jobs:
+  build:
+    strategy:
+      fail-fast: false
+      matrix:
+        os: [ubuntu-latest]
+        name: [vim-v82-x64, vim-v81-x64]
+        include:
+          - name: vim-v82-x64
+            os: ubuntu-latest
+            vim_version: 8.2.0813
+            glibc_version: 2.15
+          - name: vim-v81-x64
+            os: ubuntu-latest
+            vim_version: 8.1.2414
+            glibc_version: 2.15
+    runs-on: ${{matrix.os}}
+    steps:
+      - uses: actions/checkout@v4
+      - name: Download vim
+        shell: bash
+        run: |
+          mkdir -p ~/vim/bin
+          curl -L https://github.com/vim/vim-appimage/releases/download/v${{matrix.vim_version}}/GVim-v${{matrix.vim_version}}.glibc${{matrix.glibc_version}}-x86_64.AppImage -o ~/vim/bin/vim
+          chmod u+x ~/vim/bin/vim
+      - name: Download test runner
+        shell: bash
+        run: git clone --depth 1 --branch v1.5.4 --single-branch https://github.com/thinca/vim-themis ~/themis
+      - name: Run tests
+        shell: bash
+        run: |
+          export PATH=~/vim/bin:$PATH
+          export PATH=~/themis/bin:$PATH
+          export THEMIS_VIM=vim
+          vim --version
+          themis --reporter spec
diff --git a/.vim/bundle/asyncomplete/.github/workflows/mac_neovim.yml b/.vim/bundle/asyncomplete/.github/workflows/mac_neovim.yml
new file mode 100644 (file)
index 0000000..894b636
--- /dev/null
@@ -0,0 +1,44 @@
+name: mac_neovim
+
+on:
+  push:
+    branches:
+      - master
+  pull_request:
+    branches:
+      - master
+
+jobs:
+  build:
+    strategy:
+      fail-fast: false
+      matrix:
+        os: [macos-latest]
+        name: [neovim-v04-x64,neovim-nightly-x64]
+        include:
+          - name: neovim-v04-x64
+            os: macos-latest
+            neovim_version: v0.4.3
+          - name: neovim-nightly-x64
+            os: macos-latest
+            neovim_version: nightly
+    runs-on: ${{matrix.os}}
+    steps:
+      - uses: actions/checkout@v4
+      - name: Download neovim
+        shell: bash
+        run: curl -L https://github.com/neovim/neovim/releases/download/${{matrix.neovim_version}}/nvim-macos.tar.gz -o ~/nvim.tar.gz
+      - name: Extract neovim
+        shell: bash
+        run: tar xzf ~/nvim.tar.gz -C ~/
+      - name: Download test runner
+        shell: bash
+        run: git clone --depth 1 --branch v1.5.4 --single-branch https://github.com/thinca/vim-themis ~/themis
+      - name: Run tests
+        shell: bash
+        run: |
+          export PATH=~/nvim-osx64/bin:$PATH
+          export PATH=~/themis/bin:$PATH
+          export THEMIS_VIM=nvim
+          nvim --version
+          themis --reporter spec
diff --git a/.vim/bundle/asyncomplete/.github/workflows/reviewdog.yml b/.vim/bundle/asyncomplete/.github/workflows/reviewdog.yml
new file mode 100644 (file)
index 0000000..48f5b08
--- /dev/null
@@ -0,0 +1,22 @@
+name: reviewdog
+
+on:
+  push:
+    branches:
+      - master
+  pull_request:
+    branches:
+      - master
+
+jobs:
+  vimlint:
+    name: runner / vint
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v4
+      - name: vint
+        uses: reviewdog/action-vint@v1
+        with:
+          github_token: ${{ secrets.github_token }}
+          level: error
+          reporter: github-pr-review
diff --git a/.vim/bundle/asyncomplete/.github/workflows/windows_neovim.yml b/.vim/bundle/asyncomplete/.github/workflows/windows_neovim.yml
new file mode 100644 (file)
index 0000000..06013f6
--- /dev/null
@@ -0,0 +1,46 @@
+name: windows_neovim
+
+on:
+  push:
+    branches:
+      - master
+  pull_request:
+    branches:
+      - master
+
+jobs:
+  build:
+    strategy:
+      fail-fast: false
+      matrix:
+        os: [windows-latest]
+        name: [neovim-v04-x64,neovim-nightly-x64]
+        include:
+          - name: neovim-v04-x64
+            os: windows-latest
+            neovim_version: v0.4.3
+            neovim_arch: win64
+          - name: neovim-nightly-x64
+            os: windows-latest
+            neovim_version: nightly
+            neovim_arch: win64
+    runs-on: ${{matrix.os}}
+    steps:
+      - uses: actions/checkout@v4
+      - name: Download neovim
+        shell: PowerShell
+        run: Invoke-WebRequest -Uri https://github.com/neovim/neovim/releases/download/${{matrix.neovim_version}}/nvim-${{matrix.neovim_arch}}.zip -OutFile neovim.zip
+      - name: Extract neovim
+        shell: PowerShell
+        run: Expand-Archive -Path neovim.zip -DestinationPath $env:USERPROFILE
+      - name: Download test runner
+        shell: PowerShell
+        run: git clone --depth 1 --branch v1.5.4 --single-branch https://github.com/thinca/vim-themis $env:USERPROFILE\themis
+      - name: Run tests
+        shell: cmd
+        run: |
+          SET PATH=%USERPROFILE%\Neovim\bin;%PATH%;
+          SET PATH=%USERPROFILE%\themis\bin;%PATH%;
+          SET THEMIS_VIM=nvim
+          nvim --version
+          themis --reporter spec
diff --git a/.vim/bundle/asyncomplete/.github/workflows/windows_vim.yml b/.vim/bundle/asyncomplete/.github/workflows/windows_vim.yml
new file mode 100644 (file)
index 0000000..26b2641
--- /dev/null
@@ -0,0 +1,52 @@
+name: windows_vim
+
+on:
+  push:
+    branches:
+      - master
+  pull_request:
+    branches:
+      - master
+
+jobs:
+  build:
+    strategy:
+      fail-fast: false
+      matrix:
+        os: [windows-latest]
+        name: [vim-v82-x64, vim-v81-x64, vim-v80-x64]
+        include:
+          - name: vim-v82-x64
+            os: windows-latest
+            vim_version: 8.2.0813
+            vim_arch: x64
+            vim_ver_path: vim82
+          - name: vim-v81-x64
+            os: windows-latest
+            vim_version: 8.1.2414
+            vim_arch: x64
+            vim_ver_path: vim81
+          - name: vim-v80-x64
+            os: windows-latest
+            vim_version: 8.0.1567
+            vim_arch: x64
+            vim_ver_path: vim80
+    runs-on: ${{matrix.os}}
+    steps:
+      - uses: actions/checkout@v4
+      - name: Download vim
+        shell: PowerShell
+        run: Invoke-WebRequest -Uri https://github.com/vim/vim-win32-installer/releases/download/v${{matrix.vim_version}}/gvim_${{matrix.vim_version}}_${{matrix.vim_arch}}.zip -OutFile vim.zip
+      - name: Extract vim
+        shell: PowerShell
+        run: Expand-Archive -Path vim.zip -DestinationPath $env:USERPROFILE
+      - name: Download test runner
+        shell: PowerShell
+        run: git clone --depth 1 --branch v1.5.4 --single-branch https://github.com/thinca/vim-themis $env:USERPROFILE\themis
+      - name: Run tests
+        shell: cmd
+        run: |
+          SET PATH=%USERPROFILE%\vim\${{matrix.vim_ver_path}};%PATH%;
+          SET PATH=%USERPROFILE%\themis\bin;%PATH%;
+          vim --version
+          themis --reporter spec
diff --git a/.vim/bundle/asyncomplete/.gitignore b/.vim/bundle/asyncomplete/.gitignore
new file mode 100644 (file)
index 0000000..6e92f57
--- /dev/null
@@ -0,0 +1 @@
+tags
diff --git a/.vim/bundle/asyncomplete/.vintrc.yaml b/.vim/bundle/asyncomplete/.vintrc.yaml
new file mode 100644 (file)
index 0000000..c96daa0
--- /dev/null
@@ -0,0 +1,10 @@
+cmdargs:
+  severity: style_problem
+
+policies:
+  ProhibitUnusedVariable:
+    enabled: false
+  ProhibitImplicitScopeVariable:
+    enabled: true
+  ProhibitNoAbortFunction:
+    enabled: true
diff --git a/.vim/bundle/asyncomplete/LICENSE b/.vim/bundle/asyncomplete/LICENSE
new file mode 100644 (file)
index 0000000..cdd1845
--- /dev/null
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2019 Prabir Shrestha
+
+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.
diff --git a/.vim/bundle/asyncomplete/README.md b/.vim/bundle/asyncomplete/README.md
new file mode 100644 (file)
index 0000000..9b7711f
--- /dev/null
@@ -0,0 +1,245 @@
+asyncomplete.vim
+================
+
+Async autocompletion for Vim 8 and Neovim with |timers|.
+
+This is inspired by [nvim-complete-manager](https://github.com/roxma/nvim-complete-manager) but written
+in pure Vim Script.
+
+### Installing
+
+```viml
+Plug 'prabirshrestha/asyncomplete.vim'
+```
+
+#### Tab completion
+
+```vim
+inoremap <expr> <Tab>   pumvisible() ? "\<C-n>" : "\<Tab>"
+inoremap <expr> <S-Tab> pumvisible() ? "\<C-p>" : "\<S-Tab>"
+inoremap <expr> <cr>    pumvisible() ? asyncomplete#close_popup() : "\<cr>"
+```
+
+If you prefer the enter key to always insert a new line (even if the popup menu is visible) then
+you can amend the above mapping as follows:
+
+```vim
+inoremap <expr> <cr> pumvisible() ? asyncomplete#close_popup() . "\<cr>" : "\<cr>"
+```
+
+### Force refresh completion
+
+```vim
+imap <c-space> <Plug>(asyncomplete_force_refresh)
+" For Vim 8 (<c-@> corresponds to <c-space>):
+" imap <c-@> <Plug>(asyncomplete_force_refresh)
+```
+
+### Auto popup
+By default asyncomplete will automatically show the autocomplete popup menu as you start typing.
+If you would like to disable the default behavior set `g:asyncomplete_auto_popup` to 0.
+
+```vim
+let g:asyncomplete_auto_popup = 0
+```
+
+You can use the above `<Plug>(asyncomplete_force_refresh)` to show the popup
+or you can tab to show the autocomplete.
+
+```vim
+let g:asyncomplete_auto_popup = 0
+
+function! s:check_back_space() abort
+    let col = col('.') - 1
+    return !col || getline('.')[col - 1]  =~ '\s'
+endfunction
+
+inoremap <silent><expr> <TAB>
+  \ pumvisible() ? "\<C-n>" :
+  \ <SID>check_back_space() ? "\<TAB>" :
+  \ asyncomplete#force_refresh()
+inoremap <expr><S-TAB> pumvisible() ? "\<C-p>" : "\<C-h>"
+```
+
+#### Preview Window
+
+To enable preview window:
+
+```vim
+" allow modifying the completeopt variable, or it will
+" be overridden all the time
+let g:asyncomplete_auto_completeopt = 0
+
+set completeopt=menuone,noinsert,noselect,preview
+```
+
+To auto close preview window when completion is done.
+
+```vim
+autocmd! CompleteDone * if pumvisible() == 0 | pclose | endif
+```
+
+### Sources
+
+asyncomplete.vim deliberately does not contain any sources. Please use one of the following sources or create your own.
+
+#### Language Server Protocol (LSP)
+[Language Server Protocol](https://github.com/Microsoft/language-server-protocol) via [vim-lsp](https://github.com/prabirshrestha/vim-lsp) and [asyncomplete-lsp.vim](https://github.com/prabirshrestha/asyncomplete-lsp.vim)
+
+**Please note** that vim-lsp setup for neovim requires neovim v0.2.0 or higher, since it uses lambda setup.
+
+```vim
+Plug 'prabirshrestha/asyncomplete.vim'
+Plug 'prabirshrestha/vim-lsp'
+Plug 'prabirshrestha/asyncomplete-lsp.vim'
+
+if executable('pyls')
+    " pip install python-language-server
+    au User lsp_setup call lsp#register_server({
+        \ 'name': 'pyls',
+        \ 'cmd': {server_info->['pyls']},
+        \ 'allowlist': ['python'],
+        \ })
+endif
+```
+
+**Refer to [vim-lsp wiki](https://github.com/prabirshrestha/vim-lsp/wiki/Servers) for configuring other language servers.** Besides auto-complete language server support other features such as go to definition, find references, renaming symbols, document symbols, find workspace symbols, formatting and so on.
+
+*in alphabetical order*
+
+| Languages/FileType/Source     | Links                                                                                              |
+|-------------------------------|----------------------------------------------------------------------------------------------------|
+| [Ale][ale]                    | [asyncomplete-ale.vim](https://github.com/andreypopp/asyncomplete-ale.vim)                         |
+| Buffer                        | [asyncomplete-buffer.vim](https://github.com/prabirshrestha/asyncomplete-buffer.vim)               |
+| C/C++                         | [asyncomplete-clang.vim](https://github.com/keremc/asyncomplete-clang.vim)                         |
+| Clojure                       | [async-clj-omni](https://github.com/clojure-vim/async-clj-omni)                                    |
+| Common Lisp (vlime)           | [vlime](https://github.com/vlime/vlime)                                                            |
+| Dictionary (look)             | [asyncomplete-look](https://github.com/htlsne/asyncomplete-look)                                   |
+| [Emmet][emmet-vim]            | [asyncomplete-emmet.vim](https://github.com/prabirshrestha/asyncomplete-emmet.vim)                 |
+| English                       | [asyncomplete-nextword.vim](https://github.com/high-moctane/asyncomplete-nextword.vim)             |
+| Emoji                         | [asyncomplete-emoji.vim](https://github.com/prabirshrestha/asyncomplete-emoji.vim)                 |
+| Filenames / directories       | [asyncomplete-file.vim](https://github.com/prabirshrestha/asyncomplete-file.vim)                   |
+| [NeoInclude][neoinclude]      | [asyncomplete-neoinclude.vim](https://github.com/kyouryuukunn/asyncomplete-neoinclude.vim)         |
+| Go                            | [asyncomplete-gocode.vim](https://github.com/prabirshrestha/asyncomplete-gocode.vim)               |
+| Git commit message            | [asyncomplete-gitcommit](https://github.com/laixintao/asyncomplete-gitcommit)                      |
+| JavaScript (Flow)             | [asyncomplete-flow.vim](https://github.com/prabirshrestha/asyncomplete-flow.vim)                   |
+| [Neosnippet][neosnippet]      | [asyncomplete-neosnippet.vim](https://github.com/prabirshrestha/asyncomplete-neosnippet.vim)       |
+| Omni                          | [asyncomplete-omni.vim](https://github.com/yami-beta/asyncomplete-omni.vim)                        |
+| PivotalTracker stories        | [asyncomplete-pivotaltracker.vim](https://github.com/hauleth/asyncomplete-pivotaltracker.vim)      |
+| Rust (racer)                  | [asyncomplete-racer.vim](https://github.com/keremc/asyncomplete-racer.vim)                         |
+| [TabNine][TabNine] powered by AI | [asyncomplete-tabnine.vim](https://github.com/kitagry/asyncomplete-tabnine.vim)                 |
+| [tmux complete][tmuxcomplete] | [tmux-complete.vim][tmuxcomplete]                                                                  |
+| Typescript                    | [asyncomplete-tscompletejob.vim](https://github.com/prabirshrestha/asyncomplete-tscompletejob.vim) |
+| [UltiSnips][ultisnips]        | [asyncomplete-ultisnips.vim](https://github.com/prabirshrestha/asyncomplete-ultisnips.vim)         |
+| User (compl-function)         | [asyncomplete-user.vim](https://github.com/jsit/asyncomplete-user.vim)                             |
+| Vim Syntax                    | [asyncomplete-necosyntax.vim](https://github.com/prabirshrestha/asyncomplete-necosyntax.vim)       |
+| Vim tags                      | [asyncomplete-tags.vim](https://github.com/prabirshrestha/asyncomplete-tags.vim)                   |
+| Vim                           | [asyncomplete-necovim.vim](https://github.com/prabirshrestha/asyncomplete-necovim.vim)             |
+
+[ale]:          https://github.com/dense-analysis/ale
+[emmet-vim]:    https://github.com/mattn/emmet-vim
+[neosnippet]:   https://github.com/Shougo/neosnippet.vim
+[neoinclude]:   https://github.com/Shougo/neoinclude.vim
+[TabNine]:      https://www.tabnine.com/
+[tmuxcomplete]: https://github.com/wellle/tmux-complete.vim
+[ultisnips]:    https://github.com/SirVer/ultisnips
+
+*can't find what you are looking for? write one instead an send a PR to be included here or search github topics tagged with asyncomplete at https://github.com/topics/asyncomplete.*
+
+#### Using existing vim plugin sources
+
+Rather than writing your own completion source from scratch you could also suggests other plugin authors to provide a async completion api that works for asyncomplete.vim or any other async autocomplete libraries without taking a dependency on asyncomplete.vim. The plugin can provide a function that takes a callback which returns the list of candidates and the startcol from where it must show the popup. Candidates can be list of words or vim's `complete-items`.
+
+```vim
+function s:completor(opt, ctx)
+  call mylanguage#get_async_completions({candidates, startcol -> asyncomplete#complete(a:opt['name'], a:ctx, startcol, candidates) })
+endfunction
+
+au User asyncomplete_setup call asyncomplete#register_source({
+    \ 'name': 'mylanguage',
+    \ 'allowlist': ['*'],
+    \ 'completor': function('s:completor'),
+    \ })
+```
+
+### Example
+
+```vim
+function! s:js_completor(opt, ctx) abort
+    let l:col = a:ctx['col']
+    let l:typed = a:ctx['typed']
+
+    let l:kw = matchstr(l:typed, '\v\S+$')
+    let l:kwlen = len(l:kw)
+
+    let l:startcol = l:col - l:kwlen
+
+    let l:matches = [
+        \ "do", "if", "in", "for", "let", "new", "try", "var", "case", "else", "enum", "eval", "null", "this", "true",
+        \ "void", "with", "await", "break", "catch", "class", "const", "false", "super", "throw", "while", "yield",
+        \ "delete", "export", "import", "public", "return", "static", "switch", "typeof", "default", "extends",
+        \ "finally", "package", "private", "continue", "debugger", "function", "arguments", "interface", "protected",
+        \ "implements", "instanceof"
+        \ ]
+
+    call asyncomplete#complete(a:opt['name'], a:ctx, l:startcol, l:matches)
+endfunction
+
+au User asyncomplete_setup call asyncomplete#register_source({
+    \ 'name': 'javascript',
+    \ 'allowlist': ['javascript'],
+    \ 'completor': function('s:js_completor'),
+    \ })
+```
+
+The above sample shows synchronous completion. If you would like to make it async just call `asyncomplete#complete` whenever you have the results ready.
+
+```vim
+call timer_start(2000, {timer-> asyncomplete#complete(a:opt['name'], a:ctx, l:startcol, l:matches)})
+```
+
+If you are returning incomplete results and would like to trigger completion on the next keypress pass `1` as the fifth parameter to `asyncomplete#complete`
+which signifies the result is incomplete.
+
+```vim
+call asyncomplete#complete(a:opt['name'], a:ctx, l:startcol, l:matches, 1)
+```
+
+As a source author you do not have to worry about synchronization issues in case the server returns the async completion after the user has typed more
+characters. asyncomplete.vim uses partial caching as well as ignores if the context changes when calling `asyncomplete#complete`.
+This is one of the core reason why the original context must be passed when calling `asyncomplete#complete`.
+
+### Credits
+All the credit goes to the following projects
+* [https://github.com/roxma/nvim-complete-manager](https://github.com/roxma/nvim-complete-manager)
+* [https://github.com/maralla/completor.vim](https://github.com/maralla/completor.vim)
+
+## Contributors
+
+### Code Contributors
+
+This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].
+<a href="https://github.com/prabirshrestha/asyncomplete.vim/graphs/contributors"><img src="https://opencollective.com/asyncomplete/contributors.svg?width=890&button=false" /></a>
+
+### Financial Contributors
+
+Become a financial contributor and help us sustain our community. [[Contribute](https://opencollective.com/asyncomplete/contribute)]
+
+#### Individuals
+
+<a href="https://opencollective.com/asyncomplete"><img src="https://opencollective.com/asyncomplete/individuals.svg?width=890"></a>
+
+#### Organizations
+
+Support this project with your organization. Your logo will show up here with a link to your website. [[Contribute](https://opencollective.com/asyncomplete/contribute)]
+
+<a href="https://opencollective.com/asyncomplete/organization/0/website"><img src="https://opencollective.com/asyncomplete/organization/0/avatar.svg"></a>
+<a href="https://opencollective.com/asyncomplete/organization/1/website"><img src="https://opencollective.com/asyncomplete/organization/1/avatar.svg"></a>
+<a href="https://opencollective.com/asyncomplete/organization/2/website"><img src="https://opencollective.com/asyncomplete/organization/2/avatar.svg"></a>
+<a href="https://opencollective.com/asyncomplete/organization/3/website"><img src="https://opencollective.com/asyncomplete/organization/3/avatar.svg"></a>
+<a href="https://opencollective.com/asyncomplete/organization/4/website"><img src="https://opencollective.com/asyncomplete/organization/4/avatar.svg"></a>
+<a href="https://opencollective.com/asyncomplete/organization/5/website"><img src="https://opencollective.com/asyncomplete/organization/5/avatar.svg"></a>
+<a href="https://opencollective.com/asyncomplete/organization/6/website"><img src="https://opencollective.com/asyncomplete/organization/6/avatar.svg"></a>
+<a href="https://opencollective.com/asyncomplete/organization/7/website"><img src="https://opencollective.com/asyncomplete/organization/7/avatar.svg"></a>
+<a href="https://opencollective.com/asyncomplete/organization/8/website"><img src="https://opencollective.com/asyncomplete/organization/8/avatar.svg"></a>
+<a href="https://opencollective.com/asyncomplete/organization/9/website"><img src="https://opencollective.com/asyncomplete/organization/9/avatar.svg"></a>
diff --git a/.vim/bundle/asyncomplete/autoload/asyncomplete.vim b/.vim/bundle/asyncomplete/autoload/asyncomplete.vim
new file mode 100644 (file)
index 0000000..d5e4e4b
--- /dev/null
@@ -0,0 +1,540 @@
+function! asyncomplete#log(...) abort
+    if !empty(g:asyncomplete_log_file)
+        call writefile([json_encode(a:000)], g:asyncomplete_log_file, 'a')
+    endif
+endfunction
+
+" do nothing, place it here only to avoid the message
+augroup asyncomplete_silence_messages
+    au!
+    autocmd User asyncomplete_setup silent
+augroup END
+
+if !has('timers')
+    echohl ErrorMsg
+    echomsg 'Vim/Neovim compiled with timers required for asyncomplete.vim.'
+    echohl NONE
+    if has('nvim')
+        call asyncomplete#log('neovim compiled with timers required.')
+    else
+        call asyncomplete#log('vim compiled with timers required.')
+    endif
+    " Clear augroup so this message is only displayed once.
+    au! asyncomplete_enable *
+    finish
+endif
+
+let s:already_setup = 0
+let s:sources = {}
+let s:matches = {} " { server_name: { incomplete: 1, startcol: 0, items: [], refresh: 0, status: 'idle|pending|success|failure', ctx: ctx } }
+let s:has_complete_info = exists('*complete_info')
+let s:has_matchfuzzypos = exists('*matchfuzzypos')
+
+function! s:setup_if_required() abort
+    if !s:already_setup
+        " register asyncomplete change manager
+        for l:change_manager in g:asyncomplete_change_manager
+            call asyncomplete#log('core', 'initializing asyncomplete change manager', l:change_manager)
+            if type(l:change_manager) == type('')
+                execute 'let s:on_change_manager = function("'. l:change_manager  .'")()'
+            else
+                let s:on_change_manager = l:change_manager()
+            endif
+            if has_key(s:on_change_manager, 'error')
+                call asyncomplete#log('core', 'initializing asyncomplete change manager failed', s:on_change_manager['name'], s:on_change_manager['error'])
+            else
+                call s:on_change_manager.register(function('s:on_change'))
+                call asyncomplete#log('core', 'initializing asyncomplete change manager complete', s:on_change_manager['name'])
+                break
+            endif
+        endfor
+
+        augroup asyncomplete
+            autocmd!
+            autocmd InsertEnter * call s:on_insert_enter()
+            autocmd InsertLeave * call s:on_insert_leave()
+        augroup END
+
+        doautocmd <nomodeline> User asyncomplete_setup
+        let s:already_setup = 1
+    endif
+endfunction
+
+function! asyncomplete#enable_for_buffer() abort
+    call s:setup_if_required()
+    let b:asyncomplete_enable = 1
+endfunction
+
+function! asyncomplete#disable_for_buffer() abort
+    let b:asyncomplete_enable = 0
+endfunction
+
+function! asyncomplete#get_source_names() abort
+    return keys(s:sources)
+endfunction
+
+function! asyncomplete#get_source_info(source_name) abort
+    return s:sources[a:source_name]
+endfunction
+
+function! asyncomplete#register_source(info) abort
+    if has_key(s:sources, a:info['name'])
+        call asyncomplete#log('core', 'duplicate asyncomplete#register_source', a:info['name'])
+        return -1
+    else
+        let s:sources[a:info['name']] = a:info
+        if has_key(a:info, 'events') && has_key(a:info, 'on_event')
+            execute 'augroup asyncomplete_source_event_' . a:info['name']
+            for l:event in a:info['events']
+                let l:exec =  'if get(b:,"asyncomplete_enable",0) | call s:notify_event_to_source("' . a:info['name'] . '", "'.l:event.'",asyncomplete#context()) | endif'
+                if type(l:event) == type('')
+                    execute 'au ' . l:event . ' * ' . l:exec
+                elseif type(l:event) == type([])
+                    execute 'au ' . join(l:event,' ') .' ' .  l:exec
+                endif
+            endfor
+            execute 'augroup end'
+        endif
+
+        if exists('b:asyncomplete_active_sources')
+          unlet b:asyncomplete_active_sources
+          call s:get_active_sources_for_buffer()
+        endif
+
+        if exists('b:asyncomplete_triggers')
+          unlet b:asyncomplete_triggers
+          call s:update_trigger_characters()
+        endif
+
+        return 1
+    endif
+endfunction
+
+function! asyncomplete#unregister_source(info_or_server_name) abort
+    if type(a:info_or_server_name) == type({})
+        let l:server_name = a:info_or_server_name['name']
+    else
+        let l:server_name = a:info_or_server_name
+    endif
+    if has_key(s:sources, l:server_name)
+        let l:server = s:sources[l:server_name]
+        if has_key(l:server, 'unregister')
+            call l:server.unregister()
+        endif
+        unlet s:sources[l:server_name]
+        return 1
+    else
+        return -1
+    endif
+endfunction
+
+function! asyncomplete#context() abort
+    let l:ret = {'bufnr':bufnr('%'), 'curpos':getcurpos(), 'changedtick':b:changedtick}
+    let l:ret['lnum'] = l:ret['curpos'][1]
+    let l:ret['col'] = l:ret['curpos'][2]
+    let l:ret['filetype'] = &filetype
+    let l:ret['filepath'] = expand('%:p')
+    let l:ret['typed'] = strpart(getline(l:ret['lnum']),0,l:ret['col']-1)
+    return l:ret
+endfunction
+
+function! s:on_insert_enter() abort
+    call s:get_active_sources_for_buffer() " call to cache
+    call s:update_trigger_characters()
+endfunction
+
+function! s:on_insert_leave() abort
+    let s:matches = {}
+    if exists('s:update_pum_timer')
+        call timer_stop(s:update_pum_timer)
+        unlet s:update_pum_timer
+    endif
+endfunction
+
+function! s:get_active_sources_for_buffer() abort
+    if exists('b:asyncomplete_active_sources')
+        " active sources were cached for buffer
+        return b:asyncomplete_active_sources
+    endif
+
+    call asyncomplete#log('core', 'computing active sources for buffer', bufnr('%'))
+    let b:asyncomplete_active_sources = []
+    for [l:name, l:info] in items(s:sources)
+        let l:blocked = 0
+
+        if has_key(l:info, 'blocklist')
+            let l:blocklistkey = 'blocklist'
+        else
+            let l:blocklistkey = 'blacklist'
+        endif
+        if has_key(l:info, l:blocklistkey)
+            for l:filetype in l:info[l:blocklistkey]
+                if l:filetype == &filetype || l:filetype is# '*'
+                    let l:blocked = 1
+                    break
+                endif
+            endfor
+        endif
+
+        if l:blocked
+            continue
+        endif
+
+        if has_key(l:info, 'allowlist')
+            let l:allowlistkey = 'allowlist'
+        else
+            let l:allowlistkey = 'whitelist'
+        endif
+        if has_key(l:info, l:allowlistkey)
+            for l:filetype in l:info[l:allowlistkey]
+                if l:filetype == &filetype || l:filetype is# '*'
+                    let b:asyncomplete_active_sources += [l:name]
+                    break
+                endif
+            endfor
+        endif
+    endfor
+
+    call asyncomplete#log('core', 'active source for buffer', bufnr('%'), b:asyncomplete_active_sources)
+
+    return b:asyncomplete_active_sources
+endfunction
+
+function! s:update_trigger_characters() abort
+    if exists('b:asyncomplete_triggers')
+        " triggers were cached for buffer
+        return b:asyncomplete_triggers
+    endif
+    let b:asyncomplete_triggers = {} " { char: { 'sourcea': 1, 'sourceb': 2 } }
+
+    for l:source_name in s:get_active_sources_for_buffer()
+        let l:source_info = s:sources[l:source_name]
+        if has_key(l:source_info, 'triggers') && has_key(l:source_info['triggers'], &filetype)
+            let l:triggers = l:source_info['triggers'][&filetype]
+        elseif has_key(l:source_info, 'triggers') && has_key(l:source_info['triggers'], '*')
+            let l:triggers = l:source_info['triggers']['*']
+        elseif has_key(g:asyncomplete_triggers, &filetype)
+            let l:triggers = g:asyncomplete_triggers[&filetype]
+        elseif has_key(g:asyncomplete_triggers, '*')
+            let l:triggers = g:asyncomplete_triggers['*']
+        else
+            let l:triggers = []
+        endif
+
+        for l:trigger in l:triggers
+            let l:last_char = l:trigger[len(l:trigger) -1]
+            if !has_key(b:asyncomplete_triggers, l:last_char)
+                let b:asyncomplete_triggers[l:last_char] = {}
+            endif
+            if !has_key(b:asyncomplete_triggers[l:last_char], l:source_name)
+                let b:asyncomplete_triggers[l:last_char][l:source_name] = []
+            endif
+            call add(b:asyncomplete_triggers[l:last_char][l:source_name], l:trigger)
+        endfor
+    endfor
+    call asyncomplete#log('core', 'trigger characters for buffer', bufnr('%'), b:asyncomplete_triggers)
+endfunction
+
+function! s:should_skip() abort
+    if mode() isnot# 'i' || !get(b:, 'asyncomplete_enable', 0)
+        return 1
+    else
+        return 0
+    endif
+endfunction
+
+function! asyncomplete#close_popup() abort
+  return pumvisible() ? "\<C-y>" : ''
+endfunction
+
+function! asyncomplete#cancel_popup() abort
+  return pumvisible() ? "\<C-e>" : ''
+endfunction
+
+function! s:get_min_chars(source_name) abort
+  if exists('b:asyncomplete_min_chars')
+    return b:asyncomplete_min_chars
+  elseif has_key(s:sources, a:source_name)
+    return get(s:sources[a:source_name], 'min_chars', g:asyncomplete_min_chars)
+  endif
+  return g:asyncomplete_min_chars
+endfunction
+
+function! s:on_change() abort
+    if s:should_skip() | return | endif
+
+    if !g:asyncomplete_auto_popup
+        return
+    endif
+
+    let l:ctx = asyncomplete#context()
+    let l:last_char = l:ctx['typed'][l:ctx['col'] - 2] " col is 1-indexed, but str 0-indexed
+    if exists('b:asyncomplete_triggers')
+        let l:triggered_sources = get(b:asyncomplete_triggers, l:last_char, {})
+    else
+        let l:triggered_sources = {}
+    endif
+    let l:refresh_pattern = get(b:, 'asyncomplete_refresh_pattern', '\(\k\+$\)')
+    let [l:_, l:startidx, l:endidx] = asyncomplete#utils#matchstrpos(l:ctx['typed'], l:refresh_pattern)
+
+    for l:source_name in get(b:, 'asyncomplete_active_sources', [])
+        " match sources based on the last character if it is a trigger character
+        " TODO: also check for multiple chars instead of just last chars for
+        " languages such as cpp which uses -> and ::
+        if has_key(l:triggered_sources, l:source_name)
+            let l:startcol = l:ctx['col']
+        elseif l:startidx > -1
+            let l:startcol = l:startidx + 1 " col is 1-indexed, but str 0-indexed
+        endif
+        " here we use the existence of `l:startcol` to determine whether to
+        " use this completion source. If `l:startcol` exists, we use the
+        " source. If it does not exist, it means that we cannot get a
+        " meaningful starting point for the current source, and this implies
+        " that we cannot use this source for completion. Therefore, we remove
+        " the matches from the source.
+        if exists('l:startcol') && l:endidx - l:startidx >= s:get_min_chars(l:source_name)
+            if !has_key(s:matches, l:source_name) || s:matches[l:source_name]['ctx']['lnum'] !=# l:ctx['lnum'] || s:matches[l:source_name]['startcol'] !=# l:startcol
+                let s:matches[l:source_name] = { 'startcol': l:startcol, 'status': 'idle', 'items': [], 'refresh': 0, 'ctx': l:ctx }
+            endif
+        else
+            if has_key(s:matches, l:source_name)
+                unlet s:matches[l:source_name]
+            endif
+        endif
+    endfor
+
+    call s:trigger(l:ctx)
+    call s:update_pum()
+endfunction
+
+function! s:trigger(ctx) abort
+    " send cancellation request if supported
+    for [l:source_name, l:matches] in items(s:matches)
+        call asyncomplete#log('core', 's:trigger', l:matches)
+        if l:matches['refresh'] || l:matches['status'] ==# 'idle' || l:matches['status'] ==# 'failure'
+            let l:matches['status'] = 'pending'
+            try
+                " TODO: check for min chars
+                call asyncomplete#log('core', 's:trigger.completor()', l:source_name, s:matches[l:source_name], a:ctx)
+                call s:sources[l:source_name].completor(s:sources[l:source_name], a:ctx)
+            catch
+                let l:matches['status'] = 'failure'
+                call asyncomplete#log('core', 's:trigger', 'error', v:exception)
+                continue
+            endtry
+        endif
+    endfor
+endfunction
+
+function! asyncomplete#complete(name, ctx, startcol, items, ...) abort
+    let l:refresh = a:0 > 0 ? a:1 : 0
+    let l:ctx = asyncomplete#context()
+    if !has_key(s:matches, a:name) || l:ctx['lnum'] != a:ctx['lnum'] " TODO: handle more context changes
+        call asyncomplete#log('core', 'asyncomplete#log', 'ignoring due to context chnages', a:name, a:ctx, a:startcol, l:refresh, a:items)
+        call s:update_pum()
+        return
+    endif
+
+    call asyncomplete#log('asyncomplete#complete', a:name, a:ctx, a:startcol, l:refresh, a:items)
+
+    let l:matches = s:matches[a:name]
+    let l:matches['items'] = s:normalize_items(a:items)
+    let l:matches['refresh'] = l:refresh
+    let l:matches['startcol'] = a:startcol
+    let l:matches['status'] = 'success'
+
+    call s:update_pum()
+endfunction
+
+function! s:normalize_items(items) abort
+    if len(a:items) > 0 && type(a:items[0]) ==# type('')
+        let l:items = []
+        for l:item in a:items
+            let l:items += [{'word': l:item }]
+        endfor
+        return l:items
+    else
+        return a:items
+    endif
+endfunction
+
+function! asyncomplete#force_refresh() abort
+    return asyncomplete#menu_selected() ? "\<c-y>\<c-r>=asyncomplete#_force_refresh()\<CR>" : "\<c-r>=asyncomplete#_force_refresh()\<CR>"
+endfunction
+
+function! asyncomplete#_force_refresh() abort
+    if s:should_skip() | return | endif
+
+    let l:ctx = asyncomplete#context()
+    let l:startcol = l:ctx['col']
+    let l:last_char = l:ctx['typed'][l:startcol - 2]
+
+    " loop left and find the start of the word or trigger chars and set it as the startcol for the source instead of refresh_pattern
+    let l:refresh_pattern = get(b:, 'asyncomplete_refresh_pattern', '\(\k\+$\)')
+    let [l:_, l:startidx, l:endidx] = asyncomplete#utils#matchstrpos(l:ctx['typed'], l:refresh_pattern)
+    " When no word here, startcol is current col
+    let l:startcol = l:startidx == -1 ? col('.') : l:startidx + 1
+
+    let s:matches = {}
+
+    for l:source_name in get(b:, 'asyncomplete_active_sources', [])
+        let s:matches[l:source_name] = { 'startcol': l:startcol, 'status': 'idle', 'items': [], 'refresh': 0, 'ctx': l:ctx }
+    endfor
+
+    call s:trigger(l:ctx)
+    call s:update_pum()
+    return ''
+endfunction
+
+function! s:update_pum() abort
+    if exists('s:update_pum_timer')
+        call timer_stop(s:update_pum_timer)
+        unlet s:update_pum_timer
+    endif
+    call asyncomplete#log('core', 's:update_pum')
+    let s:update_pum_timer = timer_start(g:asyncomplete_popup_delay, function('s:recompute_pum'))
+endfunction
+
+function! s:recompute_pum(...) abort
+    if s:should_skip() | return | endif
+
+    " TODO: add support for remote recomputation of complete items,
+    " Ex: heavy computation such as fuzzy search can happen in a python thread
+
+    call asyncomplete#log('core', 's:recompute_pum')
+
+    if asyncomplete#menu_selected()
+        call asyncomplete#log('core', 's:recomputed_pum', 'ignorning refresh pum due to menu selection')
+        return
+    endif
+
+    let l:ctx = asyncomplete#context()
+
+    let l:startcols = []
+    let l:matches_to_filter = {}
+
+    for [l:source_name, l:match] in items(s:matches)
+        " ignore sources that have been unregistered
+        if !has_key(s:sources, l:source_name) | continue | endif
+        let l:startcol = l:match['startcol']
+        let l:startcols += [l:startcol]
+        let l:curitems = l:match['items']
+
+        if l:startcol > l:ctx['col']
+            call asyncomplete#log('core', 's:recompute_pum', 'ignoring due to wrong start col', l:startcol, l:ctx['col'])
+            continue
+        else
+            let l:matches_to_filter[l:source_name] = l:match
+        endif
+    endfor
+
+    let l:startcol = min(l:startcols)
+    let l:base = l:ctx['typed'][l:startcol - 1:] " col is 1-indexed, but str 0-indexed
+
+    let l:filter_ctx = extend({
+        \ 'base': l:base,
+        \ 'startcol': l:startcol,
+        \ }, l:ctx)
+
+    let l:mode = s:has_complete_info ? complete_info(['mode'])['mode'] : 'unknown'
+    if l:mode ==# '' || l:mode ==# 'eval' || l:mode ==# 'unknown'
+        let l:Preprocessor = empty(g:asyncomplete_preprocessor) ? function('s:default_preprocessor') : g:asyncomplete_preprocessor[0]
+        call l:Preprocessor(l:filter_ctx, l:matches_to_filter)
+    endif
+endfunction
+
+let s:pair = {
+\  '"':  '"',
+\  '''':  '''',
+\}
+
+function! s:default_preprocessor(options, matches) abort
+    let l:items = []
+    let l:startcols = []
+    for [l:source_name, l:matches] in items(a:matches)
+        let l:startcol = l:matches['startcol']
+        let l:base = a:options['typed'][l:startcol - 1:]
+        if has_key(s:sources[l:source_name], 'filter')
+            let l:result = s:sources[l:source_name].filter(l:matches, l:startcol, l:base)
+            let l:items += l:result[0]
+            let l:startcols += l:result[1]
+        else
+            if empty(l:base)
+                for l:item in l:matches['items']
+                    call add(l:items, s:strip_pair_characters(l:base, l:item))
+                    let l:startcols += [l:startcol]
+                endfor
+            elseif s:has_matchfuzzypos && g:asyncomplete_matchfuzzy
+                for l:item in matchfuzzypos(l:matches['items'], l:base, {'key':'word'})[0]
+                    call add(l:items, s:strip_pair_characters(l:base, l:item))
+                    let l:startcols += [l:startcol]
+                endfor
+            else
+                for l:item in l:matches['items']
+                    if stridx(l:item['word'], l:base) == 0
+                        call add(l:items, s:strip_pair_characters(l:base, l:item))
+                        let l:startcols += [l:startcol]
+                    endif
+                endfor
+            endif
+        endif
+    endfor
+
+    let a:options['startcol'] = min(l:startcols)
+
+    call asyncomplete#preprocess_complete(a:options, l:items)
+endfunction
+
+function! s:strip_pair_characters(base, item) abort
+    " Strip pair characters. If pre-typed text is '"', candidates
+    " should have '"' suffix.
+    let l:item = a:item
+    if has_key(s:pair, a:base[0])
+        let [l:lhs, l:rhs, l:str] = [a:base[0], s:pair[a:base[0]], l:item['word']]
+        if len(l:str) > 1 && l:str[0] ==# l:lhs && l:str[-1:] ==# l:rhs
+            let l:item = extend({}, l:item)
+            let l:item['word'] = l:str[:-2]
+        endif
+    endif
+    return l:item
+endfunction
+
+function! asyncomplete#preprocess_complete(ctx, items) abort
+    " TODO: handle cases where this is called asynchronsouly. Currently not supported
+    if s:should_skip() | return | endif
+
+    call asyncomplete#log('core', 'asyncomplete#preprocess_complete')
+
+    if asyncomplete#menu_selected()
+        call asyncomplete#log('core', 'asyncomplete#preprocess_complete', 'ignorning pum update due to menu selection')
+        return
+    endif
+
+    if (g:asyncomplete_auto_completeopt == 1)
+        setl completeopt=menuone,noinsert,noselect
+    endif
+
+    let l:startcol = a:ctx['startcol']
+    call asyncomplete#log('core', 'asyncomplete#preprocess_complete calling complete()', l:startcol, a:items)
+    if l:startcol > 0 " Prevent E578: Not allowed to change text here
+        call complete(l:startcol, a:items)
+    endif
+endfunction
+
+function! asyncomplete#menu_selected() abort
+    " when the popup menu is visible, v:completed_item will be the
+    " current_selected item
+    " if v:completed_item is empty, no item is selected
+    return pumvisible() && !empty(v:completed_item)
+endfunction
+
+function! s:notify_event_to_source(name, event, ctx) abort
+    try
+        if has_key(s:sources, a:name)
+            call s:sources[a:name].on_event(s:sources[a:name], a:ctx, a:event)
+        endif
+    catch
+        call asyncomplete#log('core', 's:notify_event_to_source', 'error', v:exception)
+        return
+    endtry
+endfunction
diff --git a/.vim/bundle/asyncomplete/autoload/asyncomplete/utils.vim b/.vim/bundle/asyncomplete/autoload/asyncomplete/utils.vim
new file mode 100644 (file)
index 0000000..0a1c24f
--- /dev/null
@@ -0,0 +1,21 @@
+" Find a nearest to a `path` parent directory `directoryname` by traversing the
+" filesystem upwards
+function! asyncomplete#utils#find_nearest_parent_directory(path, directoryname) abort
+    let l:relative_path = finddir(a:directoryname, a:path . ';')
+
+    if !empty(l:relative_path)
+        return fnamemodify(l:relative_path, ':p')
+    else
+        return ''
+    endif
+endfunction
+
+if exists('*matchstrpos')
+    function! asyncomplete#utils#matchstrpos(expr, pattern) abort
+        return matchstrpos(a:expr, a:pattern)
+    endfunction
+else
+    function! asyncomplete#utils#matchstrpos(expr, pattern) abort
+        return [matchstr(a:expr, a:pattern), match(a:expr, a:pattern), matchend(a:expr, a:pattern)]
+    endfunction
+endif
diff --git a/.vim/bundle/asyncomplete/autoload/asyncomplete/utils/_on_change/textchangedp.vim b/.vim/bundle/asyncomplete/autoload/asyncomplete/utils/_on_change/textchangedp.vim
new file mode 100644 (file)
index 0000000..61c49bd
--- /dev/null
@@ -0,0 +1,81 @@
+let s:callbacks = []
+
+function! asyncomplete#utils#_on_change#textchangedp#init() abort
+    if exists('##TextChangedP')
+        call s:setup_if_required()
+        return {
+            \ 'name': 'TextChangedP',
+            \ 'register': function('s:register'),
+            \ 'unregister': function('s:unregister'),
+        \ }
+    else
+        return { 'name': 'TextChangedP', 'error': 'Requires vim with TextChangedP support' }
+    endif
+endfunction
+
+function! s:setup_if_required() abort
+    augroup asyncomplete_utils_on_change_text_changed_p
+        autocmd!
+        autocmd InsertEnter * call s:on_insert_enter()
+        autocmd InsertLeave * call s:on_insert_leave()
+        autocmd TextChangedI * call s:on_text_changed_i()
+        autocmd TextChangedP * call s:on_text_changed_p()
+    augroup END
+endfunction
+
+function! s:register(cb) abort
+    call add(s:callbacks , a:cb)
+endfunction
+
+function! s:unregister(obj, cb) abort
+    " TODO: remove from s:callbacks
+endfunction
+
+function! s:on_insert_enter() abort
+    let l:context = asyncomplete#context()
+    let s:previous_context = {
+        \ 'lnum': l:context['lnum'],
+        \ 'col': l:context['col'],
+        \ 'typed': l:context['typed'],
+        \ }
+endfunction
+
+function! s:on_insert_leave() abort
+    unlet! s:previous_context
+endfunction
+
+function! s:on_text_changed_i() abort
+    call s:maybe_notify_on_change()
+endfunction
+
+function! s:on_text_changed_p() abort
+    call s:maybe_notify_on_change()
+endfunction
+
+function! s:maybe_notify_on_change() abort
+    if !exists('s:previous_context')
+        return
+    endif
+    " We notify on_change callbacks only when the cursor position
+    " has changed.
+    " Unfortunatelly we need this check because in insert mode it
+    " is possible to have TextChangedI triggered when the completion
+    " context is not changed at all: When we close the completion
+    " popup menu via <C-e> or <C-y>. If we still let on_change
+    " do the completion in this case we never close the menu.
+    " Vim doesn't allow programmatically changing buffer content
+    " in insert mode, so by comparing the cursor's position and the
+    " completion base we know whether the context has changed.
+    let l:context = asyncomplete#context()
+    let l:previous_context = s:previous_context
+    let s:previous_context = {
+        \ 'lnum': l:context['lnum'],
+        \ 'col': l:context['col'],
+        \ 'typed': l:context['typed'],
+        \ }
+    if l:previous_context !=# s:previous_context
+        for l:Cb in s:callbacks
+            call l:Cb()
+        endfor
+    endif
+endfunction
diff --git a/.vim/bundle/asyncomplete/autoload/asyncomplete/utils/_on_change/timer.vim b/.vim/bundle/asyncomplete/autoload/asyncomplete/utils/_on_change/timer.vim
new file mode 100644 (file)
index 0000000..2a0c1fc
--- /dev/null
@@ -0,0 +1,83 @@
+let s:callbacks = []
+
+let s:change_timer = -1
+let s:last_tick = []
+
+function! asyncomplete#utils#_on_change#timer#init() abort
+    call s:setup_if_required()
+    return {
+        \ 'name': 'timer',
+        \ 'register': function('s:register'),
+        \ 'unregister': function('s:unregister'),
+    \ }
+endfunction
+
+function! s:setup_if_required() abort
+    augroup asyncomplete_utils_on_change_timer
+        autocmd!
+        autocmd InsertEnter * call s:on_insert_enter()
+        autocmd InsertLeave * call s:on_insert_leave()
+        autocmd TextChangedI * call s:on_text_changed_i()
+    augroup END
+endfunction
+
+function! s:register(cb) abort
+    call add(s:callbacks , a:cb)
+endfunction
+
+function! s:unregister(obj, cb) abort
+    " TODO: remove from s:callbacks
+endfunction
+
+function! s:on_insert_enter() abort
+    let s:previous_position = getcurpos()
+    call s:change_tick_start()
+endfunction
+
+function! s:on_insert_leave() abort
+    unlet s:previous_position
+    call s:change_tick_stop()
+endfunction
+
+function! s:on_text_changed_i() abort
+    call s:check_changes()
+endfunction
+
+function! s:change_tick_start() abort
+    if !exists('s:change_timer')
+        let s:last_tick = s:change_tick()
+        " changes every 30ms, which is 0.03s, it should be fast enough
+        let s:change_timer = timer_start(30, function('s:check_changes'), { 'repeat': -1 })
+    endif
+endfunction
+
+function! s:change_tick_stop() abort
+    if exists('s:change_timer')
+        call timer_stop(s:change_timer)
+        unlet s:change_timer
+        let s:last_tick = []
+    endif
+endfunction
+
+function! s:check_changes(...) abort
+    let l:tick = s:change_tick()
+    if l:tick != s:last_tick
+        let s:last_tick = l:tick
+        call s:maybe_notify_on_change()
+    endif
+endfunction
+
+function! s:maybe_notify_on_change() abort
+    " enter to new line or backspace to previous line shouldn't cause change trigger
+    let l:previous_position = s:previous_position
+    let s:previous_position = getcurpos()
+    if l:previous_position[1] ==# getcurpos()[1]
+        for l:Cb in s:callbacks
+            call l:Cb()
+        endfor
+    endif
+endfunction
+
+function! s:change_tick() abort
+    return [b:changedtick, getcurpos()]
+endfunction
diff --git a/.vim/bundle/asyncomplete/doc/asyncomplete.txt b/.vim/bundle/asyncomplete/doc/asyncomplete.txt
new file mode 100644 (file)
index 0000000..1e15fba
--- /dev/null
@@ -0,0 +1,191 @@
+*asyncomplete.vim.txt*  Async autocompletion for Vim 8 and Neovim.
+*asyncomplete*
+
+
+===============================================================================
+CONTENTS                                                *asyncomplete-contents*
+
+    1. Introduction              |asyncomplete-introduction|
+    2. Options                   |asyncomplete-options|
+    3. Functions                 |asyncomplete-functions|
+    4. Global vim configuration  |asyncomplete-global-config|
+    5. Known Issues              |asyncomplete-known-issues|
+
+===============================================================================
+1. Introduction                                     *asyncomplete-introduction*
+
+Async autocompletion for Vim 8 and Neovim with |timers|.
+
+This is inspired by https://github.com/roxma/nvim-complete-manager but written
+in pure Vim Script.
+
+===============================================================================
+2. Options                                               *asyncomplete-options*
+
+
+g:asyncomplete_enable_for_all                   *g:asyncomplete_enable_for_all*
+
+    Type |Number|
+    Default: 1
+
+    Enable asyncomplete for all buffers. Can be overriden with
+    `b:asyncomplete_enable` on a per-buffer basis.  Setting this to 0 prevents
+    asyncomplete from loading upon entering a buffer.
+
+b:asyncomplete_enable                                   *b:asyncomplete_enable*
+
+    Type |Number|
+    Default: 1
+
+    Setting this variable to 0 disables asyncomplete for the current buffer
+    and overrides `g:asyncomplete_enable_for_all` .
+
+g:asyncomplete_auto_popup                           *g:asyncomplete_auto_popup*
+
+    Type: |Number|
+    Default: `1`
+
+    Automatically show the autocomplete popup menu as you start typing.
+
+g:asyncomplete_log_file                               *g:asyncomplete_log_file*
+
+    Type: |String|
+    Default: null
+
+    Path to log file.
+
+g:asyncomplete_popup_delay                         *g:asyncomplete_popup_delay*
+
+    Type: |Number|
+    Default: 30
+
+    Milliseconds to wait before opening the popup menu
+
+g:asyncomplete_auto_completeopt               *g:asyncomplete_auto_completeopt*
+
+    Type: |Number|
+    Default: 1
+
+    Set default `completeopt` options. These are `menuone,noinsert,noselect`.
+    This effectively overwrites what ever the user has in their config file.
+
+    Set to 0 to disable.
+
+g:asyncomplete_preprocessor                        *g:asyncomplete_preprocessor*
+
+    Type: |Array| for zero or one |Function|
+    Default: []
+
+    Set a function to allow custom filtering or sorting.
+    Below example implements removing duplicates.
+
+      function! s:my_asyncomplete_preprocessor(options, matches) abort
+        let l:visited = {}
+        let l:items = []
+        for [l:source_name, l:matches] in items(a:matches)
+          for l:item in l:matches['items']
+            if stridx(l:item['word'], a:options['base']) == 0
+              if !has_key(l:visited, l:item['word'])
+                call add(l:items, l:item)
+                let l:visited[l:item['word']] = 1
+              endif
+            endif
+          endfor
+        endfor
+
+        call asyncomplete#preprocess_complete(a:options, l:items)
+      endfunction
+
+      let g:asyncomplete_preprocessor = [function('s:my_asyncomplete_preprocessor')]
+
+    Note:
+    asyncomplete#preprocess_complete() must be called synchronously.
+    Plans to support async preprocessing will be supported in the future.
+
+    context and matches in arguments in preprecessor function should be treated
+    as immutable.
+
+g:asyncomplete_min_chars                             *g:asyncomplete_min_chars*
+
+    Type: |Number|
+    Default: 0
+
+    Minimum consecutive characters to trigger auto-popup. Overridden by buffer
+    variable if set (`b:asyncomplete_min_chars`)
+
+g:asyncomplete_matchfuzzy                           *g:asyncomplete_matchfuzzy*
+
+    Type: |Number|
+    Default: `exists('*matchfuzzypos')`
+
+    Use |matchfuzzypos| to support fuzzy matching of 'word' when completing
+    items. Requires vim with `matchfuzzypos()` function to exists.
+
+    Set to `0` to disable fuzzy matching.
+
+===============================================================================
+3. Functions                                            *asyncomplete-functions*
+
+asyncomplete#close_popup()                         *asyncomplete#close_popup()*
+
+    Insert selected candidate and close popup menu.
+    Following example prevents popup menu from re-opening after insertion.
+>
+    inoremap <expr> <C-y> pumvisible() ? asyncomplete#close_popup() : "\<C-y>"
+<
+asyncomplete#cancel_popup()                       *asyncomplete#cancel_popup()*
+
+    Cancel completion and close popup menu.
+    Following example prevents popup menu from re-opening after cancellation.
+>
+    inoremap <expr> <C-e> pumvisible() ? asyncomplete#cancel_popup() : "\<C-e>"
+<
+asyncomplete#get_source_info({source-name})    *asyncomplete#get_source_info()*
+
+    Get the source configuration info as dict.
+    Below example implements a priority sort function.
+>
+    function! s:sort_by_priority_preprocessor(options, matches) abort
+      let l:items = []
+      for [l:source_name, l:matches] in items(a:matches)
+        for l:item in l:matches['items']
+          if stridx(l:item['word'], a:options['base']) == 0
+            let l:item['priority'] =
+                \ get(asyncomplete#get_source_info(l:source_name),'priority',0)
+            call add(l:items, l:item)
+          endif
+        endfor
+      endfor
+
+      let l:items = sort(l:items, {a, b -> b['priority'] - a['priority']})
+
+      call asyncomplete#preprocess_complete(a:options, l:items)
+    endfunction
+
+    let g:asyncomplete_preprocessor = [function('s:sort_by_priority_preprocessor')]
+<
+asyncomplete#get_source_names()               *asyncomplete#get_source_names()*
+
+    Get the registered source names list.
+
+===============================================================================
+4. Global vim configuration                          *asyncomplete-global-config*
+
+If you notice messages like 'Pattern not found' or 'Match 1 of <N>' printed in
+red colour in vim command line and in `:messages` history and you are annoyed
+with them, try setting `shortmess` vim option in your `.vimrc` like so:
+>
+    set shortmess+=c
+<
+See `:help shortmess` for details and description.
+
+===============================================================================
+5. Known Issues                                       *asyncomplete-known-issues*
+
+Builtin complete such as omni func, file func flickers and closes.
+    You need vim with patch v8.1.1068.
+    https://github.com/vim/vim/commit/fd133323d4e1cc9c0e61c0ce357df4d36ea148e3
+
+===============================================================================
+
+  vim:tw=78:ts=4:sts=4:sw=4:ft=help:norl:
diff --git a/.vim/bundle/asyncomplete/plugin/asyncomplete.vim b/.vim/bundle/asyncomplete/plugin/asyncomplete.vim
new file mode 100644 (file)
index 0000000..69bde82
--- /dev/null
@@ -0,0 +1,25 @@
+if exists('g:asyncomplete_loaded')
+    finish
+endif
+let g:asyncomplete_loaded = 1
+
+if get(g:, 'asyncomplete_enable_for_all', 1)
+    augroup asyncomplete_enable
+        au!
+        au BufEnter * if exists('b:asyncomplete_enable') == 0 | call asyncomplete#enable_for_buffer() | endif
+    augroup END
+endif
+
+let g:asyncomplete_manager = get(g:, 'asyncomplete_manager', 'asyncomplete#managers#vim#init')
+let g:asyncomplete_change_manager = get(g:, 'asyncomplete_change_manager', ['asyncomplete#utils#_on_change#textchangedp#init', 'asyncomplete#utils#_on_change#timer#init'])
+let g:asyncomplete_triggers = get(g:, 'asyncomplete_triggers', {'*': ['.', '>', ':'] })
+let g:asyncomplete_min_chars = get(g:, 'asyncomplete_min_chars', 0)
+
+let g:asyncomplete_auto_completeopt = get(g:, 'asyncomplete_auto_completeopt', 1)
+let g:asyncomplete_auto_popup = get(g:, 'asyncomplete_auto_popup', 1)
+let g:asyncomplete_popup_delay = get(g:, 'asyncomplete_popup_delay', 30)
+let g:asyncomplete_log_file = get(g:, 'asyncomplete_log_file', '')
+let g:asyncomplete_preprocessor = get(g:, 'asyncomplete_preprocessor', [])
+let g:asyncomplete_matchfuzzy = get(g:, 'asyncomplete_matchfuzzy', exists('*matchfuzzypos'))
+
+inoremap <silent> <expr> <Plug>(asyncomplete_force_refresh) asyncomplete#force_refresh()
diff --git a/.vim/bundle/asyncomplete/renovate.json b/.vim/bundle/asyncomplete/renovate.json
new file mode 100644 (file)
index 0000000..39a2b6e
--- /dev/null
@@ -0,0 +1,6 @@
+{
+  "$schema": "https://docs.renovatebot.com/renovate-schema.json",
+  "extends": [
+    "config:base"
+  ]
+}
diff --git a/.vim/bundle/asyncomplete/test/.themisrc b/.vim/bundle/asyncomplete/test/.themisrc
new file mode 100644 (file)
index 0000000..d73cbf9
--- /dev/null
@@ -0,0 +1,3 @@
+set encoding=utf-8
+call themis#option('recursive', 1)
+call themis#helper('command').with(themis#helper('assert'))
diff --git a/.vim/bundle/asyncomplete/test/asyncomplete.vimspec b/.vim/bundle/asyncomplete/test/asyncomplete.vimspec
new file mode 100644 (file)
index 0000000..eaf2b54
--- /dev/null
@@ -0,0 +1,2 @@
+Describe asyncomplete
+End