I broke up with neovim....vim is my best friend now
This commit is contained in:
21
dot_vim/plugged/vim-vsnip/LICENSE
Normal file
21
dot_vim/plugged/vim-vsnip/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 hrsh7th
|
||||
|
||||
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.
|
||||
199
dot_vim/plugged/vim-vsnip/README.md
Normal file
199
dot_vim/plugged/vim-vsnip/README.md
Normal file
@@ -0,0 +1,199 @@
|
||||
# vim-vsnip
|
||||
|
||||
VSCode(LSP)'s snippet feature in vim/nvim.
|
||||
|
||||
# Features
|
||||
|
||||
- Nested placeholders
|
||||
- You can define snippet like `console.log($1${2:, $1})$0`
|
||||
- Nested snippet expansion
|
||||
- You can expand snippet even if you already activated other snippet (it will be merged as one snippet)
|
||||
- Load snippet from VSCode extension
|
||||
- If you install VSCode extension via `Plug 'golang/vscode-go'`, vsnip will load those snippets.
|
||||
- Support many LSP-client & completion-engine by [vim-vsnip-integ](https://github.com/hrsh7th/vim-vsnip-integ)
|
||||
- LSP-client
|
||||
- [vim-lsp](https://github.com/prabirshrestha/vim-lsp)
|
||||
- [vim-lsc](https://github.com/natebosch/vim-lsc)
|
||||
- [LanguageClient-neovim](https://github.com/autozimu/LanguageClient-neovim)
|
||||
- [neovim built-in lsp](https://github.com/neovim/neovim)
|
||||
- [vim-lamp](https://github.com/hrsh7th/vim-lamp)
|
||||
- completion-engine
|
||||
- [deoplete.nvim](https://github.com/Shougo/deoplete.nvim)
|
||||
- [asyncomplete.vim](https://github.com/prabirshrestha/asyncomplete.vim)
|
||||
- [vim-mucomplete](https://github.com/lifepillar/vim-mucomplete)
|
||||
- [completion-nvim](https://github.com/nvim-lua/completion-nvim)
|
||||
- Vim script interpolation
|
||||
- You can use Vim script interpolation as `${VIM:...Vim script expression...}`.
|
||||
- SnipMate-like syntax support
|
||||
- Snippet files in SnipMate format with the extension `.snippets` can be load.
|
||||
- NOTE: Full compatibility is not guaranteed. It is intended to easily create user-defined snippets.
|
||||
|
||||
# Concept
|
||||
|
||||
- Pure Vim script
|
||||
- Well tested (neovim/0.4.4, vim/8.0.1567)
|
||||
- Support VSCode snippet format
|
||||
- Provide integration with many plugins
|
||||
|
||||
# Related repository
|
||||
|
||||
[friendly-snippets](https://github.com/rafamadriz/friendly-snippets) - Set of preconfigured snippets for all kind of programming languages that integrates really well with [vim-vsnip](https://github.com/hrsh7th/vim-vsnip), so all users can benefit from them and not to worry about setting up snippets on their own.
|
||||
|
||||
# Usage
|
||||
|
||||
### 1. Install
|
||||
|
||||
You can use your favorite plugin managers to install this plugin.
|
||||
|
||||
```viml
|
||||
Plug 'hrsh7th/vim-vsnip'
|
||||
Plug 'hrsh7th/vim-vsnip-integ'
|
||||
|
||||
call dein#add('hrsh7th/vim-vsnip')
|
||||
call dein#add('hrsh7th/vim-vsnip-integ')
|
||||
|
||||
NeoBundle 'hrsh7th/vim-vsnip'
|
||||
NeoBundle 'hrsh7th/vim-vsnip-integ'
|
||||
```
|
||||
|
||||
### 2. Setting
|
||||
|
||||
```viml
|
||||
" NOTE: You can use other key to expand snippet.
|
||||
|
||||
" Expand
|
||||
imap <expr> <C-j> vsnip#expandable() ? '<Plug>(vsnip-expand)' : '<C-j>'
|
||||
smap <expr> <C-j> vsnip#expandable() ? '<Plug>(vsnip-expand)' : '<C-j>'
|
||||
|
||||
" Expand or jump
|
||||
imap <expr> <C-l> vsnip#available(1) ? '<Plug>(vsnip-expand-or-jump)' : '<C-l>'
|
||||
smap <expr> <C-l> vsnip#available(1) ? '<Plug>(vsnip-expand-or-jump)' : '<C-l>'
|
||||
|
||||
" Jump forward or backward
|
||||
imap <expr> <Tab> vsnip#jumpable(1) ? '<Plug>(vsnip-jump-next)' : '<Tab>'
|
||||
smap <expr> <Tab> vsnip#jumpable(1) ? '<Plug>(vsnip-jump-next)' : '<Tab>'
|
||||
imap <expr> <S-Tab> vsnip#jumpable(-1) ? '<Plug>(vsnip-jump-prev)' : '<S-Tab>'
|
||||
smap <expr> <S-Tab> vsnip#jumpable(-1) ? '<Plug>(vsnip-jump-prev)' : '<S-Tab>'
|
||||
|
||||
" Select or cut text to use as $TM_SELECTED_TEXT in the next snippet.
|
||||
" See https://github.com/hrsh7th/vim-vsnip/pull/50
|
||||
nmap s <Plug>(vsnip-select-text)
|
||||
xmap s <Plug>(vsnip-select-text)
|
||||
nmap S <Plug>(vsnip-cut-text)
|
||||
xmap S <Plug>(vsnip-cut-text)
|
||||
|
||||
" If you want to use snippet for multiple filetypes, you can `g:vsnip_filetypes` for it.
|
||||
let g:vsnip_filetypes = {}
|
||||
let g:vsnip_filetypes.javascriptreact = ['javascript']
|
||||
let g:vsnip_filetypes.typescriptreact = ['typescript']
|
||||
```
|
||||
|
||||
### 3. Create your own snippet
|
||||
|
||||
Snippet file will store to `g:vsnip_snippet_dir` per filetype.
|
||||
|
||||
1. Open some file (example: `Sample.js`)
|
||||
2. Invoke `:VsnipOpen` command.
|
||||
3. Edit snippet.
|
||||
|
||||
```json
|
||||
{
|
||||
"Class": {
|
||||
"prefix": ["class"],
|
||||
"body": [
|
||||
"/**",
|
||||
" * @author ${VIM:\\$USER}",
|
||||
" */",
|
||||
"class $1 ${2:extends ${3:Parent} }{",
|
||||
"\tconstructor() {",
|
||||
"\t\t$0",
|
||||
"\t}",
|
||||
"}"
|
||||
],
|
||||
"description": "Class definition template."
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The snippet format was described in [here](https://code.visualstudio.com/docs/editor/userdefinedsnippets#_snippet-syntax) or [here](https://github.com/Microsoft/language-server-protocol/blob/master/snippetSyntax.md).
|
||||
|
||||
# Recipe
|
||||
|
||||
### $TM_FILENAME_BASE
|
||||
|
||||
You can insert the filename via `fname\<Plug>(vsnip-expand)`.
|
||||
|
||||
```json
|
||||
{
|
||||
"filename": {
|
||||
"prefix": ["fname"],
|
||||
"body": "$TM_FILENAME_BASE"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Log $TM_SELECTED_TEXT
|
||||
|
||||
You can fill `$TM_SELECTED_TEXT` by `<Plug>(vsnip-select-text)` or `<Plug>(vsnip-cut-text)`.
|
||||
|
||||
```json
|
||||
{
|
||||
"log": {
|
||||
"prefix": ["log"],
|
||||
"body": "console.log(${1:$TM_SELECTED_TEXT});"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Insert environment vars
|
||||
|
||||
You can insert value by Vim script expression.
|
||||
|
||||
```json
|
||||
{
|
||||
"user": {
|
||||
"prefix": "username",
|
||||
"body": "${VIM:\\$USER}"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Insert UUID via python
|
||||
|
||||
You can insert UUID via python.
|
||||
|
||||
```json
|
||||
{
|
||||
"uuid": {
|
||||
"prefix": "uuid",
|
||||
"body": [
|
||||
"${VIM:system('python -c \"import uuid, sys;sys.stdout.write(str(uuid.uuid4()))\"')}"
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
NOTE: `$VIM` is only in vsnip. So that makes to lost the snippet portability.
|
||||
|
||||
# DEMO
|
||||
|
||||
### LSP integration
|
||||
|
||||
<img src="https://user-images.githubusercontent.com/629908/90160819-3bd3ec80-ddcd-11ea-919b-577d7eb559a4.gif" width="480" alt="Nested snippet expansion" />
|
||||
|
||||
### `<Plug(vsnip-cut-text)` with `$TM_SELECTED_TEXT`
|
||||
|
||||
<img src="https://user-images.githubusercontent.com/629908/90157756-17761100-ddc9-11ea-843f-d8b0d529ac61.gif" width="480" alt="<Plug&rt;(vsnip-cut-text) with $TM_SELECTED_TEXT" />
|
||||
|
||||
# Development
|
||||
|
||||
### How to run test it?
|
||||
|
||||
You can run `npm run test` after install [vim-themis](https://github.com/thinca/vim-themis).
|
||||
|
||||
### How sync same tabstop placeholders?
|
||||
|
||||
1. compute the `user-diff` ... `s:Session.flush_changes`
|
||||
2. reflect the `user-diff` to snippet ast ... `s:Snippet.follow`
|
||||
3. reflect the `sync-diff` to buffer content ... `s:Snippet.sync & s:Session.flush_changes`
|
||||
|
||||
9
dot_vim/plugged/vim-vsnip/autoload/vital/_vsnip.vim
Normal file
9
dot_vim/plugged/vim-vsnip/autoload/vital/_vsnip.vim
Normal file
@@ -0,0 +1,9 @@
|
||||
let s:_plugin_name = expand('<sfile>:t:r')
|
||||
|
||||
function! vital#{s:_plugin_name}#new() abort
|
||||
return vital#{s:_plugin_name[1:]}#new()
|
||||
endfunction
|
||||
|
||||
function! vital#{s:_plugin_name}#function(funcname) abort
|
||||
silent! return function(a:funcname)
|
||||
endfunction
|
||||
164
dot_vim/plugged/vim-vsnip/autoload/vital/_vsnip/VS/LSP/Diff.vim
Normal file
164
dot_vim/plugged/vim-vsnip/autoload/vital/_vsnip/VS/LSP/Diff.vim
Normal file
@@ -0,0 +1,164 @@
|
||||
" ___vital___
|
||||
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
|
||||
" Do not modify the code nor insert new lines before '" ___vital___'
|
||||
function! s:_SID() abort
|
||||
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||||
endfunction
|
||||
execute join(['function! vital#_vsnip#VS#LSP#Diff#import() abort', printf("return map({'try_enable_lua': '', 'compute': ''}, \"vital#_vsnip#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||||
delfunction s:_SID
|
||||
" ___vital___
|
||||
"
|
||||
" compute
|
||||
"
|
||||
function! s:compute(old, new) abort
|
||||
let l:old = a:old
|
||||
let l:new = a:new
|
||||
|
||||
let l:old_len = len(l:old)
|
||||
let l:new_len = len(l:new)
|
||||
let l:min_len = min([l:old_len, l:new_len])
|
||||
|
||||
" empty -> empty
|
||||
if l:old_len == 0 && l:new_len == 0
|
||||
return {
|
||||
\ 'range': {
|
||||
\ 'start': {
|
||||
\ 'line': 0,
|
||||
\ 'character': 0,
|
||||
\ },
|
||||
\ 'end': {
|
||||
\ 'line': 0,
|
||||
\ 'character': 0,
|
||||
\ }
|
||||
\ },
|
||||
\ 'text': '',
|
||||
\ 'rangeLength': 0
|
||||
\ }
|
||||
" not empty -> empty
|
||||
elseif l:old_len != 0 && l:new_len == 0
|
||||
return {
|
||||
\ 'range': {
|
||||
\ 'start': {
|
||||
\ 'line': 0,
|
||||
\ 'character': 0,
|
||||
\ },
|
||||
\ 'end': {
|
||||
\ 'line': l:old_len - 1,
|
||||
\ 'character': strchars(l:old[-1]),
|
||||
\ }
|
||||
\ },
|
||||
\ 'text': '',
|
||||
\ 'rangeLength': strchars(join(l:old, "\n"))
|
||||
\ }
|
||||
" empty -> not empty
|
||||
elseif l:old_len == 0 && l:new_len != 0
|
||||
return {
|
||||
\ 'range': {
|
||||
\ 'start': {
|
||||
\ 'line': 0,
|
||||
\ 'character': 0,
|
||||
\ },
|
||||
\ 'end': {
|
||||
\ 'line': 0,
|
||||
\ 'character': 0,
|
||||
\ }
|
||||
\ },
|
||||
\ 'text': join(l:new, "\n"),
|
||||
\ 'rangeLength': 0
|
||||
\ }
|
||||
endif
|
||||
|
||||
if s:is_lua_enabled
|
||||
let [l:first_line, l:last_line] = luaeval('vital_vs_lsp_diff_search_line_region(_A[1], _A[2])', [l:old, l:new])
|
||||
else
|
||||
let l:first_line = 0
|
||||
while l:first_line < l:min_len - 1
|
||||
if l:old[l:first_line] !=# l:new[l:first_line]
|
||||
break
|
||||
endif
|
||||
let l:first_line += 1
|
||||
endwhile
|
||||
|
||||
let l:last_line = -1
|
||||
while l:last_line > -l:min_len + l:first_line
|
||||
if l:old[l:last_line] !=# l:new[l:last_line]
|
||||
break
|
||||
endif
|
||||
let l:last_line -= 1
|
||||
endwhile
|
||||
endif
|
||||
|
||||
let l:old_lines = l:old[l:first_line : l:last_line]
|
||||
let l:new_lines = l:new[l:first_line : l:last_line]
|
||||
let l:old_text = join(l:old_lines, "\n") . "\n"
|
||||
let l:new_text = join(l:new_lines, "\n") . "\n"
|
||||
let l:old_text_len = strchars(l:old_text)
|
||||
let l:new_text_len = strchars(l:new_text)
|
||||
let l:min_text_len = min([l:old_text_len, l:new_text_len])
|
||||
|
||||
let l:first_char = 0
|
||||
for l:first_char in range(0, l:min_text_len - 1)
|
||||
if strgetchar(l:old_text, l:first_char) != strgetchar(l:new_text, l:first_char)
|
||||
break
|
||||
endif
|
||||
endfor
|
||||
|
||||
let l:last_char = 0
|
||||
for l:last_char in range(0, -l:min_text_len + l:first_char, -1)
|
||||
if strgetchar(l:old_text, l:old_text_len + l:last_char - 1) != strgetchar(l:new_text, l:new_text_len + l:last_char - 1)
|
||||
break
|
||||
endif
|
||||
endfor
|
||||
|
||||
return {
|
||||
\ 'range': {
|
||||
\ 'start': {
|
||||
\ 'line': l:first_line,
|
||||
\ 'character': l:first_char,
|
||||
\ },
|
||||
\ 'end': {
|
||||
\ 'line': l:old_len + l:last_line,
|
||||
\ 'character': strchars(l:old_lines[-1]) + l:last_char + 1,
|
||||
\ }
|
||||
\ },
|
||||
\ 'text': strcharpart(l:new_text, l:first_char, l:new_text_len + l:last_char - l:first_char),
|
||||
\ 'rangeLength': l:old_text_len + l:last_char - l:first_char
|
||||
\ }
|
||||
endfunction
|
||||
|
||||
function! s:try_enable_lua() abort
|
||||
lua <<EOF
|
||||
function vital_vs_lsp_diff_search_line_region(old, new)
|
||||
local old_len = #old
|
||||
local new_len = #new
|
||||
local min_len = math.min(#old, #new)
|
||||
|
||||
local first_line = 0
|
||||
while first_line < min_len - 1 do
|
||||
if old[first_line + 1] ~= new[first_line + 1] then
|
||||
break
|
||||
end
|
||||
first_line = first_line + 1
|
||||
end
|
||||
|
||||
local last_line = -1
|
||||
while last_line > -min_len + first_line do
|
||||
if old[(old_len + last_line) + 1] ~= new[(new_len + last_line) + 1] then
|
||||
break
|
||||
end
|
||||
last_line = last_line - 1
|
||||
end
|
||||
return { first_line, last_line }
|
||||
end
|
||||
EOF
|
||||
endfunction
|
||||
|
||||
let s:is_lua_enabled = v:false
|
||||
if has('nvim')
|
||||
try
|
||||
call s:try_enable_lua()
|
||||
let s:is_lua_enabled = v:true
|
||||
catch /.*/
|
||||
endtry
|
||||
endif
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
" ___vital___
|
||||
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
|
||||
" Do not modify the code nor insert new lines before '" ___vital___'
|
||||
function! s:_SID() abort
|
||||
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||||
endfunction
|
||||
execute join(['function! vital#_vsnip#VS#LSP#Position#import() abort', printf("return map({'cursor': '', 'vim_to_lsp': '', 'lsp_to_vim': ''}, \"vital#_vsnip#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||||
delfunction s:_SID
|
||||
" ___vital___
|
||||
"
|
||||
" cursor
|
||||
"
|
||||
function! s:cursor() abort
|
||||
return s:vim_to_lsp('%', getpos('.')[1 : 3])
|
||||
endfunction
|
||||
|
||||
"
|
||||
" vim_to_lsp
|
||||
"
|
||||
function! s:vim_to_lsp(expr, pos) abort
|
||||
let l:line = s:_get_buffer_line(a:expr, a:pos[0])
|
||||
if l:line is v:null
|
||||
return {
|
||||
\ 'line': a:pos[0] - 1,
|
||||
\ 'character': a:pos[1] - 1
|
||||
\ }
|
||||
endif
|
||||
|
||||
return {
|
||||
\ 'line': a:pos[0] - 1,
|
||||
\ 'character': strchars(strpart(l:line, 0, a:pos[1] - 1))
|
||||
\ }
|
||||
endfunction
|
||||
|
||||
"
|
||||
" lsp_to_vim
|
||||
"
|
||||
function! s:lsp_to_vim(expr, position) abort
|
||||
let l:line = s:_get_buffer_line(a:expr, a:position.line + 1)
|
||||
if l:line is v:null
|
||||
return [a:position.line + 1, a:position.character + 1]
|
||||
endif
|
||||
return [a:position.line + 1, byteidx(l:line, a:position.character) + 1]
|
||||
endfunction
|
||||
|
||||
"
|
||||
" _get_buffer_line
|
||||
"
|
||||
function! s:_get_buffer_line(expr, lnum) abort
|
||||
try
|
||||
let l:expr = bufnr(a:expr)
|
||||
catch /.*/
|
||||
let l:expr = a:expr
|
||||
endtry
|
||||
if bufloaded(l:expr)
|
||||
return get(getbufline(l:expr, a:lnum), 0, v:null)
|
||||
elseif filereadable(a:expr)
|
||||
return get(readfile(a:expr, '', a:lnum), 0, v:null)
|
||||
endif
|
||||
return v:null
|
||||
endfunction
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
" ___vital___
|
||||
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
|
||||
" Do not modify the code nor insert new lines before '" ___vital___'
|
||||
function! s:_SID() abort
|
||||
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||||
endfunction
|
||||
execute join(['function! vital#_vsnip#VS#LSP#Text#import() abort', printf("return map({'normalize_eol': '', 'split_by_eol': ''}, \"vital#_vsnip#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||||
delfunction s:_SID
|
||||
" ___vital___
|
||||
"
|
||||
" normalize_eol
|
||||
"
|
||||
function! s:normalize_eol(text) abort
|
||||
return substitute(a:text, "\r\n\\|\r", "\n", 'g')
|
||||
endfunction
|
||||
|
||||
"
|
||||
" split_by_eol
|
||||
"
|
||||
function! s:split_by_eol(text) abort
|
||||
return split(a:text, "\r\n\\|\r\\|\n", v:true)
|
||||
endfunction
|
||||
|
||||
@@ -0,0 +1,185 @@
|
||||
" ___vital___
|
||||
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
|
||||
" Do not modify the code nor insert new lines before '" ___vital___'
|
||||
function! s:_SID() abort
|
||||
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||||
endfunction
|
||||
execute join(['function! vital#_vsnip#VS#LSP#TextEdit#import() abort', printf("return map({'_vital_depends': '', 'apply': '', '_vital_loaded': ''}, \"vital#_vsnip#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||||
delfunction s:_SID
|
||||
" ___vital___
|
||||
"
|
||||
" _vital_loaded
|
||||
"
|
||||
function! s:_vital_loaded(V) abort
|
||||
let s:Text = a:V.import('VS.LSP.Text')
|
||||
let s:Position = a:V.import('VS.LSP.Position')
|
||||
let s:Buffer = a:V.import('VS.Vim.Buffer')
|
||||
let s:Option = a:V.import('VS.Vim.Option')
|
||||
endfunction
|
||||
|
||||
"
|
||||
" _vital_depends
|
||||
"
|
||||
function! s:_vital_depends() abort
|
||||
return ['VS.LSP.Text', 'VS.LSP.Position', 'VS.Vim.Buffer', 'VS.Vim.Option']
|
||||
endfunction
|
||||
|
||||
"
|
||||
" apply
|
||||
"
|
||||
function! s:apply(path, text_edits) abort
|
||||
let l:current_bufname = bufname('%')
|
||||
let l:current_position = s:Position.cursor()
|
||||
|
||||
let l:target_bufnr = s:_switch(a:path)
|
||||
call s:_substitute(l:target_bufnr, a:text_edits, l:current_position)
|
||||
let l:current_bufnr = s:_switch(l:current_bufname)
|
||||
|
||||
if l:current_bufnr == l:target_bufnr
|
||||
call cursor(s:Position.lsp_to_vim('%', l:current_position))
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"
|
||||
" _substitute
|
||||
"
|
||||
function! s:_substitute(bufnr, text_edits, current_position) abort
|
||||
try
|
||||
" Save state.
|
||||
let l:Restore = s:Option.define({
|
||||
\ 'foldenable': '0',
|
||||
\ })
|
||||
let l:view = winsaveview()
|
||||
|
||||
" Apply substitute.
|
||||
let [l:fixeol, l:text_edits] = s:_normalize(a:bufnr, a:text_edits)
|
||||
for l:text_edit in l:text_edits
|
||||
let l:start = s:Position.lsp_to_vim(a:bufnr, l:text_edit.range.start)
|
||||
let l:end = s:Position.lsp_to_vim(a:bufnr, l:text_edit.range.end)
|
||||
let l:text = s:Text.normalize_eol(l:text_edit.newText)
|
||||
execute printf('noautocmd keeppatterns keepjumps silent %ssubstitute/\%%%sl\%%%sc\_.\{-}\%%%sl\%%%sc/\=l:text/%se',
|
||||
\ l:start[0],
|
||||
\ l:start[0],
|
||||
\ l:start[1],
|
||||
\ l:end[0],
|
||||
\ l:end[1],
|
||||
\ &gdefault ? 'g' : ''
|
||||
\ )
|
||||
call s:_fix_cursor_position(a:current_position, l:text_edit, s:Text.split_by_eol(l:text))
|
||||
endfor
|
||||
|
||||
" Remove last empty line if fixeol enabled.
|
||||
if l:fixeol && getline('$') ==# ''
|
||||
noautocmd keeppatterns keepjumps silent $delete _
|
||||
endif
|
||||
catch /.*/
|
||||
echomsg string({ 'exception': v:exception, 'throwpoint': v:throwpoint })
|
||||
finally
|
||||
" Restore state.
|
||||
call l:Restore()
|
||||
call winrestview(l:view)
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
"
|
||||
" _fix_cursor_position
|
||||
"
|
||||
function! s:_fix_cursor_position(position, text_edit, lines) abort
|
||||
let l:lines_len = len(a:lines)
|
||||
let l:range_len = (a:text_edit.range.end.line - a:text_edit.range.start.line) + 1
|
||||
|
||||
if a:text_edit.range.end.line < a:position.line
|
||||
let a:position.line += l:lines_len - l:range_len
|
||||
elseif a:text_edit.range.end.line == a:position.line && a:text_edit.range.end.character <= a:position.character
|
||||
let a:position.line += l:lines_len - l:range_len
|
||||
let a:position.character = strchars(a:lines[-1]) + (a:position.character - a:text_edit.range.end.character)
|
||||
if l:lines_len == 1
|
||||
let a:position.character += a:text_edit.range.start.character
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"
|
||||
" _normalize
|
||||
"
|
||||
function! s:_normalize(bufnr, text_edits) abort
|
||||
let l:text_edits = type(a:text_edits) == type([]) ? a:text_edits : [a:text_edits]
|
||||
let l:text_edits = s:_range(l:text_edits)
|
||||
let l:text_edits = sort(l:text_edits, function('s:_compare'))
|
||||
let l:text_edits = reverse(l:text_edits)
|
||||
return s:_fix_text_edits(a:bufnr, l:text_edits)
|
||||
endfunction
|
||||
|
||||
"
|
||||
" _range
|
||||
"
|
||||
function! s:_range(text_edits) abort
|
||||
let l:text_edits = []
|
||||
for l:text_edit in a:text_edits
|
||||
if type(l:text_edit) != type({})
|
||||
continue
|
||||
endif
|
||||
if l:text_edit.range.start.line > l:text_edit.range.end.line || (
|
||||
\ l:text_edit.range.start.line == l:text_edit.range.end.line &&
|
||||
\ l:text_edit.range.start.character > l:text_edit.range.end.character
|
||||
\ )
|
||||
let l:text_edit.range = { 'start': l:text_edit.range.end, 'end': l:text_edit.range.start }
|
||||
endif
|
||||
let l:text_edits += [l:text_edit]
|
||||
endfor
|
||||
return l:text_edits
|
||||
endfunction
|
||||
|
||||
"
|
||||
" _compare
|
||||
"
|
||||
function! s:_compare(text_edit1, text_edit2) abort
|
||||
let l:diff = a:text_edit1.range.start.line - a:text_edit2.range.start.line
|
||||
if l:diff == 0
|
||||
return a:text_edit1.range.start.character - a:text_edit2.range.start.character
|
||||
endif
|
||||
return l:diff
|
||||
endfunction
|
||||
|
||||
"
|
||||
" _fix_text_edits
|
||||
"
|
||||
function! s:_fix_text_edits(bufnr, text_edits) abort
|
||||
let l:max = s:Buffer.get_line_count(a:bufnr)
|
||||
|
||||
let l:fixeol = v:false
|
||||
let l:text_edits = []
|
||||
for l:text_edit in a:text_edits
|
||||
if l:max <= l:text_edit.range.start.line
|
||||
let l:text_edit.range.start.line = l:max - 1
|
||||
let l:text_edit.range.start.character = strchars(get(getbufline(a:bufnr, '$'), 0, ''))
|
||||
let l:text_edit.newText = "\n" . l:text_edit.newText
|
||||
let l:fixeol = &fixendofline && !&binary
|
||||
endif
|
||||
if l:max <= l:text_edit.range.end.line
|
||||
let l:text_edit.range.end.line = l:max - 1
|
||||
let l:text_edit.range.end.character = strchars(get(getbufline(a:bufnr, '$'), 0, ''))
|
||||
let l:fixeol = &fixendofline && !&binary
|
||||
endif
|
||||
call add(l:text_edits, l:text_edit)
|
||||
endfor
|
||||
|
||||
return [l:fixeol, l:text_edits]
|
||||
endfunction
|
||||
|
||||
"
|
||||
" _switch
|
||||
"
|
||||
function! s:_switch(path) abort
|
||||
let l:curr = bufnr('%')
|
||||
let l:next = bufnr(a:path)
|
||||
if l:next >= 0
|
||||
if l:curr != l:next
|
||||
execute printf('noautocmd keepalt keepjumps %sbuffer!', bufnr(a:path))
|
||||
endif
|
||||
else
|
||||
execute printf('noautocmd keepalt keepjumps edit! %s', fnameescape(a:path))
|
||||
endif
|
||||
return bufnr('%')
|
||||
endfunction
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
" ___vital___
|
||||
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
|
||||
" Do not modify the code nor insert new lines before '" ___vital___'
|
||||
function! s:_SID() abort
|
||||
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||||
endfunction
|
||||
execute join(['function! vital#_vsnip#VS#Vim#Buffer#import() abort', printf("return map({'get_line_count': '', 'do': '', 'create': '', 'pseudo': '', 'ensure': '', 'load': ''}, \"vital#_vsnip#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||||
delfunction s:_SID
|
||||
" ___vital___
|
||||
let s:Do = { -> {} }
|
||||
|
||||
let g:___VS_Vim_Buffer_id = get(g:, '___VS_Vim_Buffer_id', 0)
|
||||
|
||||
"
|
||||
" get_line_count
|
||||
"
|
||||
if exists('*nvim_buf_line_count')
|
||||
function! s:get_line_count(bufnr) abort
|
||||
return nvim_buf_line_count(a:bufnr)
|
||||
endfunction
|
||||
elseif has('patch-8.2.0019')
|
||||
function! s:get_line_count(bufnr) abort
|
||||
return getbufinfo(a:bufnr)[0].linecount
|
||||
endfunction
|
||||
else
|
||||
function! s:get_line_count(bufnr) abort
|
||||
if bufnr('%') == bufnr(a:bufnr)
|
||||
return line('$')
|
||||
endif
|
||||
return len(getbufline(a:bufnr, '^', '$'))
|
||||
endfunction
|
||||
endif
|
||||
|
||||
"
|
||||
" create
|
||||
"
|
||||
function! s:create(...) abort
|
||||
let g:___VS_Vim_Buffer_id += 1
|
||||
let l:bufname = printf('VS.Vim.Buffer: %s: %s',
|
||||
\ g:___VS_Vim_Buffer_id,
|
||||
\ get(a:000, 0, 'VS.Vim.Buffer.Default')
|
||||
\ )
|
||||
return s:load(l:bufname)
|
||||
endfunction
|
||||
|
||||
"
|
||||
" ensure
|
||||
"
|
||||
function! s:ensure(expr) abort
|
||||
if !bufexists(a:expr)
|
||||
if type(a:expr) == type(0)
|
||||
throw printf('VS.Vim.Buffer: `%s` is not valid expr.', a:expr)
|
||||
endif
|
||||
badd `=a:expr`
|
||||
endif
|
||||
return bufnr(a:expr)
|
||||
endfunction
|
||||
|
||||
"
|
||||
" load
|
||||
"
|
||||
if exists('*bufload')
|
||||
function! s:load(expr) abort
|
||||
let l:bufnr = s:ensure(a:expr)
|
||||
if !bufloaded(l:bufnr)
|
||||
call bufload(l:bufnr)
|
||||
endif
|
||||
return l:bufnr
|
||||
endfunction
|
||||
else
|
||||
function! s:load(expr) abort
|
||||
let l:curr_bufnr = bufnr('%')
|
||||
try
|
||||
let l:bufnr = s:ensure(a:expr)
|
||||
execute printf('keepalt keepjumps silent %sbuffer', l:bufnr)
|
||||
catch /.*/
|
||||
echomsg string({ 'exception': v:exception, 'throwpoint': v:throwpoint })
|
||||
finally
|
||||
execute printf('noautocmd keepalt keepjumps silent %sbuffer', l:curr_bufnr)
|
||||
endtry
|
||||
return l:bufnr
|
||||
endfunction
|
||||
endif
|
||||
|
||||
"
|
||||
" do
|
||||
"
|
||||
function! s:do(bufnr, func) abort
|
||||
let l:curr_bufnr = bufnr('%')
|
||||
if l:curr_bufnr == a:bufnr
|
||||
call a:func()
|
||||
return
|
||||
endif
|
||||
|
||||
try
|
||||
execute printf('noautocmd keepalt keepjumps silent %sbuffer', a:bufnr)
|
||||
call a:func()
|
||||
catch /.*/
|
||||
echomsg string({ 'exception': v:exception, 'throwpoint': v:throwpoint })
|
||||
finally
|
||||
execute printf('noautocmd keepalt keepjumps silent %sbuffer', l:curr_bufnr)
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
"
|
||||
" pseudo
|
||||
"
|
||||
function! s:pseudo(filepath) abort
|
||||
if !filereadable(a:filepath)
|
||||
throw printf('VS.Vim.Buffer: `%s` is not valid filepath.', a:filepath)
|
||||
endif
|
||||
|
||||
" create pseudo buffer
|
||||
let l:bufname = printf('VSVimBufferPseudo://%s', a:filepath)
|
||||
if bufexists(l:bufname)
|
||||
return s:ensure(l:bufname)
|
||||
endif
|
||||
|
||||
let l:bufnr = s:ensure(l:bufname)
|
||||
let l:group = printf('VS_Vim_Buffer_pseudo:%s', l:bufnr)
|
||||
execute printf('augroup %s', l:group)
|
||||
execute printf('autocmd BufReadCmd <buffer=%s> call setline(1, readfile(bufname("%")[20 : -1])) | try | filetype detect | catch /.*/ | endtry | augroup %s | autocmd! | augroup END', l:bufnr, l:group)
|
||||
augroup END
|
||||
return l:bufnr
|
||||
endfunction
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
" ___vital___
|
||||
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
|
||||
" Do not modify the code nor insert new lines before '" ___vital___'
|
||||
function! s:_SID() abort
|
||||
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||||
endfunction
|
||||
execute join(['function! vital#_vsnip#VS#Vim#Option#import() abort', printf("return map({'define': ''}, \"vital#_vsnip#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||||
delfunction s:_SID
|
||||
" ___vital___
|
||||
"
|
||||
" define
|
||||
"
|
||||
function! s:define(map) abort
|
||||
let l:old = {}
|
||||
for [l:key, l:value] in items(a:map)
|
||||
let l:old[l:key] = eval(printf('&%s', l:key))
|
||||
execute printf('let &%s = "%s"', l:key, l:value)
|
||||
endfor
|
||||
return { -> s:define(l:old) }
|
||||
endfunction
|
||||
|
||||
330
dot_vim/plugged/vim-vsnip/autoload/vital/vsnip.vim
Normal file
330
dot_vim/plugged/vim-vsnip/autoload/vital/vsnip.vim
Normal file
@@ -0,0 +1,330 @@
|
||||
let s:plugin_name = expand('<sfile>:t:r')
|
||||
let s:vital_base_dir = expand('<sfile>:h')
|
||||
let s:project_root = expand('<sfile>:h:h:h')
|
||||
let s:is_vital_vim = s:plugin_name is# 'vital'
|
||||
|
||||
let s:loaded = {}
|
||||
let s:cache_sid = {}
|
||||
|
||||
function! vital#{s:plugin_name}#new() abort
|
||||
return s:new(s:plugin_name)
|
||||
endfunction
|
||||
|
||||
function! vital#{s:plugin_name}#import(...) abort
|
||||
if !exists('s:V')
|
||||
let s:V = s:new(s:plugin_name)
|
||||
endif
|
||||
return call(s:V.import, a:000, s:V)
|
||||
endfunction
|
||||
|
||||
let s:Vital = {}
|
||||
|
||||
function! s:new(plugin_name) abort
|
||||
let base = deepcopy(s:Vital)
|
||||
let base._plugin_name = a:plugin_name
|
||||
return base
|
||||
endfunction
|
||||
|
||||
function! s:vital_files() abort
|
||||
if !exists('s:vital_files')
|
||||
let s:vital_files = map(
|
||||
\ s:is_vital_vim ? s:_global_vital_files() : s:_self_vital_files(),
|
||||
\ 'fnamemodify(v:val, ":p:gs?[\\\\/]?/?")')
|
||||
endif
|
||||
return copy(s:vital_files)
|
||||
endfunction
|
||||
let s:Vital.vital_files = function('s:vital_files')
|
||||
|
||||
function! s:import(name, ...) abort dict
|
||||
let target = {}
|
||||
let functions = []
|
||||
for a in a:000
|
||||
if type(a) == type({})
|
||||
let target = a
|
||||
elseif type(a) == type([])
|
||||
let functions = a
|
||||
endif
|
||||
unlet a
|
||||
endfor
|
||||
let module = self._import(a:name)
|
||||
if empty(functions)
|
||||
call extend(target, module, 'keep')
|
||||
else
|
||||
for f in functions
|
||||
if has_key(module, f) && !has_key(target, f)
|
||||
let target[f] = module[f]
|
||||
endif
|
||||
endfor
|
||||
endif
|
||||
return target
|
||||
endfunction
|
||||
let s:Vital.import = function('s:import')
|
||||
|
||||
function! s:load(...) abort dict
|
||||
for arg in a:000
|
||||
let [name; as] = type(arg) == type([]) ? arg[: 1] : [arg, arg]
|
||||
let target = split(join(as, ''), '\W\+')
|
||||
let dict = self
|
||||
let dict_type = type({})
|
||||
while !empty(target)
|
||||
let ns = remove(target, 0)
|
||||
if !has_key(dict, ns)
|
||||
let dict[ns] = {}
|
||||
endif
|
||||
if type(dict[ns]) == dict_type
|
||||
let dict = dict[ns]
|
||||
else
|
||||
unlet dict
|
||||
break
|
||||
endif
|
||||
endwhile
|
||||
if exists('dict')
|
||||
call extend(dict, self._import(name))
|
||||
endif
|
||||
unlet arg
|
||||
endfor
|
||||
return self
|
||||
endfunction
|
||||
let s:Vital.load = function('s:load')
|
||||
|
||||
function! s:unload() abort dict
|
||||
let s:loaded = {}
|
||||
let s:cache_sid = {}
|
||||
unlet! s:vital_files
|
||||
endfunction
|
||||
let s:Vital.unload = function('s:unload')
|
||||
|
||||
function! s:exists(name) abort dict
|
||||
if a:name !~# '\v^\u\w*%(\.\u\w*)*$'
|
||||
throw 'vital: Invalid module name: ' . a:name
|
||||
endif
|
||||
return s:_module_path(a:name) isnot# ''
|
||||
endfunction
|
||||
let s:Vital.exists = function('s:exists')
|
||||
|
||||
function! s:search(pattern) abort dict
|
||||
let paths = s:_extract_files(a:pattern, self.vital_files())
|
||||
let modules = sort(map(paths, 's:_file2module(v:val)'))
|
||||
return uniq(modules)
|
||||
endfunction
|
||||
let s:Vital.search = function('s:search')
|
||||
|
||||
function! s:plugin_name() abort dict
|
||||
return self._plugin_name
|
||||
endfunction
|
||||
let s:Vital.plugin_name = function('s:plugin_name')
|
||||
|
||||
function! s:_self_vital_files() abort
|
||||
let builtin = printf('%s/__%s__/', s:vital_base_dir, s:plugin_name)
|
||||
let installed = printf('%s/_%s/', s:vital_base_dir, s:plugin_name)
|
||||
let base = builtin . ',' . installed
|
||||
return split(globpath(base, '**/*.vim', 1), "\n")
|
||||
endfunction
|
||||
|
||||
function! s:_global_vital_files() abort
|
||||
let pattern = 'autoload/vital/__*__/**/*.vim'
|
||||
return split(globpath(&runtimepath, pattern, 1), "\n")
|
||||
endfunction
|
||||
|
||||
function! s:_extract_files(pattern, files) abort
|
||||
let tr = {'.': '/', '*': '[^/]*', '**': '.*'}
|
||||
let target = substitute(a:pattern, '\.\|\*\*\?', '\=tr[submatch(0)]', 'g')
|
||||
let regexp = printf('autoload/vital/[^/]\+/%s.vim$', target)
|
||||
return filter(a:files, 'v:val =~# regexp')
|
||||
endfunction
|
||||
|
||||
function! s:_file2module(file) abort
|
||||
let filename = fnamemodify(a:file, ':p:gs?[\\/]?/?')
|
||||
let tail = matchstr(filename, 'autoload/vital/_\w\+/\zs.*\ze\.vim$')
|
||||
return join(split(tail, '[\\/]\+'), '.')
|
||||
endfunction
|
||||
|
||||
" @param {string} name e.g. Data.List
|
||||
function! s:_import(name) abort dict
|
||||
if has_key(s:loaded, a:name)
|
||||
return copy(s:loaded[a:name])
|
||||
endif
|
||||
let module = self._get_module(a:name)
|
||||
if has_key(module, '_vital_created')
|
||||
call module._vital_created(module)
|
||||
endif
|
||||
let export_module = filter(copy(module), 'v:key =~# "^\\a"')
|
||||
" Cache module before calling module._vital_loaded() to avoid cyclic
|
||||
" dependences but remove the cache if module._vital_loaded() fails.
|
||||
" let s:loaded[a:name] = export_module
|
||||
let s:loaded[a:name] = export_module
|
||||
if has_key(module, '_vital_loaded')
|
||||
try
|
||||
call module._vital_loaded(vital#{s:plugin_name}#new())
|
||||
catch
|
||||
unlet s:loaded[a:name]
|
||||
throw 'vital: fail to call ._vital_loaded(): ' . v:exception . " from:\n" . s:_format_throwpoint(v:throwpoint)
|
||||
endtry
|
||||
endif
|
||||
return copy(s:loaded[a:name])
|
||||
endfunction
|
||||
let s:Vital._import = function('s:_import')
|
||||
|
||||
function! s:_format_throwpoint(throwpoint) abort
|
||||
let funcs = []
|
||||
let stack = matchstr(a:throwpoint, '^function \zs.*, .\{-} \d\+$')
|
||||
for line in split(stack, '\.\.')
|
||||
let m = matchlist(line, '^\(.\+\)\%(\[\(\d\+\)\]\|, .\{-} \(\d\+\)\)$')
|
||||
if !empty(m)
|
||||
let [name, lnum, lnum2] = m[1:3]
|
||||
if empty(lnum)
|
||||
let lnum = lnum2
|
||||
endif
|
||||
let info = s:_get_func_info(name)
|
||||
if !empty(info)
|
||||
let attrs = empty(info.attrs) ? '' : join([''] + info.attrs)
|
||||
let flnum = info.lnum == 0 ? '' : printf(' Line:%d', info.lnum + lnum)
|
||||
call add(funcs, printf('function %s(...)%s Line:%d (%s%s)',
|
||||
\ info.funcname, attrs, lnum, info.filename, flnum))
|
||||
continue
|
||||
endif
|
||||
endif
|
||||
" fallback when function information cannot be detected
|
||||
call add(funcs, line)
|
||||
endfor
|
||||
return join(funcs, "\n")
|
||||
endfunction
|
||||
|
||||
function! s:_get_func_info(name) abort
|
||||
let name = a:name
|
||||
if a:name =~# '^\d\+$' " is anonymous-function
|
||||
let name = printf('{%s}', a:name)
|
||||
elseif a:name =~# '^<lambda>\d\+$' " is lambda-function
|
||||
let name = printf("{'%s'}", a:name)
|
||||
endif
|
||||
if !exists('*' . name)
|
||||
return {}
|
||||
endif
|
||||
let body = execute(printf('verbose function %s', name))
|
||||
let lines = split(body, "\n")
|
||||
let signature = matchstr(lines[0], '^\s*\zs.*')
|
||||
let [_, file, lnum; __] = matchlist(lines[1],
|
||||
\ '^\t\%(Last set from\|.\{-}:\)\s*\zs\(.\{-}\)\%( \S\+ \(\d\+\)\)\?$')
|
||||
return {
|
||||
\ 'filename': substitute(file, '[/\\]\+', '/', 'g'),
|
||||
\ 'lnum': 0 + lnum,
|
||||
\ 'funcname': a:name,
|
||||
\ 'arguments': split(matchstr(signature, '(\zs.*\ze)'), '\s*,\s*'),
|
||||
\ 'attrs': filter(['dict', 'abort', 'range', 'closure'], 'signature =~# (").*" . v:val)'),
|
||||
\ }
|
||||
endfunction
|
||||
|
||||
" s:_get_module() returns module object wihch has all script local functions.
|
||||
function! s:_get_module(name) abort dict
|
||||
let funcname = s:_import_func_name(self.plugin_name(), a:name)
|
||||
try
|
||||
return call(funcname, [])
|
||||
catch /^Vim\%((\a\+)\)\?:E117:/
|
||||
return s:_get_builtin_module(a:name)
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
function! s:_get_builtin_module(name) abort
|
||||
return s:sid2sfuncs(s:_module_sid(a:name))
|
||||
endfunction
|
||||
|
||||
if s:is_vital_vim
|
||||
" For vital.vim, we can use s:_get_builtin_module directly
|
||||
let s:Vital._get_module = function('s:_get_builtin_module')
|
||||
else
|
||||
let s:Vital._get_module = function('s:_get_module')
|
||||
endif
|
||||
|
||||
function! s:_import_func_name(plugin_name, module_name) abort
|
||||
return printf('vital#_%s#%s#import', a:plugin_name, s:_dot_to_sharp(a:module_name))
|
||||
endfunction
|
||||
|
||||
function! s:_module_sid(name) abort
|
||||
let path = s:_module_path(a:name)
|
||||
if !filereadable(path)
|
||||
throw 'vital: module not found: ' . a:name
|
||||
endif
|
||||
let vital_dir = s:is_vital_vim ? '__\w\+__' : printf('_\{1,2}%s\%%(__\)\?', s:plugin_name)
|
||||
let base = join([vital_dir, ''], '[/\\]\+')
|
||||
let p = base . substitute('' . a:name, '\.', '[/\\\\]\\+', 'g')
|
||||
let sid = s:_sid(path, p)
|
||||
if !sid
|
||||
call s:_source(path)
|
||||
let sid = s:_sid(path, p)
|
||||
if !sid
|
||||
throw printf('vital: cannot get <SID> from path: %s', path)
|
||||
endif
|
||||
endif
|
||||
return sid
|
||||
endfunction
|
||||
|
||||
function! s:_module_path(name) abort
|
||||
return get(s:_extract_files(a:name, s:vital_files()), 0, '')
|
||||
endfunction
|
||||
|
||||
function! s:_module_sid_base_dir() abort
|
||||
return s:is_vital_vim ? &rtp : s:project_root
|
||||
endfunction
|
||||
|
||||
function! s:_dot_to_sharp(name) abort
|
||||
return substitute(a:name, '\.', '#', 'g')
|
||||
endfunction
|
||||
|
||||
function! s:_source(path) abort
|
||||
execute 'source' fnameescape(a:path)
|
||||
endfunction
|
||||
|
||||
" @vimlint(EVL102, 1, l:_)
|
||||
" @vimlint(EVL102, 1, l:__)
|
||||
function! s:_sid(path, filter_pattern) abort
|
||||
let unified_path = s:_unify_path(a:path)
|
||||
if has_key(s:cache_sid, unified_path)
|
||||
return s:cache_sid[unified_path]
|
||||
endif
|
||||
for line in filter(split(execute(':scriptnames'), "\n"), 'v:val =~# a:filter_pattern')
|
||||
let [_, sid, path; __] = matchlist(line, '^\s*\(\d\+\):\s\+\(.\+\)\s*$')
|
||||
if s:_unify_path(path) is# unified_path
|
||||
let s:cache_sid[unified_path] = sid
|
||||
return s:cache_sid[unified_path]
|
||||
endif
|
||||
endfor
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
if filereadable(expand('<sfile>:r') . '.VIM') " is case-insensitive or not
|
||||
let s:_unify_path_cache = {}
|
||||
" resolve() is slow, so we cache results.
|
||||
" Note: On windows, vim can't expand path names from 8.3 formats.
|
||||
" So if getting full path via <sfile> and $HOME was set as 8.3 format,
|
||||
" vital load duplicated scripts. Below's :~ avoid this issue.
|
||||
function! s:_unify_path(path) abort
|
||||
if has_key(s:_unify_path_cache, a:path)
|
||||
return s:_unify_path_cache[a:path]
|
||||
endif
|
||||
let value = tolower(fnamemodify(resolve(fnamemodify(
|
||||
\ a:path, ':p')), ':~:gs?[\\/]?/?'))
|
||||
let s:_unify_path_cache[a:path] = value
|
||||
return value
|
||||
endfunction
|
||||
else
|
||||
function! s:_unify_path(path) abort
|
||||
return resolve(fnamemodify(a:path, ':p:gs?[\\/]?/?'))
|
||||
endfunction
|
||||
endif
|
||||
|
||||
" copied and modified from Vim.ScriptLocal
|
||||
let s:SNR = join(map(range(len("\<SNR>")), '"[\\x" . printf("%0x", char2nr("\<SNR>"[v:val])) . "]"'), '')
|
||||
function! s:sid2sfuncs(sid) abort
|
||||
let fs = split(execute(printf(':function /^%s%s_', s:SNR, a:sid)), "\n")
|
||||
let r = {}
|
||||
let pattern = printf('\m^function\s<SNR>%d_\zs\w\{-}\ze(', a:sid)
|
||||
for fname in map(fs, 'matchstr(v:val, pattern)')
|
||||
let r[fname] = function(s:_sfuncname(a:sid, fname))
|
||||
endfor
|
||||
return r
|
||||
endfunction
|
||||
|
||||
"" Return funcname of script local functions with SID
|
||||
function! s:_sfuncname(sid, funcname) abort
|
||||
return printf('<SNR>%s_%s', a:sid, a:funcname)
|
||||
endfunction
|
||||
6
dot_vim/plugged/vim-vsnip/autoload/vital/vsnip.vital
Normal file
6
dot_vim/plugged/vim-vsnip/autoload/vital/vsnip.vital
Normal file
@@ -0,0 +1,6 @@
|
||||
vsnip
|
||||
2755f0c8fbd3442bcb7f567832e4d1455b57f9a2
|
||||
|
||||
VS.LSP.TextEdit
|
||||
VS.LSP.Diff
|
||||
VS.LSP.Position
|
||||
243
dot_vim/plugged/vim-vsnip/autoload/vsnip.vim
Normal file
243
dot_vim/plugged/vim-vsnip/autoload/vsnip.vim
Normal file
@@ -0,0 +1,243 @@
|
||||
let s:Session = vsnip#session#import()
|
||||
let s:Snippet = vsnip#snippet#import()
|
||||
let s:TextEdit = vital#vsnip#import('VS.LSP.TextEdit')
|
||||
let s:Position = vital#vsnip#import('VS.LSP.Position')
|
||||
|
||||
let s:session = v:null
|
||||
let s:selected_text = ''
|
||||
|
||||
let g:vsnip#DeactivateOn = {}
|
||||
let g:vsnip#DeactivateOn.OutsideOfSnippet = 1
|
||||
let g:vsnip#DeactivateOn.OutsideOfCurrentTabstop = 2
|
||||
|
||||
"
|
||||
" vsnip#selected_text.
|
||||
"
|
||||
function! vsnip#selected_text(...) abort
|
||||
if len(a:000) == 1
|
||||
let s:selected_text = a:000[0]
|
||||
else
|
||||
return s:selected_text
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"
|
||||
" vsnip#available.
|
||||
"
|
||||
function! vsnip#available(...) abort
|
||||
let l:direction = get(a:000, 0, 1)
|
||||
return vsnip#expandable() || vsnip#jumpable(l:direction)
|
||||
endfunction
|
||||
|
||||
"
|
||||
" vsnip#expandable.
|
||||
"
|
||||
function! vsnip#expandable() abort
|
||||
return !empty(vsnip#get_context())
|
||||
endfunction
|
||||
|
||||
"
|
||||
" vsnip#jumpable.
|
||||
"
|
||||
function! vsnip#jumpable(...) abort
|
||||
let l:direction = get(a:000, 0, 1)
|
||||
return !empty(s:session) && s:session.jumpable(l:direction)
|
||||
endfunction
|
||||
|
||||
"
|
||||
" vsnip#expand
|
||||
"
|
||||
function! vsnip#expand() abort
|
||||
let l:context = vsnip#get_context()
|
||||
if !empty(l:context)
|
||||
call s:TextEdit.apply(bufnr('%'), [{
|
||||
\ 'range': l:context.range,
|
||||
\ 'newText': ''
|
||||
\ }])
|
||||
call vsnip#anonymous(join(l:context.snippet.body, "\n"), {
|
||||
\ 'position': l:context.range.start
|
||||
\ })
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"
|
||||
" vsnip#anonymous.
|
||||
"
|
||||
function! vsnip#anonymous(text, ...) abort
|
||||
let l:option = get(a:000, 0, {})
|
||||
let l:prefix = get(l:option, 'prefix', v:null)
|
||||
let l:position = get(l:option, 'position', s:Position.cursor())
|
||||
|
||||
if l:prefix isnot# v:null
|
||||
let l:position.character -= strchars(l:prefix)
|
||||
call s:TextEdit.apply(bufnr('%'), [{
|
||||
\ 'range': {
|
||||
\ 'start': l:position,
|
||||
\ 'end': {
|
||||
\ 'line': l:position.line,
|
||||
\ 'character': l:position.character + strchars(l:prefix),
|
||||
\ },
|
||||
\ },
|
||||
\ 'newText': ''
|
||||
\ }])
|
||||
endif
|
||||
|
||||
let l:session = s:Session.new(bufnr('%'), l:position, a:text)
|
||||
|
||||
call vsnip#selected_text('')
|
||||
|
||||
if !empty(s:session)
|
||||
call s:session.flush_changes() " try to sync buffer content because vsnip#expand maybe remove prefix
|
||||
endif
|
||||
|
||||
if empty(s:session)
|
||||
let s:session = l:session
|
||||
call s:session.expand()
|
||||
else
|
||||
call s:session.merge(l:session)
|
||||
endif
|
||||
|
||||
doautocmd <nomodeline> User vsnip#expand
|
||||
|
||||
call s:session.refresh()
|
||||
call s:session.jump(1)
|
||||
endfunction
|
||||
|
||||
"
|
||||
" vsnip#get_session
|
||||
"
|
||||
function! vsnip#get_session() abort
|
||||
return s:session
|
||||
endfunction
|
||||
|
||||
"
|
||||
" vsnip#deactivate
|
||||
"
|
||||
function! vsnip#deactivate() abort
|
||||
let s:session = {}
|
||||
endfunction
|
||||
|
||||
"
|
||||
" get_context.
|
||||
"
|
||||
function! vsnip#get_context() abort
|
||||
let l:offset = mode()[0] ==# 'i' ? 2 : 1
|
||||
let l:before_text = getline('.')[0 : col('.') - l:offset]
|
||||
let l:before_text_len = strchars(l:before_text)
|
||||
|
||||
if l:before_text_len == 0
|
||||
return {}
|
||||
endif
|
||||
|
||||
let l:sources = vsnip#source#find(bufnr('%'))
|
||||
|
||||
" Search prefix
|
||||
for l:source in l:sources
|
||||
for l:snippet in l:source
|
||||
for l:prefix in l:snippet.prefix
|
||||
let l:prefix_len = strchars(l:prefix)
|
||||
if strcharpart(l:before_text, l:before_text_len - l:prefix_len, l:prefix_len) !=# l:prefix
|
||||
continue
|
||||
endif
|
||||
if l:prefix =~# '^\h' && l:before_text !~# '\<\V' . escape(l:prefix, '\/?') . '\m$'
|
||||
continue
|
||||
endif
|
||||
return s:create_context(l:snippet, l:before_text_len, l:prefix_len)
|
||||
endfor
|
||||
endfor
|
||||
endfor
|
||||
|
||||
" Search prefix-alias
|
||||
for l:source in l:sources
|
||||
for l:snippet in l:source
|
||||
for l:prefix in l:snippet.prefix_alias
|
||||
let l:prefix_len = strchars(l:prefix)
|
||||
if strcharpart(l:before_text, l:before_text_len - l:prefix_len, l:prefix_len) !=# l:prefix
|
||||
continue
|
||||
endif
|
||||
if l:prefix =~# '^\h' && l:before_text !~# '\<\V' . escape(l:prefix, '\/?') . '\m$'
|
||||
continue
|
||||
endif
|
||||
return s:create_context(l:snippet, l:before_text_len, l:prefix_len)
|
||||
endfor
|
||||
endfor
|
||||
endfor
|
||||
|
||||
return {}
|
||||
endfunction
|
||||
|
||||
"
|
||||
" vsnip#get_complete_items
|
||||
"
|
||||
function! vsnip#get_complete_items(bufnr) abort
|
||||
let l:uniq = {}
|
||||
let l:candidates = []
|
||||
|
||||
for l:source in vsnip#source#find(a:bufnr)
|
||||
for l:snippet in l:source
|
||||
for l:prefix in l:snippet.prefix
|
||||
if has_key(l:uniq, l:prefix)
|
||||
continue
|
||||
endif
|
||||
let l:uniq[l:prefix] = v:true
|
||||
|
||||
let l:menu = ''
|
||||
let l:menu .= '[v]'
|
||||
let l:menu .= ' '
|
||||
let l:menu .= (strlen(l:snippet.description) > 0 ? l:snippet.description : l:snippet.label)
|
||||
|
||||
call add(l:candidates, {
|
||||
\ 'word': l:prefix,
|
||||
\ 'abbr': l:prefix,
|
||||
\ 'kind': 'Snippet',
|
||||
\ 'menu': l:menu,
|
||||
\ 'dup': 1,
|
||||
\ 'user_data': json_encode({
|
||||
\ 'vsnip': {
|
||||
\ 'snippet': l:snippet.body
|
||||
\ }
|
||||
\ })
|
||||
\ })
|
||||
endfor
|
||||
endfor
|
||||
endfor
|
||||
|
||||
return l:candidates
|
||||
endfunction
|
||||
|
||||
"
|
||||
" vsnip#decode
|
||||
"
|
||||
function! vsnip#to_string(text) abort
|
||||
let l:text = type(a:text) == type([]) ? join(a:text, "\n") : a:text
|
||||
return s:Snippet.new(s:Position.cursor(), l:text).text()
|
||||
endfunction
|
||||
|
||||
"
|
||||
" vsnip#debug
|
||||
"
|
||||
function! vsnip#debug() abort
|
||||
if !empty(s:session)
|
||||
call s:session.snippet.debug()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"
|
||||
" create_context
|
||||
"
|
||||
function! s:create_context(snippet, before_text_len, prefix_len) abort
|
||||
let l:line = line('.') - 1
|
||||
return {
|
||||
\ 'range': {
|
||||
\ 'start': {
|
||||
\ 'line': l:line,
|
||||
\ 'character': a:before_text_len - a:prefix_len
|
||||
\ },
|
||||
\ 'end': {
|
||||
\ 'line': l:line,
|
||||
\ 'character': a:before_text_len
|
||||
\ }
|
||||
\ },
|
||||
\ 'snippet': a:snippet
|
||||
\ }
|
||||
endfunction
|
||||
61
dot_vim/plugged/vim-vsnip/autoload/vsnip/indent.vim
Normal file
61
dot_vim/plugged/vim-vsnip/autoload/vsnip/indent.vim
Normal file
@@ -0,0 +1,61 @@
|
||||
"
|
||||
" vsnip#indent#get_one_indent
|
||||
"
|
||||
function! vsnip#indent#get_one_indent() abort
|
||||
return !&expandtab ? "\t" : repeat(' ', &shiftwidth ? &shiftwidth : &tabstop)
|
||||
endfunction
|
||||
|
||||
"
|
||||
" vsnip#indent#get_base_indent
|
||||
"
|
||||
function! vsnip#indent#get_base_indent(text) abort
|
||||
return matchstr(a:text, '^\s*')
|
||||
endfunction
|
||||
|
||||
"
|
||||
" vsnip#indent#adjust_snippet_body
|
||||
"
|
||||
function! vsnip#indent#adjust_snippet_body(line, text) abort
|
||||
let l:one_indent = vsnip#indent#get_one_indent()
|
||||
let l:base_indent = vsnip#indent#get_base_indent(a:line)
|
||||
let l:text = a:text
|
||||
if l:one_indent !=# "\t"
|
||||
while match(l:text, "\\%(^\\|\n\\)\\s*\\zs\\t") != -1
|
||||
let l:text = substitute(l:text, "\\%(^\\|\n\\)\\s*\\zs\\t", l:one_indent, 'g') " convert \t as one indent
|
||||
endwhile
|
||||
endif
|
||||
let l:text = substitute(l:text, "\n\\zs", l:base_indent, 'g') " add base_indent for all lines
|
||||
let l:text = substitute(l:text, "\n\\s*\\ze\n", "\n", 'g') " remove empty line's indent
|
||||
return l:text
|
||||
endfunction
|
||||
|
||||
"
|
||||
" vsnip#indent#trim_base_indent
|
||||
"
|
||||
function! vsnip#indent#trim_base_indent(text) abort
|
||||
let l:is_char_wise = match(a:text, "\n$") == -1
|
||||
let l:text = substitute(a:text, "\n$", '', 'g')
|
||||
|
||||
let l:is_first_line = v:true
|
||||
let l:base_indent = ''
|
||||
for l:line in split(l:text, "\n", v:true)
|
||||
" Ignore the first line when the text created as char-wise.
|
||||
if l:is_char_wise && l:is_first_line
|
||||
let l:is_first_line = v:false
|
||||
continue
|
||||
endif
|
||||
|
||||
" Ignore empty line.
|
||||
if l:line ==# ''
|
||||
continue
|
||||
endif
|
||||
|
||||
" Detect most minimum base indent.
|
||||
let l:indent = matchstr(l:line, '^\s*')
|
||||
if l:base_indent ==# '' || strlen(l:indent) < strlen(l:base_indent)
|
||||
let l:base_indent = l:indent
|
||||
endif
|
||||
endfor
|
||||
return substitute(l:text, "\\%(^\\|\n\\)\\zs\\V" . l:base_indent, '', 'g')
|
||||
endfunction
|
||||
|
||||
223
dot_vim/plugged/vim-vsnip/autoload/vsnip/parser/combinator.vim
Normal file
223
dot_vim/plugged/vim-vsnip/autoload/vsnip/parser/combinator.vim
Normal file
@@ -0,0 +1,223 @@
|
||||
function! vsnip#parser#combinator#import() abort
|
||||
return {
|
||||
\ 'skip': function('s:skip'),
|
||||
\ 'token': function('s:token'),
|
||||
\ 'many': function('s:many'),
|
||||
\ 'or': function('s:or'),
|
||||
\ 'seq': function('s:seq'),
|
||||
\ 'pattern': function('s:pattern'),
|
||||
\ 'lazy': function('s:lazy'),
|
||||
\ 'option': function('s:option'),
|
||||
\ 'map': function('s:map')
|
||||
\ }
|
||||
endfunction
|
||||
|
||||
"
|
||||
" string.
|
||||
"
|
||||
function! s:skip(stop, escape) abort
|
||||
let l:fn = {}
|
||||
let l:fn.stop = a:stop
|
||||
let l:fn.escape = a:escape
|
||||
function! l:fn.parse(text, pos) abort
|
||||
let l:pos = a:pos
|
||||
let l:value = ''
|
||||
|
||||
let l:len = strchars(a:text)
|
||||
while l:pos < l:len
|
||||
let l:char = s:getchar(a:text, l:pos)
|
||||
|
||||
" check escaped stop chars.
|
||||
if l:char ==# '\'
|
||||
let l:pos += 1
|
||||
let l:char = s:getchar(a:text, l:pos)
|
||||
if index(self.stop + self.escape + ['\'], l:char) == -1
|
||||
let l:value .= '\'
|
||||
continue " ignore invalid escape char.
|
||||
endif
|
||||
let l:pos += 1
|
||||
let l:value .= l:char
|
||||
continue
|
||||
endif
|
||||
|
||||
" check stop char.
|
||||
if index(self.stop, l:char) >= 0
|
||||
if a:pos != l:pos
|
||||
return [v:true, [strcharpart(a:text, a:pos, l:pos - a:pos), l:value], l:pos]
|
||||
else
|
||||
return [v:false, v:null, l:pos]
|
||||
endif
|
||||
endif
|
||||
|
||||
let l:value .= l:char
|
||||
let l:pos += 1
|
||||
endwhile
|
||||
|
||||
" everything was string.
|
||||
return [v:true, [strcharpart(a:text, a:pos), l:value], l:len]
|
||||
endfunction
|
||||
return l:fn
|
||||
endfunction
|
||||
|
||||
"
|
||||
" token.
|
||||
"
|
||||
function! s:token(token) abort
|
||||
let l:fn = {}
|
||||
let l:fn.token = a:token
|
||||
function! l:fn.parse(text, pos) abort
|
||||
let l:token_len = strchars(self.token)
|
||||
let l:value = strcharpart(a:text, a:pos, l:token_len)
|
||||
if l:value ==# self.token
|
||||
return [v:true, self.token, a:pos + l:token_len]
|
||||
endif
|
||||
return [v:false, v:null, a:pos]
|
||||
endfunction
|
||||
return l:fn
|
||||
endfunction
|
||||
|
||||
"
|
||||
" many.
|
||||
"
|
||||
function! s:many(parser) abort
|
||||
let l:fn = {}
|
||||
let l:fn.parser = a:parser
|
||||
function! l:fn.parse(text, pos) abort
|
||||
let l:pos = a:pos
|
||||
let l:values = []
|
||||
|
||||
let l:len = strchars(a:text)
|
||||
while l:pos < l:len
|
||||
let l:parsed = self.parser.parse(a:text, l:pos)
|
||||
if l:parsed[0]
|
||||
call add(l:values, l:parsed[1])
|
||||
let l:pos = l:parsed[2]
|
||||
else
|
||||
break
|
||||
endif
|
||||
endwhile
|
||||
if len(l:values) > 0
|
||||
return [v:true, l:values, l:pos]
|
||||
else
|
||||
return [v:false, v:null, l:pos]
|
||||
endif
|
||||
endfunction
|
||||
return l:fn
|
||||
endfunction
|
||||
|
||||
"
|
||||
" or.
|
||||
"
|
||||
function! s:or(...) abort
|
||||
let l:fn = {}
|
||||
let l:fn.parsers = a:000
|
||||
function! l:fn.parse(text, pos) abort
|
||||
for l:parser in self.parsers
|
||||
let l:parsed = l:parser.parse(a:text, a:pos)
|
||||
if l:parsed[0]
|
||||
return l:parsed
|
||||
endif
|
||||
endfor
|
||||
return [v:false, v:null, a:pos]
|
||||
endfunction
|
||||
return l:fn
|
||||
endfunction
|
||||
|
||||
"
|
||||
" seq.
|
||||
"
|
||||
function! s:seq(...) abort
|
||||
let l:fn = {}
|
||||
let l:fn.parsers = a:000
|
||||
function! l:fn.parse(text, pos) abort
|
||||
let l:pos = a:pos
|
||||
let l:values = []
|
||||
for l:parser in self.parsers
|
||||
let l:parsed = l:parser.parse(a:text, l:pos)
|
||||
if !l:parsed[0]
|
||||
return [v:false, v:null, a:pos]
|
||||
endif
|
||||
call add(l:values, l:parsed[1])
|
||||
let l:pos = l:parsed[2]
|
||||
endfor
|
||||
return [v:true, l:values, l:pos]
|
||||
endfunction
|
||||
return l:fn
|
||||
endfunction
|
||||
|
||||
"
|
||||
" lazy.
|
||||
"
|
||||
function! s:lazy(callback) abort
|
||||
let l:fn = {}
|
||||
let l:fn.callback = a:callback
|
||||
function! l:fn.parse(text, pos) abort
|
||||
if !has_key(self, 'parser')
|
||||
let self.parser = self.callback()
|
||||
endif
|
||||
return self.parser.parse(a:text, a:pos)
|
||||
endfunction
|
||||
return l:fn
|
||||
endfunction
|
||||
|
||||
"
|
||||
" pattern.
|
||||
"
|
||||
function! s:pattern(pattern) abort
|
||||
let l:fn = {}
|
||||
let l:fn.pattern = a:pattern[0] ==# '^' ? a:pattern : '^' . a:pattern
|
||||
function! l:fn.parse(text, pos) abort
|
||||
let l:text = strcharpart(a:text, a:pos)
|
||||
let l:matches = matchstrpos(l:text, self.pattern, 0, 1)
|
||||
if l:matches[0] !=# ''
|
||||
return [v:true, l:matches[0], a:pos + l:matches[2]]
|
||||
endif
|
||||
return [v:false, v:null, a:pos]
|
||||
endfunction
|
||||
return l:fn
|
||||
endfunction
|
||||
|
||||
"
|
||||
" map.
|
||||
"
|
||||
function! s:map(parser, callback) abort
|
||||
let l:fn = {}
|
||||
let l:fn.callback = a:callback
|
||||
let l:fn.parser = a:parser
|
||||
function! l:fn.parse(text, pos) abort
|
||||
let l:parsed = self.parser.parse(a:text, a:pos)
|
||||
if l:parsed[0]
|
||||
return [v:true, self.callback(l:parsed[1]), l:parsed[2]]
|
||||
endif
|
||||
return l:parsed
|
||||
endfunction
|
||||
return l:fn
|
||||
endfunction
|
||||
|
||||
"
|
||||
" option.
|
||||
"
|
||||
function! s:option(parser) abort
|
||||
let l:fn = {}
|
||||
let l:fn.parser = a:parser
|
||||
function! l:fn.parse(text, pos) abort
|
||||
let l:parsed = self.parser.parse(a:text, a:pos)
|
||||
if l:parsed[0]
|
||||
return l:parsed
|
||||
endif
|
||||
return [v:true, v:null, a:pos]
|
||||
endfunction
|
||||
return l:fn
|
||||
endfunction
|
||||
|
||||
"
|
||||
" getchar.
|
||||
"
|
||||
function! s:getchar(text, pos) abort
|
||||
let l:nr = strgetchar(a:text, a:pos)
|
||||
if l:nr != -1
|
||||
return nr2char(l:nr)
|
||||
endif
|
||||
return ''
|
||||
endfunction
|
||||
|
||||
10
dot_vim/plugged/vim-vsnip/autoload/vsnip/range.vim
Normal file
10
dot_vim/plugged/vim-vsnip/autoload/vsnip/range.vim
Normal file
@@ -0,0 +1,10 @@
|
||||
"
|
||||
" vsnip#range#cover
|
||||
"
|
||||
function! vsnip#range#cover(whole_range, target_range) abort
|
||||
let l:cover = v:true
|
||||
let l:cover = l:cover && (a:whole_range.start.line < a:target_range.start.line || a:whole_range.start.line == a:target_range.start.line && a:whole_range.start.character <= a:target_range.start.character)
|
||||
let l:cover = l:cover && (a:target_range.end.line < a:whole_range.end.line || a:target_range.end.line == a:whole_range.end.line && a:target_range.end.character <= a:whole_range.end.character)
|
||||
return l:cover
|
||||
endfunction
|
||||
|
||||
260
dot_vim/plugged/vim-vsnip/autoload/vsnip/session.vim
Normal file
260
dot_vim/plugged/vim-vsnip/autoload/vsnip/session.vim
Normal file
@@ -0,0 +1,260 @@
|
||||
let s:Snippet = vsnip#snippet#import()
|
||||
let s:TextEdit = vital#vsnip#import('VS.LSP.TextEdit')
|
||||
let s:Position = vital#vsnip#import('VS.LSP.Position')
|
||||
let s:Diff = vital#vsnip#import('VS.LSP.Diff')
|
||||
|
||||
"
|
||||
" import.
|
||||
"
|
||||
function! vsnip#session#import() abort
|
||||
return s:Session
|
||||
endfunction
|
||||
|
||||
let s:Session = {}
|
||||
|
||||
"
|
||||
" new.
|
||||
"
|
||||
function! s:Session.new(bufnr, position, text) abort
|
||||
return extend(deepcopy(s:Session), {
|
||||
\ 'bufnr': a:bufnr,
|
||||
\ 'buffer': getbufline(a:bufnr, '^', '$'),
|
||||
\ 'timer_id': -1,
|
||||
\ 'changedtick': getbufvar(a:bufnr, 'changedtick', 0),
|
||||
\ 'snippet': s:Snippet.new(a:position, vsnip#indent#adjust_snippet_body(getline('.'), a:text)),
|
||||
\ 'tabstop': -1,
|
||||
\ 'changenr': changenr(),
|
||||
\ 'changenrs': {},
|
||||
\ })
|
||||
endfunction
|
||||
|
||||
"
|
||||
" expand.
|
||||
"
|
||||
function! s:Session.expand() abort
|
||||
" insert snippet.
|
||||
call s:TextEdit.apply(self.bufnr, [{
|
||||
\ 'range': {
|
||||
\ 'start': self.snippet.position,
|
||||
\ 'end': self.snippet.position
|
||||
\ },
|
||||
\ 'newText': self.snippet.text()
|
||||
\ }])
|
||||
call self.store(changenr())
|
||||
endfunction
|
||||
|
||||
"
|
||||
" merge.
|
||||
"
|
||||
function! s:Session.merge(session) abort
|
||||
call s:TextEdit.apply(self.bufnr, self.snippet.sync())
|
||||
call self.store(self.changenr)
|
||||
|
||||
call a:session.expand()
|
||||
call self.snippet.merge(self.tabstop, a:session.snippet)
|
||||
call self.snippet.insert(deepcopy(a:session.snippet.position), a:session.snippet.children)
|
||||
call s:TextEdit.apply(self.bufnr, self.snippet.sync())
|
||||
call self.store(changenr())
|
||||
endfunction
|
||||
|
||||
"
|
||||
" jumpable.
|
||||
"
|
||||
function! s:Session.jumpable(direction) abort
|
||||
if a:direction == 1
|
||||
let l:jumpable = !empty(self.snippet.get_next_jump_point(self.tabstop))
|
||||
else
|
||||
let l:jumpable = !empty(self.snippet.get_prev_jump_point(self.tabstop))
|
||||
endif
|
||||
return l:jumpable
|
||||
endfunction
|
||||
|
||||
"
|
||||
" jump.
|
||||
"
|
||||
function! s:Session.jump(direction) abort
|
||||
call self.flush_changes()
|
||||
|
||||
if a:direction == 1
|
||||
let l:jump_point = self.snippet.get_next_jump_point(self.tabstop)
|
||||
else
|
||||
let l:jump_point = self.snippet.get_prev_jump_point(self.tabstop)
|
||||
endif
|
||||
|
||||
if empty(l:jump_point)
|
||||
return
|
||||
endif
|
||||
|
||||
let self.tabstop = l:jump_point.placeholder.id
|
||||
|
||||
" choice.
|
||||
if len(l:jump_point.placeholder.choice) > 0
|
||||
call self.choice(l:jump_point)
|
||||
|
||||
" select.
|
||||
elseif l:jump_point.range.start.character != l:jump_point.range.end.character
|
||||
call self.select(l:jump_point)
|
||||
|
||||
" move.
|
||||
else
|
||||
call self.move(l:jump_point)
|
||||
endif
|
||||
|
||||
doautocmd <nomodeline> User vsnip#jump
|
||||
endfunction
|
||||
|
||||
"
|
||||
" choice.
|
||||
"
|
||||
function! s:Session.choice(jump_point) abort
|
||||
call self.move(a:jump_point)
|
||||
|
||||
let l:fn = {}
|
||||
let l:fn.jump_point = a:jump_point
|
||||
function! l:fn.next_tick() abort
|
||||
if mode()[0] ==# 'i'
|
||||
let l:pos = s:Position.lsp_to_vim('%', self.jump_point.range.start)
|
||||
call complete(l:pos[1], map(copy(self.jump_point.placeholder.choice), { k, v -> {
|
||||
\ 'word': v.escaped,
|
||||
\ 'abbr': v.escaped,
|
||||
\ 'menu': '[vsnip]',
|
||||
\ 'kind': 'Choice'
|
||||
\ } }))
|
||||
endif
|
||||
endfunction
|
||||
call timer_start(g:vsnip_choice_delay, { -> l:fn.next_tick() })
|
||||
endfunction
|
||||
|
||||
"
|
||||
" select.
|
||||
"
|
||||
" @NOTE: Must work even if virtualedit=all/onmore or not.
|
||||
"
|
||||
function! s:Session.select(jump_point) abort
|
||||
let l:start_pos = s:Position.lsp_to_vim('%', a:jump_point.range.start)
|
||||
let l:end_pos = s:Position.lsp_to_vim('%', a:jump_point.range.end)
|
||||
|
||||
let l:cmd = ''
|
||||
let l:cmd .= "\<Cmd>set virtualedit=onemore\<CR>"
|
||||
let l:cmd .= mode()[0] ==# 'i' ? "\<Esc>" : ''
|
||||
let l:cmd .= printf("\<Cmd>call cursor(%s, %s)\<CR>", l:start_pos[0], l:start_pos[1])
|
||||
let l:cmd .= 'v'
|
||||
let l:cmd .= printf("\<Cmd>call cursor(%s, %s)\<CR>%s", l:end_pos[0], l:end_pos[1], &selection ==# 'exclusive' ? '' : 'h')
|
||||
if get(g:, 'vsnip_test_mode', v:false)
|
||||
let l:cmd .= "\<Esc>gv"
|
||||
endif
|
||||
let l:cmd .= printf("\<Cmd>set virtualedit=%s\<CR>", &virtualedit)
|
||||
let l:cmd .= "\<C-g>"
|
||||
call feedkeys(l:cmd, 'ni')
|
||||
endfunction
|
||||
|
||||
"
|
||||
" move.
|
||||
"
|
||||
" @NOTE: Must work even if virtualedit=all/onmore or not.
|
||||
"
|
||||
function! s:Session.move(jump_point) abort
|
||||
let l:pos = s:Position.lsp_to_vim('%', a:jump_point.range.end)
|
||||
|
||||
call cursor(l:pos)
|
||||
|
||||
if mode()[0] ==# 'n'
|
||||
if l:pos[1] != getcurpos()[2]
|
||||
call feedkeys('a', 'ni')
|
||||
else
|
||||
call feedkeys('i', 'ni')
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"
|
||||
" refresh
|
||||
"
|
||||
function! s:Session.refresh() abort
|
||||
let self.buffer = getbufline(self.bufnr, '^', '$')
|
||||
let self.changedtick = getbufvar(self.bufnr, 'changedtick', 0)
|
||||
endfunction
|
||||
|
||||
"
|
||||
" on_insert_leave
|
||||
"
|
||||
function! s:Session.on_insert_leave() abort
|
||||
call self.flush_changes()
|
||||
endfunction
|
||||
|
||||
"
|
||||
" on_text_changed
|
||||
"
|
||||
function! s:Session.on_text_changed() abort
|
||||
if self.bufnr != bufnr('%')
|
||||
return vsnip#deactivate()
|
||||
endif
|
||||
|
||||
let l:changenr = changenr()
|
||||
|
||||
" save state.
|
||||
if self.changenr != l:changenr
|
||||
call self.store(self.changenr)
|
||||
if has_key(self.changenrs, l:changenr)
|
||||
let self.tabstop = self.changenrs[l:changenr].tabstop
|
||||
let self.snippet = self.changenrs[l:changenr].snippet
|
||||
let self.changenr = l:changenr
|
||||
let self.buffer = getbufline(self.bufnr, '^', '$')
|
||||
return
|
||||
endif
|
||||
endif
|
||||
|
||||
if g:vsnip_sync_delay == 0
|
||||
call self.flush_changes()
|
||||
elseif g:vsnip_sync_delay > 0
|
||||
call timer_stop(self.timer_id)
|
||||
let self.timer_id = timer_start(g:vsnip_sync_delay, { -> self.flush_changes() }, { 'repeat': 1 })
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"
|
||||
" flush_changes
|
||||
"
|
||||
function! s:Session.flush_changes() abort
|
||||
let l:changedtick = getbufvar(self.bufnr, 'changedtick', 0)
|
||||
if self.changedtick == l:changedtick
|
||||
return
|
||||
endif
|
||||
let self.changedtick = l:changedtick
|
||||
|
||||
" compute diff.
|
||||
let l:buffer = getbufline(self.bufnr, '^', '$')
|
||||
let l:diff = s:Diff.compute(self.buffer, l:buffer)
|
||||
let self.buffer = l:buffer
|
||||
if l:diff.rangeLength == 0 && l:diff.text ==# ''
|
||||
return
|
||||
endif
|
||||
|
||||
" if follow succeeded, sync placeholders and write back to the buffer.
|
||||
if self.snippet.follow(self.tabstop, l:diff)
|
||||
try
|
||||
let l:text_edits = self.snippet.sync()
|
||||
if len(l:text_edits) > 0
|
||||
undojoin | call s:TextEdit.apply(self.bufnr, l:text_edits)
|
||||
endif
|
||||
call self.refresh()
|
||||
catch /.*/
|
||||
" TODO: More strict changenrs mangement.
|
||||
call vsnip#deactivate()
|
||||
endtry
|
||||
else
|
||||
call vsnip#deactivate()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"
|
||||
" save.
|
||||
"
|
||||
function! s:Session.store(changenr) abort
|
||||
let self.changenrs[a:changenr] = {
|
||||
\ 'tabstop': self.tabstop,
|
||||
\ 'snippet': deepcopy(self.snippet)
|
||||
\ }
|
||||
let self.changenr = a:changenr
|
||||
endfunction
|
||||
|
||||
557
dot_vim/plugged/vim-vsnip/autoload/vsnip/snippet.vim
Normal file
557
dot_vim/plugged/vim-vsnip/autoload/vsnip/snippet.vim
Normal file
@@ -0,0 +1,557 @@
|
||||
let s:max_tabstop = 1000000
|
||||
let s:Position = vital#vsnip#import('VS.LSP.Position')
|
||||
|
||||
"
|
||||
" import.
|
||||
"
|
||||
function! vsnip#snippet#import() abort
|
||||
return s:Snippet
|
||||
endfunction
|
||||
|
||||
let s:Snippet = {}
|
||||
|
||||
"
|
||||
" new.
|
||||
"
|
||||
function! s:Snippet.new(position, text) abort
|
||||
let l:pos = s:Position.lsp_to_vim('%', a:position)
|
||||
let l:snippet = extend(deepcopy(s:Snippet), {
|
||||
\ 'type': 'snippet',
|
||||
\ 'position': a:position,
|
||||
\ 'before_text': getline(l:pos[0])[0 : l:pos[1] - 2],
|
||||
\ 'children': vsnip#snippet#node#create_from_ast(
|
||||
\ vsnip#snippet#parser#parse(a:text)
|
||||
\ )
|
||||
\ })
|
||||
call l:snippet.init()
|
||||
call l:snippet.sync()
|
||||
return l:snippet
|
||||
endfunction
|
||||
|
||||
"
|
||||
" init.
|
||||
"
|
||||
" NOTE: Must not use the node range in this method.
|
||||
"
|
||||
function! s:Snippet.init() abort
|
||||
let l:fn = {}
|
||||
let l:fn.self = self
|
||||
let l:fn.group = {}
|
||||
let l:fn.variable_placeholder = {}
|
||||
let l:fn.has_final_tabstop = v:false
|
||||
function! l:fn.traverse(context) abort
|
||||
if a:context.node.type ==# 'placeholder'
|
||||
" Mark as follower placeholder.
|
||||
if !has_key(self.group, a:context.node.id)
|
||||
let self.group[a:context.node.id] = a:context.node
|
||||
else
|
||||
let a:context.node.follower = v:true
|
||||
endif
|
||||
|
||||
" Mark as having final tabstop
|
||||
if a:context.node.is_final
|
||||
let self.has_final_tabstop = v:true
|
||||
endif
|
||||
elseif a:context.node.type ==# 'variable'
|
||||
" TODO refactor
|
||||
" variable placeholder
|
||||
if a:context.node.unknown
|
||||
let a:context.node.type = 'placeholder'
|
||||
let a:context.node.choice = []
|
||||
|
||||
if !has_key(self.variable_placeholder, a:context.node.name)
|
||||
let self.variable_placeholder[a:context.node.name] = s:max_tabstop - (len(self.variable_placeholder) + 1)
|
||||
let a:context.node.id = self.variable_placeholder[a:context.node.name]
|
||||
let a:context.node.follower = v:false
|
||||
let a:context.node.children = empty(a:context.node.children) ? [vsnip#snippet#node#create_text(a:context.node.name)] : a:context.node.children
|
||||
let self.group[a:context.node.id] = a:context.node
|
||||
else
|
||||
let a:context.node.id = self.variable_placeholder[a:context.node.name]
|
||||
let a:context.node.follower = v:true
|
||||
let a:context.node.children = [vsnip#snippet#node#create_text(self.group[a:context.node.id].text())]
|
||||
endif
|
||||
else
|
||||
let l:text = a:context.node.resolve(a:context)
|
||||
let l:text = l:text is# v:null ? a:context.text : l:text
|
||||
let l:index = index(a:context.parent.children, a:context.node)
|
||||
call remove(a:context.parent.children, l:index)
|
||||
call insert(a:context.parent.children, vsnip#snippet#node#create_text(l:text), l:index)
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
call self.traverse(self, l:fn.traverse)
|
||||
|
||||
" Append ${MAX_TABSTOP} for the end of snippet.
|
||||
if !l:fn.has_final_tabstop && g:vsnip_append_final_tabstop
|
||||
let self.children += [vsnip#snippet#node#create_from_ast({
|
||||
\ 'type': 'placeholder',
|
||||
\ 'id': 0,
|
||||
\ 'choice': [],
|
||||
\ })]
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"
|
||||
" follow.
|
||||
"
|
||||
function! s:Snippet.follow(current_tabstop, diff) abort
|
||||
if !self.is_followable(a:current_tabstop, a:diff)
|
||||
return v:false
|
||||
endif
|
||||
|
||||
let a:diff.range = [
|
||||
\ self.position_to_offset(a:diff.range.start),
|
||||
\ self.position_to_offset(a:diff.range.end),
|
||||
\ ]
|
||||
|
||||
let l:fn = {}
|
||||
let l:fn.current_tabstop = a:current_tabstop
|
||||
let l:fn.diff = a:diff
|
||||
let l:fn.is_target_context_fixed = v:false
|
||||
let l:fn.target_context = v:null
|
||||
let l:fn.contexts = []
|
||||
function! l:fn.traverse(context) abort
|
||||
if self.diff.range[1] < a:context.range[0]
|
||||
return v:true
|
||||
endif
|
||||
if a:context.node.type !=# 'text'
|
||||
return
|
||||
endif
|
||||
|
||||
let l:included = v:false
|
||||
let l:included = l:included || a:context.range[0] <= self.diff.range[0] && self.diff.range[0] < a:context.range[1] " right
|
||||
let l:included = l:included || a:context.range[0] < self.diff.range[1] && self.diff.range[1] <= a:context.range[1] " left
|
||||
let l:included = l:included || self.diff.range[0] <= a:context.range[0] && a:context.range[1] <= self.diff.range[1] " middle
|
||||
if l:included
|
||||
if !self.is_target_context_fixed && (empty(self.target_context) && a:context.parent.type ==# 'placeholder' || get(a:context.parent, 'id', -1) == self.current_tabstop)
|
||||
let self.is_target_context_fixed = get(a:context.parent, 'id', -1) == self.current_tabstop
|
||||
let self.target_context = a:context
|
||||
endif
|
||||
call add(self.contexts, a:context)
|
||||
endif
|
||||
endfunction
|
||||
call self.traverse(self, l:fn.traverse)
|
||||
|
||||
if empty(l:fn.contexts)
|
||||
return v:false
|
||||
endif
|
||||
|
||||
let l:fn.target_context = empty(l:fn.target_context) ? l:fn.contexts[-1] : l:fn.target_context
|
||||
|
||||
let l:diff_text = a:diff.text
|
||||
for l:context in l:fn.contexts
|
||||
let l:diff_range = [max([a:diff.range[0], l:context.range[0]]), min([a:diff.range[1], l:context.range[1]])]
|
||||
let l:start = l:diff_range[0] - l:context.range[0]
|
||||
let l:end = l:diff_range[1] - l:context.range[0]
|
||||
|
||||
" Create patched new text.
|
||||
let l:new_text = strcharpart(l:context.text, 0, l:start)
|
||||
if l:fn.target_context is# l:context
|
||||
let l:new_text .= l:diff_text
|
||||
let l:followed = v:true
|
||||
endif
|
||||
let l:new_text .= strcharpart(l:context.text, l:end, l:context.length - l:end)
|
||||
|
||||
" Apply patched new text.
|
||||
let l:context.node.value = l:new_text
|
||||
endfor
|
||||
|
||||
" Squash nodes when the edit was unexpected
|
||||
let l:squashed = []
|
||||
for l:context in l:fn.contexts
|
||||
let l:squash_targets = l:context.parents + [l:context.node]
|
||||
for l:i in range(len(l:squash_targets) - 1, 1, -1)
|
||||
let l:node = l:squash_targets[l:i]
|
||||
let l:parent = l:squash_targets[l:i - 1]
|
||||
|
||||
let l:should_squash = v:false
|
||||
let l:should_squash = l:should_squash || get(l:node, 'follower', v:false)
|
||||
let l:should_squash = l:should_squash || get(l:parent, 'id', v:null) is# a:current_tabstop
|
||||
let l:should_squash = l:should_squash || l:context isnot# l:fn.target_context && strlen(l:node.text()) == 0
|
||||
if l:should_squash && index(l:squashed, l:node) == -1
|
||||
let l:index = index(l:parent.children, l:node)
|
||||
call remove(l:parent.children, l:index)
|
||||
call insert(l:parent.children, vsnip#snippet#node#create_text(l:node.text()), l:index)
|
||||
call add(l:squashed, l:node)
|
||||
endif
|
||||
endfor
|
||||
endfor
|
||||
|
||||
return v:true
|
||||
endfunction
|
||||
|
||||
"
|
||||
" sync.
|
||||
"
|
||||
function! s:Snippet.sync() abort
|
||||
let l:fn = {}
|
||||
let l:fn.new_texts = {}
|
||||
let l:fn.targets = []
|
||||
function! l:fn.traverse(context) abort
|
||||
if a:context.node.type ==# 'placeholder'
|
||||
if !has_key(self.new_texts, a:context.node.id)
|
||||
let self.new_texts[a:context.node.id] = a:context.text
|
||||
else
|
||||
if self.new_texts[a:context.node.id] !=# a:context.text
|
||||
call add(self.targets, {
|
||||
\ 'range': a:context.range,
|
||||
\ 'node': a:context.node,
|
||||
\ 'new_text': a:context.node.transform.text(self.new_texts[a:context.node.id]),
|
||||
\ })
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
call self.traverse(self, l:fn.traverse)
|
||||
|
||||
" Create text_edits.
|
||||
let l:text_edits = []
|
||||
for l:target in l:fn.targets
|
||||
call add(l:text_edits, {
|
||||
\ 'node': l:target.node,
|
||||
\ 'range': {
|
||||
\ 'start': self.offset_to_position(l:target.range[0]),
|
||||
\ 'end': self.offset_to_position(l:target.range[1]),
|
||||
\ },
|
||||
\ 'newText': l:target.new_text
|
||||
\ })
|
||||
endfor
|
||||
|
||||
" Sync placeholder text after created text_edits (the reason is to avoid using a modified range).
|
||||
for l:text_edit in l:text_edits
|
||||
let l:text_edit.node.children = [vsnip#snippet#node#create_text(l:text_edit.newText)]
|
||||
endfor
|
||||
|
||||
return l:text_edits
|
||||
endfunction
|
||||
|
||||
"
|
||||
" range.
|
||||
"
|
||||
function! s:Snippet.range() abort
|
||||
return {
|
||||
\ 'start': self.offset_to_position(0),
|
||||
\ 'end': self.offset_to_position(strchars(self.text()))
|
||||
\ }
|
||||
endfunction
|
||||
|
||||
"
|
||||
" text.
|
||||
"
|
||||
function! s:Snippet.text() abort
|
||||
return join(map(copy(self.children), 'v:val.text()'), '')
|
||||
endfunction
|
||||
|
||||
"
|
||||
" is_followable.
|
||||
"
|
||||
function! s:Snippet.is_followable(current_tabstop, diff) abort
|
||||
if g:vsnip#DeactivateOn.OutsideOfSnippet == g:vsnip_deactivate_on
|
||||
return vsnip#range#cover(self.range(), a:diff.range)
|
||||
elseif g:vsnip#DeactivateOn.OutsideOfCurrentTabstop == g:vsnip_deactivate_on
|
||||
let l:context = self.get_placeholder_context_by_tabstop(a:current_tabstop)
|
||||
if empty(l:context)
|
||||
return v:false
|
||||
endif
|
||||
return vsnip#range#cover({
|
||||
\ 'start': self.offset_to_position(l:context.range[0]),
|
||||
\ 'end': self.offset_to_position(l:context.range[1]),
|
||||
\ }, a:diff.range)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"
|
||||
" get_placeholder_nodes
|
||||
"
|
||||
function! s:Snippet.get_placeholder_nodes() abort
|
||||
let l:fn = {}
|
||||
let l:fn.nodes = []
|
||||
function! l:fn.traverse(context) abort
|
||||
if a:context.node.type ==# 'placeholder'
|
||||
call add(self.nodes, a:context.node)
|
||||
endif
|
||||
endfunction
|
||||
call self.traverse(self, l:fn.traverse)
|
||||
|
||||
return sort(l:fn.nodes, { a, b -> a.id - b.id })
|
||||
endfunction
|
||||
|
||||
"
|
||||
" get_placeholder_context_by_tabstop
|
||||
"
|
||||
function! s:Snippet.get_placeholder_context_by_tabstop(current_tabstop) abort
|
||||
let l:fn = {}
|
||||
let l:fn.current_tabstop = a:current_tabstop
|
||||
let l:fn.context = v:null
|
||||
function! l:fn.traverse(context) abort
|
||||
if a:context.node.type ==# 'placeholder' && a:context.node.id == self.current_tabstop
|
||||
let self.context = a:context
|
||||
return v:true
|
||||
endif
|
||||
endfunction
|
||||
call self.traverse(self, l:fn.traverse)
|
||||
return l:fn.context
|
||||
endfunction
|
||||
|
||||
"
|
||||
" get_next_jump_point.
|
||||
"
|
||||
function! s:Snippet.get_next_jump_point(current_tabstop) abort
|
||||
let l:fn = {}
|
||||
let l:fn.current_tabstop = a:current_tabstop
|
||||
let l:fn.context = v:null
|
||||
function! l:fn.traverse(context) abort
|
||||
if a:context.node.type ==# 'placeholder' && self.current_tabstop < a:context.node.id
|
||||
if !empty(self.context) && self.context.node.id <= a:context.node.id
|
||||
return v:false
|
||||
endif
|
||||
|
||||
let self.context = copy(a:context)
|
||||
endif
|
||||
endfunction
|
||||
call self.traverse(self, l:fn.traverse)
|
||||
|
||||
let l:context = l:fn.context
|
||||
if empty(l:context)
|
||||
return {}
|
||||
endif
|
||||
|
||||
return {
|
||||
\ 'placeholder': l:context.node,
|
||||
\ 'range': {
|
||||
\ 'start': self.offset_to_position(l:context.range[0]),
|
||||
\ 'end': self.offset_to_position(l:context.range[1])
|
||||
\ }
|
||||
\ }
|
||||
endfunction
|
||||
|
||||
"
|
||||
" get_prev_jump_point.
|
||||
"
|
||||
function! s:Snippet.get_prev_jump_point(current_tabstop) abort
|
||||
let l:fn = {}
|
||||
let l:fn.current_tabstop = a:current_tabstop
|
||||
let l:fn.context = v:null
|
||||
function! l:fn.traverse(context) abort
|
||||
if a:context.node.type ==# 'placeholder' && self.current_tabstop > a:context.node.id
|
||||
if !empty(self.context) && self.context.node.id >= a:context.node.id
|
||||
return v:false
|
||||
endif
|
||||
let self.context = copy(a:context)
|
||||
endif
|
||||
endfunction
|
||||
call self.traverse(self, l:fn.traverse)
|
||||
|
||||
let l:context = l:fn.context
|
||||
if empty(l:context)
|
||||
return {}
|
||||
endif
|
||||
|
||||
return {
|
||||
\ 'placeholder': l:context.node,
|
||||
\ 'range': {
|
||||
\ 'start': self.offset_to_position(l:context.range[0]),
|
||||
\ 'end': self.offset_to_position(l:context.range[1])
|
||||
\ }
|
||||
\ }
|
||||
endfunction
|
||||
|
||||
"
|
||||
" normalize
|
||||
"
|
||||
" - merge adjacent text-nodes
|
||||
"
|
||||
function! s:Snippet.normalize() abort
|
||||
let l:fn = {}
|
||||
let l:fn.prev_context = v:null
|
||||
function! l:fn.traverse(context) abort
|
||||
if !empty(self.prev_context)
|
||||
if self.prev_context.node.type ==# 'text' && a:context.node.type ==# 'text' && self.prev_context.parent is# a:context.parent
|
||||
let a:context.node.value = self.prev_context.node.value . a:context.node.value
|
||||
call remove(self.prev_context.parent.children, index(self.prev_context.parent.children, self.prev_context.node))
|
||||
endif
|
||||
endif
|
||||
let self.prev_context = copy(a:context)
|
||||
endfunction
|
||||
call self.traverse(self, l:fn.traverse)
|
||||
endfunction
|
||||
|
||||
"
|
||||
" merge
|
||||
"
|
||||
function! s:Snippet.merge(tabstop, snippet) abort
|
||||
" increase new snippet's tabstop by current snippet's current tabstop
|
||||
let l:offset = 1
|
||||
let l:tabstop_map = {}
|
||||
for l:node in a:snippet.get_placeholder_nodes()
|
||||
if !has_key(l:tabstop_map, l:node.id)
|
||||
let l:tabstop_map[l:node.id] = a:tabstop + l:offset
|
||||
endif
|
||||
let l:node.id = l:tabstop_map[l:node.id]
|
||||
let l:offset += 1
|
||||
endfor
|
||||
if empty(l:tabstop_map)
|
||||
return
|
||||
endif
|
||||
|
||||
let l:tail = l:node
|
||||
|
||||
" re-assign current snippet's tabstop by new snippet's final tabstop
|
||||
let l:offset = 1
|
||||
let l:tabstop_map = {}
|
||||
for l:node in self.get_placeholder_nodes()
|
||||
if l:node.id > a:tabstop
|
||||
if !has_key(l:tabstop_map, l:node.id)
|
||||
let l:tabstop_map[l:node.id] = l:tail.id + l:offset
|
||||
endif
|
||||
let l:node.id = l:tabstop_map[l:node.id]
|
||||
let l:offset += 1
|
||||
endif
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
"
|
||||
" insert
|
||||
"
|
||||
function! s:Snippet.insert(position, nodes_to_insert) abort
|
||||
let l:offset = self.position_to_offset(a:position)
|
||||
|
||||
" Search target node for inserting nodes.
|
||||
let l:fn = {}
|
||||
let l:fn.offset = l:offset
|
||||
let l:fn.context = v:null
|
||||
function! l:fn.traverse(context) abort
|
||||
if a:context.range[0] <= self.offset && self.offset <= a:context.range[1] && a:context.node.type ==# 'text'
|
||||
" prefer more deeper node.
|
||||
if empty(self.context) || self.context.depth <= a:context.depth
|
||||
let self.context = copy(a:context)
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
call self.traverse(self, l:fn.traverse)
|
||||
|
||||
" This condition is unexpected normally
|
||||
let l:context = l:fn.context
|
||||
if empty(l:context)
|
||||
return
|
||||
endif
|
||||
|
||||
" Remove target text node
|
||||
let l:index = index(l:context.parent.children, l:context.node)
|
||||
call remove(l:context.parent.children, l:index)
|
||||
|
||||
" Should insert into existing text node when position is middle of node
|
||||
let l:nodes_to_insert = reverse(a:nodes_to_insert)
|
||||
if l:context.node.value !=# ''
|
||||
let l:off = l:offset - l:context.range[0]
|
||||
let l:before = vsnip#snippet#node#create_text(strcharpart(l:context.node.value, 0, l:off))
|
||||
let l:after = vsnip#snippet#node#create_text(strcharpart(l:context.node.value, l:off, strchars(l:context.node.value) - l:off))
|
||||
let l:nodes_to_insert = [l:after] + l:nodes_to_insert + [l:before]
|
||||
endif
|
||||
|
||||
" Insert nodes.
|
||||
for l:node in l:nodes_to_insert
|
||||
call insert(l:context.parent.children, l:node, l:index)
|
||||
endfor
|
||||
|
||||
call self.normalize()
|
||||
endfunction
|
||||
|
||||
"
|
||||
" offset_to_position.
|
||||
"
|
||||
" @param offset 0-based index for snippet text.
|
||||
" @return position buffer position
|
||||
"
|
||||
function! s:Snippet.offset_to_position(offset) abort
|
||||
let l:lines = split(strcharpart(self.text(), 0, a:offset), "\n", v:true)
|
||||
return {
|
||||
\ 'line': self.position.line + len(l:lines) - 1,
|
||||
\ 'character': strchars(l:lines[-1]) + (len(l:lines) == 1 ? self.position.character : 0),
|
||||
\ }
|
||||
endfunction
|
||||
|
||||
"
|
||||
" position_to_offset.
|
||||
"
|
||||
" @param position buffer position
|
||||
" @return 0-based index for snippet text.
|
||||
"
|
||||
function! s:Snippet.position_to_offset(position) abort
|
||||
let l:line = a:position.line - self.position.line
|
||||
let l:char = a:position.character - (l:line == 0 ? self.position.character : 0)
|
||||
let l:lines = split(self.text(), "\n", v:true)[0 : l:line]
|
||||
let l:lines[-1] = strcharpart(l:lines[-1], 0, l:char)
|
||||
return strchars(join(l:lines, "\n"))
|
||||
endfunction
|
||||
|
||||
"
|
||||
" traverse.
|
||||
"
|
||||
function! s:Snippet.traverse(node, callback) abort
|
||||
let l:state = {
|
||||
\ 'offset': 0,
|
||||
\ 'before_text': self.before_text,
|
||||
\ }
|
||||
let l:context = {
|
||||
\ 'depth': 0,
|
||||
\ 'parent': v:null,
|
||||
\ 'parents': [],
|
||||
\ }
|
||||
call s:traverse(a:node, a:callback, l:state, l:context)
|
||||
endfunction
|
||||
function! s:traverse(node, callback, state, context) abort
|
||||
let l:text = ''
|
||||
let l:length = 0
|
||||
if a:node.type !=# 'snippet'
|
||||
let l:text = a:node.text()
|
||||
let l:length = strchars(l:text)
|
||||
if a:callback({
|
||||
\ 'node': a:node,
|
||||
\ 'text': l:text,
|
||||
\ 'length': l:length,
|
||||
\ 'parent': a:context.parent,
|
||||
\ 'parents': a:context.parents,
|
||||
\ 'depth': a:context.depth,
|
||||
\ 'offset': a:state.offset,
|
||||
\ 'before_text': a:state.before_text,
|
||||
\ 'range': [a:state.offset, a:state.offset + l:length],
|
||||
\ })
|
||||
return v:true
|
||||
endif
|
||||
endif
|
||||
|
||||
if len(a:node.children) > 0
|
||||
let l:next_context = {
|
||||
\ 'parent': a:node,
|
||||
\ 'parents': a:context.parents + [a:node],
|
||||
\ 'depth': len(a:context.parents) + 1,
|
||||
\ }
|
||||
for l:child in copy(a:node.children)
|
||||
if s:traverse(l:child, a:callback, a:state, l:next_context)
|
||||
return v:true
|
||||
endif
|
||||
endfor
|
||||
else
|
||||
let a:state.before_text .= l:text
|
||||
let a:state.offset += l:length
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"
|
||||
" debug
|
||||
"
|
||||
function! s:Snippet.debug() abort
|
||||
echomsg 'snippet.text()'
|
||||
for l:line in split(self.text(), "\n", v:true)
|
||||
echomsg string(l:line)
|
||||
endfor
|
||||
echomsg '-----'
|
||||
|
||||
let l:fn = {}
|
||||
function! l:fn.traverse(context) abort
|
||||
echomsg repeat(' ', a:context.depth - 1) . a:context.node.to_string()
|
||||
endfunction
|
||||
call self.traverse(self, l:fn.traverse)
|
||||
echomsg ' '
|
||||
endfunction
|
||||
43
dot_vim/plugged/vim-vsnip/autoload/vsnip/snippet/node.vim
Normal file
43
dot_vim/plugged/vim-vsnip/autoload/vsnip/snippet/node.vim
Normal file
@@ -0,0 +1,43 @@
|
||||
let s:Placeholder = vsnip#snippet#node#placeholder#import()
|
||||
let s:Variable = vsnip#snippet#node#variable#import()
|
||||
let s:Text = vsnip#snippet#node#text#import()
|
||||
let s:Transform = vsnip#snippet#node#transform#import()
|
||||
|
||||
"
|
||||
" vsnip#snippet#node#create_from_ast
|
||||
"
|
||||
function! vsnip#snippet#node#create_from_ast(ast) abort
|
||||
if type(a:ast) == type([])
|
||||
return map(a:ast, 'vsnip#snippet#node#create_from_ast(v:val)')
|
||||
endif
|
||||
|
||||
if a:ast.type ==# 'placeholder'
|
||||
return s:Placeholder.new(a:ast)
|
||||
endif
|
||||
if a:ast.type ==# 'variable'
|
||||
return s:Variable.new(a:ast)
|
||||
endif
|
||||
if a:ast.type ==# 'text'
|
||||
return s:Text.new(a:ast)
|
||||
endif
|
||||
|
||||
throw 'vsnip: invalid node type'
|
||||
endfunction
|
||||
|
||||
"
|
||||
" vsnip#snippet#node#create_text
|
||||
"
|
||||
function! vsnip#snippet#node#create_text(text) abort
|
||||
return s:Text.new({
|
||||
\ 'type': 'text',
|
||||
\ 'raw': a:text,
|
||||
\ 'escaped': a:text
|
||||
\ })
|
||||
endfunction
|
||||
|
||||
"
|
||||
" vsnip#snippet#node#create_transform
|
||||
"
|
||||
function! vsnip#snippet#node#create_transform(transform) abort
|
||||
return s:Transform.new(a:transform)
|
||||
endfunction
|
||||
@@ -0,0 +1,55 @@
|
||||
let s:max_tabstop = 1000000
|
||||
let s:uid = 0
|
||||
|
||||
function! vsnip#snippet#node#placeholder#import() abort
|
||||
return s:Placeholder
|
||||
endfunction
|
||||
|
||||
let s:Placeholder = {}
|
||||
|
||||
"
|
||||
" new.
|
||||
"
|
||||
function! s:Placeholder.new(ast) abort
|
||||
let s:uid += 1
|
||||
|
||||
let l:node = extend(deepcopy(s:Placeholder), {
|
||||
\ 'uid': s:uid,
|
||||
\ 'type': 'placeholder',
|
||||
\ 'id': a:ast.id,
|
||||
\ 'is_final': a:ast.id == 0,
|
||||
\ 'follower': v:false,
|
||||
\ 'choice': get(a:ast, 'choice', []),
|
||||
\ 'children': vsnip#snippet#node#create_from_ast(get(a:ast, 'children', [])),
|
||||
\ 'transform': vsnip#snippet#node#create_transform(get(a:ast, 'transform')),
|
||||
\ })
|
||||
|
||||
if l:node.is_final
|
||||
let l:node.id = s:max_tabstop
|
||||
endif
|
||||
|
||||
if len(l:node.children) == 0
|
||||
let l:node.children = [vsnip#snippet#node#create_text('')]
|
||||
endif
|
||||
|
||||
return l:node
|
||||
endfunction
|
||||
|
||||
"
|
||||
" text.
|
||||
"
|
||||
function! s:Placeholder.text() abort
|
||||
return join(map(copy(self.children), 'v:val.text()'), '')
|
||||
endfunction
|
||||
|
||||
"
|
||||
" to_string
|
||||
"
|
||||
function! s:Placeholder.to_string() abort
|
||||
return printf('%s(id=%s, follower=%s, choise=%s)',
|
||||
\ self.type,
|
||||
\ self.id,
|
||||
\ self.follower ? 'true' : 'false',
|
||||
\ self.choice
|
||||
\ )
|
||||
endfunction
|
||||
@@ -0,0 +1,38 @@
|
||||
let s:uid = 0
|
||||
|
||||
function! vsnip#snippet#node#text#import() abort
|
||||
return s:Text
|
||||
endfunction
|
||||
|
||||
let s:Text = {}
|
||||
|
||||
"
|
||||
" new.
|
||||
"
|
||||
function! s:Text.new(ast) abort
|
||||
let s:uid += 1
|
||||
|
||||
return extend(deepcopy(s:Text), {
|
||||
\ 'uid': s:uid,
|
||||
\ 'type': 'text',
|
||||
\ 'value': a:ast.escaped,
|
||||
\ 'children': [],
|
||||
\ })
|
||||
endfunction
|
||||
|
||||
"
|
||||
" text.
|
||||
"
|
||||
function! s:Text.text() abort
|
||||
return self.value
|
||||
endfunction
|
||||
|
||||
"
|
||||
" to_string
|
||||
"
|
||||
function! s:Text.to_string() abort
|
||||
return printf('%s(%s)',
|
||||
\ self.type,
|
||||
\ self.value
|
||||
\ )
|
||||
endfunction
|
||||
@@ -0,0 +1,112 @@
|
||||
function! vsnip#snippet#node#transform#import() abort
|
||||
return s:Transform
|
||||
endfunction
|
||||
|
||||
let s:Transform = {}
|
||||
|
||||
"
|
||||
" new.
|
||||
"
|
||||
function! s:Transform.new(ast) abort
|
||||
let l:transform = empty(a:ast) ? {} : a:ast
|
||||
|
||||
let l:node = extend(deepcopy(s:Transform), {
|
||||
\ 'type': 'transform',
|
||||
\ 'regex': get(l:transform, 'regex', v:null),
|
||||
\ 'replacements': get(l:transform, 'format', []),
|
||||
\ 'options': get(l:transform, 'option', []),
|
||||
\ })
|
||||
|
||||
let l:node.is_noop = l:node.regex is v:null
|
||||
|
||||
return l:node
|
||||
endfunction
|
||||
|
||||
"
|
||||
" text.
|
||||
"
|
||||
function! s:Transform.text(input_text) abort
|
||||
if empty(a:input_text) || self.is_noop
|
||||
return a:input_text
|
||||
endif
|
||||
|
||||
if self.regex.pattern !=# '(.*)'
|
||||
" TODO: fully support regex
|
||||
return a:input_text
|
||||
endif
|
||||
|
||||
let l:text = ''
|
||||
|
||||
for l:replacement in self.replacements
|
||||
if l:replacement.type ==# 'format'
|
||||
if l:replacement.modifier ==# '/capitalize'
|
||||
let l:text .= s:capitalize(a:input_text)
|
||||
elseif l:replacement.modifier ==# '/downcase'
|
||||
let l:text .= s:downcase(a:input_text)
|
||||
elseif l:replacement.modifier ==# '/upcase'
|
||||
let l:text .= s:upcase(a:input_text)
|
||||
elseif l:replacement.modifier ==# '/camelcase'
|
||||
let l:text .= s:camelcase(a:input_text)
|
||||
elseif l:replacement.modifier ==# '/pascalcase'
|
||||
let l:text .= s:capitalize(s:camelcase(a:input_text))
|
||||
endif
|
||||
elseif l:replacement.type ==# 'text'
|
||||
let l:text .= l:replacement.escaped
|
||||
endif
|
||||
endfor
|
||||
|
||||
return l:text
|
||||
endfunction
|
||||
|
||||
"
|
||||
" to_string
|
||||
"
|
||||
function! s:Transform.to_string() abort
|
||||
if self.is_noop
|
||||
return
|
||||
end
|
||||
|
||||
return printf('%s(regex=%s, total_replacements=%s, options=%s)',
|
||||
\ self.type,
|
||||
\ get(self.regex, 'pattern', ''),
|
||||
\ len(self.replacements),
|
||||
\ join(self.options, ''),
|
||||
\ )
|
||||
endfunction
|
||||
|
||||
"
|
||||
" upcase
|
||||
"
|
||||
function! s:upcase(word) abort
|
||||
let word = toupper(a:word)
|
||||
return word
|
||||
endfunction
|
||||
|
||||
"
|
||||
" downcase
|
||||
"
|
||||
function! s:downcase(word) abort
|
||||
let word = tolower(a:word)
|
||||
return word
|
||||
endfunction
|
||||
|
||||
"
|
||||
" capitalize
|
||||
"
|
||||
function! s:capitalize(word) abort
|
||||
let word = s:upcase(strpart(a:word, 0, 1)) . strpart(a:word, 1)
|
||||
return word
|
||||
endfunction
|
||||
|
||||
"
|
||||
" camelcase
|
||||
" @see https://github.com/tpope/vim-abolish/blob/3f0c8faa/plugin/abolish.vim#L111-L118
|
||||
"
|
||||
function! s:camelcase(word) abort
|
||||
let word = substitute(a:word, '-', '_', 'g')
|
||||
if word !~# '_' && word =~# '\l'
|
||||
return substitute(word,'^.','\l&','')
|
||||
else
|
||||
return substitute(word,'\C\(_\)\=\(.\)','\=submatch(1)==""?tolower(submatch(2)) : toupper(submatch(2))','g')
|
||||
endif
|
||||
endfunction
|
||||
@@ -0,0 +1,63 @@
|
||||
let s:uid = 0
|
||||
|
||||
"
|
||||
" vsnip#snippet#node#variable#import
|
||||
"
|
||||
function! vsnip#snippet#node#variable#import() abort
|
||||
return s:Variable
|
||||
endfunction
|
||||
|
||||
let s:Variable = {}
|
||||
|
||||
"
|
||||
" new.
|
||||
"
|
||||
function! s:Variable.new(ast) abort
|
||||
let s:uid += 1
|
||||
|
||||
let l:resolver = vsnip#variable#get(a:ast.name)
|
||||
return extend(deepcopy(s:Variable), {
|
||||
\ 'uid': s:uid,
|
||||
\ 'type': 'variable',
|
||||
\ 'name': a:ast.name,
|
||||
\ 'unknown': empty(l:resolver),
|
||||
\ 'resolver': l:resolver,
|
||||
\ 'children': vsnip#snippet#node#create_from_ast(get(a:ast, 'children', [])),
|
||||
\ 'transform': vsnip#snippet#node#create_transform(get(a:ast, 'transform')),
|
||||
\ })
|
||||
endfunction
|
||||
|
||||
"
|
||||
" text.
|
||||
"
|
||||
function! s:Variable.text() abort
|
||||
return self.transform.text(join(map(copy(self.children), 'v:val.text()'), ''))
|
||||
endfunction
|
||||
|
||||
"
|
||||
" resolve.
|
||||
"
|
||||
function! s:Variable.resolve(context) abort
|
||||
if !self.unknown
|
||||
let l:resolved = self.transform.text(self.resolver.func({ 'node': self }))
|
||||
if l:resolved isnot v:null
|
||||
" Fix indent when one variable returns multiple lines
|
||||
let l:base_indent = vsnip#indent#get_base_indent(split(a:context.before_text, "\n", v:true)[-1])
|
||||
return substitute(l:resolved, "\n\\zs", l:base_indent, 'g')
|
||||
endif
|
||||
endif
|
||||
return v:null
|
||||
endfunction
|
||||
|
||||
"
|
||||
" to_string
|
||||
"
|
||||
function! s:Variable.to_string() abort
|
||||
return printf('%s(name=%s, unknown=%s, text=%s)',
|
||||
\ self.type,
|
||||
\ self.name,
|
||||
\ self.unknown ? 'true' : 'false',
|
||||
\ self.text()
|
||||
\ )
|
||||
endfunction
|
||||
|
||||
212
dot_vim/plugged/vim-vsnip/autoload/vsnip/snippet/parser.vim
Normal file
212
dot_vim/plugged/vim-vsnip/autoload/vsnip/snippet/parser.vim
Normal file
@@ -0,0 +1,212 @@
|
||||
let s:Combinator = vsnip#parser#combinator#import()
|
||||
|
||||
"
|
||||
" vsnip#snippet#parser#parse.
|
||||
" @see https://github.com/Microsoft/language-server-protocol/blob/master/snippetSyntax.md
|
||||
"
|
||||
function! vsnip#snippet#parser#parse(text) abort
|
||||
if strlen(a:text) == 0
|
||||
return []
|
||||
endif
|
||||
|
||||
let l:parsed = s:parser.parse(a:text, 0)
|
||||
if !l:parsed[0]
|
||||
throw json_encode({ 'text': a:text, 'result': l:parsed })
|
||||
endif
|
||||
return l:parsed[1]
|
||||
endfunction
|
||||
|
||||
let s:skip = s:Combinator.skip
|
||||
let s:token = s:Combinator.token
|
||||
let s:many = s:Combinator.many
|
||||
let s:or = s:Combinator.or
|
||||
let s:seq = s:Combinator.seq
|
||||
let s:lazy = s:Combinator.lazy
|
||||
let s:option = s:Combinator.option
|
||||
let s:pattern = s:Combinator.pattern
|
||||
let s:map = s:Combinator.map
|
||||
|
||||
"
|
||||
" primitives.
|
||||
"
|
||||
let s:dollar = s:token('$')
|
||||
let s:open = s:token('{')
|
||||
let s:close = s:token('}')
|
||||
let s:colon = s:token(':')
|
||||
let s:slash = s:token('/')
|
||||
let s:comma = s:token(',')
|
||||
let s:pipe = s:token('|')
|
||||
let s:varname = s:pattern('[_[:alpha:]]\w*')
|
||||
let s:int = s:map(s:pattern('\d\+'), { value -> str2nr(value[0]) })
|
||||
let s:text = { stop, escape -> s:map(
|
||||
\ s:skip(stop, escape),
|
||||
\ { value -> {
|
||||
\ 'type': 'text',
|
||||
\ 'raw': value[0],
|
||||
\ 'escaped': value[1]
|
||||
\ }
|
||||
\ }) }
|
||||
let s:regex = s:map(s:text(['/'], []), { value -> {
|
||||
\ 'type': 'regex',
|
||||
\ 'pattern': value.raw
|
||||
\ } })
|
||||
|
||||
"
|
||||
" any (without text).
|
||||
"
|
||||
let s:any = s:or(
|
||||
\ s:lazy({ -> s:choice }),
|
||||
\ s:lazy({ -> s:variable }),
|
||||
\ s:lazy({ -> s:tabstop }),
|
||||
\ s:lazy({ -> s:placeholder }),
|
||||
\ )
|
||||
|
||||
"
|
||||
" format.
|
||||
"
|
||||
let s:format1 = s:map(s:seq(s:dollar, s:int), { value -> {
|
||||
\ 'type': 'format',
|
||||
\ 'id': value[1]
|
||||
\ } })
|
||||
let s:format2 = s:map(s:seq(s:dollar, s:open, s:int, s:close), { value -> {
|
||||
\ 'type': 'format',
|
||||
\ 'id': value[2]
|
||||
\ } })
|
||||
let s:format3 = s:map(
|
||||
\ s:seq(
|
||||
\ s:dollar,
|
||||
\ s:open,
|
||||
\ s:int,
|
||||
\ s:colon,
|
||||
\ s:or(
|
||||
\ s:token('/upcase'),
|
||||
\ s:token('/downcase'),
|
||||
\ s:token('/capitalize'),
|
||||
\ s:token('/camelcase'),
|
||||
\ s:token('/pascalcase'),
|
||||
\ s:token('+if'),
|
||||
\ s:token('?if:else'),
|
||||
\ s:token('-else'),
|
||||
\ s:token('else')
|
||||
\ ),
|
||||
\ s:close
|
||||
\ ), { value -> {
|
||||
\ 'type': 'format',
|
||||
\ 'id': value[2],
|
||||
\ 'modifier': value[4]
|
||||
\ } })
|
||||
let s:format = s:or(s:format1, s:format2, s:format3)
|
||||
|
||||
"
|
||||
" transform
|
||||
"
|
||||
let s:transform = s:map(s:seq(
|
||||
\ s:slash,
|
||||
\ s:regex,
|
||||
\ s:slash,
|
||||
\ s:many(s:or(s:format, s:text(['/', '$'], []))),
|
||||
\ s:slash,
|
||||
\ s:option(s:many(s:or(s:token('i'), s:token('g'))))
|
||||
\ ), { value -> {
|
||||
\ 'type': 'transform',
|
||||
\ 'regex': value[1],
|
||||
\ 'format': value[3],
|
||||
\ 'option': value[5]
|
||||
\ } })
|
||||
|
||||
"
|
||||
" variable
|
||||
"
|
||||
let s:variable1 = s:map(s:seq(s:dollar, s:varname), { value -> {
|
||||
\ 'type': 'variable',
|
||||
\ 'name': value[1],
|
||||
\ 'children': [],
|
||||
\ } })
|
||||
let s:variable2 = s:map(s:seq(s:dollar, s:open, s:varname, s:close), { value -> {
|
||||
\ 'type': 'variable',
|
||||
\ 'name': value[2],
|
||||
\ 'children': [],
|
||||
\ } })
|
||||
let s:variable3 = s:map(s:seq(
|
||||
\ s:dollar,
|
||||
\ s:open,
|
||||
\ s:varname,
|
||||
\ s:colon,
|
||||
\ s:many(s:or(s:any, s:text(['$', '}'], []))),
|
||||
\ s:close
|
||||
\ ), { value -> {
|
||||
\ 'type': 'variable',
|
||||
\ 'name': value[2],
|
||||
\ 'children': value[4]
|
||||
\ } })
|
||||
let s:variable4 = s:map(s:seq(s:dollar, s:open, s:varname, s:transform, s:close), { value -> {
|
||||
\ 'type': 'variable',
|
||||
\ 'name': value[2],
|
||||
\ 'transform': value[3],
|
||||
\ 'children': [],
|
||||
\ } })
|
||||
|
||||
let s:variable = s:or(s:variable1, s:variable2, s:variable3, s:variable4)
|
||||
|
||||
"
|
||||
" placeholder.
|
||||
"
|
||||
let s:placeholder = s:map(s:seq(
|
||||
\ s:dollar,
|
||||
\ s:open,
|
||||
\ s:int,
|
||||
\ s:colon,
|
||||
\ s:many(s:or(s:any, s:text(['$', '}'], []))),
|
||||
\ s:close
|
||||
\ ), { value -> {
|
||||
\ 'type': 'placeholder',
|
||||
\ 'id': value[2],
|
||||
\ 'children': value[4]
|
||||
\ } })
|
||||
|
||||
"
|
||||
" tabstop
|
||||
"
|
||||
let s:tabstop1 = s:map(s:seq(s:dollar, s:int), { value -> {
|
||||
\ 'type': 'placeholder',
|
||||
\ 'id': value[1],
|
||||
\ 'children': [],
|
||||
\ } })
|
||||
let s:tabstop2 = s:map(s:seq(s:dollar, s:open, s:int, s:option(s:colon), s:close), { value -> {
|
||||
\ 'type': 'placeholder',
|
||||
\ 'id': value[2],
|
||||
\ 'children': [],
|
||||
\ } })
|
||||
let s:tabstop3 = s:map(s:seq(s:dollar, s:open, s:int, s:transform, s:close), { value -> {
|
||||
\ 'type': 'placeholder',
|
||||
\ 'id': value[2],
|
||||
\ 'children': [],
|
||||
\ 'transform': value[3]
|
||||
\ } })
|
||||
let s:tabstop = s:or(s:tabstop1, s:tabstop2, s:tabstop3)
|
||||
|
||||
"
|
||||
" choice
|
||||
"
|
||||
let s:choice = s:map(s:seq(
|
||||
\ s:dollar,
|
||||
\ s:open,
|
||||
\ s:int,
|
||||
\ s:pipe,
|
||||
\ s:many(
|
||||
\ s:map(s:seq(s:text([',', '|'], []), s:option(s:comma)), { value -> value[0] }),
|
||||
\ ),
|
||||
\ s:pipe,
|
||||
\ s:close
|
||||
\ ), { value -> {
|
||||
\ 'type': 'placeholder',
|
||||
\ 'id': value[2],
|
||||
\ 'choice': value[4],
|
||||
\ 'children': [copy(value[4][0])],
|
||||
\ } })
|
||||
|
||||
"
|
||||
" parser.
|
||||
"
|
||||
let s:parser = s:many(s:or(s:any, s:text(['$'], ['}'])))
|
||||
|
||||
116
dot_vim/plugged/vim-vsnip/autoload/vsnip/source.vim
Normal file
116
dot_vim/plugged/vim-vsnip/autoload/vsnip/source.vim
Normal file
@@ -0,0 +1,116 @@
|
||||
"
|
||||
" vsnip#source#refresh.
|
||||
"
|
||||
function! vsnip#source#refresh(path) abort
|
||||
call vsnip#source#user_snippet#refresh(a:path)
|
||||
call vsnip#source#vscode#refresh(a:path)
|
||||
call vsnip#source#snipmate#refresh(a:path)
|
||||
endfunction
|
||||
|
||||
"
|
||||
" vsnip#source#find.
|
||||
"
|
||||
function! vsnip#source#find(bufnr) abort
|
||||
let l:sources = []
|
||||
let l:sources += vsnip#source#user_snippet#find(a:bufnr)
|
||||
let l:sources += vsnip#source#vscode#find(a:bufnr)
|
||||
let l:sources += vsnip#source#snipmate#find(a:bufnr)
|
||||
return l:sources
|
||||
endfunction
|
||||
|
||||
"
|
||||
" vsnip#source#filetypes
|
||||
"
|
||||
function! vsnip#source#filetypes(bufnr) abort
|
||||
let l:filetype = getbufvar(a:bufnr, '&filetype', '')
|
||||
return split(l:filetype, '\.') + get(g:vsnip_filetypes, l:filetype, []) + ['global']
|
||||
endfunction
|
||||
|
||||
"
|
||||
" vsnip#source#create.
|
||||
"
|
||||
function! vsnip#source#create(path) abort
|
||||
try
|
||||
let l:file = readfile(a:path)
|
||||
let l:file = type(l:file) == type([]) ? join(l:file, "\n") : l:file
|
||||
let l:file = iconv(l:file, 'utf-8', &encoding)
|
||||
let l:json = json_decode(l:file)
|
||||
|
||||
if type(l:json) != type({})
|
||||
throw printf('%s is not valid json.', a:path)
|
||||
endif
|
||||
catch /.*/
|
||||
let l:json = {}
|
||||
echohl ErrorMsg
|
||||
echomsg printf('[vsnip] Parsing error occurred on: %s', a:path)
|
||||
echohl None
|
||||
echomsg string({ 'exception': v:exception, 'throwpint': v:throwpoint })
|
||||
endtry
|
||||
|
||||
" @see https://github.com/microsoft/vscode/blob/0ba9f6631daec96a2b71eeb337e29f50dd21c7e1/src/vs/workbench/contrib/snippets/browser/snippetsFile.ts#L216
|
||||
let l:source = []
|
||||
for [l:key, l:value] in items(l:json)
|
||||
if s:is_snippet(l:value)
|
||||
call add(l:source, s:format_snippet(l:key, l:value))
|
||||
else
|
||||
for [l:key, l:value_] in items(l:value)
|
||||
if s:is_snippet(l:value_)
|
||||
call add(l:source, s:format_snippet(l:key, l:value_))
|
||||
endif
|
||||
endfor
|
||||
endif
|
||||
endfor
|
||||
return sort(l:source, { a, b -> strlen(b.prefix[0]) - strlen(a.prefix[0]) })
|
||||
endfunction
|
||||
|
||||
"
|
||||
" format_snippet
|
||||
"
|
||||
function! s:format_snippet(label, snippet) abort
|
||||
let [l:prefixes, l:prefixes_alias] = vsnip#source#resolve_prefix(a:snippet.prefix)
|
||||
let l:description = get(a:snippet, 'description', '')
|
||||
|
||||
return {
|
||||
\ 'label': a:label,
|
||||
\ 'prefix': l:prefixes,
|
||||
\ 'prefix_alias': l:prefixes_alias,
|
||||
\ 'body': type(a:snippet.body) == type([]) ? a:snippet.body : [a:snippet.body],
|
||||
\ 'description': type(l:description) == type([]) ? join(l:description, '') : l:description,
|
||||
\ }
|
||||
endfunction
|
||||
|
||||
"
|
||||
" is_snippet
|
||||
"
|
||||
function! s:is_snippet(snippet_or_source) abort
|
||||
return type(a:snippet_or_source) == type({}) && has_key(a:snippet_or_source, 'prefix') && has_key(a:snippet_or_source, 'body')
|
||||
endfunction
|
||||
|
||||
"
|
||||
" resolve_prefix.
|
||||
"
|
||||
function! vsnip#source#resolve_prefix(prefix) abort
|
||||
let l:prefixes = []
|
||||
let l:prefixes_alias = []
|
||||
|
||||
for l:prefix in type(a:prefix) == type([]) ? a:prefix : [a:prefix]
|
||||
" namspace.
|
||||
if strlen(g:vsnip_namespace) > 0
|
||||
call add(l:prefixes, g:vsnip_namespace . l:prefix)
|
||||
endif
|
||||
|
||||
" prefix.
|
||||
call add(l:prefixes, l:prefix)
|
||||
|
||||
" alias.
|
||||
if l:prefix =~# '^\h\w*\%(-\w\+\)\+$'
|
||||
call add(l:prefixes_alias, join(map(split(l:prefix, '-'), { i, v -> v[0] }), ''))
|
||||
endif
|
||||
endfor
|
||||
|
||||
return [
|
||||
\ sort(l:prefixes, { a, b -> strlen(b) - strlen(a) }),
|
||||
\ sort(l:prefixes_alias, { a, b -> strlen(b) - strlen(a) })
|
||||
\ ]
|
||||
endfunction
|
||||
|
||||
88
dot_vim/plugged/vim-vsnip/autoload/vsnip/source/snipmate.vim
Normal file
88
dot_vim/plugged/vim-vsnip/autoload/vsnip/source/snipmate.vim
Normal file
@@ -0,0 +1,88 @@
|
||||
let s:cache = {}
|
||||
|
||||
function! vsnip#source#snipmate#refresh(path) abort
|
||||
if has_key(s:cache, a:path)
|
||||
unlet s:cache[a:path]
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! vsnip#source#snipmate#find(bufnr) abort
|
||||
let filetypes = vsnip#source#filetypes(a:bufnr)
|
||||
return s:find(filetypes, a:bufnr)
|
||||
endfunction
|
||||
|
||||
function! s:find(filetypes, bufnr) abort
|
||||
let sources = []
|
||||
for path in s:get_source_paths(a:filetypes, a:bufnr)
|
||||
if !has_key(s:cache, path)
|
||||
let s:cache[path] = s:create(path, a:bufnr)
|
||||
endif
|
||||
call add(sources, s:cache[path])
|
||||
endfor
|
||||
return sources
|
||||
endfunction
|
||||
|
||||
function! s:get_source_paths(filetypes, bufnr) abort
|
||||
let paths = []
|
||||
for dir in s:get_source_dirs(a:bufnr)
|
||||
for filetype in a:filetypes
|
||||
let path = resolve(expand(printf('%s/%s.snippets', dir, filetype)))
|
||||
if has_key(s:cache, path) || filereadable(path)
|
||||
call add(paths, path)
|
||||
endif
|
||||
endfor
|
||||
endfor
|
||||
return paths
|
||||
endfunction
|
||||
|
||||
function! s:get_source_dirs(bufnr) abort
|
||||
let dirs = []
|
||||
let buf_dir = getbufvar(a:bufnr, 'vsnip_snippet_dir', '')
|
||||
if buf_dir !=# ''
|
||||
let dirs += [buf_dir]
|
||||
endif
|
||||
let dirs += getbufvar(a:bufnr, 'vsnip_snippet_dirs', [])
|
||||
let dirs += [g:vsnip_snippet_dir]
|
||||
let dirs += g:vsnip_snippet_dirs
|
||||
return dirs
|
||||
endfunction
|
||||
|
||||
function! s:create(path, bufnr) abort
|
||||
let file = readfile(a:path)
|
||||
let file = type(file) == v:t_list ? file : [file]
|
||||
call map(file, { _, f -> iconv(f, 'utf-8', &encoding) })
|
||||
let source = []
|
||||
let i = -1
|
||||
while i + 1 < len(file)
|
||||
let [i, line] = [i + 1, file[i + 1]]
|
||||
if line =~# '^\(#\|\s*$\)'
|
||||
" Comment, or blank line before snippets
|
||||
elseif line =~# '^extends\s\+\S'
|
||||
let filetypes = map(split(line[7:], ','), 'trim(v:val)')
|
||||
let source += flatten(s:find(filetypes, a:bufnr))
|
||||
elseif line =~# '^snippet\s\+\S' && i + 1 < len(file)
|
||||
let matched = matchlist(line, '^snippet\s\+\(\S\+\)\s*\(.*\)')
|
||||
let [prefix, description] = [matched[1], matched[2]]
|
||||
let body = []
|
||||
let indent = matchstr(file[i + 1], '^\s\+')
|
||||
while i + 1 < len(file) && file[i + 1] =~# '^\(' . indent . '\|\s*$\)'
|
||||
let [i, line] = [i + 1, file[i + 1]]
|
||||
call add(body, line[strlen(indent):])
|
||||
endwhile
|
||||
let [prefixes, prefixes_alias] = vsnip#source#resolve_prefix(prefix)
|
||||
call add(source, {
|
||||
\ 'label': prefix,
|
||||
\ 'prefix': prefixes,
|
||||
\ 'prefix_alias': prefixes_alias,
|
||||
\ 'body': body,
|
||||
\ 'description': description
|
||||
\ })
|
||||
else
|
||||
echohl ErrorMsg
|
||||
echomsg printf('[vsnip] Parsing error occurred on: %s#L%s', a:path, i + 1)
|
||||
echohl None
|
||||
break
|
||||
endif
|
||||
endwhile
|
||||
return sort(source, { a, b -> strlen(b.prefix[0]) - strlen(a.prefix[0]) })
|
||||
endfunction
|
||||
@@ -0,0 +1,69 @@
|
||||
let s:cache = {}
|
||||
|
||||
"
|
||||
" vsnip#source#user_snippet#find.
|
||||
"
|
||||
function! vsnip#source#user_snippet#find(bufnr) abort
|
||||
let l:sources = []
|
||||
for l:path in s:get_source_paths(a:bufnr)
|
||||
if !has_key(s:cache, l:path)
|
||||
let s:cache[l:path] = vsnip#source#create(l:path)
|
||||
endif
|
||||
call add(l:sources, s:cache[l:path])
|
||||
endfor
|
||||
return l:sources
|
||||
endfunction
|
||||
|
||||
"
|
||||
" vsnip#source#user_snippet#refresh.
|
||||
"
|
||||
function! vsnip#source#user_snippet#refresh(path) abort
|
||||
if has_key(s:cache, a:path)
|
||||
unlet s:cache[a:path]
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:get_source_dirs(bufnr) abort
|
||||
let l:dirs = []
|
||||
let l:buf_dir = getbufvar(a:bufnr, 'vsnip_snippet_dir', v:null)
|
||||
if l:buf_dir isnot v:null
|
||||
let l:dirs += [l:buf_dir]
|
||||
endif
|
||||
let l:dirs += getbufvar(a:bufnr, 'vsnip_snippet_dirs', [])
|
||||
let l:dirs += [g:vsnip_snippet_dir]
|
||||
let l:dirs += g:vsnip_snippet_dirs
|
||||
return l:dirs
|
||||
endfunction
|
||||
|
||||
"
|
||||
" get_source_paths.
|
||||
"
|
||||
function! s:get_source_paths(bufnr) abort
|
||||
let l:filetypes = vsnip#source#filetypes(a:bufnr)
|
||||
|
||||
let l:paths = []
|
||||
for l:dir in s:get_source_dirs(a:bufnr)
|
||||
for l:filetype in l:filetypes
|
||||
let l:path = resolve(expand(printf('%s/%s.json', l:dir, l:filetype)))
|
||||
if has_key(s:cache, l:path) || filereadable(l:path)
|
||||
call add(l:paths, l:path)
|
||||
endif
|
||||
endfor
|
||||
endfor
|
||||
return l:paths
|
||||
endfunction
|
||||
|
||||
"
|
||||
" vsnip#source#user_snippet#dirs
|
||||
"
|
||||
fun! vsnip#source#user_snippet#dirs(...) abort
|
||||
return s:get_source_dirs(a:0 ? a:1 : bufnr(''))
|
||||
endfun
|
||||
|
||||
"
|
||||
" vsnip#source#user_snippet#paths
|
||||
"
|
||||
fun! vsnip#source#user_snippet#paths(...) abort
|
||||
return s:get_source_paths(a:0 ? a:1 : bufnr(''))
|
||||
endfun
|
||||
|
||||
104
dot_vim/plugged/vim-vsnip/autoload/vsnip/source/vscode.vim
Normal file
104
dot_vim/plugged/vim-vsnip/autoload/vsnip/source/vscode.vim
Normal file
@@ -0,0 +1,104 @@
|
||||
let s:snippets = {}
|
||||
let s:runtimepaths = {}
|
||||
|
||||
"
|
||||
" vsnip#source#vscode#refresh.
|
||||
"
|
||||
function! vsnip#source#vscode#refresh(path) abort
|
||||
if has_key(s:snippets, a:path)
|
||||
unlet s:snippets[a:path]
|
||||
|
||||
for [l:rtp, l:v] in items(s:runtimepaths)
|
||||
if stridx(l:rtp, a:path) == 0
|
||||
unlet s:runtimepaths[l:rtp]
|
||||
endif
|
||||
endfor
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"
|
||||
" vsnip#source#vscode#find.
|
||||
"
|
||||
function! vsnip#source#vscode#find(bufnr) abort
|
||||
return s:find(map(vsnip#source#filetypes(a:bufnr), 's:get_language(v:val)'))
|
||||
endfunction
|
||||
|
||||
"
|
||||
" find.
|
||||
"
|
||||
function! s:find(languages) abort
|
||||
" Load `package.json#contributes.snippets` if does not exists it's cache.
|
||||
let l:rtp_list = exists('*nvim_list_runtime_paths') ? nvim_list_runtime_paths() : split(&runtimepath, ',')
|
||||
for l:rtp in l:rtp_list
|
||||
if has_key(s:runtimepaths, l:rtp)
|
||||
continue
|
||||
endif
|
||||
let s:runtimepaths[l:rtp] = v:true
|
||||
|
||||
try
|
||||
let l:package_json = resolve(expand(l:rtp . '/package.json'))
|
||||
if !filereadable(l:package_json)
|
||||
continue
|
||||
endif
|
||||
let l:package_json = readfile(l:package_json)
|
||||
let l:package_json = type(l:package_json) == type([]) ? join(l:package_json, "\n") : l:package_json
|
||||
let l:package_json = iconv(l:package_json, 'utf-8', &encoding)
|
||||
let l:package_json = json_decode(l:package_json)
|
||||
|
||||
" if package.json has not `contributes.snippets` fields, skip it.
|
||||
if !has_key(l:package_json, 'contributes')
|
||||
\ || !has_key(l:package_json.contributes, 'snippets')
|
||||
continue
|
||||
endif
|
||||
|
||||
" Create source if does not exists it's cache.
|
||||
for l:snippet in l:package_json.contributes.snippets
|
||||
let l:path = resolve(expand(l:rtp . '/' . l:snippet.path))
|
||||
let l:languages = type(l:snippet.language) == type([]) ? l:snippet.language : [l:snippet.language]
|
||||
|
||||
" if already cached `snippets.json`, add new language.
|
||||
if has_key(s:snippets, l:path)
|
||||
for l:language in l:languages
|
||||
if index(s:snippets[l:path].languages, l:language) == -1
|
||||
call add(s:snippets[l:path].languages, l:language)
|
||||
endif
|
||||
endfor
|
||||
continue
|
||||
endif
|
||||
|
||||
" register new snippet.
|
||||
let s:snippets[l:path] = {
|
||||
\ 'languages': l:languages,
|
||||
\ }
|
||||
endfor
|
||||
catch /.*/
|
||||
endtry
|
||||
endfor
|
||||
|
||||
" filter by language.
|
||||
let l:sources = []
|
||||
for l:language in a:languages
|
||||
for [l:path, l:snippet] in items(s:snippets)
|
||||
if index(l:snippet.languages, l:language) >= 0
|
||||
if !has_key(l:snippet, 'source')
|
||||
let l:snippet.source = vsnip#source#create(l:path)
|
||||
end
|
||||
call add(l:sources, l:snippet.source)
|
||||
endif
|
||||
endfor
|
||||
endfor
|
||||
return l:sources
|
||||
endfunction
|
||||
|
||||
"
|
||||
" get_language.
|
||||
"
|
||||
function! s:get_language(filetype) abort
|
||||
return get({
|
||||
\ 'javascript.jsx': 'javascriptreact',
|
||||
\ 'typescript.tsx': 'typescriptreact',
|
||||
\ 'sh': 'shellscript',
|
||||
\ 'cs': 'csharp',
|
||||
\ }, a:filetype, a:filetype)
|
||||
endfunction
|
||||
|
||||
189
dot_vim/plugged/vim-vsnip/autoload/vsnip/variable.vim
Normal file
189
dot_vim/plugged/vim-vsnip/autoload/vsnip/variable.vim
Normal file
@@ -0,0 +1,189 @@
|
||||
let s:variables = {}
|
||||
|
||||
"
|
||||
" vsnip#variable#register
|
||||
"
|
||||
function! vsnip#variable#register(name, func, ...) abort
|
||||
let l:option = get(a:000, 0, {})
|
||||
let s:variables[a:name] = {
|
||||
\ 'func': a:func,
|
||||
\ 'once': get(l:option, 'once', v:false)
|
||||
\ }
|
||||
endfunction
|
||||
|
||||
"
|
||||
" vsnip#variable#get
|
||||
"
|
||||
function! vsnip#variable#get(name) abort
|
||||
return get(s:variables, a:name, v:null)
|
||||
endfunction
|
||||
|
||||
"
|
||||
" Register built-in variables.
|
||||
"
|
||||
" @see https://code.visualstudio.com/docs/editor/userdefinedsnippets#_variables
|
||||
"
|
||||
|
||||
function! s:TM_SELECTED_TEXT(context) abort
|
||||
let l:selected_text = vsnip#selected_text()
|
||||
if empty(l:selected_text)
|
||||
return v:null
|
||||
endif
|
||||
return vsnip#indent#trim_base_indent(l:selected_text)
|
||||
endfunction
|
||||
call vsnip#variable#register('TM_SELECTED_TEXT', function('s:TM_SELECTED_TEXT'))
|
||||
|
||||
function! s:TM_CURRENT_LINE(context) abort
|
||||
return getline('.')
|
||||
endfunction
|
||||
call vsnip#variable#register('TM_CURRENT_LINE', function('s:TM_CURRENT_LINE'))
|
||||
|
||||
function! s:TM_CURRENT_WORD(context) abort
|
||||
return v:null
|
||||
endfunction
|
||||
call vsnip#variable#register('TM_CURRENT_WORD', function('s:TM_CURRENT_WORD'))
|
||||
|
||||
function! s:TM_LINE_INDEX(context) abort
|
||||
return line('.') - 1
|
||||
endfunction
|
||||
call vsnip#variable#register('TM_LINE_INDEX', function('s:TM_LINE_INDEX'))
|
||||
|
||||
function! s:TM_LINE_NUMBER(context) abort
|
||||
return line('.')
|
||||
endfunction
|
||||
call vsnip#variable#register('TM_LINE_NUMBER', function('s:TM_LINE_NUMBER'))
|
||||
|
||||
function! s:TM_FILENAME(context) abort
|
||||
return expand('%:p:t')
|
||||
endfunction
|
||||
call vsnip#variable#register('TM_FILENAME', function('s:TM_FILENAME'))
|
||||
|
||||
function! s:TM_FILENAME_BASE(context) abort
|
||||
return substitute(expand('%:p:t'), '^\@<!\..*$', '', '')
|
||||
endfunction
|
||||
call vsnip#variable#register('TM_FILENAME_BASE', function('s:TM_FILENAME_BASE'))
|
||||
|
||||
function! s:TM_DIRECTORY(context) abort
|
||||
return expand('%:p:h:t')
|
||||
endfunction
|
||||
call vsnip#variable#register('TM_DIRECTORY', function('s:TM_DIRECTORY'))
|
||||
|
||||
function! s:TM_FILEPATH(context) abort
|
||||
return expand('%:p')
|
||||
endfunction
|
||||
call vsnip#variable#register('TM_FILEPATH', function('s:TM_FILEPATH'))
|
||||
|
||||
function! s:RELATIVE_FILEPATH(context) abort
|
||||
return expand('%')
|
||||
endfunction
|
||||
call vsnip#variable#register('RELATIVE_FILEPATH', function('s:RELATIVE_FILEPATH'))
|
||||
|
||||
function! s:CLIPBOARD(context) abort
|
||||
let l:clipboard = getreg(v:register)
|
||||
if empty(l:clipboard)
|
||||
return v:null
|
||||
endif
|
||||
return vsnip#indent#trim_base_indent(l:clipboard)
|
||||
endfunction
|
||||
call vsnip#variable#register('CLIPBOARD', function('s:CLIPBOARD'))
|
||||
|
||||
function! s:WORKSPACE_NAME(context) abort
|
||||
return v:null
|
||||
endfunction
|
||||
call vsnip#variable#register('WORKSPACE_NAME', function('s:WORKSPACE_NAME'))
|
||||
|
||||
function! s:CURRENT_YEAR(context) abort
|
||||
return strftime('%Y')
|
||||
endfunction
|
||||
call vsnip#variable#register('CURRENT_YEAR', function('s:CURRENT_YEAR'))
|
||||
|
||||
function! s:CURRENT_YEAR_SHORT(context) abort
|
||||
return strftime('%y')
|
||||
endfunction
|
||||
call vsnip#variable#register('CURRENT_YEAR_SHORT', function('s:CURRENT_YEAR_SHORT'))
|
||||
|
||||
function! s:CURRENT_MONTH(context) abort
|
||||
return strftime('%m')
|
||||
endfunction
|
||||
call vsnip#variable#register('CURRENT_MONTH', function('s:CURRENT_MONTH'))
|
||||
|
||||
function! s:CURRENT_MONTH_NAME(context) abort
|
||||
return strftime('%B')
|
||||
endfunction
|
||||
call vsnip#variable#register('CURRENT_MONTH_NAME', function('s:CURRENT_MONTH_NAME'))
|
||||
|
||||
function! s:CURRENT_MONTH_NAME_SHORT(context) abort
|
||||
return strftime('%b')
|
||||
endfunction
|
||||
call vsnip#variable#register('CURRENT_MONTH_NAME_SHORT', function('s:CURRENT_MONTH_NAME_SHORT'))
|
||||
|
||||
function! s:CURRENT_DATE(context) abort
|
||||
return strftime('%d')
|
||||
endfunction
|
||||
call vsnip#variable#register('CURRENT_DATE', function('s:CURRENT_DATE'))
|
||||
|
||||
function! s:CURRENT_DAY_NAME(context) abort
|
||||
return strftime('%A')
|
||||
endfunction
|
||||
call vsnip#variable#register('CURRENT_DAY_NAME', function('s:CURRENT_DAY_NAME'))
|
||||
|
||||
function! s:CURRENT_DAY_NAME_SHORT(context) abort
|
||||
return strftime('%a')
|
||||
endfunction
|
||||
call vsnip#variable#register('CURRENT_DAY_NAME_SHORT', function('s:CURRENT_DAY_NAME_SHORT'))
|
||||
|
||||
function! s:CURRENT_HOUR(context) abort
|
||||
return strftime('%H')
|
||||
endfunction
|
||||
call vsnip#variable#register('CURRENT_HOUR', function('s:CURRENT_HOUR'))
|
||||
|
||||
function! s:CURRENT_MINUTE(context) abort
|
||||
return strftime('%M')
|
||||
endfunction
|
||||
call vsnip#variable#register('CURRENT_MINUTE', function('s:CURRENT_MINUTE'))
|
||||
|
||||
function! s:CURRENT_SECOND(context) abort
|
||||
return strftime('%S')
|
||||
endfunction
|
||||
call vsnip#variable#register('CURRENT_SECOND', function('s:CURRENT_SECOND'))
|
||||
|
||||
function! s:CURRENT_SECONDS_UNIX(context) abort
|
||||
return localtime()
|
||||
endfunction
|
||||
call vsnip#variable#register('CURRENT_SECONDS_UNIX', function('s:CURRENT_SECONDS_UNIX'))
|
||||
|
||||
function! s:BLOCK_COMMENT_START(context) abort
|
||||
return split(&commentstring, '%s')[0]
|
||||
endfunction
|
||||
call vsnip#variable#register('BLOCK_COMMENT_START', function('s:BLOCK_COMMENT_START'))
|
||||
|
||||
function! s:BLOCK_COMMENT_END(context) abort
|
||||
let l:chars = split(&commentstring, '%s')
|
||||
let l:comment = len(l:chars) > 1 ? l:chars[1] : l:chars[0]
|
||||
return trim(l:comment)
|
||||
endfunction
|
||||
call vsnip#variable#register('BLOCK_COMMENT_END', function('s:BLOCK_COMMENT_END'))
|
||||
|
||||
function! s:LINE_COMMENT(context) abort
|
||||
let l:chars = split(&commentstring, '%s')
|
||||
let l:comment = &commentstring =~# '^/\*' ? '//' : substitute(&commentstring, '%s', '', 'g')
|
||||
return trim(l:comment)
|
||||
endfunction
|
||||
call vsnip#variable#register('LINE_COMMENT', function('s:LINE_COMMENT'))
|
||||
|
||||
function! s:VIM(context) abort
|
||||
let l:script = join(map(copy(a:context.node.children), 'v:val.text()'), '')
|
||||
try
|
||||
return eval(l:script)
|
||||
catch /.*/
|
||||
endtry
|
||||
return v:null
|
||||
endfunction
|
||||
call vsnip#variable#register('VIM', function('s:VIM'))
|
||||
|
||||
function! s:VSNIP_CAMELCASE_FILENAME(context) abort
|
||||
let l:basename = substitute(expand('%:p:t'), '^\@<!\..*$', '', '')
|
||||
return substitute(l:basename, '\(\%(\<\l\+\)\%(_\)\@=\)\|_\(\l\)', '\u\1\2', 'g')
|
||||
endfunction
|
||||
call vsnip#variable#register('VSNIP_CAMELCASE_FILENAME', function('s:VSNIP_CAMELCASE_FILENAME'))
|
||||
|
||||
12
dot_vim/plugged/vim-vsnip/doc/tags
Normal file
12
dot_vim/plugged/vim-vsnip/doc/tags
Normal file
@@ -0,0 +1,12 @@
|
||||
vim-vsnip vsnip.txt /*vim-vsnip*
|
||||
vsnip vsnip.txt /*vsnip*
|
||||
vsnip-built-in-variable vsnip.txt /*vsnip-built-in-variable*
|
||||
vsnip-changelog vsnip.txt /*vsnip-changelog*
|
||||
vsnip-command vsnip.txt /*vsnip-command*
|
||||
vsnip-contents vsnip.txt /*vsnip-contents*
|
||||
vsnip-function vsnip.txt /*vsnip-function*
|
||||
vsnip-install vsnip.txt /*vsnip-install*
|
||||
vsnip-limitation vsnip.txt /*vsnip-limitation*
|
||||
vsnip-mapping vsnip.txt /*vsnip-mapping*
|
||||
vsnip-snipmate-support vsnip.txt /*vsnip-snipmate-support*
|
||||
vsnip-variable vsnip.txt /*vsnip-variable*
|
||||
323
dot_vim/plugged/vim-vsnip/doc/vsnip.txt
Normal file
323
dot_vim/plugged/vim-vsnip/doc/vsnip.txt
Normal file
@@ -0,0 +1,323 @@
|
||||
*vim-vsnip* *vsnip*
|
||||
|
||||
V(SCode) Snip(pet) like plugin.
|
||||
|
||||
|
||||
==============================================================================
|
||||
CONTENTS *vsnip-contents*
|
||||
|
||||
INSTALL |vsnip-install|
|
||||
VARIABLE |vsnip-variable|
|
||||
FUNCTION |vsnip-function|
|
||||
MAPPING |vsnip-mapping|
|
||||
COMMAND |vsnip-command|
|
||||
BUILT-IN VARIABLE |vsnip-built-in-variable|
|
||||
LIMITATION |vsnip-limitation|
|
||||
CHANGELOG |vsnip-changelog|
|
||||
|
||||
|
||||
|
||||
==============================================================================
|
||||
INSTALL *vsnip-install*
|
||||
|
||||
You can use your favorite plugin manager.
|
||||
|
||||
>
|
||||
" dein.vim
|
||||
call dein#add('hrsh7th/vim-vsnip')
|
||||
|
||||
" vim-plug
|
||||
Plug 'hrsh7th/vim-vsnip'
|
||||
|
||||
" neobundle
|
||||
NeoBundle 'hrsh7th/vim-vsnip'
|
||||
<
|
||||
|
||||
If you use `deoplete.nvim` or other supported integration, you can use `vim-vsnip-integ`.
|
||||
|
||||
>
|
||||
" dein.vim
|
||||
call dein#add('hrsh7th/vim-vsnip-integ')
|
||||
|
||||
" vim-plug
|
||||
Plug 'hrsh7th/vim-vsnip-integ'
|
||||
|
||||
" neobundle
|
||||
NeoBundle 'hrsh7th/vim-vsnip-integ'
|
||||
<
|
||||
|
||||
If you want to know supported plugins, you can see https://github.com/hrsh7th/vim-vsnip-integ
|
||||
|
||||
|
||||
|
||||
==============================================================================
|
||||
VARIABLE *vsnip-variable*
|
||||
|
||||
let g:vsnip_extra_mapping = v:true~
|
||||
Enable or disable extra mappings.
|
||||
|
||||
let g:vsnip_snippet_dir = expand('~/.vsnip')~
|
||||
Specify user snippet directory.
|
||||
Also as buffer-local variable: `b:vsnip_snippet_dir`
|
||||
|
||||
let g:vsnip_snippet_dirs = []~
|
||||
List of user snippet directories.
|
||||
Also as buffer-local variable: `b:vsnip_snippet_dirs`
|
||||
|
||||
let g:vsnip_filetypes = {}~
|
||||
Specify extended filetypes.
|
||||
For example, you can extend `javascript` filetype with `javascriptreact` filetype.
|
||||
>
|
||||
let g:vsnip_filetypes = {}
|
||||
let g:vsnip_filetypes.javascriptreact = ['javascript']
|
||||
<
|
||||
let g:vsnip_deactivate_on = g:vsnip#DeactivateOn.OutsideOfSnippet~
|
||||
Specify when to deactivate the current snippet.
|
||||
|
||||
`g:vsnip#DeactivateOn.OutsideOfSnippet`:
|
||||
Deactivate on edit the outside of snippet.
|
||||
`g:vsnip#DeactivateOn.OutsideOfCurrentTabstop`:
|
||||
Deactivate on edit the outside of current tabstop.
|
||||
|
||||
let g:vsnip_sync_delay = 0~
|
||||
Specify delay time to sync same tabstop placeholder.
|
||||
|
||||
-1: No sync
|
||||
0: Always sync
|
||||
N: Debounce N milliseconds
|
||||
|
||||
let g:vsnip_choice_delay = 500~
|
||||
Specify delay time to show choice candidates.
|
||||
Sometimes choice completion menu is closed by auto-completion engine.
|
||||
You can use this variable to solve this conflict.
|
||||
|
||||
let g:vsnip_namespace = ''~
|
||||
Specify all snippet prefix's prefix.
|
||||
It useful when you use auto-completion.
|
||||
|
||||
let g:vsnip_append_final_tabstop = v:true~
|
||||
Specify whether to add a final tabstop.
|
||||
|
||||
|
||||
|
||||
==============================================================================
|
||||
FUNCTION *vsnip-function*
|
||||
|
||||
vsnip#variable#register({VAR_NAME}, {FUNCREF}, [{OPTION}}])
|
||||
|
||||
Register your own custom variable resolver.
|
||||
|
||||
|
||||
|
||||
==============================================================================
|
||||
MAPPING *vsnip-mapping*
|
||||
|
||||
You can use your favorite key to expand or jump snippet.
|
||||
The below example uses '<Tab>' key.
|
||||
|
||||
>
|
||||
" Expand
|
||||
imap <expr> <C-j> vsnip#expandable() ? '<Plug>(vsnip-expand)' : '<C-j>'
|
||||
smap <expr> <C-j> vsnip#expandable() ? '<Plug>(vsnip-expand)' : '<C-j>'
|
||||
|
||||
" Expand or jump
|
||||
imap <expr> <C-l> vsnip#available(1) ? '<Plug>(vsnip-expand-or-jump)' : '<C-l>'
|
||||
smap <expr> <C-l> vsnip#available(1) ? '<Plug>(vsnip-expand-or-jump)' : '<C-l>'
|
||||
|
||||
" Jump forward or backward
|
||||
imap <expr> <Tab> vsnip#jumpable(1) ? '<Plug>(vsnip-jump-next)' : '<Tab>'
|
||||
smap <expr> <Tab> vsnip#jumpable(1) ? '<Plug>(vsnip-jump-next)' : '<Tab>'
|
||||
imap <expr> <S-Tab> vsnip#jumpable(-1) ? '<Plug>(vsnip-jump-prev)' : '<S-Tab>'
|
||||
smap <expr> <S-Tab> vsnip#jumpable(-1) ? '<Plug>(vsnip-jump-prev)' : '<S-Tab>'
|
||||
|
||||
" Select or cut text to use as $TM_SELECTED_TEXT in the next snippet.
|
||||
" See https://github.com/hrsh7th/vim-vsnip/pull/50
|
||||
nmap s <Plug>(vsnip-select-text)
|
||||
xmap s <Plug>(vsnip-select-text)
|
||||
nmap S <Plug>(vsnip-cut-text)
|
||||
xmap S <Plug>(vsnip-cut-text)
|
||||
<
|
||||
|
||||
|
||||
|
||||
==============================================================================
|
||||
COMMAND *vsnip-command*
|
||||
|
||||
VsnipOpen~
|
||||
|
||||
|
||||
:VsnipOpen [-format {type}]
|
||||
:VsnipOpenEdit [-format {type}]
|
||||
:VsnipOpenSplit [-format {type}]
|
||||
:VsnipOpenVsplit [-format {type}]
|
||||
|
||||
|
||||
Open snippet source file under `g:vsnip_snippet_dir`.
|
||||
{type} is either 'snipmate' or 'vscode'. If omitted, it is 'vscode'.
|
||||
|
||||
|
||||
VsnipYank~
|
||||
|
||||
Copy the given range formatted as json into the clipboard.
|
||||
Use this command to yank the current line as a snippet with the keyword 'key'
|
||||
and open the snippets file.
|
||||
>
|
||||
:VsnipYank key | VsnipOpen
|
||||
<
|
||||
|
||||
|
||||
|
||||
==============================================================================
|
||||
BULT-IN VARIABLE *vsnip-built-in-variable*
|
||||
|
||||
Basically, vsnip provides some of built-in variables that defined in VSCode or LSP spec.
|
||||
|
||||
The following variables can be used in the same way they are in VSCode:
|
||||
|
||||
`TM_SELECTED_TEXT` The currently selected text or the empty string
|
||||
`TM_CURRENT_LINE` The contents of the current line
|
||||
`TM_CURRENT_WORD` The contents of the word under cursor or the empty string
|
||||
`TM_LINE_INDEX` The zero-index based line number
|
||||
`TM_LINE_NUMBER` The one-index based line number
|
||||
`TM_FILENAME` The filename of the current document
|
||||
`TM_FILENAME_BASE` The filename of the current document without its extensions
|
||||
`TM_DIRECTORY` The directory of the current document
|
||||
`TM_FILEPATH` The full file path of the current document
|
||||
`RELATIVE_FILEPATH` The relative (to the current working directory) file path of the current document
|
||||
`CLIPBOARD` The contents of your clipboard
|
||||
`WORKSPACE_NAME` The name of the opened workspace or folder
|
||||
|
||||
For inserting the current date and time:
|
||||
|
||||
`CURRENT_YEAR` The current year
|
||||
`CURRENT_YEAR_SHORT` The current year's last two digits
|
||||
`CURRENT_MONTH` The month as two digits (example '02')
|
||||
`CURRENT_MONTH_NAME` The full name of the month (example 'July')
|
||||
`CURRENT_MONTH_NAME_SHORT` The short name of the month (example 'Jul')
|
||||
`CURRENT_DATE` The day of the month
|
||||
`CURRENT_DAY_NAME` The name of day (example 'Monday')
|
||||
`CURRENT_DAY_NAME_SHORT` The short name of the day (example 'Mon')
|
||||
`CURRENT_HOUR` The current hour in 24-hour clock format
|
||||
`CURRENT_MINUTE` The current minute
|
||||
`CURRENT_SECOND` The current second
|
||||
`CURRENT_SECONDS_UNIX` The number of seconds since the Unix epoch
|
||||
|
||||
For inserting line or block comments, honoring the current language:
|
||||
|
||||
`BLOCK_COMMENT_START` Example output: in PHP /* or in HTML <!--
|
||||
`BLOCK_COMMENT_END` Example output: in PHP */ or in HTML -->
|
||||
`LINE_COMMENT` Example output: in PHP //
|
||||
|
||||
|
||||
In addition, vsnip provides the below custom variables too.
|
||||
|
||||
`VSNIP_CAMELCASE_FILENAME` The filename of the current document without its extensions in CamelCase format
|
||||
|
||||
${VIM:...Vim script expression...}~
|
||||
|
||||
You can use this variable for `Vim script interpolation`.
|
||||
For example, the below snippet will be current filetype.
|
||||
|
||||
>
|
||||
{
|
||||
"filetype": {
|
||||
"prefix": "filetype",
|
||||
"body": "${VIM:&filetype}"
|
||||
}
|
||||
}
|
||||
<
|
||||
|
||||
You can also using any Vim script expression.
|
||||
|
||||
>
|
||||
{
|
||||
"sum": {
|
||||
"prefix": "sum",
|
||||
"body": "${VIM:1 + 2}"
|
||||
}
|
||||
}
|
||||
<
|
||||
|
||||
Currently, vsnip only once resolves variable at the snippet initialization.
|
||||
|
||||
|
||||
|
||||
|
||||
==============================================================================
|
||||
SNIPMATE SUPPORT *vsnip-snipmate-support*
|
||||
|
||||
Files with the extension 'snippets' in directories `g:vsnip_snippet_dir` or
|
||||
`g:vsnip_snippet_dirs` are recognized as snippets with SnipMate-like syntax.
|
||||
|
||||
NOTE: This feature does not guarantee that SnipMate's snippet collection can
|
||||
be read in its entirety. It is intended to provide an easy way for users to
|
||||
write their own new snippet definitions.
|
||||
|
||||
The following two examples are equivalent.
|
||||
In SnipMate format. >
|
||||
snippet fn vim's function
|
||||
function! $1($2) abort
|
||||
$0
|
||||
endfunction
|
||||
<
|
||||
In VSCode format. >
|
||||
{
|
||||
"fn": {
|
||||
"prefix": "fn",
|
||||
"body": [
|
||||
"function! $1($2) abort",
|
||||
"\t$0",
|
||||
"endfunction"
|
||||
],
|
||||
"description": "vim's function"
|
||||
}
|
||||
}
|
||||
<
|
||||
You can also use the extends syntax. For example, the first line of
|
||||
cpp.snippets should have this. >
|
||||
extends c
|
||||
<
|
||||
|
||||
|
||||
|
||||
|
||||
==============================================================================
|
||||
LIMITATION *vsnip-limitation*
|
||||
|
||||
Currently vsnip has below limitations.
|
||||
|
||||
1. placeholder transform feature is not supported.~
|
||||
I plan to support it later.
|
||||
|
||||
|
||||
2. if text diff has multiple candidates, always use last one.~
|
||||
|
||||
below snippet is not work for expected.
|
||||
>
|
||||
class $1${2: extends ${3:SuperClass}} {
|
||||
$0
|
||||
}
|
||||
<
|
||||
|
||||
below one is work as expected.
|
||||
>
|
||||
class $1 ${2:extends ${3:SuperClass} }{
|
||||
$0
|
||||
}
|
||||
<
|
||||
|
||||
3. if edit the placeholder that does not the current_tabstop, vsnip try to follow correctly but sometimes it makes unexpected result.~
|
||||
|
||||
For example, you expand `console.log(${1:foo}${2:bar}, ${2})`, remove `foo` and change `bar` without jump.
|
||||
In this case, vsnip will detects `$1 is edited.` so vsnip does not sync $2 placeholder.
|
||||
|
||||
|
||||
==============================================================================
|
||||
CHANGELOG *vsnip-changelog*
|
||||
|
||||
2019/12/01~
|
||||
- publish v2.
|
||||
|
||||
|
||||
==============================================================================
|
||||
vim:tw=78:ts=4:et:ft=help:norl:
|
||||
1
dot_vim/plugged/vim-vsnip/dot_git/HEAD
Normal file
1
dot_vim/plugged/vim-vsnip/dot_git/HEAD
Normal file
@@ -0,0 +1 @@
|
||||
ref: refs/heads/master
|
||||
0
dot_vim/plugged/vim-vsnip/dot_git/branches/.keep
Normal file
0
dot_vim/plugged/vim-vsnip/dot_git/branches/.keep
Normal file
11
dot_vim/plugged/vim-vsnip/dot_git/config
Normal file
11
dot_vim/plugged/vim-vsnip/dot_git/config
Normal file
@@ -0,0 +1,11 @@
|
||||
[core]
|
||||
repositoryformatversion = 0
|
||||
filemode = true
|
||||
bare = false
|
||||
logallrefupdates = true
|
||||
[remote "origin"]
|
||||
url = https://github.com/hrsh7th/vim-vsnip.git
|
||||
fetch = +refs/heads/*:refs/remotes/origin/*
|
||||
[branch "master"]
|
||||
remote = origin
|
||||
merge = refs/heads/master
|
||||
1
dot_vim/plugged/vim-vsnip/dot_git/description
Normal file
1
dot_vim/plugged/vim-vsnip/dot_git/description
Normal file
@@ -0,0 +1 @@
|
||||
Unnamed repository; edit this file 'description' to name the repository.
|
||||
@@ -0,0 +1,15 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# An example hook script to check the commit log message taken by
|
||||
# applypatch from an e-mail message.
|
||||
#
|
||||
# The hook should exit with non-zero status after issuing an
|
||||
# appropriate message if it wants to stop the commit. The hook is
|
||||
# allowed to edit the commit message file.
|
||||
#
|
||||
# To enable this hook, rename this file to "applypatch-msg".
|
||||
|
||||
. git-sh-setup
|
||||
commitmsg="$(git rev-parse --git-path hooks/commit-msg)"
|
||||
test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"}
|
||||
:
|
||||
24
dot_vim/plugged/vim-vsnip/dot_git/hooks/commit-msg.sample
Normal file
24
dot_vim/plugged/vim-vsnip/dot_git/hooks/commit-msg.sample
Normal file
@@ -0,0 +1,24 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# An example hook script to check the commit log message.
|
||||
# Called by "git commit" with one argument, the name of the file
|
||||
# that has the commit message. The hook should exit with non-zero
|
||||
# status after issuing an appropriate message if it wants to stop the
|
||||
# commit. The hook is allowed to edit the commit message file.
|
||||
#
|
||||
# To enable this hook, rename this file to "commit-msg".
|
||||
|
||||
# Uncomment the below to add a Signed-off-by line to the message.
|
||||
# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
|
||||
# hook is more suited to it.
|
||||
#
|
||||
# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
|
||||
# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
|
||||
|
||||
# This example catches duplicate Signed-off-by lines.
|
||||
|
||||
test "" = "$(grep '^Signed-off-by: ' "$1" |
|
||||
sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || {
|
||||
echo >&2 Duplicate Signed-off-by lines.
|
||||
exit 1
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use IPC::Open2;
|
||||
|
||||
# An example hook script to integrate Watchman
|
||||
# (https://facebook.github.io/watchman/) with git to speed up detecting
|
||||
# new and modified files.
|
||||
#
|
||||
# The hook is passed a version (currently 2) and last update token
|
||||
# formatted as a string and outputs to stdout a new update token and
|
||||
# all files that have been modified since the update token. Paths must
|
||||
# be relative to the root of the working tree and separated by a single NUL.
|
||||
#
|
||||
# To enable this hook, rename this file to "query-watchman" and set
|
||||
# 'git config core.fsmonitor .git/hooks/query-watchman'
|
||||
#
|
||||
my ($version, $last_update_token) = @ARGV;
|
||||
|
||||
# Uncomment for debugging
|
||||
# print STDERR "$0 $version $last_update_token\n";
|
||||
|
||||
# Check the hook interface version
|
||||
if ($version ne 2) {
|
||||
die "Unsupported query-fsmonitor hook version '$version'.\n" .
|
||||
"Falling back to scanning...\n";
|
||||
}
|
||||
|
||||
my $git_work_tree = get_working_dir();
|
||||
|
||||
my $retry = 1;
|
||||
|
||||
my $json_pkg;
|
||||
eval {
|
||||
require JSON::XS;
|
||||
$json_pkg = "JSON::XS";
|
||||
1;
|
||||
} or do {
|
||||
require JSON::PP;
|
||||
$json_pkg = "JSON::PP";
|
||||
};
|
||||
|
||||
launch_watchman();
|
||||
|
||||
sub launch_watchman {
|
||||
my $o = watchman_query();
|
||||
if (is_work_tree_watched($o)) {
|
||||
output_result($o->{clock}, @{$o->{files}});
|
||||
}
|
||||
}
|
||||
|
||||
sub output_result {
|
||||
my ($clockid, @files) = @_;
|
||||
|
||||
# Uncomment for debugging watchman output
|
||||
# open (my $fh, ">", ".git/watchman-output.out");
|
||||
# binmode $fh, ":utf8";
|
||||
# print $fh "$clockid\n@files\n";
|
||||
# close $fh;
|
||||
|
||||
binmode STDOUT, ":utf8";
|
||||
print $clockid;
|
||||
print "\0";
|
||||
local $, = "\0";
|
||||
print @files;
|
||||
}
|
||||
|
||||
sub watchman_clock {
|
||||
my $response = qx/watchman clock "$git_work_tree"/;
|
||||
die "Failed to get clock id on '$git_work_tree'.\n" .
|
||||
"Falling back to scanning...\n" if $? != 0;
|
||||
|
||||
return $json_pkg->new->utf8->decode($response);
|
||||
}
|
||||
|
||||
sub watchman_query {
|
||||
my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'watchman -j --no-pretty')
|
||||
or die "open2() failed: $!\n" .
|
||||
"Falling back to scanning...\n";
|
||||
|
||||
# In the query expression below we're asking for names of files that
|
||||
# changed since $last_update_token but not from the .git folder.
|
||||
#
|
||||
# To accomplish this, we're using the "since" generator to use the
|
||||
# recency index to select candidate nodes and "fields" to limit the
|
||||
# output to file names only. Then we're using the "expression" term to
|
||||
# further constrain the results.
|
||||
my $last_update_line = "";
|
||||
if (substr($last_update_token, 0, 1) eq "c") {
|
||||
$last_update_token = "\"$last_update_token\"";
|
||||
$last_update_line = qq[\n"since": $last_update_token,];
|
||||
}
|
||||
my $query = <<" END";
|
||||
["query", "$git_work_tree", {$last_update_line
|
||||
"fields": ["name"],
|
||||
"expression": ["not", ["dirname", ".git"]]
|
||||
}]
|
||||
END
|
||||
|
||||
# Uncomment for debugging the watchman query
|
||||
# open (my $fh, ">", ".git/watchman-query.json");
|
||||
# print $fh $query;
|
||||
# close $fh;
|
||||
|
||||
print CHLD_IN $query;
|
||||
close CHLD_IN;
|
||||
my $response = do {local $/; <CHLD_OUT>};
|
||||
|
||||
# Uncomment for debugging the watch response
|
||||
# open ($fh, ">", ".git/watchman-response.json");
|
||||
# print $fh $response;
|
||||
# close $fh;
|
||||
|
||||
die "Watchman: command returned no output.\n" .
|
||||
"Falling back to scanning...\n" if $response eq "";
|
||||
die "Watchman: command returned invalid output: $response\n" .
|
||||
"Falling back to scanning...\n" unless $response =~ /^\{/;
|
||||
|
||||
return $json_pkg->new->utf8->decode($response);
|
||||
}
|
||||
|
||||
sub is_work_tree_watched {
|
||||
my ($output) = @_;
|
||||
my $error = $output->{error};
|
||||
if ($retry > 0 and $error and $error =~ m/unable to resolve root .* directory (.*) is not watched/) {
|
||||
$retry--;
|
||||
my $response = qx/watchman watch "$git_work_tree"/;
|
||||
die "Failed to make watchman watch '$git_work_tree'.\n" .
|
||||
"Falling back to scanning...\n" if $? != 0;
|
||||
$output = $json_pkg->new->utf8->decode($response);
|
||||
$error = $output->{error};
|
||||
die "Watchman: $error.\n" .
|
||||
"Falling back to scanning...\n" if $error;
|
||||
|
||||
# Uncomment for debugging watchman output
|
||||
# open (my $fh, ">", ".git/watchman-output.out");
|
||||
# close $fh;
|
||||
|
||||
# Watchman will always return all files on the first query so
|
||||
# return the fast "everything is dirty" flag to git and do the
|
||||
# Watchman query just to get it over with now so we won't pay
|
||||
# the cost in git to look up each individual file.
|
||||
my $o = watchman_clock();
|
||||
$error = $output->{error};
|
||||
|
||||
die "Watchman: $error.\n" .
|
||||
"Falling back to scanning...\n" if $error;
|
||||
|
||||
output_result($o->{clock}, ("/"));
|
||||
$last_update_token = $o->{clock};
|
||||
|
||||
eval { launch_watchman() };
|
||||
return 0;
|
||||
}
|
||||
|
||||
die "Watchman: $error.\n" .
|
||||
"Falling back to scanning...\n" if $error;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub get_working_dir {
|
||||
my $working_dir;
|
||||
if ($^O =~ 'msys' || $^O =~ 'cygwin') {
|
||||
$working_dir = Win32::GetCwd();
|
||||
$working_dir =~ tr/\\/\//;
|
||||
} else {
|
||||
require Cwd;
|
||||
$working_dir = Cwd::cwd();
|
||||
}
|
||||
|
||||
return $working_dir;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# An example hook script to prepare a packed repository for use over
|
||||
# dumb transports.
|
||||
#
|
||||
# To enable this hook, rename this file to "post-update".
|
||||
|
||||
exec git update-server-info
|
||||
@@ -0,0 +1,14 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# An example hook script to verify what is about to be committed
|
||||
# by applypatch from an e-mail message.
|
||||
#
|
||||
# The hook should exit with non-zero status after issuing an
|
||||
# appropriate message if it wants to stop the commit.
|
||||
#
|
||||
# To enable this hook, rename this file to "pre-applypatch".
|
||||
|
||||
. git-sh-setup
|
||||
precommit="$(git rev-parse --git-path hooks/pre-commit)"
|
||||
test -x "$precommit" && exec "$precommit" ${1+"$@"}
|
||||
:
|
||||
49
dot_vim/plugged/vim-vsnip/dot_git/hooks/pre-commit.sample
Normal file
49
dot_vim/plugged/vim-vsnip/dot_git/hooks/pre-commit.sample
Normal file
@@ -0,0 +1,49 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# An example hook script to verify what is about to be committed.
|
||||
# Called by "git commit" with no arguments. The hook should
|
||||
# exit with non-zero status after issuing an appropriate message if
|
||||
# it wants to stop the commit.
|
||||
#
|
||||
# To enable this hook, rename this file to "pre-commit".
|
||||
|
||||
if git rev-parse --verify HEAD >/dev/null 2>&1
|
||||
then
|
||||
against=HEAD
|
||||
else
|
||||
# Initial commit: diff against an empty tree object
|
||||
against=$(git hash-object -t tree /dev/null)
|
||||
fi
|
||||
|
||||
# If you want to allow non-ASCII filenames set this variable to true.
|
||||
allownonascii=$(git config --type=bool hooks.allownonascii)
|
||||
|
||||
# Redirect output to stderr.
|
||||
exec 1>&2
|
||||
|
||||
# Cross platform projects tend to avoid non-ASCII filenames; prevent
|
||||
# them from being added to the repository. We exploit the fact that the
|
||||
# printable range starts at the space character and ends with tilde.
|
||||
if [ "$allownonascii" != "true" ] &&
|
||||
# Note that the use of brackets around a tr range is ok here, (it's
|
||||
# even required, for portability to Solaris 10's /usr/bin/tr), since
|
||||
# the square bracket bytes happen to fall in the designated range.
|
||||
test $(git diff --cached --name-only --diff-filter=A -z $against |
|
||||
LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
|
||||
then
|
||||
cat <<\EOF
|
||||
Error: Attempt to add a non-ASCII file name.
|
||||
|
||||
This can cause problems if you want to work with people on other platforms.
|
||||
|
||||
To be portable it is advisable to rename the file.
|
||||
|
||||
If you know what you are doing you can disable this check using:
|
||||
|
||||
git config hooks.allownonascii true
|
||||
EOF
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# If there are whitespace errors, print the offending file names and fail.
|
||||
exec git diff-index --check --cached $against --
|
||||
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# An example hook script to verify what is about to be committed.
|
||||
# Called by "git merge" with no arguments. The hook should
|
||||
# exit with non-zero status after issuing an appropriate message to
|
||||
# stderr if it wants to stop the merge commit.
|
||||
#
|
||||
# To enable this hook, rename this file to "pre-merge-commit".
|
||||
|
||||
. git-sh-setup
|
||||
test -x "$GIT_DIR/hooks/pre-commit" &&
|
||||
exec "$GIT_DIR/hooks/pre-commit"
|
||||
:
|
||||
53
dot_vim/plugged/vim-vsnip/dot_git/hooks/pre-push.sample
Normal file
53
dot_vim/plugged/vim-vsnip/dot_git/hooks/pre-push.sample
Normal file
@@ -0,0 +1,53 @@
|
||||
#!/bin/sh
|
||||
|
||||
# An example hook script to verify what is about to be pushed. Called by "git
|
||||
# push" after it has checked the remote status, but before anything has been
|
||||
# pushed. If this script exits with a non-zero status nothing will be pushed.
|
||||
#
|
||||
# This hook is called with the following parameters:
|
||||
#
|
||||
# $1 -- Name of the remote to which the push is being done
|
||||
# $2 -- URL to which the push is being done
|
||||
#
|
||||
# If pushing without using a named remote those arguments will be equal.
|
||||
#
|
||||
# Information about the commits which are being pushed is supplied as lines to
|
||||
# the standard input in the form:
|
||||
#
|
||||
# <local ref> <local oid> <remote ref> <remote oid>
|
||||
#
|
||||
# This sample shows how to prevent push of commits where the log message starts
|
||||
# with "WIP" (work in progress).
|
||||
|
||||
remote="$1"
|
||||
url="$2"
|
||||
|
||||
zero=$(git hash-object --stdin </dev/null | tr '[0-9a-f]' '0')
|
||||
|
||||
while read local_ref local_oid remote_ref remote_oid
|
||||
do
|
||||
if test "$local_oid" = "$zero"
|
||||
then
|
||||
# Handle delete
|
||||
:
|
||||
else
|
||||
if test "$remote_oid" = "$zero"
|
||||
then
|
||||
# New branch, examine all commits
|
||||
range="$local_oid"
|
||||
else
|
||||
# Update to existing branch, examine new commits
|
||||
range="$remote_oid..$local_oid"
|
||||
fi
|
||||
|
||||
# Check for WIP commit
|
||||
commit=$(git rev-list -n 1 --grep '^WIP' "$range")
|
||||
if test -n "$commit"
|
||||
then
|
||||
echo >&2 "Found WIP commit in $local_ref, not pushing"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
exit 0
|
||||
169
dot_vim/plugged/vim-vsnip/dot_git/hooks/pre-rebase.sample
Normal file
169
dot_vim/plugged/vim-vsnip/dot_git/hooks/pre-rebase.sample
Normal file
@@ -0,0 +1,169 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2006, 2008 Junio C Hamano
|
||||
#
|
||||
# The "pre-rebase" hook is run just before "git rebase" starts doing
|
||||
# its job, and can prevent the command from running by exiting with
|
||||
# non-zero status.
|
||||
#
|
||||
# The hook is called with the following parameters:
|
||||
#
|
||||
# $1 -- the upstream the series was forked from.
|
||||
# $2 -- the branch being rebased (or empty when rebasing the current branch).
|
||||
#
|
||||
# This sample shows how to prevent topic branches that are already
|
||||
# merged to 'next' branch from getting rebased, because allowing it
|
||||
# would result in rebasing already published history.
|
||||
|
||||
publish=next
|
||||
basebranch="$1"
|
||||
if test "$#" = 2
|
||||
then
|
||||
topic="refs/heads/$2"
|
||||
else
|
||||
topic=`git symbolic-ref HEAD` ||
|
||||
exit 0 ;# we do not interrupt rebasing detached HEAD
|
||||
fi
|
||||
|
||||
case "$topic" in
|
||||
refs/heads/??/*)
|
||||
;;
|
||||
*)
|
||||
exit 0 ;# we do not interrupt others.
|
||||
;;
|
||||
esac
|
||||
|
||||
# Now we are dealing with a topic branch being rebased
|
||||
# on top of master. Is it OK to rebase it?
|
||||
|
||||
# Does the topic really exist?
|
||||
git show-ref -q "$topic" || {
|
||||
echo >&2 "No such branch $topic"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Is topic fully merged to master?
|
||||
not_in_master=`git rev-list --pretty=oneline ^master "$topic"`
|
||||
if test -z "$not_in_master"
|
||||
then
|
||||
echo >&2 "$topic is fully merged to master; better remove it."
|
||||
exit 1 ;# we could allow it, but there is no point.
|
||||
fi
|
||||
|
||||
# Is topic ever merged to next? If so you should not be rebasing it.
|
||||
only_next_1=`git rev-list ^master "^$topic" ${publish} | sort`
|
||||
only_next_2=`git rev-list ^master ${publish} | sort`
|
||||
if test "$only_next_1" = "$only_next_2"
|
||||
then
|
||||
not_in_topic=`git rev-list "^$topic" master`
|
||||
if test -z "$not_in_topic"
|
||||
then
|
||||
echo >&2 "$topic is already up to date with master"
|
||||
exit 1 ;# we could allow it, but there is no point.
|
||||
else
|
||||
exit 0
|
||||
fi
|
||||
else
|
||||
not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"`
|
||||
/usr/bin/perl -e '
|
||||
my $topic = $ARGV[0];
|
||||
my $msg = "* $topic has commits already merged to public branch:\n";
|
||||
my (%not_in_next) = map {
|
||||
/^([0-9a-f]+) /;
|
||||
($1 => 1);
|
||||
} split(/\n/, $ARGV[1]);
|
||||
for my $elem (map {
|
||||
/^([0-9a-f]+) (.*)$/;
|
||||
[$1 => $2];
|
||||
} split(/\n/, $ARGV[2])) {
|
||||
if (!exists $not_in_next{$elem->[0]}) {
|
||||
if ($msg) {
|
||||
print STDERR $msg;
|
||||
undef $msg;
|
||||
}
|
||||
print STDERR " $elem->[1]\n";
|
||||
}
|
||||
}
|
||||
' "$topic" "$not_in_next" "$not_in_master"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
<<\DOC_END
|
||||
|
||||
This sample hook safeguards topic branches that have been
|
||||
published from being rewound.
|
||||
|
||||
The workflow assumed here is:
|
||||
|
||||
* Once a topic branch forks from "master", "master" is never
|
||||
merged into it again (either directly or indirectly).
|
||||
|
||||
* Once a topic branch is fully cooked and merged into "master",
|
||||
it is deleted. If you need to build on top of it to correct
|
||||
earlier mistakes, a new topic branch is created by forking at
|
||||
the tip of the "master". This is not strictly necessary, but
|
||||
it makes it easier to keep your history simple.
|
||||
|
||||
* Whenever you need to test or publish your changes to topic
|
||||
branches, merge them into "next" branch.
|
||||
|
||||
The script, being an example, hardcodes the publish branch name
|
||||
to be "next", but it is trivial to make it configurable via
|
||||
$GIT_DIR/config mechanism.
|
||||
|
||||
With this workflow, you would want to know:
|
||||
|
||||
(1) ... if a topic branch has ever been merged to "next". Young
|
||||
topic branches can have stupid mistakes you would rather
|
||||
clean up before publishing, and things that have not been
|
||||
merged into other branches can be easily rebased without
|
||||
affecting other people. But once it is published, you would
|
||||
not want to rewind it.
|
||||
|
||||
(2) ... if a topic branch has been fully merged to "master".
|
||||
Then you can delete it. More importantly, you should not
|
||||
build on top of it -- other people may already want to
|
||||
change things related to the topic as patches against your
|
||||
"master", so if you need further changes, it is better to
|
||||
fork the topic (perhaps with the same name) afresh from the
|
||||
tip of "master".
|
||||
|
||||
Let's look at this example:
|
||||
|
||||
o---o---o---o---o---o---o---o---o---o "next"
|
||||
/ / / /
|
||||
/ a---a---b A / /
|
||||
/ / / /
|
||||
/ / c---c---c---c B /
|
||||
/ / / \ /
|
||||
/ / / b---b C \ /
|
||||
/ / / / \ /
|
||||
---o---o---o---o---o---o---o---o---o---o---o "master"
|
||||
|
||||
|
||||
A, B and C are topic branches.
|
||||
|
||||
* A has one fix since it was merged up to "next".
|
||||
|
||||
* B has finished. It has been fully merged up to "master" and "next",
|
||||
and is ready to be deleted.
|
||||
|
||||
* C has not merged to "next" at all.
|
||||
|
||||
We would want to allow C to be rebased, refuse A, and encourage
|
||||
B to be deleted.
|
||||
|
||||
To compute (1):
|
||||
|
||||
git rev-list ^master ^topic next
|
||||
git rev-list ^master next
|
||||
|
||||
if these match, topic has not merged in next at all.
|
||||
|
||||
To compute (2):
|
||||
|
||||
git rev-list master..topic
|
||||
|
||||
if this is empty, it is fully merged to "master".
|
||||
|
||||
DOC_END
|
||||
24
dot_vim/plugged/vim-vsnip/dot_git/hooks/pre-receive.sample
Normal file
24
dot_vim/plugged/vim-vsnip/dot_git/hooks/pre-receive.sample
Normal file
@@ -0,0 +1,24 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# An example hook script to make use of push options.
|
||||
# The example simply echoes all push options that start with 'echoback='
|
||||
# and rejects all pushes when the "reject" push option is used.
|
||||
#
|
||||
# To enable this hook, rename this file to "pre-receive".
|
||||
|
||||
if test -n "$GIT_PUSH_OPTION_COUNT"
|
||||
then
|
||||
i=0
|
||||
while test "$i" -lt "$GIT_PUSH_OPTION_COUNT"
|
||||
do
|
||||
eval "value=\$GIT_PUSH_OPTION_$i"
|
||||
case "$value" in
|
||||
echoback=*)
|
||||
echo "echo from the pre-receive-hook: ${value#*=}" >&2
|
||||
;;
|
||||
reject)
|
||||
exit 1
|
||||
esac
|
||||
i=$((i + 1))
|
||||
done
|
||||
fi
|
||||
@@ -0,0 +1,42 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# An example hook script to prepare the commit log message.
|
||||
# Called by "git commit" with the name of the file that has the
|
||||
# commit message, followed by the description of the commit
|
||||
# message's source. The hook's purpose is to edit the commit
|
||||
# message file. If the hook fails with a non-zero status,
|
||||
# the commit is aborted.
|
||||
#
|
||||
# To enable this hook, rename this file to "prepare-commit-msg".
|
||||
|
||||
# This hook includes three examples. The first one removes the
|
||||
# "# Please enter the commit message..." help message.
|
||||
#
|
||||
# The second includes the output of "git diff --name-status -r"
|
||||
# into the message, just before the "git status" output. It is
|
||||
# commented because it doesn't cope with --amend or with squashed
|
||||
# commits.
|
||||
#
|
||||
# The third example adds a Signed-off-by line to the message, that can
|
||||
# still be edited. This is rarely a good idea.
|
||||
|
||||
COMMIT_MSG_FILE=$1
|
||||
COMMIT_SOURCE=$2
|
||||
SHA1=$3
|
||||
|
||||
/usr/bin/perl -i.bak -ne 'print unless(m/^. Please enter the commit message/..m/^#$/)' "$COMMIT_MSG_FILE"
|
||||
|
||||
# case "$COMMIT_SOURCE,$SHA1" in
|
||||
# ,|template,)
|
||||
# /usr/bin/perl -i.bak -pe '
|
||||
# print "\n" . `git diff --cached --name-status -r`
|
||||
# if /^#/ && $first++ == 0' "$COMMIT_MSG_FILE" ;;
|
||||
# *) ;;
|
||||
# esac
|
||||
|
||||
# SOB=$(git var GIT_COMMITTER_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
|
||||
# git interpret-trailers --in-place --trailer "$SOB" "$COMMIT_MSG_FILE"
|
||||
# if test -z "$COMMIT_SOURCE"
|
||||
# then
|
||||
# /usr/bin/perl -i.bak -pe 'print "\n" if !$first_line++' "$COMMIT_MSG_FILE"
|
||||
# fi
|
||||
@@ -0,0 +1,78 @@
|
||||
#!/bin/sh
|
||||
|
||||
# An example hook script to update a checked-out tree on a git push.
|
||||
#
|
||||
# This hook is invoked by git-receive-pack(1) when it reacts to git
|
||||
# push and updates reference(s) in its repository, and when the push
|
||||
# tries to update the branch that is currently checked out and the
|
||||
# receive.denyCurrentBranch configuration variable is set to
|
||||
# updateInstead.
|
||||
#
|
||||
# By default, such a push is refused if the working tree and the index
|
||||
# of the remote repository has any difference from the currently
|
||||
# checked out commit; when both the working tree and the index match
|
||||
# the current commit, they are updated to match the newly pushed tip
|
||||
# of the branch. This hook is to be used to override the default
|
||||
# behaviour; however the code below reimplements the default behaviour
|
||||
# as a starting point for convenient modification.
|
||||
#
|
||||
# The hook receives the commit with which the tip of the current
|
||||
# branch is going to be updated:
|
||||
commit=$1
|
||||
|
||||
# It can exit with a non-zero status to refuse the push (when it does
|
||||
# so, it must not modify the index or the working tree).
|
||||
die () {
|
||||
echo >&2 "$*"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Or it can make any necessary changes to the working tree and to the
|
||||
# index to bring them to the desired state when the tip of the current
|
||||
# branch is updated to the new commit, and exit with a zero status.
|
||||
#
|
||||
# For example, the hook can simply run git read-tree -u -m HEAD "$1"
|
||||
# in order to emulate git fetch that is run in the reverse direction
|
||||
# with git push, as the two-tree form of git read-tree -u -m is
|
||||
# essentially the same as git switch or git checkout that switches
|
||||
# branches while keeping the local changes in the working tree that do
|
||||
# not interfere with the difference between the branches.
|
||||
|
||||
# The below is a more-or-less exact translation to shell of the C code
|
||||
# for the default behaviour for git's push-to-checkout hook defined in
|
||||
# the push_to_deploy() function in builtin/receive-pack.c.
|
||||
#
|
||||
# Note that the hook will be executed from the repository directory,
|
||||
# not from the working tree, so if you want to perform operations on
|
||||
# the working tree, you will have to adapt your code accordingly, e.g.
|
||||
# by adding "cd .." or using relative paths.
|
||||
|
||||
if ! git update-index -q --ignore-submodules --refresh
|
||||
then
|
||||
die "Up-to-date check failed"
|
||||
fi
|
||||
|
||||
if ! git diff-files --quiet --ignore-submodules --
|
||||
then
|
||||
die "Working directory has unstaged changes"
|
||||
fi
|
||||
|
||||
# This is a rough translation of:
|
||||
#
|
||||
# head_has_history() ? "HEAD" : EMPTY_TREE_SHA1_HEX
|
||||
if git cat-file -e HEAD 2>/dev/null
|
||||
then
|
||||
head=HEAD
|
||||
else
|
||||
head=$(git hash-object -t tree --stdin </dev/null)
|
||||
fi
|
||||
|
||||
if ! git diff-index --quiet --cached --ignore-submodules $head --
|
||||
then
|
||||
die "Working directory has staged changes"
|
||||
fi
|
||||
|
||||
if ! git read-tree -u -m "$commit"
|
||||
then
|
||||
die "Could not update working tree to new HEAD"
|
||||
fi
|
||||
128
dot_vim/plugged/vim-vsnip/dot_git/hooks/update.sample
Normal file
128
dot_vim/plugged/vim-vsnip/dot_git/hooks/update.sample
Normal file
@@ -0,0 +1,128 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# An example hook script to block unannotated tags from entering.
|
||||
# Called by "git receive-pack" with arguments: refname sha1-old sha1-new
|
||||
#
|
||||
# To enable this hook, rename this file to "update".
|
||||
#
|
||||
# Config
|
||||
# ------
|
||||
# hooks.allowunannotated
|
||||
# This boolean sets whether unannotated tags will be allowed into the
|
||||
# repository. By default they won't be.
|
||||
# hooks.allowdeletetag
|
||||
# This boolean sets whether deleting tags will be allowed in the
|
||||
# repository. By default they won't be.
|
||||
# hooks.allowmodifytag
|
||||
# This boolean sets whether a tag may be modified after creation. By default
|
||||
# it won't be.
|
||||
# hooks.allowdeletebranch
|
||||
# This boolean sets whether deleting branches will be allowed in the
|
||||
# repository. By default they won't be.
|
||||
# hooks.denycreatebranch
|
||||
# This boolean sets whether remotely creating branches will be denied
|
||||
# in the repository. By default this is allowed.
|
||||
#
|
||||
|
||||
# --- Command line
|
||||
refname="$1"
|
||||
oldrev="$2"
|
||||
newrev="$3"
|
||||
|
||||
# --- Safety check
|
||||
if [ -z "$GIT_DIR" ]; then
|
||||
echo "Don't run this script from the command line." >&2
|
||||
echo " (if you want, you could supply GIT_DIR then run" >&2
|
||||
echo " $0 <ref> <oldrev> <newrev>)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
|
||||
echo "usage: $0 <ref> <oldrev> <newrev>" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- Config
|
||||
allowunannotated=$(git config --type=bool hooks.allowunannotated)
|
||||
allowdeletebranch=$(git config --type=bool hooks.allowdeletebranch)
|
||||
denycreatebranch=$(git config --type=bool hooks.denycreatebranch)
|
||||
allowdeletetag=$(git config --type=bool hooks.allowdeletetag)
|
||||
allowmodifytag=$(git config --type=bool hooks.allowmodifytag)
|
||||
|
||||
# check for no description
|
||||
projectdesc=$(sed -e '1q' "$GIT_DIR/description")
|
||||
case "$projectdesc" in
|
||||
"Unnamed repository"* | "")
|
||||
echo "*** Project description file hasn't been set" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# --- Check types
|
||||
# if $newrev is 0000...0000, it's a commit to delete a ref.
|
||||
zero=$(git hash-object --stdin </dev/null | tr '[0-9a-f]' '0')
|
||||
if [ "$newrev" = "$zero" ]; then
|
||||
newrev_type=delete
|
||||
else
|
||||
newrev_type=$(git cat-file -t $newrev)
|
||||
fi
|
||||
|
||||
case "$refname","$newrev_type" in
|
||||
refs/tags/*,commit)
|
||||
# un-annotated tag
|
||||
short_refname=${refname##refs/tags/}
|
||||
if [ "$allowunannotated" != "true" ]; then
|
||||
echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2
|
||||
echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
refs/tags/*,delete)
|
||||
# delete tag
|
||||
if [ "$allowdeletetag" != "true" ]; then
|
||||
echo "*** Deleting a tag is not allowed in this repository" >&2
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
refs/tags/*,tag)
|
||||
# annotated tag
|
||||
if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1
|
||||
then
|
||||
echo "*** Tag '$refname' already exists." >&2
|
||||
echo "*** Modifying a tag is not allowed in this repository." >&2
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
refs/heads/*,commit)
|
||||
# branch
|
||||
if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then
|
||||
echo "*** Creating a branch is not allowed in this repository" >&2
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
refs/heads/*,delete)
|
||||
# delete branch
|
||||
if [ "$allowdeletebranch" != "true" ]; then
|
||||
echo "*** Deleting a branch is not allowed in this repository" >&2
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
refs/remotes/*,commit)
|
||||
# tracking branch
|
||||
;;
|
||||
refs/remotes/*,delete)
|
||||
# delete tracking branch
|
||||
if [ "$allowdeletebranch" != "true" ]; then
|
||||
echo "*** Deleting a tracking branch is not allowed in this repository" >&2
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
# Anything else (is there anything else?)
|
||||
echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# --- Finished
|
||||
exit 0
|
||||
BIN
dot_vim/plugged/vim-vsnip/dot_git/index
Normal file
BIN
dot_vim/plugged/vim-vsnip/dot_git/index
Normal file
Binary file not shown.
6
dot_vim/plugged/vim-vsnip/dot_git/info/exclude
Normal file
6
dot_vim/plugged/vim-vsnip/dot_git/info/exclude
Normal file
@@ -0,0 +1,6 @@
|
||||
# git ls-files --others --exclude-from=.git/info/exclude
|
||||
# Lines that start with '#' are comments.
|
||||
# For a project mostly in C, the following would be a good set of
|
||||
# exclude patterns (uncomment them if you want to use them):
|
||||
# *.[oa]
|
||||
# *~
|
||||
2
dot_vim/plugged/vim-vsnip/dot_git/logs/HEAD
Normal file
2
dot_vim/plugged/vim-vsnip/dot_git/logs/HEAD
Normal file
@@ -0,0 +1,2 @@
|
||||
0000000000000000000000000000000000000000 8dde8c0ef10bb1afdbb301e2bd7eb1c153dd558e LinlyBoi <libkyy@e.email> 1676062730 +0200 clone: from https://github.com/hrsh7th/vim-vsnip.git
|
||||
8dde8c0ef10bb1afdbb301e2bd7eb1c153dd558e 8dde8c0ef10bb1afdbb301e2bd7eb1c153dd558e LinlyBoi <libkyy@e.email> 1676062731 +0200 checkout: moving from master to master
|
||||
1
dot_vim/plugged/vim-vsnip/dot_git/logs/refs/heads/master
Normal file
1
dot_vim/plugged/vim-vsnip/dot_git/logs/refs/heads/master
Normal file
@@ -0,0 +1 @@
|
||||
0000000000000000000000000000000000000000 8dde8c0ef10bb1afdbb301e2bd7eb1c153dd558e LinlyBoi <libkyy@e.email> 1676062730 +0200 clone: from https://github.com/hrsh7th/vim-vsnip.git
|
||||
@@ -0,0 +1 @@
|
||||
0000000000000000000000000000000000000000 8dde8c0ef10bb1afdbb301e2bd7eb1c153dd558e LinlyBoi <libkyy@e.email> 1676062730 +0200 clone: from https://github.com/hrsh7th/vim-vsnip.git
|
||||
Binary file not shown.
Binary file not shown.
8
dot_vim/plugged/vim-vsnip/dot_git/packed-refs
Normal file
8
dot_vim/plugged/vim-vsnip/dot_git/packed-refs
Normal file
@@ -0,0 +1,8 @@
|
||||
# pack-refs with: peeled fully-peeled sorted
|
||||
920cb43d5904726aa05efbae2e135bca6275ce4a refs/remotes/origin/custom-variable
|
||||
c947871a69a614113617649bf7717308576fa602 refs/remotes/origin/editor
|
||||
130b118ec45ecb9799cb0263baa76b191be27d10 refs/remotes/origin/fix-issue249
|
||||
eee2a1b15b44ec73f96d19ae4667123d51ca15f7 refs/remotes/origin/improve-sync
|
||||
8dde8c0ef10bb1afdbb301e2bd7eb1c153dd558e refs/remotes/origin/master
|
||||
d75388bd7e395e1960bac2145b4699ab0c2ba4e7 refs/remotes/origin/prefer-depth
|
||||
2c3e2b203d49802f1bac0b16ef4132d42c6b128e refs/remotes/origin/refactor-node
|
||||
1
dot_vim/plugged/vim-vsnip/dot_git/refs/heads/master
Normal file
1
dot_vim/plugged/vim-vsnip/dot_git/refs/heads/master
Normal file
@@ -0,0 +1 @@
|
||||
8dde8c0ef10bb1afdbb301e2bd7eb1c153dd558e
|
||||
@@ -0,0 +1 @@
|
||||
ref: refs/remotes/origin/master
|
||||
0
dot_vim/plugged/vim-vsnip/dot_git/refs/tags/.keep
Normal file
0
dot_vim/plugged/vim-vsnip/dot_git/refs/tags/.keep
Normal file
7
dot_vim/plugged/vim-vsnip/dot_git/shallow
Normal file
7
dot_vim/plugged/vim-vsnip/dot_git/shallow
Normal file
@@ -0,0 +1,7 @@
|
||||
130b118ec45ecb9799cb0263baa76b191be27d10
|
||||
2c3e2b203d49802f1bac0b16ef4132d42c6b128e
|
||||
8dde8c0ef10bb1afdbb301e2bd7eb1c153dd558e
|
||||
920cb43d5904726aa05efbae2e135bca6275ce4a
|
||||
c947871a69a614113617649bf7717308576fa602
|
||||
d75388bd7e395e1960bac2145b4699ab0c2ba4e7
|
||||
eee2a1b15b44ec73f96d19ae4667123d51ca15f7
|
||||
@@ -0,0 +1,49 @@
|
||||
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.4
|
||||
- name: neovim-nightly-x64
|
||||
os: ubuntu-latest
|
||||
neovim_version: nightly
|
||||
runs-on: ${{matrix.os}}
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- 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.5 --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
|
||||
ls -al
|
||||
export VIRTUALEDIT=0
|
||||
themis ./spec
|
||||
export VIRTUALEDIT=1
|
||||
themis ./spec
|
||||
|
||||
50
dot_vim/plugged/vim-vsnip/dot_github/workflows/linux_vim.yml
Normal file
50
dot_vim/plugged/vim-vsnip/dot_github/workflows/linux_vim.yml
Normal file
@@ -0,0 +1,50 @@
|
||||
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@v1
|
||||
- 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.5 --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
|
||||
ls -al
|
||||
export VIRTUALEDIT=0
|
||||
themis ./spec
|
||||
export VIRTUALEDIT=1
|
||||
themis ./spec
|
||||
@@ -0,0 +1,49 @@
|
||||
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.4
|
||||
- name: neovim-nightly-x64
|
||||
os: macos-latest
|
||||
neovim_version: nightly
|
||||
runs-on: ${{matrix.os}}
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- 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.5 --single-branch https://github.com/thinca/vim-themis ~/themis
|
||||
- name: Run tests
|
||||
shell: bash
|
||||
run: |
|
||||
export PATH=~/nvim-osx64/bin:$PATH
|
||||
export PATH=~/langservers:$PATH
|
||||
export PATH=~/themis/bin:$PATH
|
||||
export THEMIS_VIM=nvim
|
||||
nvim --version
|
||||
ls -al
|
||||
export VIRTUALEDIT=0
|
||||
themis ./spec
|
||||
export VIRTUALEDIT=1
|
||||
themis ./spec
|
||||
@@ -0,0 +1,50 @@
|
||||
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.4
|
||||
neovim_arch: win64
|
||||
- name: neovim-nightly-x64
|
||||
os: windows-latest
|
||||
neovim_version: nightly
|
||||
neovim_arch: win64
|
||||
runs-on: ${{matrix.os}}
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- 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.5 --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
|
||||
ls -al
|
||||
export VIRTUALEDIT=0
|
||||
themis ./spec
|
||||
export VIRTUALEDIT=1
|
||||
themis ./spec
|
||||
@@ -0,0 +1,56 @@
|
||||
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@v1
|
||||
- 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.5 --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
|
||||
ls -al
|
||||
export VIRTUALEDIT=0
|
||||
themis ./spec
|
||||
export VIRTUALEDIT=1
|
||||
themis ./spec
|
||||
2
dot_vim/plugged/vim-vsnip/dot_gitignore
Normal file
2
dot_vim/plugged/vim-vsnip/dot_gitignore
Normal file
@@ -0,0 +1,2 @@
|
||||
node_modules
|
||||
/doc/tags
|
||||
1
dot_vim/plugged/vim-vsnip/dot_npmrc
Normal file
1
dot_vim/plugged/vim-vsnip/dot_npmrc
Normal file
@@ -0,0 +1 @@
|
||||
package-lock=false
|
||||
58
dot_vim/plugged/vim-vsnip/dot_themisrc
Normal file
58
dot_vim/plugged/vim-vsnip/dot_themisrc
Normal file
@@ -0,0 +1,58 @@
|
||||
call themis#option('recursive', 1)
|
||||
call themis#option('exclude', '\.vim$')
|
||||
|
||||
set shiftwidth=2
|
||||
set expandtab
|
||||
|
||||
if get(environ(), 'VIRTUALEDIT', '0') == '1'
|
||||
set virtualedit=all
|
||||
else
|
||||
set virtualedit=
|
||||
endif
|
||||
if get(environ(), 'EXCLUSIVE', '0') == '1'
|
||||
set selection=exclusive
|
||||
else
|
||||
set selection=inclusive
|
||||
endif
|
||||
|
||||
let g:vsnip_test_mode = v:true
|
||||
let g:vsnip_snippet_dir = fnamemodify(expand('<sfile>'), ':h') . '/misc'
|
||||
let g:vsnip_deactivate_on = g:vsnip#DeactivateOn.OutsideOfSnippet
|
||||
let g:vsnip_filetypes = {}
|
||||
let g:vsnip_filetypes.source_spec_enhanced = ['source_spec']
|
||||
|
||||
let &runtimepath .= ',' . g:vsnip_snippet_dir . '/source_spec_vscode'
|
||||
|
||||
inoremap <Plug>(vsnip-C-j) <C-j>
|
||||
inoremap <Plug>(vsnip-Tab) <Tab>
|
||||
inoremap <Plug>(vsnip-S-Tab) <S-Tab>
|
||||
|
||||
imap <expr> <C-j> vsnip#expandable() ? '<Plug>(vsnip-expand)' : '<Plug>(vsnip-C-j)'
|
||||
smap <expr> <C-j> vsnip#expandable() ? '<Plug>(vsnip-expand)' : '<Plug>(vsnip-C-j)'
|
||||
|
||||
imap <expr> <Tab> vsnip#available(1) ? '<Plug>(vsnip-expand-or-jump)' : '<Plug>(vsnip-Tab)'
|
||||
smap <expr> <Tab> vsnip#jumpable(1) ? '<Plug>(vsnip-jump-next)' : '<Plug>(vsnip-Tab)'
|
||||
imap <expr> <S-Tab> vsnip#jumpable(-1) ? '<Plug>(vsnip-jump-prev)' : '<Plug>(vsnip-S-Tab)'
|
||||
smap <expr> <S-Tab> vsnip#jumpable(-1) ? '<Plug>(vsnip-jump-prev)' : '<Plug>(vsnip-S-Tab)'
|
||||
|
||||
imap <Plug>(vsnip-assert) <C-r>=<SID>assert()<CR>
|
||||
nmap <expr><Plug>(vsnip-assert) <SID>assert()
|
||||
smap <expr><Plug>(vsnip-assert) <SID>assert()
|
||||
|
||||
function! s:assert() abort
|
||||
let l:keys = sort(keys(g:vsnip_assert))
|
||||
if len(l:keys) > 0
|
||||
let l:session = vsnip#get_session()
|
||||
if !empty(l:session)
|
||||
call l:session.on_text_changed()
|
||||
endif
|
||||
|
||||
let l:key = l:keys[0]
|
||||
let l:Fn = g:vsnip_assert[l:key]
|
||||
unlet! g:vsnip_assert[l:key]
|
||||
call l:Fn()
|
||||
endif
|
||||
|
||||
return ''
|
||||
endfunction
|
||||
|
||||
47
dot_vim/plugged/vim-vsnip/dot_vimrc
Normal file
47
dot_vim/plugged/vim-vsnip/dot_vimrc
Normal file
@@ -0,0 +1,47 @@
|
||||
if has('vim_starting')
|
||||
set encoding=utf-8
|
||||
endif
|
||||
scriptencoding utf-8
|
||||
|
||||
if &compatible
|
||||
" vint: -ProhibitSetNoCompatible
|
||||
set nocompatible
|
||||
endif
|
||||
|
||||
if !isdirectory(expand('~/.vim/plugged/vim-plug'))
|
||||
silent !curl -fLo ~/.vim/plugged/vim-plug/plug.vim --create-dirs https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
|
||||
end
|
||||
execute printf('source %s', expand('~/.vim/plugged/vim-plug/plug.vim'))
|
||||
|
||||
call plug#begin('~/.vim/plugged')
|
||||
Plug 'gruvbox-community/gruvbox'
|
||||
Plug expand('<sfile>:p:h:h') . '/vim-vsnip'
|
||||
Plug expand('<sfile>:p:h:h') . '/vim-vsnip-integ'
|
||||
call plug#end()
|
||||
|
||||
PlugInstall
|
||||
|
||||
colorscheme gruvbox
|
||||
|
||||
let g:mapleader = ' '
|
||||
|
||||
"
|
||||
" required options.
|
||||
"
|
||||
set hidden
|
||||
set ambiwidth=double
|
||||
set completeopt=menu,menuone,noselect
|
||||
|
||||
let g:vsnip_snippet_dirs = [dein#get('vim-vsnip').rtp . '/misc']
|
||||
|
||||
"
|
||||
" vim-vsnip mapping.
|
||||
"
|
||||
imap <expr><C-j> vsnip#available(1) ? '<Plug>(vsnip-expand-or-jump)' : '<C-j>'
|
||||
smap <expr><C-j> vsnip#available(1) ? '<Plug>(vsnip-expand-or-jump)' : '<C-j>'
|
||||
|
||||
imap <expr><Tab> vsnip#available(1) ? '<Plug>(vsnip-jump-next)' : '<Tab>'
|
||||
smap <expr><Tab> vsnip#available(1) ? '<Plug>(vsnip-jump-next)' : '<Tab>'
|
||||
imap <expr><S-Tab> vsnip#available(-1) ? '<Plug>(vsnip-jump-prev)' : '<S-Tab>'
|
||||
smap <expr><S-Tab> vsnip#available(-1) ? '<Plug>(vsnip-jump-prev)' : '<S-Tab>'
|
||||
|
||||
39
dot_vim/plugged/vim-vsnip/ftplugin/snippets.vim
Normal file
39
dot_vim/plugged/vim-vsnip/ftplugin/snippets.vim
Normal file
@@ -0,0 +1,39 @@
|
||||
" MIT License
|
||||
"
|
||||
" Copyright 2009-2010 Michael Sanders. All rights reserved.
|
||||
|
||||
" 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." From https://github.com/garbas/vim-snipmate
|
||||
|
||||
|
||||
" Vim filetype plugin for SnipMate snippets (.snippets and .snippet files)
|
||||
|
||||
if exists("b:did_ftplugin")
|
||||
finish
|
||||
endif
|
||||
let b:did_ftplugin = 1
|
||||
|
||||
let b:undo_ftplugin = "setl et< sts< cms< fdm< fde<"
|
||||
|
||||
" Use hard tabs
|
||||
setlocal noexpandtab softtabstop=0
|
||||
|
||||
setlocal foldmethod=expr foldexpr=getline(v:lnum)!~'^\\t\\\\|^$'?'>1':1
|
||||
|
||||
setlocal commentstring=#\ %s
|
||||
setlocal nospell
|
||||
55
dot_vim/plugged/vim-vsnip/indent/snippets.vim
Normal file
55
dot_vim/plugged/vim-vsnip/indent/snippets.vim
Normal file
@@ -0,0 +1,55 @@
|
||||
" MIT License
|
||||
"
|
||||
" Copyright 2009-2010 Michael Sanders. All rights reserved.
|
||||
|
||||
" 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." From https://github.com/garbas/vim-snipmate
|
||||
|
||||
|
||||
" Simple indent support for SnipMate snippets files
|
||||
|
||||
if exists('b:did_indent')
|
||||
finish
|
||||
endif
|
||||
let b:did_indent = 1
|
||||
|
||||
setlocal nosmartindent
|
||||
setlocal indentkeys=!^F,o,O,=snippet,=extends
|
||||
setlocal indentexpr=GetSnippetIndent()
|
||||
|
||||
if exists("*GetSnippetIndent")
|
||||
finish
|
||||
endif
|
||||
|
||||
function! GetSnippetIndent()
|
||||
let line = getline(v:lnum)
|
||||
let prev_lnum = v:lnum - 1
|
||||
let prev_line = prev_lnum != 0 ? getline(prev_lnum) : ""
|
||||
|
||||
if line =~# '\v^(snippet|extends) '
|
||||
return 0
|
||||
elseif indent(v:lnum) > 0
|
||||
return indent(v:lnum)
|
||||
elseif prev_line =~# '^snippet '
|
||||
return &sw
|
||||
elseif indent(prev_lnum) > 0
|
||||
return indent(prev_lnum)
|
||||
endif
|
||||
|
||||
return 0
|
||||
endfunction
|
||||
16
dot_vim/plugged/vim-vsnip/misc/basic_spec.json
Normal file
16
dot_vim/plugged/vim-vsnip/misc/basic_spec.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"if": {
|
||||
"prefix": "if",
|
||||
"body": [
|
||||
"if ${1:condition}",
|
||||
"\t$0",
|
||||
"endif"
|
||||
]
|
||||
},
|
||||
"inline-fn": {
|
||||
"prefix": ["inline-fn"],
|
||||
"body": [
|
||||
"{ -> $1 }$0"
|
||||
]
|
||||
}
|
||||
}
|
||||
185
dot_vim/plugged/vim-vsnip/misc/integration.json
Normal file
185
dot_vim/plugged/vim-vsnip/misc/integration.json
Normal file
@@ -0,0 +1,185 @@
|
||||
{
|
||||
"spec1": {
|
||||
"description": "simple snippet",
|
||||
"prefix": ["spec1"],
|
||||
"body": [
|
||||
"snippet"
|
||||
]
|
||||
},
|
||||
"spec2": {
|
||||
"description": "jump at first of snippet",
|
||||
"prefix": ["spec2"],
|
||||
"body": [
|
||||
"$1$2snippet"
|
||||
]
|
||||
},
|
||||
"spec3": {
|
||||
"description": "jump at middle of snippet",
|
||||
"prefix": ["spec3"],
|
||||
"body": [
|
||||
"$1sni$2ppet"
|
||||
]
|
||||
},
|
||||
"spec4": {
|
||||
"description": "jump at last of snippet",
|
||||
"prefix": ["spec4"],
|
||||
"body": [
|
||||
"$1snippet"
|
||||
]
|
||||
},
|
||||
"spec5": {
|
||||
"description": "select 1 length first of snippet text",
|
||||
"prefix": ["spec5"],
|
||||
"body": [
|
||||
"$1${2:s}nippet"
|
||||
]
|
||||
},
|
||||
"spec6": {
|
||||
"description": "select 1 length middle of snippet text",
|
||||
"prefix": ["spec6"],
|
||||
"body": [
|
||||
"$1sn${2:i}ppet"
|
||||
]
|
||||
},
|
||||
"spec7": {
|
||||
"description": "select 1 length last of snippet text",
|
||||
"prefix": ["spec7"],
|
||||
"body": [
|
||||
"$1snippe${2:t}"
|
||||
]
|
||||
},
|
||||
"spec8": {
|
||||
"description": "select 3 length first of snippet text",
|
||||
"prefix": ["spec8"],
|
||||
"body": [
|
||||
"$1${2:sni}ppet"
|
||||
]
|
||||
},
|
||||
"spec9": {
|
||||
"description": "select 3 length middle of snippet text",
|
||||
"prefix": ["spec9"],
|
||||
"body": [
|
||||
"$1sn${2:ipp}et"
|
||||
]
|
||||
},
|
||||
"spec10": {
|
||||
"description": "select 3 length last of snippet text",
|
||||
"prefix": ["spec10"],
|
||||
"body": [
|
||||
"$1snip${2:pet}"
|
||||
]
|
||||
},
|
||||
"multi1": {
|
||||
"description": "jump at middle of snippet",
|
||||
"prefix": ["マルチ1"],
|
||||
"body": [
|
||||
"あ$1い$2う"
|
||||
]
|
||||
},
|
||||
"multi2": {
|
||||
"description": "select 4 length middle of snippet text",
|
||||
"prefix": ["マルチ2"],
|
||||
"body": [
|
||||
"あ$1い${2:かkaか}う"
|
||||
]
|
||||
},
|
||||
"deactivate1": {
|
||||
"prefix": "deactivate",
|
||||
"body": [
|
||||
"function! $1() abort",
|
||||
"\t$0",
|
||||
"endfunction"
|
||||
]
|
||||
},
|
||||
"realworld1": {
|
||||
"description": "Complex example",
|
||||
"prefix": ["realworld1"],
|
||||
"body": [
|
||||
"/** @class ${1:ClassName} */",
|
||||
"class ${1} ${2:extends ${3:ParentClassName} }{",
|
||||
"\tpublic constructor() {",
|
||||
"\t\t$0",
|
||||
"\t}",
|
||||
"}"
|
||||
]
|
||||
},
|
||||
"realworld2": {
|
||||
"description": "$VIM variable",
|
||||
"prefix": ["realworld2"],
|
||||
"body": [
|
||||
"${VIM:\\$USER}"
|
||||
]
|
||||
},
|
||||
"realworld3": {
|
||||
"description": "indented $TM_SELECTED_TEXT",
|
||||
"prefix": ["realworld3"],
|
||||
"body": [
|
||||
"<div>",
|
||||
"\t$TM_SELECTED_TEXT",
|
||||
"</div>"
|
||||
]
|
||||
},
|
||||
"realworld4": {
|
||||
"description": "no indented $TM_SELECTED_TEXT",
|
||||
"prefix": ["realworld4"],
|
||||
"body": [
|
||||
"<div>$TM_SELECTED_TEXT</div>"
|
||||
]
|
||||
},
|
||||
"realworld5": {
|
||||
"description": "modify follower placeholder manually",
|
||||
"prefix": ["realworld5"],
|
||||
"body": [
|
||||
"$1, ${2:_${3:___$1___}_}"
|
||||
]
|
||||
},
|
||||
"issue82": {
|
||||
"description": "issue82",
|
||||
"prefix": ["'"],
|
||||
"body": [
|
||||
"'$0'"
|
||||
]
|
||||
},
|
||||
"issue85": {
|
||||
"description": "issue85",
|
||||
"prefix": ["issue85"],
|
||||
"body": [
|
||||
"for ${1:i}=${2:1},${3:10}",
|
||||
"\t${0:print(i)}"
|
||||
]
|
||||
},
|
||||
"issue106": {
|
||||
"description": "issue106",
|
||||
"prefix": ["issue106"],
|
||||
"body": [
|
||||
"$1"
|
||||
]
|
||||
},
|
||||
"issue122": {
|
||||
"description": "issue122",
|
||||
"prefix": ["issue122>"],
|
||||
"body": [
|
||||
"$1"
|
||||
]
|
||||
},
|
||||
"issue129": {
|
||||
"description": "issue129",
|
||||
"prefix": ["issue129"],
|
||||
"body": [
|
||||
"console.log('$1', $2);"
|
||||
]
|
||||
},
|
||||
"issue139": {
|
||||
"description": "issue139",
|
||||
"prefix": "issue139",
|
||||
"body": [
|
||||
"for (${1:size_t }${2:i}=0; ${2} < ${3:count}; ${4:${2}++}) {",
|
||||
"\t$TM_SELECTED_TEXT$5",
|
||||
"}$0"
|
||||
]
|
||||
},
|
||||
"issue249": {
|
||||
"prefix": "issue249",
|
||||
"body": ["${1:FOO}\n"]
|
||||
}
|
||||
}
|
||||
6
dot_vim/plugged/vim-vsnip/misc/snipmate.snippets
Normal file
6
dot_vim/plugged/vim-vsnip/misc/snipmate.snippets
Normal file
@@ -0,0 +1,6 @@
|
||||
snippet arrow-function
|
||||
() =>
|
||||
snippet fn vim's function
|
||||
function! $1($2) abort
|
||||
$0
|
||||
endfunction
|
||||
13
dot_vim/plugged/vim-vsnip/misc/source_spec.json
Normal file
13
dot_vim/plugged/vim-vsnip/misc/source_spec.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"no-prefix-alias": {
|
||||
"prefix": ["---"],
|
||||
"body": ["${VIM:repeat('-', &tw)}"]
|
||||
},
|
||||
"prefix-alias": {
|
||||
"prefix": ["arrow-function"],
|
||||
"body": "() => "
|
||||
},
|
||||
"has-no-prefix": {
|
||||
"body": "() => "
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"contributes": {
|
||||
"snippets": [
|
||||
{
|
||||
"path": "./source_spec_vscode.json",
|
||||
"language": "source_spec_vscode"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"func": {
|
||||
"prefix": "func",
|
||||
"body": [
|
||||
"function! ${1:name}() abort",
|
||||
"\t$0",
|
||||
"endfunction"
|
||||
]
|
||||
}
|
||||
}
|
||||
38
dot_vim/plugged/vim-vsnip/package.json
Normal file
38
dot_vim/plugged/vim-vsnip/package.json
Normal file
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"name": "vim-vsnip",
|
||||
"version": "1.0.0",
|
||||
"description": "This aims to plugin like Visual Studio Code's Snippet feature.",
|
||||
"scripts": {
|
||||
"open": "nvim -u .vimrc",
|
||||
"test": "run-s test:*",
|
||||
"test:01": "THEMIS_VIM=vim EXCLUSIVE=0 VIRTUALEDIT=0 themis ./spec",
|
||||
"test:02": "THEMIS_VIM=vim EXCLUSIVE=0 VIRTUALEDIT=1 themis ./spec",
|
||||
"test:03": "THEMIS_VIM=vim EXCLUSIVE=1 VIRTUALEDIT=0 themis ./spec",
|
||||
"test:04": "THEMIS_VIM=vim EXCLUSIVE=1 VIRTUALEDIT=1 themis ./spec",
|
||||
"test:05": "THEMIS_VIM=nvim EXCLUSIVE=0 VIRTUALEDIT=0 themis ./spec",
|
||||
"test:06": "THEMIS_VIM=nvim EXCLUSIVE=0 VIRTUALEDIT=1 themis ./spec",
|
||||
"test:07": "THEMIS_VIM=nvim EXCLUSIVE=1 VIRTUALEDIT=0 themis ./spec",
|
||||
"test:08": "THEMIS_VIM=nvim EXCLUSIVE=1 VIRTUALEDIT=1 themis ./spec",
|
||||
"lint": "vint ."
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"pre-commit": "npm run lint && npm run test"
|
||||
}
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/hrsh7th/vim-test-snips.git"
|
||||
},
|
||||
"author": "hrsh7th",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/hrsh7th/vim-test-snips/issues"
|
||||
},
|
||||
"homepage": "https://github.com/hrsh7th/vim-test-snips#readme",
|
||||
"devDependencies": {
|
||||
"husky": "^3.0.5",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"watch": "^1.0.2"
|
||||
}
|
||||
}
|
||||
225
dot_vim/plugged/vim-vsnip/plugin/vsnip.vim
Normal file
225
dot_vim/plugged/vim-vsnip/plugin/vsnip.vim
Normal file
@@ -0,0 +1,225 @@
|
||||
if exists('g:loaded_vsnip')
|
||||
finish
|
||||
endif
|
||||
let g:loaded_vsnip = 1
|
||||
|
||||
"
|
||||
" variable
|
||||
"
|
||||
let g:vsnip_extra_mapping = get(g:, 'vsnip_extra_mapping', v:true)
|
||||
let g:vsnip_deactivate_on = get(g:, 'vsnip_deactivate_on', g:vsnip#DeactivateOn.OutsideOfCurrentTabstop)
|
||||
let g:vsnip_snippet_dir = get(g:, 'vsnip_snippet_dir', expand('~/.vsnip'))
|
||||
let g:vsnip_snippet_dirs = get(g:, 'vsnip_snippet_dirs', [])
|
||||
let g:vsnip_sync_delay = get(g:, 'vsnip_sync_delay', 0)
|
||||
let g:vsnip_choice_delay = get(g:, 'vsnip_choice_delay', 500)
|
||||
let g:vsnip_append_final_tabstop = get(g:, 'vsnip_append_final_tabstop', v:true)
|
||||
let g:vsnip_namespace = get(g:, 'vsnip_namespace', '')
|
||||
let g:vsnip_filetypes = get(g:, 'vsnip_filetypes', {})
|
||||
let g:vsnip_filetypes.typescriptreact = get(g:vsnip_filetypes, 'typescriptreact', ['typescript'])
|
||||
let g:vsnip_filetypes.javascriptreact = get(g:vsnip_filetypes, 'javascriptreact', ['javascript'])
|
||||
let g:vsnip_filetypes.vimspec = get(g:vsnip_filetypes, 'vimspec', ['vim'])
|
||||
|
||||
augroup vsnip#silent
|
||||
autocmd!
|
||||
autocmd User vsnip#expand silent
|
||||
autocmd User vsnip#jump silent
|
||||
augroup END
|
||||
|
||||
"
|
||||
" command
|
||||
"
|
||||
command! -nargs=* -bang VsnipOpen call s:open_command(<bang>0, 'vsplit', <q-args>)
|
||||
command! -nargs=* -bang VsnipOpenEdit call s:open_command(<bang>0, 'edit', <q-args>)
|
||||
command! -nargs=* -bang VsnipOpenVsplit call s:open_command(<bang>0, 'vsplit', <q-args>)
|
||||
command! -nargs=* -bang VsnipOpenSplit call s:open_command(<bang>0, 'split', <q-args>)
|
||||
function! s:open_command(bang, cmd, arg)
|
||||
let l:candidates = vsnip#source#filetypes(bufnr('%'))
|
||||
if a:bang
|
||||
let l:idx = 1
|
||||
else
|
||||
let l:idx = inputlist(['Select type: '] + map(copy(l:candidates), { k, v -> printf('%s: %s', k + 1, v) }))
|
||||
if l:idx == 0
|
||||
return
|
||||
endif
|
||||
endif
|
||||
|
||||
let l:expanded_dir = expand(g:vsnip_snippet_dir)
|
||||
if !isdirectory(l:expanded_dir)
|
||||
let l:prompt = printf('`%s` does not exists, create? y(es)/n(o): ', g:vsnip_snippet_dir)
|
||||
if index(['y', 'ye', 'yes'], input(l:prompt)) >= 0
|
||||
call mkdir(l:expanded_dir, 'p')
|
||||
else
|
||||
return
|
||||
endif
|
||||
endif
|
||||
|
||||
let l:ext = a:arg =~# '-format\s\+snipmate' ? 'snippets' : 'json'
|
||||
|
||||
execute printf('%s %s', a:cmd, fnameescape(printf('%s/%s.%s',
|
||||
\ resolve(l:expanded_dir),
|
||||
\ l:candidates[l:idx - 1],
|
||||
\ l:ext
|
||||
\ )))
|
||||
endfunction
|
||||
|
||||
command! -range -nargs=? -bar VsnipYank call s:add_command(<line1>, <line2>, <q-args>)
|
||||
function! s:add_command(start, end, name) abort
|
||||
let lines = map(getbufline('%', a:start, a:end), { key, val -> json_encode(substitute(val, '\$', '\\$', 'ge')) })
|
||||
let format = " \"%s\": {\n \"prefix\": [\"%s\"],\n \"body\": [\n %s\n ]\n }"
|
||||
let name = empty(a:name) ? 'new' : a:name
|
||||
|
||||
let reg = &clipboard =~# 'unnamed' ? '*' : '"'
|
||||
let reg = &clipboard =~# 'unnamedplus' ? '+' : reg
|
||||
call setreg(reg, printf(format, name, name, join(lines, ",\n ")), 'l')
|
||||
endfunction
|
||||
|
||||
"
|
||||
" extra mapping
|
||||
"
|
||||
if g:vsnip_extra_mapping
|
||||
snoremap <expr> <BS> ("\<BS>" . (&virtualedit ==# '' && getcurpos()[2] >= col('$') - 1 ? 'a' : 'i'))
|
||||
endif
|
||||
|
||||
"
|
||||
" <Plug>(vsnip-expand-or-jump)
|
||||
"
|
||||
inoremap <silent> <Plug>(vsnip-expand-or-jump) <Esc>:<C-u>call <SID>expand_or_jump()<CR>
|
||||
snoremap <silent> <Plug>(vsnip-expand-or-jump) <Esc>:<C-u>call <SID>expand_or_jump()<CR>
|
||||
function! s:expand_or_jump()
|
||||
let l:ctx = {}
|
||||
function! l:ctx.callback() abort
|
||||
let l:context = vsnip#get_context()
|
||||
let l:session = vsnip#get_session()
|
||||
if !empty(l:context)
|
||||
call vsnip#expand()
|
||||
elseif !empty(l:session) && l:session.jumpable(1)
|
||||
call l:session.jump(1)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" This is needed to keep normal-mode during 0ms to prevent CompleteDone handling by LSP Client.
|
||||
let l:maybe_complete_done = !empty(v:completed_item) && has_key(v:completed_item, 'user_data') && !empty(v:completed_item.user_data)
|
||||
if l:maybe_complete_done
|
||||
call timer_start(0, { -> l:ctx.callback() })
|
||||
else
|
||||
call l:ctx.callback()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"
|
||||
" <Plug>(vsnip-expand)
|
||||
"
|
||||
inoremap <silent> <Plug>(vsnip-expand) <Esc>:<C-u>call <SID>expand()<CR>
|
||||
snoremap <silent> <Plug>(vsnip-expand) <C-g><Esc>:<C-u>call <SID>expand()<CR>
|
||||
function! s:expand() abort
|
||||
let l:ctx = {}
|
||||
function! l:ctx.callback() abort
|
||||
call vsnip#expand()
|
||||
endfunction
|
||||
|
||||
" This is needed to keep normal-mode during 0ms to prevent CompleteDone handling by LSP Client.
|
||||
let l:maybe_complete_done = !empty(v:completed_item) && has_key(v:completed_item, 'user_data') && !empty(v:completed_item.user_data)
|
||||
if l:maybe_complete_done
|
||||
call timer_start(0, { -> l:ctx.callback() })
|
||||
else
|
||||
call l:ctx.callback()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"
|
||||
" <Plug>(vsnip-jump-next)
|
||||
" <Plug>(vsnip-jump-prev)
|
||||
"
|
||||
inoremap <silent> <Plug>(vsnip-jump-next) <Esc>:<C-u>call <SID>jump(1)<CR>
|
||||
snoremap <silent> <Plug>(vsnip-jump-next) <Esc>:<C-u>call <SID>jump(1)<CR>
|
||||
inoremap <silent> <Plug>(vsnip-jump-prev) <Esc>:<C-u>call <SID>jump(-1)<CR>
|
||||
snoremap <silent> <Plug>(vsnip-jump-prev) <Esc>:<C-u>call <SID>jump(-1)<CR>
|
||||
function! s:jump(direction) abort
|
||||
let l:session = vsnip#get_session()
|
||||
if !empty(l:session) && l:session.jumpable(a:direction)
|
||||
call l:session.jump(a:direction)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"
|
||||
" <Plug>(vsnip-select-text)
|
||||
"
|
||||
nnoremap <silent> <Plug>(vsnip-select-text) :set operatorfunc=<SID>vsnip_select_text_normal<CR>g@
|
||||
snoremap <silent> <Plug>(vsnip-select-text) <C-g>:<C-u>call <SID>vsnip_visual_text(visualmode())<CR>gv<C-g>
|
||||
xnoremap <silent> <Plug>(vsnip-select-text) :<C-u>call <SID>vsnip_visual_text(visualmode())<CR>gv
|
||||
function! s:vsnip_select_text_normal(type) abort
|
||||
call s:vsnip_set_text(a:type)
|
||||
endfunction
|
||||
|
||||
"
|
||||
" <Plug>(vsnip-cut-text)
|
||||
"
|
||||
nnoremap <silent> <Plug>(vsnip-cut-text) :set operatorfunc=<SID>vsnip_cut_text_normal<CR>g@
|
||||
snoremap <silent> <Plug>(vsnip-cut-text) <C-g>:<C-u>call <SID>vsnip_visual_text(visualmode())<CR>gv"_c
|
||||
xnoremap <silent> <Plug>(vsnip-cut-text) :<C-u>call <SID>vsnip_visual_text(visualmode())<CR>gv"_c
|
||||
|
||||
function! s:vsnip_cut_text_normal(type) abort
|
||||
call feedkeys(s:vsnip_set_text(a:type) . '"_c', 'n')
|
||||
endfunction
|
||||
function! s:vsnip_visual_text(type) abort
|
||||
call s:vsnip_set_text(a:type)
|
||||
endfunction
|
||||
function! s:vsnip_set_text(type) abort
|
||||
let oldreg = [getreg('"'), getregtype('"')]
|
||||
if a:type ==# 'v'
|
||||
let select = '`<v`>'
|
||||
elseif a:type ==# 'V'
|
||||
let select = "'<V'>"
|
||||
elseif a:type ==? "\<C-V>"
|
||||
let select = "`<\<C-V>`>"
|
||||
elseif a:type ==# 'char'
|
||||
let select = '`[v`]'
|
||||
elseif a:type ==# 'line'
|
||||
let select = "'[V']"
|
||||
else
|
||||
return
|
||||
endif
|
||||
execute 'normal! ' . select . 'y'
|
||||
call vsnip#selected_text(@")
|
||||
call setreg('"', oldreg[0], oldreg[1])
|
||||
return select
|
||||
endfunction
|
||||
|
||||
"
|
||||
" augroup.
|
||||
"
|
||||
augroup vsnip
|
||||
autocmd!
|
||||
autocmd InsertLeave * call s:on_insert_leave()
|
||||
autocmd TextChanged,TextChangedI,TextChangedP * call s:on_text_changed()
|
||||
autocmd BufWritePost * call s:on_buf_write_post()
|
||||
autocmd BufRead,BufNewFile *.snippets setlocal filetype=snippets
|
||||
augroup END
|
||||
|
||||
"
|
||||
" on_insert_leave
|
||||
"
|
||||
function! s:on_insert_leave() abort
|
||||
let l:session = vsnip#get_session()
|
||||
if !empty(l:session)
|
||||
call l:session.on_insert_leave()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"
|
||||
" on_text_changed
|
||||
"
|
||||
function! s:on_text_changed() abort
|
||||
let l:session = vsnip#get_session()
|
||||
if !empty(l:session)
|
||||
call l:session.on_text_changed()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"
|
||||
" on_buf_write_post
|
||||
"
|
||||
function! s:on_buf_write_post() abort
|
||||
call vsnip#source#refresh(resolve(fnamemodify(bufname('%'), ':p')))
|
||||
endfunction
|
||||
|
||||
149
dot_vim/plugged/vim-vsnip/spec/autoload/vsnip.vimspec
Normal file
149
dot_vim/plugged/vim-vsnip/spec/autoload/vsnip.vimspec
Normal file
@@ -0,0 +1,149 @@
|
||||
let s:expect = themis#helper('expect')
|
||||
|
||||
Describe vsnip
|
||||
|
||||
Describe #get_context
|
||||
|
||||
It should return context information in insert-mode
|
||||
enew!
|
||||
set filetype=basic_spec
|
||||
call setline(1, 'if')
|
||||
call cursor([1, 2])
|
||||
|
||||
let g:vsnip_assert = {}
|
||||
function g:vsnip_assert.step1()
|
||||
call s:expect(mode(1)).to_equal('i')
|
||||
call s:expect(vsnip#get_context()).to_equal({
|
||||
\ 'range': {
|
||||
\ 'start': {
|
||||
\ 'line': 0,
|
||||
\ 'character': 0,
|
||||
\ },
|
||||
\ 'end': {
|
||||
\ 'line': 0,
|
||||
\ 'character': 2,
|
||||
\ },
|
||||
\ },
|
||||
\ 'snippet': {
|
||||
\ 'label': 'if',
|
||||
\ 'description': '',
|
||||
\ 'prefix': ['if'],
|
||||
\ 'prefix_alias': [],
|
||||
\ 'body': [
|
||||
\ "if ${1:condition}",
|
||||
\ "\t$0",
|
||||
\ "endif",
|
||||
\ ],
|
||||
\ }
|
||||
\ })
|
||||
endfunction
|
||||
call feedkeys("a\<Plug>(vsnip-assert)", 'x')
|
||||
End
|
||||
|
||||
It should return context information in normal-mode
|
||||
enew!
|
||||
set filetype=basic_spec
|
||||
call setline(1, 'if')
|
||||
call cursor([1, 2])
|
||||
|
||||
call s:expect(mode(1)).to_equal('n')
|
||||
call s:expect(vsnip#get_context()).to_equal({
|
||||
\ 'range': {
|
||||
\ 'start': {
|
||||
\ 'line': 0,
|
||||
\ 'character': 0,
|
||||
\ },
|
||||
\ 'end': {
|
||||
\ 'line': 0,
|
||||
\ 'character': 2,
|
||||
\ },
|
||||
\ },
|
||||
\ 'snippet': {
|
||||
\ 'label': 'if',
|
||||
\ 'description': '',
|
||||
\ 'prefix': ['if'],
|
||||
\ 'prefix_alias': [],
|
||||
\ 'body': [
|
||||
\ "if ${1:condition}",
|
||||
\ "\t$0",
|
||||
\ "endif",
|
||||
\ ],
|
||||
\ }
|
||||
\ })
|
||||
End
|
||||
|
||||
It should return context information in select-mode
|
||||
enew!
|
||||
set filetype=basic_spec
|
||||
call setline(1, 'if')
|
||||
call feedkeys("v\<C-g>", 'x')
|
||||
call cursor([1, 2])
|
||||
|
||||
call s:expect(mode(1)).to_equal('s')
|
||||
call s:expect(vsnip#get_context()).to_equal({
|
||||
\ 'range': {
|
||||
\ 'start': {
|
||||
\ 'line': 0,
|
||||
\ 'character': 0,
|
||||
\ },
|
||||
\ 'end': {
|
||||
\ 'line': 0,
|
||||
\ 'character': 2,
|
||||
\ },
|
||||
\ },
|
||||
\ 'snippet': {
|
||||
\ 'label': 'if',
|
||||
\ 'description': '',
|
||||
\ 'prefix': ['if'],
|
||||
\ 'prefix_alias': [],
|
||||
\ 'body': [
|
||||
\ "if ${1:condition}",
|
||||
\ "\t$0",
|
||||
\ "endif",
|
||||
\ ],
|
||||
\ }
|
||||
\ })
|
||||
End
|
||||
|
||||
End
|
||||
|
||||
Describe #get_complete_items
|
||||
|
||||
It should return complete items
|
||||
enew!
|
||||
set filetype=basic_spec
|
||||
call s:expect(vsnip#get_complete_items(bufnr('%'))[-1]).to_equal({
|
||||
\ 'word': 'if',
|
||||
\ 'abbr': 'if',
|
||||
\ 'kind': 'Snippet',
|
||||
\ 'menu': '[v] if',
|
||||
\ 'dup': 1,
|
||||
\ 'user_data': json_encode({
|
||||
\ 'vsnip': {
|
||||
\ 'snippet': [
|
||||
\ "if ${1:condition}",
|
||||
\ "\t$0",
|
||||
\ "endif",
|
||||
\ ]
|
||||
\ }
|
||||
\ })
|
||||
\ }, {
|
||||
\ 'word': 'inline-fn',
|
||||
\ 'abbr': 'inline-fn',
|
||||
\ 'kind': 'Snippet',
|
||||
\ 'menu': '[v] inline-fn',
|
||||
\ 'dup': 1,
|
||||
\ 'user_data': json_encode({
|
||||
\ 'vsnip': {
|
||||
\ 'snippet': [
|
||||
\ "{ -> $1 }$0"
|
||||
\ ]
|
||||
\ }
|
||||
\ })
|
||||
\ })
|
||||
End
|
||||
|
||||
End
|
||||
|
||||
End
|
||||
|
||||
129
dot_vim/plugged/vim-vsnip/spec/autoload/vsnip/indent.vimspec
Normal file
129
dot_vim/plugged/vim-vsnip/spec/autoload/vsnip/indent.vimspec
Normal file
@@ -0,0 +1,129 @@
|
||||
let s:expect = themis#helper('expect')
|
||||
|
||||
Describe vsnip#indent
|
||||
|
||||
After each
|
||||
set expandtab shiftwidth=2
|
||||
End
|
||||
|
||||
Describe #get_one_indent
|
||||
|
||||
It should return one indent
|
||||
enew!
|
||||
for l:execute in [
|
||||
\ 'set expandtab shiftwidth=4 tabstop=2',
|
||||
\ 'set expandtab shiftwidth=2 tabstop=4',
|
||||
\ 'set expandtab shiftwidth=0 tabstop=2',
|
||||
\ 'set noexpandtab shiftwidth=4 tabstop=4',
|
||||
\ ]
|
||||
execute l:execute
|
||||
%delete _
|
||||
call setline(1, '<')
|
||||
normal! >>
|
||||
call s:expect(vsnip#indent#get_one_indent()).to_equal(getline(1)[0 : -2])
|
||||
endfor
|
||||
|
||||
End
|
||||
|
||||
End
|
||||
|
||||
Describe #get_base_indent
|
||||
|
||||
It should return base indent
|
||||
enew!
|
||||
|
||||
call setline(1, ['foo'])
|
||||
call s:expect(vsnip#indent#get_base_indent(getline(1))).to_equal('')
|
||||
|
||||
call setline(1, [' foo'])
|
||||
call s:expect(vsnip#indent#get_base_indent(getline(1))).to_equal(' ')
|
||||
|
||||
call setline(1, ["\tfoo"])
|
||||
call s:expect(vsnip#indent#get_base_indent(getline(1))).to_equal("\t")
|
||||
End
|
||||
|
||||
End
|
||||
|
||||
Describe #adjust_snippet_body
|
||||
|
||||
It should return adjusted snippet body for expandtab
|
||||
set expandtab shiftwidth=2
|
||||
call s:expect(vsnip#indent#adjust_snippet_body(' foo', join([
|
||||
\ "class $1 {",
|
||||
\ "\tpublic constructor() {",
|
||||
\ "\t\t$0",
|
||||
\ "\t}",
|
||||
\ "}"
|
||||
\ ], "\n"))).to_equal(join([
|
||||
\ "class $1 {",
|
||||
\ " public constructor() {",
|
||||
\ " $0",
|
||||
\ " }",
|
||||
\ " }"
|
||||
\ ], "\n"))
|
||||
End
|
||||
|
||||
It should return adjusted snippet body for noexpandtab
|
||||
set noexpandtab shiftwidth=2
|
||||
call s:expect(vsnip#indent#adjust_snippet_body("\tfoo", join([
|
||||
\ "class $1 {",
|
||||
\ "\tpublic constructor() {",
|
||||
\ "\t\t$0",
|
||||
\ "\t}",
|
||||
\ "}"
|
||||
\ ], "\n"))).to_equal(join([
|
||||
\ "class $1 {",
|
||||
\ "\t\tpublic constructor() {",
|
||||
\ "\t\t\t$0",
|
||||
\ "\t\t}",
|
||||
\ "\t}"
|
||||
\ ], "\n"))
|
||||
End
|
||||
|
||||
End
|
||||
|
||||
Describe #trim_base_indent
|
||||
|
||||
It should trim base indent when target is line-wise multiline text
|
||||
call s:expect(vsnip#indent#trim_base_indent(join([
|
||||
\ " function! s:foo()",
|
||||
\ " return 'foo'",
|
||||
\ " endfunction"
|
||||
\ ], "\n") . "\n")).to_equal(join([
|
||||
\ "function! s:foo()",
|
||||
\ " return 'foo'",
|
||||
\ "endfunction"
|
||||
\ ], "\n"))
|
||||
End
|
||||
|
||||
It should trim base indent when target is char-wise multiline text
|
||||
call s:expect(vsnip#indent#trim_base_indent(join([
|
||||
\ "function! s:foo()",
|
||||
\ " return 'foo'",
|
||||
\ " endfunction"
|
||||
\ ], "\n"))).to_equal(join([
|
||||
\ "function! s:foo()",
|
||||
\ " return 'foo'",
|
||||
\ "endfunction"
|
||||
\ ], "\n"))
|
||||
End
|
||||
|
||||
It should trim base indent when target is line-wise singleline selection
|
||||
call s:expect(vsnip#indent#trim_base_indent(join([
|
||||
\ " function! s:foo()",
|
||||
\ ], "\n") . "\n")).to_equal(join([
|
||||
\ "function! s:foo()",
|
||||
\ ], "\n"))
|
||||
End
|
||||
|
||||
It should trim base indent when target is char-wise singleline selection
|
||||
call s:expect(vsnip#indent#trim_base_indent(join([
|
||||
\ " function! s:foo()",
|
||||
\ ], "\n"))).to_equal(join([
|
||||
\ " function! s:foo()",
|
||||
\ ], "\n"))
|
||||
End
|
||||
|
||||
End
|
||||
|
||||
End
|
||||
573
dot_vim/plugged/vim-vsnip/spec/autoload/vsnip/snippet.vimspec
Normal file
573
dot_vim/plugged/vim-vsnip/spec/autoload/vsnip/snippet.vimspec
Normal file
@@ -0,0 +1,573 @@
|
||||
let s:expect = themis#helper('expect')
|
||||
let s:Snippet = vsnip#snippet#import()
|
||||
|
||||
let s:start_position = {
|
||||
\ 'line': 1,
|
||||
\ 'character': 1
|
||||
\ }
|
||||
|
||||
Describe vsnip#snippet
|
||||
|
||||
Describe #init
|
||||
|
||||
It should mark follower placeholders
|
||||
let l:snippet = s:Snippet.new(s:start_position, 'console.log(${1:default}, $1, $1)')
|
||||
call s:expect(l:snippet.children[3].follower).to_equal(v:true)
|
||||
call s:expect(l:snippet.children[5].follower).to_equal(v:true)
|
||||
End
|
||||
|
||||
It should add final tabstop
|
||||
let l:snippet = s:Snippet.new(s:start_position, 'console.log($1)')
|
||||
call s:expect(l:snippet.children[3].is_final).to_equal(v:true)
|
||||
End
|
||||
|
||||
It should convert variable to placeholder
|
||||
let l:snippet = s:Snippet.new(s:start_position, 'console.log(${variable:default}, $variable)')
|
||||
call s:expect(l:snippet.text()).to_equal('console.log(default, default)')
|
||||
call s:expect(l:snippet.children[3].follower).to_equal(v:true)
|
||||
End
|
||||
|
||||
It should resolve known variables
|
||||
let l:snippet = s:Snippet.new(s:start_position, 'console.log(${CURRENT_YEAR})')
|
||||
call s:expect(l:snippet.text()).to_equal('console.log(' . strftime('%Y') . ')')
|
||||
End
|
||||
|
||||
It should support whole word transform
|
||||
let l:snippet = s:Snippet.new(s:start_position, '${1:state}, set${1/(.*)/${1:/capitalize}/}')
|
||||
call s:expect(l:snippet.text()).to_equal('state, setState')
|
||||
End
|
||||
End
|
||||
|
||||
Describe #sync
|
||||
|
||||
It should sync placeholder text in same tabstop groups
|
||||
let l:snippet = s:Snippet.new(s:start_position, 'console.log(${1:default}, $1)')
|
||||
call l:snippet.follow(0, {
|
||||
\ 'range': {
|
||||
\ 'start': {
|
||||
\ 'line': 1,
|
||||
\ 'character': 13
|
||||
\ },
|
||||
\ 'end': {
|
||||
\ 'line': 1,
|
||||
\ 'character': 17
|
||||
\ }
|
||||
\ },
|
||||
\ 'text': '___'
|
||||
\ })
|
||||
call l:snippet.sync()
|
||||
call s:expect(l:snippet.text()).to_equal('console.log(___ult, ___ult)')
|
||||
End
|
||||
|
||||
End
|
||||
|
||||
Describe #follow
|
||||
|
||||
It should not affect following empty diff
|
||||
let l:snippet = s:Snippet.new(s:start_position, "class $1 {\n\tpublic ${2:default}() {\n\t\t$0\n\t}\n}")
|
||||
let l:followed = l:snippet.follow(0, {
|
||||
\ 'range': {
|
||||
\ 'start': {
|
||||
\ 'line': 1,
|
||||
\ 'character': 1
|
||||
\ },
|
||||
\ 'end': {
|
||||
\ 'line': 1,
|
||||
\ 'character': 1
|
||||
\ }
|
||||
\ },
|
||||
\ 'text': ''
|
||||
\ })
|
||||
call s:expect(l:followed).to_equal(v:true)
|
||||
call s:expect(l:snippet.text()).to_equal("class {\n\tpublic default() {\n\t\t\n\t}\n}")
|
||||
End
|
||||
|
||||
It should follow when diff range covers whole of snippet
|
||||
let l:snippet = s:Snippet.new(s:start_position, "class $1 {\n\tpublic ${2:default}() {\n\t\t$0\n\t}\n}")
|
||||
let l:followed = l:snippet.follow(0, {
|
||||
\ 'range': {
|
||||
\ 'start': {
|
||||
\ 'line': 1,
|
||||
\ 'character': 1
|
||||
\ },
|
||||
\ 'end': {
|
||||
\ 'line': 5,
|
||||
\ 'character': 1
|
||||
\ }
|
||||
\ },
|
||||
\ 'text': ''
|
||||
\ })
|
||||
call s:expect(l:followed).to_equal(v:true)
|
||||
call s:expect(l:snippet.text()).to_equal("")
|
||||
End
|
||||
|
||||
It should squash placeholder when diff range covers multiple placeholders
|
||||
let l:snippet = s:Snippet.new(s:start_position, "console.log(${1:first}, ${2:second})")
|
||||
call s:expect(l:snippet.get_placeholder_nodes()).to_have_length(3)
|
||||
let l:followed = l:snippet.follow(0, {
|
||||
\ 'range': {
|
||||
\ 'start': {
|
||||
\ 'line': 1,
|
||||
\ 'character': 13
|
||||
\ },
|
||||
\ 'end': {
|
||||
\ 'line': 1,
|
||||
\ 'character': 26
|
||||
\ }
|
||||
\ },
|
||||
\ 'text': ''
|
||||
\ })
|
||||
call s:expect(l:followed).to_equal(v:true)
|
||||
call s:expect(l:snippet.get_placeholder_nodes()).to_have_length(2)
|
||||
call s:expect(l:snippet.text()).to_equal('console.log()')
|
||||
End
|
||||
|
||||
It should not squash placeholder when diff range includes multiple placeholders but last one does not covered
|
||||
let l:snippet = s:Snippet.new(s:start_position, "console.log(${1:first}, ${2:second})")
|
||||
call s:expect(l:snippet.get_placeholder_nodes()).to_have_length(3)
|
||||
let l:followed = l:snippet.follow(0, {
|
||||
\ 'range': {
|
||||
\ 'start': {
|
||||
\ 'line': 1,
|
||||
\ 'character': 13
|
||||
\ },
|
||||
\ 'end': {
|
||||
\ 'line': 1,
|
||||
\ 'character': 25
|
||||
\ }
|
||||
\ },
|
||||
\ 'text': ''
|
||||
\ })
|
||||
call s:expect(l:followed).to_equal(v:true)
|
||||
call s:expect(l:snippet.get_placeholder_nodes()).to_have_length(3)
|
||||
call s:expect(l:snippet.text()).to_equal('console.log(d)')
|
||||
End
|
||||
|
||||
It should prefer current placeholder
|
||||
let l:snippet = s:Snippet.new(s:start_position, 'console.log(${1}, ${2:, ${3:default}})')
|
||||
let l:followed = l:snippet.follow(3, {
|
||||
\ 'range': {
|
||||
\ 'start': {
|
||||
\ 'line': 1,
|
||||
\ 'character': 17
|
||||
\ },
|
||||
\ 'end': {
|
||||
\ 'line': 1,
|
||||
\ 'character': 17
|
||||
\ }
|
||||
\ },
|
||||
\ 'text': '___'
|
||||
\ })
|
||||
call s:expect(l:followed).to_equal(v:true)
|
||||
call s:expect(l:snippet.get_placeholder_nodes()[2].text()).to_equal('___default')
|
||||
End
|
||||
|
||||
It should follow when diff range is within one node range
|
||||
let l:snippet = s:Snippet.new(s:start_position, "class $1 {\n\tpublic ${2:default}() {\n\t\t$0\n\t}\n}")
|
||||
call l:snippet.follow(0, {
|
||||
\ 'range': {
|
||||
\ 'start': {
|
||||
\ 'line': 2,
|
||||
\ 'character': 9
|
||||
\ },
|
||||
\ 'end': {
|
||||
\ 'line': 2,
|
||||
\ 'character': 12
|
||||
\ }
|
||||
\ },
|
||||
\ 'text': '___'
|
||||
\ })
|
||||
call s:expect(l:snippet.text()).to_equal("class {\n\tpublic d___ult() {\n\t\t\n\t}\n}")
|
||||
call s:expect(l:snippet.get_next_jump_point(1).placeholder.text()).to_equal('d___ult')
|
||||
End
|
||||
|
||||
It should follow when diff range included only text node
|
||||
let l:snippet = s:Snippet.new(s:start_position, "class $1 {\n\tpublic ${2:default}() {\n\t\t$0\n\t}\n}")
|
||||
call l:snippet.follow(1, {
|
||||
\ 'range': {
|
||||
\ 'start': {
|
||||
\ 'line': 1,
|
||||
\ 'character': 1
|
||||
\ },
|
||||
\ 'end': {
|
||||
\ 'line': 1,
|
||||
\ 'character': 6
|
||||
\ }
|
||||
\ },
|
||||
\ 'text': 'modified'
|
||||
\ })
|
||||
call s:expect(l:snippet.text()).to_equal("modified {\n\tpublic default() {\n\t\t\n\t}\n}")
|
||||
End
|
||||
|
||||
It should prefer placeholder node than text node when both followable (left)
|
||||
let l:snippet = s:Snippet.new(s:start_position, '[${1:text1}][${2:text2}][${3:text3}]')
|
||||
call l:snippet.follow(1, {
|
||||
\ 'range': {
|
||||
\ 'start': {
|
||||
\ 'line': 1,
|
||||
\ 'character': 9
|
||||
\ },
|
||||
\ 'end': {
|
||||
\ 'line': 1,
|
||||
\ 'character': 9
|
||||
\ }
|
||||
\ },
|
||||
\ 'text': '___'
|
||||
\ })
|
||||
call s:expect(l:snippet.text()).to_equal('[text1][___text2][text3]')
|
||||
call s:expect(l:snippet.children[3].text()).to_equal('___text2')
|
||||
End
|
||||
|
||||
It should prefer placeholder node than text node when both followable (right)
|
||||
let l:snippet = s:Snippet.new(s:start_position, '[${1:text1}][${2:text2}][${3:text3}]')
|
||||
call l:snippet.follow(1, {
|
||||
\ 'range': {
|
||||
\ 'start': {
|
||||
\ 'line': 1,
|
||||
\ 'character': 14
|
||||
\ },
|
||||
\ 'end': {
|
||||
\ 'line': 1,
|
||||
\ 'character': 14
|
||||
\ }
|
||||
\ },
|
||||
\ 'text': '___'
|
||||
\ })
|
||||
call s:expect(l:snippet.text()).to_equal('[text1][text2___][text3]')
|
||||
call s:expect(l:snippet.children[3].text()).to_equal('text2___')
|
||||
End
|
||||
|
||||
End
|
||||
|
||||
Describe #text
|
||||
|
||||
It should return text1
|
||||
let l:snippet = s:Snippet.new(s:start_position, 'console.log($0${1:default})')
|
||||
call s:expect(l:snippet.text()).to_equal('console.log(default)')
|
||||
End
|
||||
|
||||
It should return text2
|
||||
call vsnip#selected_text('THIS_IS_SELECTED_TEXT')
|
||||
let l:snippet = s:Snippet.new(s:start_position, '$TM_SELECTED_TEXT')
|
||||
call s:expect(l:snippet.text()).to_equal('THIS_IS_SELECTED_TEXT')
|
||||
End
|
||||
|
||||
It should return text2
|
||||
call vsnip#selected_text('THIS_IS_SELECTED_TEXT')
|
||||
let l:snippet = s:Snippet.new(s:start_position, '${TM_SELECTED_TEXT}')
|
||||
call s:expect(l:snippet.text()).to_equal('THIS_IS_SELECTED_TEXT')
|
||||
End
|
||||
|
||||
It should return text3
|
||||
call vsnip#selected_text('')
|
||||
let l:snippet = s:Snippet.new(s:start_position, '${TM_SELECTED_TEXT:default}')
|
||||
call s:expect(l:snippet.text()).to_equal('default')
|
||||
End
|
||||
|
||||
It should support whole word transform (upcase) on tabstop
|
||||
let l:snippet = s:Snippet.new(s:start_position, '${1:varName}, ${1/(.*)/${1:/upcase}/}')
|
||||
call s:expect(l:snippet.text()).to_equal('varName, VARNAME')
|
||||
End
|
||||
|
||||
It should support whole word transform (downcase) on variable
|
||||
call vsnip#selected_text('varName')
|
||||
let l:snippet = s:Snippet.new(s:start_position, '${TM_SELECTED_TEXT/(.*)/${1:/downcase}/}')
|
||||
call s:expect(l:snippet.text()).to_equal('varname')
|
||||
End
|
||||
|
||||
It should support whole word transform (capitalize)
|
||||
call vsnip#selected_text('varName')
|
||||
let l:snippet = s:Snippet.new(s:start_position, '${TM_SELECTED_TEXT/(.*)/${1:/capitalize}/}')
|
||||
call s:expect(l:snippet.text()).to_equal('VarName')
|
||||
End
|
||||
|
||||
It should support whole word transform (camelcase)
|
||||
call vsnip#selected_text('var_name')
|
||||
call s:expect(
|
||||
\ s:Snippet.new(s:start_position, '${TM_SELECTED_TEXT/(.*)/${1:/camelcase}/}').text()
|
||||
\ ).to_equal('varName')
|
||||
|
||||
call vsnip#selected_text('VAR_NAME')
|
||||
call s:expect(
|
||||
\ s:Snippet.new(s:start_position, '${TM_SELECTED_TEXT/(.*)/${1:/camelcase}/}').text()
|
||||
\ ).to_equal('varName')
|
||||
|
||||
call vsnip#selected_text('VarName')
|
||||
call s:expect(
|
||||
\ s:Snippet.new(s:start_position, '${TM_SELECTED_TEXT/(.*)/${1:/camelcase}/}').text()
|
||||
\ ).to_equal('varName')
|
||||
End
|
||||
|
||||
It should support whole word transform (pascalcase)
|
||||
call vsnip#selected_text('var_name')
|
||||
call s:expect(
|
||||
\ s:Snippet.new(s:start_position, '${TM_SELECTED_TEXT/(.*)/${1:/pascalcase}/}').text()
|
||||
\ ).to_equal('VarName')
|
||||
|
||||
call vsnip#selected_text('VAR_NAME')
|
||||
call s:expect(
|
||||
\ s:Snippet.new(s:start_position, '${TM_SELECTED_TEXT/(.*)/${1:/pascalcase}/}').text()
|
||||
\ ).to_equal('VarName')
|
||||
|
||||
call vsnip#selected_text('varName')
|
||||
call s:expect(
|
||||
\ s:Snippet.new(s:start_position, '${TM_SELECTED_TEXT/(.*)/${1:/pascalcase}/}').text()
|
||||
\ ).to_equal('VarName')
|
||||
End
|
||||
|
||||
It should support whole word transform with additional text
|
||||
call vsnip#selected_text('varName')
|
||||
let l:snippet = s:Snippet.new(s:start_position, '${TM_SELECTED_TEXT/(.*)/start-lowercase-${1:/downcase}/}-end')
|
||||
call s:expect(l:snippet.text()).to_equal('start-lowercase-varname-end')
|
||||
End
|
||||
End
|
||||
|
||||
Describe #range
|
||||
|
||||
It should return range1
|
||||
let l:snippet = s:Snippet.new(s:start_position, "01234\n56789")
|
||||
call s:expect(l:snippet.range()).to_equal({
|
||||
\ 'start': {
|
||||
\ 'line': s:start_position.line,
|
||||
\ 'character': s:start_position.character
|
||||
\ },
|
||||
\ 'end': {
|
||||
\ 'line': s:start_position.line + 1,
|
||||
\ 'character': 5
|
||||
\ }
|
||||
\ })
|
||||
End
|
||||
|
||||
It should return range2
|
||||
let l:snippet = s:Snippet.new(s:start_position, "012345")
|
||||
call s:expect(l:snippet.range()).to_equal({
|
||||
\ 'start': {
|
||||
\ 'line': s:start_position.line,
|
||||
\ 'character': s:start_position.character
|
||||
\ },
|
||||
\ 'end': {
|
||||
\ 'line': s:start_position.line,
|
||||
\ 'character': 7
|
||||
\ }
|
||||
\ })
|
||||
End
|
||||
|
||||
End
|
||||
|
||||
Describe #offset_to_position
|
||||
|
||||
It should return position from offset
|
||||
let l:snippet = s:Snippet.new(s:start_position, "class クラス {\n\tpublic constructor() {\n\t\t$0\n\t}\n}")
|
||||
call s:expect(l:snippet.offset_to_position(13)).to_equal({
|
||||
\ 'line': 2,
|
||||
\ 'character': 1
|
||||
\ })
|
||||
End
|
||||
|
||||
End
|
||||
|
||||
Describe #position_to_offset
|
||||
|
||||
It should return offset from position
|
||||
let l:snippet = s:Snippet.new(s:start_position, "class クラス {\n\tpublic constructor() {\n\t\t$0\n\t}\n}")
|
||||
call s:expect(l:snippet.position_to_offset({
|
||||
\ 'line': 2,
|
||||
\ 'character': 1
|
||||
\ })).to_equal(13)
|
||||
End
|
||||
|
||||
End
|
||||
|
||||
Describe #normalize
|
||||
|
||||
It should not normalize when does not exists adjacent text nodes
|
||||
let l:snippet = s:Snippet.new(s:start_position, 'console.log(${1:i}${2:++})')
|
||||
let l:text = l:snippet.text()
|
||||
call s:expect(len(l:snippet.children)).to_equal(5)
|
||||
call l:snippet.normalize()
|
||||
call s:expect(len(l:snippet.children)).to_equal(5)
|
||||
call s:expect(l:text).to_equal(l:snippet.text())
|
||||
End
|
||||
|
||||
It should normalize adjacent text nodes
|
||||
let l:snippet = s:Snippet.new(s:start_position, 'console.log')
|
||||
call insert(l:snippet.children, vsnip#snippet#node#create_text('___'), 1)
|
||||
let l:text = l:snippet.text()
|
||||
call s:expect(len(l:snippet.children)).to_equal(3)
|
||||
call l:snippet.normalize()
|
||||
call s:expect(len(l:snippet.children)).to_equal(2)
|
||||
call s:expect(l:text).to_equal(l:snippet.text())
|
||||
End
|
||||
|
||||
It should normalize correctly when the node has the same structure children
|
||||
let l:snippet = s:Snippet.new(s:start_position, '')
|
||||
let l:snippet.children = vsnip#snippet#node#create_from_ast([{
|
||||
\ 'type': 'text',
|
||||
\ 'value': '*',
|
||||
\ 'escaped': '*',
|
||||
\ }, {
|
||||
\ 'type': 'placeholder',
|
||||
\ 'id': 1,
|
||||
\ 'children': [{
|
||||
\ 'type': 'text',
|
||||
\ 'value': '',
|
||||
\ 'escaped': '',
|
||||
\ }]
|
||||
\ }, {
|
||||
\ 'type': 'text',
|
||||
\ 'value': '*',
|
||||
\ 'escaped': '*',
|
||||
\ }, {
|
||||
\ 'type': 'text',
|
||||
\ 'value': '_',
|
||||
\ 'escaped': '_',
|
||||
\ }, {
|
||||
\ 'type': 'placeholder',
|
||||
\ 'id': 1,
|
||||
\ 'children': [{
|
||||
\ 'type': 'text',
|
||||
\ 'value': '',
|
||||
\ 'escaped': '',
|
||||
\ }]
|
||||
\ }, {
|
||||
\ 'type': 'text',
|
||||
\ 'value': '*',
|
||||
\ 'escaped': '*',
|
||||
\ }, {
|
||||
\ 'type': 'text',
|
||||
\ 'value': '__',
|
||||
\ 'escaped': '__',
|
||||
\ }])
|
||||
let l:text = l:snippet.text()
|
||||
call l:snippet.normalize()
|
||||
call s:expect(l:text).to_equal(l:snippet.text())
|
||||
End
|
||||
|
||||
End
|
||||
|
||||
Describe #insert
|
||||
|
||||
It should insert node 1
|
||||
let l:snippet = s:Snippet.new(s:start_position, 'console.log(${1}, ${2:${1}})')
|
||||
call l:snippet.insert({ 'line': 1, 'character': 13 }, s:Snippet.new(s:start_position, 'console.log(${3}, ${4:${3}})').children)
|
||||
call s:expect(l:snippet.text()).to_equal('console.log(console.log(, ), )')
|
||||
End
|
||||
|
||||
It should insert node 2
|
||||
let l:snippet = s:Snippet.new(s:start_position, 'console.log(${1}, ${2:${1}})')
|
||||
call l:snippet.insert({ 'line': 1, 'character': 15 }, s:Snippet.new(s:start_position, 'console.log()').children)
|
||||
call s:expect(l:snippet.text()).to_equal('console.log(, console.log())')
|
||||
call s:expect(len(l:snippet.get_placeholder_nodes())).to_equal(5)
|
||||
End
|
||||
|
||||
It should insert node 3
|
||||
let l:snippet = s:Snippet.new(s:start_position, 'console.log(aiueo)')
|
||||
call l:snippet.insert({ 'line': 1, 'character': 13 }, s:Snippet.new(s:start_position, '___').children)
|
||||
call s:expect(l:snippet.text()).to_equal('console.log(___aiueo)')
|
||||
End
|
||||
|
||||
It should insert node 4
|
||||
let l:snippet = s:Snippet.new(s:start_position, 'console.log(aiueo)')
|
||||
call l:snippet.insert({ 'line': 1, 'character': 15 }, s:Snippet.new(s:start_position, '___').children)
|
||||
call s:expect(l:snippet.text()).to_equal('console.log(ai___ueo)')
|
||||
End
|
||||
|
||||
It should insert node 5
|
||||
let l:snippet = s:Snippet.new(s:start_position, 'console.log(aiueo)')
|
||||
call l:snippet.insert({ 'line': 1, 'character': 18 }, [vsnip#snippet#node#create_text('___')])
|
||||
call s:expect(l:snippet.text()).to_equal('console.log(aiueo___)')
|
||||
End
|
||||
|
||||
End
|
||||
|
||||
Describe #get_next_jump_point
|
||||
|
||||
It should return next jump point 1
|
||||
let l:snippet = s:Snippet.new(s:start_position, 'console.log(${1:012345})')
|
||||
call s:expect(l:snippet.get_next_jump_point(0).range).to_equal({
|
||||
\ 'start': {
|
||||
\ 'line': 1,
|
||||
\ 'character': 13
|
||||
\ },
|
||||
\ 'end': {
|
||||
\ 'line': 1,
|
||||
\ 'character': 19
|
||||
\ }
|
||||
\ })
|
||||
End
|
||||
|
||||
It should return next jump point 2
|
||||
let l:snippet = s:Snippet.new(s:start_position, 'console.log(${1:0123${2:456}7890})')
|
||||
call s:expect(l:snippet.get_next_jump_point(0).range).to_equal({
|
||||
\ 'start': {
|
||||
\ 'line': 1,
|
||||
\ 'character': 13
|
||||
\ },
|
||||
\ 'end': {
|
||||
\ 'line': 1,
|
||||
\ 'character': 24
|
||||
\ }
|
||||
\ })
|
||||
call s:expect(l:snippet.get_next_jump_point(1).range).to_equal({
|
||||
\ 'start': {
|
||||
\ 'line': 1,
|
||||
\ 'character': 17,
|
||||
\ },
|
||||
\ 'end': {
|
||||
\ 'line': 1,
|
||||
\ 'character': 20
|
||||
\ }
|
||||
\ })
|
||||
End
|
||||
|
||||
It should return next jump point 3
|
||||
let l:snippet = s:Snippet.new(s:start_position, 'console.log(${1:0${3:12}3${2:456}7890})')
|
||||
call s:expect(l:snippet.get_next_jump_point(0).range).to_equal({
|
||||
\ 'start': {
|
||||
\ 'line': 1,
|
||||
\ 'character': 13
|
||||
\ },
|
||||
\ 'end': {
|
||||
\ 'line': 1,
|
||||
\ 'character': 24
|
||||
\ }
|
||||
\ })
|
||||
call s:expect(l:snippet.get_next_jump_point(1).range).to_equal({
|
||||
\ 'start': {
|
||||
\ 'line': 1,
|
||||
\ 'character': 17,
|
||||
\ },
|
||||
\ 'end': {
|
||||
\ 'line': 1,
|
||||
\ 'character': 20
|
||||
\ }
|
||||
\ })
|
||||
call s:expect(l:snippet.get_next_jump_point(2).range).to_equal({
|
||||
\ 'start': {
|
||||
\ 'line': 1,
|
||||
\ 'character': 14,
|
||||
\ },
|
||||
\ 'end': {
|
||||
\ 'line': 1,
|
||||
\ 'character': 16
|
||||
\ }
|
||||
\ })
|
||||
End
|
||||
|
||||
It should return next jump point 4
|
||||
let l:snippet = s:Snippet.new(s:start_position, 'console.log(0${1}123456789${1}0)')
|
||||
call s:expect(l:snippet.get_next_jump_point(0).range).to_equal({
|
||||
\ 'start': {
|
||||
\ 'line': 1,
|
||||
\ 'character': 14
|
||||
\ },
|
||||
\ 'end': {
|
||||
\ 'line': 1,
|
||||
\ 'character': 14
|
||||
\ }
|
||||
\ })
|
||||
End
|
||||
|
||||
End
|
||||
|
||||
End
|
||||
@@ -0,0 +1,231 @@
|
||||
let s:expect = themis#helper('expect')
|
||||
|
||||
Describe vsnip#snippet#parser
|
||||
|
||||
Describe #parse
|
||||
|
||||
It should parse text
|
||||
let l:parsed = vsnip#snippet#parser#parse('console.log()')
|
||||
call s:expect(len(l:parsed)).to_equal(1)
|
||||
call s:expect(l:parsed[0]).to_equal({
|
||||
\ 'type': 'text',
|
||||
\ 'raw': 'console.log()',
|
||||
\ 'escaped': 'console.log()'
|
||||
\ })
|
||||
End
|
||||
|
||||
It should parse tabstop
|
||||
let l:parsed = vsnip#snippet#parser#parse('console.log($0$1${1/(.*)/${1:/capitalize}/})')
|
||||
call s:expect(len(l:parsed)).to_equal(5)
|
||||
call s:expect(l:parsed[0]).to_equal({
|
||||
\ 'type': 'text',
|
||||
\ 'raw': 'console.log(',
|
||||
\ 'escaped': 'console.log('
|
||||
\ })
|
||||
call s:expect(l:parsed[1]).to_equal({
|
||||
\ 'type': 'placeholder',
|
||||
\ 'id': 0,
|
||||
\ 'children': []
|
||||
\ })
|
||||
call s:expect(l:parsed[2]).to_equal({
|
||||
\ 'type': 'placeholder',
|
||||
\ 'id': 1,
|
||||
\ 'children': []
|
||||
\ })
|
||||
call s:expect(l:parsed[3]).to_equal({
|
||||
\ 'type': 'placeholder',
|
||||
\ 'id': 1,
|
||||
\ 'children': [],
|
||||
\ 'transform': {
|
||||
\ 'type': 'transform',
|
||||
\ 'regex': {
|
||||
\ 'type': 'regex',
|
||||
\ 'pattern': '(.*)',
|
||||
\ },
|
||||
\ 'format': [{
|
||||
\ 'type': 'format',
|
||||
\ 'id': 1,
|
||||
\ 'modifier': '/capitalize'
|
||||
\ }],
|
||||
\ 'option': v:null
|
||||
\ }
|
||||
\ })
|
||||
call s:expect(l:parsed[4]).to_equal({
|
||||
\ 'type': 'text',
|
||||
\ 'raw': ')',
|
||||
\ 'escaped': ')'
|
||||
\ })
|
||||
End
|
||||
|
||||
It should parse choice
|
||||
let l:parsed = vsnip#snippet#parser#parse("${1|log,warn,error|}")
|
||||
call s:expect(l:parsed[0]).to_equal({
|
||||
\ 'type': 'placeholder',
|
||||
\ 'id': 1,
|
||||
\ 'choice': [{
|
||||
\ 'type': 'text',
|
||||
\ 'raw': 'log',
|
||||
\ 'escaped': 'log'
|
||||
\ }, {
|
||||
\ 'type': 'text',
|
||||
\ 'raw': 'warn',
|
||||
\ 'escaped': 'warn'
|
||||
\ }, {
|
||||
\ 'type': 'text',
|
||||
\ 'raw': 'error',
|
||||
\ 'escaped': 'error'
|
||||
\ }],
|
||||
\ 'children': [{
|
||||
\ 'type': 'text',
|
||||
\ 'raw': 'log',
|
||||
\ 'escaped': 'log'
|
||||
\ }]
|
||||
\ })
|
||||
End
|
||||
|
||||
It should parse complex escaped chars
|
||||
let l:parsed = vsnip#snippet#parser#parse('\\\$variable\}')
|
||||
call s:expect(len(l:parsed)).to_equal(1)
|
||||
call s:expect(l:parsed[0]).to_equal({
|
||||
\ 'type': 'text',
|
||||
\ 'raw': '\\\$variable\}',
|
||||
\ 'escaped': '\$variable}'
|
||||
\ })
|
||||
End
|
||||
|
||||
It should parse escapable char
|
||||
let l:parsed = vsnip#snippet#parser#parse('{\}')
|
||||
call s:expect(len(l:parsed)).to_equal(1)
|
||||
call s:expect(l:parsed[0]).to_equal({
|
||||
\ 'type': 'text',
|
||||
\ 'raw': '{\}',
|
||||
\ 'escaped': '{}'
|
||||
\ })
|
||||
End
|
||||
|
||||
It should not remove unmeaningful escape
|
||||
let l:parsed = vsnip#snippet#parser#parse('\{}')
|
||||
call s:expect(len(l:parsed)).to_equal(1)
|
||||
call s:expect(l:parsed[0]).to_equal({
|
||||
\ 'type': 'text',
|
||||
\ 'raw': '\{}',
|
||||
\ 'escaped': '\{}'
|
||||
\ })
|
||||
End
|
||||
|
||||
It should parse omitted backslash for the escapable non-stop char
|
||||
let l:parsed = vsnip#snippet#parser#parse('{}')
|
||||
call s:expect(len(l:parsed)).to_equal(1)
|
||||
call s:expect(l:parsed[0]).to_equal({
|
||||
\ 'type': 'text',
|
||||
\ 'raw': '{}',
|
||||
\ 'escaped': '{}'
|
||||
\ })
|
||||
End
|
||||
|
||||
It should parse nested placeholder
|
||||
let l:parsed = vsnip#snippet#parser#parse('class $1${2: extends ${3:SuperClass}} { $0 }')
|
||||
call s:expect(len(l:parsed)).to_equal(6)
|
||||
call s:expect(l:parsed[0]).to_equal({
|
||||
\ 'type': 'text',
|
||||
\ 'raw': 'class ',
|
||||
\ 'escaped': 'class '
|
||||
\ })
|
||||
call s:expect(l:parsed[1]).to_equal({
|
||||
\ 'type': 'placeholder',
|
||||
\ 'id': 1,
|
||||
\ 'children': []
|
||||
\ })
|
||||
call s:expect(l:parsed[2]).to_equal({
|
||||
\ 'type': 'placeholder',
|
||||
\ 'id': 2,
|
||||
\ 'children': [{
|
||||
\ 'type': 'text',
|
||||
\ 'raw': ' extends ',
|
||||
\ 'escaped': ' extends '
|
||||
\ }, {
|
||||
\ 'type': 'placeholder',
|
||||
\ 'id': 3,
|
||||
\ 'children': [{
|
||||
\ 'type': 'text',
|
||||
\ 'raw': 'SuperClass',
|
||||
\ 'escaped': 'SuperClass'
|
||||
\ }]
|
||||
\ }]
|
||||
\ })
|
||||
call s:expect(l:parsed[3]).to_equal({
|
||||
\ 'type': 'text',
|
||||
\ 'raw': ' { ',
|
||||
\ 'escaped': ' { '
|
||||
\ })
|
||||
call s:expect(l:parsed[4]).to_equal({
|
||||
\ 'type': 'placeholder',
|
||||
\ 'id': 0,
|
||||
\ 'children': []
|
||||
\ })
|
||||
call s:expect(l:parsed[5]).to_equal({
|
||||
\ 'type': 'text',
|
||||
\ 'raw': ' }',
|
||||
\ 'escaped': ' }'
|
||||
\ })
|
||||
End
|
||||
|
||||
It should parse simple variable
|
||||
let l:parsed = vsnip#snippet#parser#parse('${variable:default}')
|
||||
call s:expect(len(l:parsed)).to_equal(1)
|
||||
call s:expect(l:parsed[0]).to_equal({
|
||||
\ 'type': 'variable',
|
||||
\ 'name': 'variable',
|
||||
\ 'children': [{
|
||||
\ 'type': 'text',
|
||||
\ 'raw': 'default',
|
||||
\ 'escaped': 'default',
|
||||
\ }]
|
||||
\ })
|
||||
End
|
||||
|
||||
It should parse variable with multiple children
|
||||
let l:parsed = vsnip#snippet#parser#parse('${variable: $1}')
|
||||
call s:expect(len(l:parsed)).to_equal(1)
|
||||
call s:expect(l:parsed[0]).to_equal({
|
||||
\ 'type': 'variable',
|
||||
\ 'name': 'variable',
|
||||
\ 'children': [{
|
||||
\ 'type': 'text',
|
||||
\ 'raw': ' ',
|
||||
\ 'escaped': ' ',
|
||||
\ }, {
|
||||
\ 'type': 'placeholder',
|
||||
\ 'id': 1,
|
||||
\ 'children': []
|
||||
\ }],
|
||||
\ })
|
||||
End
|
||||
|
||||
It should parse variable with regex
|
||||
let l:parsed = vsnip#snippet#parser#parse('${variable/(.*)/${1:/capitalize}/}')
|
||||
call s:expect(len(l:parsed)).to_equal(1)
|
||||
call s:expect(l:parsed[0]).to_equal({
|
||||
\ 'type': 'variable',
|
||||
\ 'name': 'variable',
|
||||
\ 'children': [],
|
||||
\ 'transform': {
|
||||
\ 'type': 'transform',
|
||||
\ 'regex': {
|
||||
\ 'type': 'regex',
|
||||
\ 'pattern': '(.*)',
|
||||
\ },
|
||||
\ 'format': [{
|
||||
\ 'type': 'format',
|
||||
\ 'id': 1,
|
||||
\ 'modifier': '/capitalize'
|
||||
\ }],
|
||||
\ 'option': v:null
|
||||
\ }
|
||||
\ })
|
||||
End
|
||||
|
||||
End
|
||||
|
||||
End
|
||||
|
||||
97
dot_vim/plugged/vim-vsnip/spec/autoload/vsnip/source.vimspec
Normal file
97
dot_vim/plugged/vim-vsnip/spec/autoload/vsnip/source.vimspec
Normal file
@@ -0,0 +1,97 @@
|
||||
let s:expect = themis#helper('expect')
|
||||
|
||||
Describe vsnip#source
|
||||
|
||||
Describe #filetypes
|
||||
|
||||
It should return all filetype
|
||||
enew!
|
||||
set filetype=javascript.jsx
|
||||
call s:expect(vsnip#source#filetypes(bufnr('%'))).to_equal([
|
||||
\ 'javascript',
|
||||
\ 'jsx',
|
||||
\ 'global'
|
||||
\ ])
|
||||
End
|
||||
|
||||
End
|
||||
|
||||
Describe #find
|
||||
|
||||
It should load snippet for extended filetypes
|
||||
enew!
|
||||
set filetype=source_spec_enhanced
|
||||
let l:snippets = vsnip#source#find(bufnr('%'))
|
||||
call s:expect(l:snippets[0]).to_have_length(2)
|
||||
End
|
||||
|
||||
It should load snippet from vscode extension
|
||||
enew!
|
||||
set filetype=source_spec_vscode
|
||||
let l:snippets = vsnip#source#find(bufnr('%'))
|
||||
call s:expect(l:snippets[0]).to_have_length(1)
|
||||
End
|
||||
|
||||
It should format snippets
|
||||
enew!
|
||||
set filetype=source_spec
|
||||
let l:snippets = vsnip#source#find(bufnr('%'))
|
||||
call s:expect(sort(l:snippets[0])).to_equal(sort([{
|
||||
\ 'label': 'no-prefix-alias',
|
||||
\ 'description': '',
|
||||
\ 'prefix': ['---'],
|
||||
\ 'prefix_alias': [],
|
||||
\ 'body': [
|
||||
\ "${VIM:repeat('-', &tw)}"
|
||||
\ ]
|
||||
\ }, {
|
||||
\ 'label': 'prefix-alias',
|
||||
\ 'description': '',
|
||||
\ 'prefix': ['arrow-function'],
|
||||
\ 'prefix_alias': ['af'],
|
||||
\ 'body': [
|
||||
\ "() => "
|
||||
\ ]
|
||||
\ }]))
|
||||
End
|
||||
|
||||
End
|
||||
|
||||
Describe #snipmate
|
||||
|
||||
It should load snippets
|
||||
enew!
|
||||
set filetype=snipmate
|
||||
let l:snippets = vsnip#source#find(bufnr('%'))
|
||||
call s:expect(l:snippets[0]).to_have_length(2)
|
||||
End
|
||||
|
||||
It should format snippets
|
||||
enew!
|
||||
set filetype=snipmate
|
||||
let l:snippets = vsnip#source#find(bufnr('%'))
|
||||
call s:expect(sort(l:snippets[0])).to_equal(sort([{
|
||||
\ 'label': 'arrow-function',
|
||||
\ 'description': '',
|
||||
\ 'prefix': ['arrow-function'],
|
||||
\ 'prefix_alias': ['af'],
|
||||
\ 'body': [
|
||||
\ "() => "
|
||||
\ ]
|
||||
\ }, {
|
||||
\ 'label': 'fn',
|
||||
\ 'description': "vim's function",
|
||||
\ 'prefix': ['fn'],
|
||||
\ 'prefix_alias': [],
|
||||
\ 'body': [
|
||||
\ "function! $1($2) abort",
|
||||
\ "\t$0",
|
||||
\ "endfunction",
|
||||
\ ]
|
||||
\ }]))
|
||||
End
|
||||
|
||||
End
|
||||
|
||||
End
|
||||
|
||||
709
dot_vim/plugged/vim-vsnip/spec/plugin/vsnip.vimspec
Normal file
709
dot_vim/plugged/vim-vsnip/spec/plugin/vsnip.vimspec
Normal file
@@ -0,0 +1,709 @@
|
||||
let s:expect = themis#helper('expect')
|
||||
|
||||
function! s:expect_selection(s, e) abort
|
||||
if &selection ==# 'exclusive' && &virtualedit ==# ''
|
||||
return
|
||||
endif
|
||||
|
||||
call s:expect(getpos("'<")[1 : 2]).to_equal([a:s[0], a:s[1]])
|
||||
if &selection ==# 'exclusive'
|
||||
let l:text = getline('.')
|
||||
let l:char = strcharpart(l:text, charidx(l:text, a:e[1] - 1), 1)
|
||||
let a:e[1] = a:e[1] + strlen(l:char)
|
||||
endif
|
||||
call s:expect(getpos("'>")[1 : 2]).to_equal([a:e[0], a:e[1]])
|
||||
endfunction
|
||||
|
||||
Describe vsnip
|
||||
|
||||
After each
|
||||
call vsnip#deactivate()
|
||||
End
|
||||
|
||||
Context expand
|
||||
|
||||
It should expand when prefix start col is 1
|
||||
enew!
|
||||
set filetype=integration
|
||||
call setline(1, 'spec1')
|
||||
call cursor([1, 5])
|
||||
|
||||
let g:vsnip_assert = {}
|
||||
function g:vsnip_assert.step1()
|
||||
call s:expect(getcurpos()[1 : 2]).to_equal([1, 8])
|
||||
call s:expect(getbufline('%', '^', '$')).to_equal(['snippet'])
|
||||
endfunction
|
||||
call feedkeys("a\<C-j>\<Plug>(vsnip-assert)", 'x')
|
||||
End
|
||||
|
||||
It should expand when prefix is in middle of line
|
||||
enew!
|
||||
set filetype=integration
|
||||
call setline(1, '(spec1)')
|
||||
call cursor([1, 6])
|
||||
|
||||
let g:vsnip_assert = {}
|
||||
function g:vsnip_assert.step1()
|
||||
call s:expect(getbufline('%', '^', '$')).to_equal(['(snippet)'])
|
||||
endfunction
|
||||
call feedkeys("a\<C-j>\<Plug>(vsnip-assert)", 'x')
|
||||
End
|
||||
|
||||
It should expand when prefix was selected in select-mode
|
||||
enew!
|
||||
set filetype=integration
|
||||
call setline(1, 'spec1')
|
||||
call cursor([1, 5])
|
||||
|
||||
let g:vsnip_assert = {}
|
||||
function g:vsnip_assert.step1()
|
||||
call s:expect(getbufline('%', '^', '$')).to_equal(['snippet'])
|
||||
endfunction
|
||||
call feedkeys("v$\<C-g>\<C-j>\<Plug>(vsnip-assert)", 'x')
|
||||
End
|
||||
|
||||
It should not expand when prefix is word and it does not separate by word boundary
|
||||
enew!
|
||||
set filetype=integration
|
||||
set iskeyword=@,48-57,_,192-255
|
||||
call setline(1, '(aspec1)')
|
||||
call cursor([1, 7])
|
||||
|
||||
let g:vsnip_assert = {}
|
||||
function g:vsnip_assert.step1()
|
||||
call s:expect(getbufline('%', '^', '$')).to_equal(['(aspec1', ')'])
|
||||
endfunction
|
||||
call feedkeys("a\<C-j>\<Plug>(vsnip-assert)", 'x')
|
||||
End
|
||||
|
||||
It should jump to first placeholder when expanded snippet
|
||||
enew!
|
||||
set filetype=integration
|
||||
call setline(1, 'spec2')
|
||||
call cursor([1, 5])
|
||||
|
||||
let g:vsnip_assert = {}
|
||||
function g:vsnip_assert.step1()
|
||||
call s:expect(getcurpos()[1 : 2]).to_equal([1, 1])
|
||||
call s:expect(getbufline('%', '^', '$')).to_equal(['snippet'])
|
||||
endfunction
|
||||
call feedkeys("a\<C-j>\<Plug>(vsnip-assert)", 'x')
|
||||
End
|
||||
|
||||
End
|
||||
|
||||
Context jump
|
||||
|
||||
It should jump to first of snippet
|
||||
enew!
|
||||
set filetype=integration
|
||||
call setline(1, 'spec2')
|
||||
call cursor([1, 5])
|
||||
|
||||
let g:vsnip_assert = {}
|
||||
function g:vsnip_assert.step1()
|
||||
call s:expect(getcurpos()[1 : 2]).to_equal([1, 1])
|
||||
call s:expect(getbufline('%', '^', '$')).to_equal(['snippet'])
|
||||
endfunction
|
||||
call feedkeys("a\<C-j>\<Tab>\<Plug>(vsnip-assert)", 'x')
|
||||
End
|
||||
|
||||
It should jump to middle of snippet
|
||||
enew!
|
||||
set filetype=integration
|
||||
call setline(1, 'spec3')
|
||||
call cursor([1, 5])
|
||||
|
||||
let g:vsnip_assert = {}
|
||||
function g:vsnip_assert.step1()
|
||||
call s:expect(getcurpos()[1 : 2]).to_equal([1, 4])
|
||||
call s:expect(getbufline('%', '^', '$')).to_equal(['snippet'])
|
||||
endfunction
|
||||
call feedkeys("a\<C-j>\<Tab>\<Plug>(vsnip-assert)", 'x')
|
||||
End
|
||||
|
||||
It should jump to last of snippet
|
||||
enew!
|
||||
set filetype=integration
|
||||
call setline(1, 'spec4')
|
||||
call cursor([1, 5])
|
||||
|
||||
let g:vsnip_assert = {}
|
||||
function g:vsnip_assert.step1()
|
||||
call s:expect(getcurpos()[1 : 2]).to_equal([1, 8])
|
||||
call s:expect(getbufline('%', '^', '$')).to_equal(['snippet'])
|
||||
endfunction
|
||||
call feedkeys("a\<C-j>\<Tab>\<Plug>(vsnip-assert)", 'x')
|
||||
End
|
||||
|
||||
It should select 1 length first of snippet text
|
||||
enew!
|
||||
set filetype=integration
|
||||
call setline(1, 'spec5')
|
||||
call cursor([1, 5])
|
||||
|
||||
let g:vsnip_assert = {}
|
||||
function g:vsnip_assert.step1()
|
||||
call s:expect_selection([1, 1], [1, 1])
|
||||
call s:expect(getbufline('%', '^', '$')).to_equal(['snippet'])
|
||||
endfunction
|
||||
call feedkeys("a\<C-j>\<Tab>\<Plug>(vsnip-assert)", 'x')
|
||||
End
|
||||
|
||||
It should select 1 length middle of snippet text
|
||||
enew!
|
||||
set filetype=integration
|
||||
call setline(1, 'spec6')
|
||||
call cursor([1, 5])
|
||||
|
||||
let g:vsnip_assert = {}
|
||||
function g:vsnip_assert.step1()
|
||||
call s:expect_selection([1, 3], [1, 3])
|
||||
call s:expect(getbufline('%', '^', '$')).to_equal(['snippet'])
|
||||
endfunction
|
||||
call feedkeys("a\<C-j>\<Tab>\<Plug>(vsnip-assert)", 'x')
|
||||
End
|
||||
|
||||
It should select 1 length last of snippet text
|
||||
enew!
|
||||
set filetype=integration
|
||||
call setline(1, 'spec7')
|
||||
call cursor([1, 5])
|
||||
|
||||
let g:vsnip_assert = {}
|
||||
function g:vsnip_assert.step1()
|
||||
call s:expect_selection([1, 7], [1, 7])
|
||||
call s:expect(getbufline('%', '^', '$')).to_equal(['snippet'])
|
||||
endfunction
|
||||
call feedkeys("a\<C-j>\<Tab>\<Plug>(vsnip-assert)", 'x')
|
||||
End
|
||||
|
||||
It should select 3 length first of snippet text
|
||||
enew!
|
||||
set filetype=integration
|
||||
call setline(1, 'spec8')
|
||||
call cursor([1, 5])
|
||||
|
||||
let g:vsnip_assert = {}
|
||||
function g:vsnip_assert.step1()
|
||||
call s:expect_selection([1, 1], [1, 3])
|
||||
call s:expect(getbufline('%', '^', '$')).to_equal(['snippet'])
|
||||
endfunction
|
||||
call feedkeys("a\<C-j>\<Tab>\<Plug>(vsnip-assert)", 'x')
|
||||
End
|
||||
|
||||
It should select 3 length middle of snippet text
|
||||
enew!
|
||||
set filetype=integration
|
||||
call setline(1, 'spec9')
|
||||
call cursor([1, 5])
|
||||
|
||||
let g:vsnip_assert = {}
|
||||
function g:vsnip_assert.step1()
|
||||
call s:expect_selection([1, 3], [1, 5])
|
||||
call s:expect(getbufline('%', '^', '$')).to_equal(['snippet'])
|
||||
endfunction
|
||||
call feedkeys("a\<C-j>\<Tab>\<Plug>(vsnip-assert)", 'x')
|
||||
End
|
||||
|
||||
It should select 3 length last of snippet text
|
||||
enew!
|
||||
set filetype=integration
|
||||
call setline(1, 'spec10')
|
||||
call cursor([1, 6])
|
||||
|
||||
let g:vsnip_assert = {}
|
||||
function g:vsnip_assert.step1()
|
||||
call s:expect_selection([1, 5], [1, 7])
|
||||
call s:expect(getbufline('%', '^', '$')).to_equal(['snippet'])
|
||||
endfunction
|
||||
call feedkeys("a\<C-j>\<Tab>\<Plug>(vsnip-assert)", 'x')
|
||||
End
|
||||
|
||||
End
|
||||
|
||||
Context multibyte
|
||||
|
||||
It should jump to middle of snippet
|
||||
enew!
|
||||
set filetype=integration
|
||||
call setline(1, 'マルチ1')
|
||||
call cursor([1, 10])
|
||||
|
||||
let g:vsnip_assert = {}
|
||||
function g:vsnip_assert.step1()
|
||||
call s:expect(getcurpos()[1 : 2]).to_equal([1, 7])
|
||||
call s:expect(getbufline('%', '^', '$')).to_equal(['あいう'])
|
||||
endfunction
|
||||
call feedkeys("a\<C-j>\<Tab>\<Plug>(vsnip-assert)", 'x')
|
||||
End
|
||||
|
||||
It should select 4 length middle of snippet text
|
||||
enew!
|
||||
set filetype=integration
|
||||
call setline(1, 'マルチ2')
|
||||
call cursor([1, 10])
|
||||
|
||||
let g:vsnip_assert = {}
|
||||
function g:vsnip_assert.step1()
|
||||
call s:expect_selection([1, 7], [1, 12])
|
||||
call s:expect(getbufline('%', '^', '$')).to_equal(['あいかkaかう'])
|
||||
endfunction
|
||||
call feedkeys("a\<C-j>\<Tab>\<Plug>(vsnip-assert)", 'x')
|
||||
End
|
||||
|
||||
End
|
||||
|
||||
Context g:vsnip_deactivate_on
|
||||
It should deactivate snippet on edit the outside of snippet
|
||||
enew!
|
||||
set filetype=integration
|
||||
let g:vsnip_deactivate_on = g:vsnip#DeactivateOn.OutsideOfSnippet
|
||||
|
||||
call setline(1, [
|
||||
\ 'outside',
|
||||
\ 'deactivate',
|
||||
\ 'outside',
|
||||
\ ])
|
||||
call cursor([2, 11])
|
||||
|
||||
let g:vsnip_assert = {}
|
||||
let l:sequence = ''
|
||||
|
||||
function g:vsnip_assert.step1()
|
||||
call s:expect(vsnip#get_session()).not.to_be_empty()
|
||||
endfunction
|
||||
let l:sequence .= "a\<C-j>\<Plug>(vsnip-assert)"
|
||||
|
||||
function g:vsnip_assert.step2()
|
||||
call s:expect(vsnip#get_session()).not.to_be_empty()
|
||||
endfunction
|
||||
let l:sequence .= "funcname\<Plug>(vsnip-assert)"
|
||||
|
||||
function g:vsnip_assert.step3()
|
||||
call s:expect(vsnip#get_session()).not.to_be_empty()
|
||||
endfunction
|
||||
let l:sequence .= "\<Tab>return 1\<Plug>(vsnip-assert)"
|
||||
|
||||
function g:vsnip_assert.step4()
|
||||
call s:expect(vsnip#get_session()).to_be_empty()
|
||||
endfunction
|
||||
let l:sequence .= "\<Cmd>call cursor([1, 1])\<CR>modified\<Esc>"
|
||||
|
||||
call feedkeys(l:sequence, 'x')
|
||||
|
||||
let g:vsnip_deactivate_on = g:vsnip#DeactivateOn.OutsideOfSnippet
|
||||
End
|
||||
|
||||
It should deactivate snippet on edit the outside of current tabstop
|
||||
enew!
|
||||
set filetype=integration
|
||||
let g:vsnip_deactivate_on = g:vsnip#DeactivateOn.OutsideOfCurrentTabstop
|
||||
|
||||
call setline(1, [
|
||||
\ 'outside',
|
||||
\ 'deactivate',
|
||||
\ 'outside',
|
||||
\ ])
|
||||
call cursor([2, 11])
|
||||
|
||||
let g:vsnip_assert = {}
|
||||
let l:sequence = ''
|
||||
|
||||
function g:vsnip_assert.step1()
|
||||
call s:expect(vsnip#get_session()).not.to_be_empty()
|
||||
endfunction
|
||||
let l:sequence .= "a\<C-j>\<Plug>(vsnip-assert)"
|
||||
|
||||
function g:vsnip_assert.step2()
|
||||
call s:expect(vsnip#get_session()).not.to_be_empty()
|
||||
endfunction
|
||||
let l:sequence .= "funcname\<Plug>(vsnip-assert)"
|
||||
|
||||
function g:vsnip_assert.step3()
|
||||
call s:expect(vsnip#get_session()).to_be_empty()
|
||||
endfunction
|
||||
let l:sequence .= "\<Right>arguments\<Plug>(vsnip-assert)"
|
||||
|
||||
call feedkeys(l:sequence, 'x')
|
||||
|
||||
let g:vsnip_deactivate_on = g:vsnip#DeactivateOn.OutsideOfSnippet
|
||||
End
|
||||
End
|
||||
|
||||
Context realworld
|
||||
|
||||
It should work (complex example)
|
||||
enew!
|
||||
set filetype=integration
|
||||
call setline(1, 'realworld1')
|
||||
call cursor([1, 10])
|
||||
|
||||
let g:vsnip_assert = {}
|
||||
let l:sequence = ''
|
||||
|
||||
" expand and jump
|
||||
let l:sequence .= "a\<C-j>\<Plug>(vsnip-assert)"
|
||||
function g:vsnip_assert.step1()
|
||||
call s:expect(getbufline('%', '^', '$')).to_equal([
|
||||
\ '/** @class ClassName */',
|
||||
\ 'class ClassName extends ParentClassName {',
|
||||
\ ' public constructor() {',
|
||||
\ ' ',
|
||||
\ ' }',
|
||||
\ '}',
|
||||
\ ])
|
||||
endfunction
|
||||
|
||||
" sync placeholder
|
||||
let l:sequence .= "ModifiedClassName\<Plug>(vsnip-assert)"
|
||||
function g:vsnip_assert.step2()
|
||||
call s:expect(getbufline('%', '^', '$')).to_equal([
|
||||
\ '/** @class ModifiedClassName */',
|
||||
\ 'class ModifiedClassName extends ParentClassName {',
|
||||
\ ' public constructor() {',
|
||||
\ ' ',
|
||||
\ ' }',
|
||||
\ '}',
|
||||
\ ])
|
||||
endfunction
|
||||
|
||||
" edit nested placeholder
|
||||
let l:sequence .= "\<Tab>\<Tab>ModifiedParentClassName\<Plug>(vsnip-assert)"
|
||||
function g:vsnip_assert.step3()
|
||||
call s:expect(getbufline('%', '^', '$')).to_equal([
|
||||
\ '/** @class ModifiedClassName */',
|
||||
\ 'class ModifiedClassName extends ModifiedParentClassName {',
|
||||
\ ' public constructor() {',
|
||||
\ ' ',
|
||||
\ ' }',
|
||||
\ '}',
|
||||
\ ])
|
||||
endfunction
|
||||
|
||||
" remove nested placeholder by <BS>
|
||||
let l:sequence .= "\<S-Tab>\<BS>\<Plug>(vsnip-assert)"
|
||||
function g:vsnip_assert.step4()
|
||||
call s:expect(getbufline('%', '^', '$')).to_equal([
|
||||
\ '/** @class ModifiedClassName */',
|
||||
\ 'class ModifiedClassName {',
|
||||
\ ' public constructor() {',
|
||||
\ ' ',
|
||||
\ ' }',
|
||||
\ '}',
|
||||
\ ])
|
||||
endfunction
|
||||
|
||||
" jump to final tabstop
|
||||
let l:sequence .= "\<Tab>\<Plug>(vsnip-assert)"
|
||||
function g:vsnip_assert.step5()
|
||||
call s:expect(getcurpos()[1 : 2]).to_equal([4, 5])
|
||||
call s:expect(getbufline('%', '^', '$')).to_equal([
|
||||
\ '/** @class ModifiedClassName */',
|
||||
\ 'class ModifiedClassName {',
|
||||
\ ' public constructor() {',
|
||||
\ ' ',
|
||||
\ ' }',
|
||||
\ '}',
|
||||
\ ])
|
||||
endfunction
|
||||
call feedkeys(l:sequence, 'x')
|
||||
End
|
||||
|
||||
It should work ($VIM variable)
|
||||
enew!
|
||||
set filetype=integration
|
||||
call setline(1, 'realworld2')
|
||||
call cursor([1, 10])
|
||||
|
||||
let g:vsnip_assert = {}
|
||||
function! g:vsnip_assert.step1() abort
|
||||
call s:expect(getbufline('%', '^', '$')).to_equal([
|
||||
\ $USER
|
||||
\ ])
|
||||
endfunction
|
||||
call feedkeys("a\<C-j>\<Plug>(vsnip-assert)", 'x')
|
||||
End
|
||||
|
||||
It should work (indented $TM_SELECTED_TEXT char-wise)
|
||||
enew!
|
||||
set filetype=integration
|
||||
call setline(1, [
|
||||
\ ' <div>',
|
||||
\ ' <span />',
|
||||
\ ' </div>'
|
||||
\ ])
|
||||
let g:vsnip_assert = {}
|
||||
function! g:vsnip_assert.step1() abort
|
||||
call s:expect(getbufline('%', '^', '$')).to_equal([
|
||||
\ ' <div>',
|
||||
\ ' <div>',
|
||||
\ ' <span />',
|
||||
\ ' </div>',
|
||||
\ ' </div>'
|
||||
\ ])
|
||||
endfunction
|
||||
call feedkeys("1G3|v3G7|\<Plug>(vsnip-cut-text)realworld3\<C-j>", 'x')
|
||||
End
|
||||
|
||||
It should work (indented $TM_SELECTED_TEXT line-wise)
|
||||
enew!
|
||||
set filetype=integration
|
||||
call setline(1, [
|
||||
\ ' <div>',
|
||||
\ ' <span />',
|
||||
\ ' </div>'
|
||||
\ ])
|
||||
let g:vsnip_assert = {}
|
||||
function! g:vsnip_assert.step1() abort
|
||||
call s:expect(getbufline('%', '^', '$')).to_equal([
|
||||
\ ' <div>',
|
||||
\ ' <div>',
|
||||
\ ' <span />',
|
||||
\ ' </div>',
|
||||
\ ' </div>'
|
||||
\ ])
|
||||
endfunction
|
||||
call feedkeys("1GV3G\<Plug>(vsnip-cut-text)realworld3\<C-j>", 'x')
|
||||
End
|
||||
|
||||
It should work (no indented $TM_SELECTED_TEXT char-wise)
|
||||
enew!
|
||||
set filetype=integration
|
||||
call setline(1, [
|
||||
\ ' <div>',
|
||||
\ ' <span />',
|
||||
\ ' </div>'
|
||||
\ ])
|
||||
let g:vsnip_assert = {}
|
||||
function! g:vsnip_assert.step1() abort
|
||||
call s:expect(getbufline('%', '^', '$')).to_equal([
|
||||
\ ' <div><div>',
|
||||
\ ' <span />',
|
||||
\ ' </div></div>'
|
||||
\ ])
|
||||
endfunction
|
||||
call feedkeys("1G3|v3G7|\<Plug>(vsnip-cut-text)realworld4\<C-j>", 'x')
|
||||
End
|
||||
|
||||
It should work (no indented $TM_SELECTED_TEXT line-wise)
|
||||
enew!
|
||||
set filetype=integration
|
||||
call setline(1, [
|
||||
\ ' <div>',
|
||||
\ ' <span />',
|
||||
\ ' </div>'
|
||||
\ ])
|
||||
let g:vsnip_assert = {}
|
||||
function! g:vsnip_assert.step1() abort
|
||||
call s:expect(getbufline('%', '^', '$')).to_equal([
|
||||
\ ' <div><div>',
|
||||
\ ' <span />',
|
||||
\ ' </div></div>'
|
||||
\ ])
|
||||
endfunction
|
||||
call feedkeys("1GV3G\<Plug>(vsnip-cut-text)realworld4\<C-j>", 'x')
|
||||
End
|
||||
|
||||
It should work (modify follower placeholder manually)
|
||||
enew!
|
||||
set filetype=integration
|
||||
call setline(1, 'realworld5')
|
||||
call cursor([1, 10])
|
||||
|
||||
let g:vsnip_assert = {}
|
||||
let l:sequence = ''
|
||||
|
||||
" expand and jump
|
||||
let l:sequence .= "a\<C-j>\<Plug>(vsnip-assert)"
|
||||
function g:vsnip_assert.step1()
|
||||
call s:expect(getbufline('%', '^', '$')).to_equal([
|
||||
\ ', ________'
|
||||
\ ])
|
||||
endfunction
|
||||
|
||||
" edit $1
|
||||
let l:sequence .= "foobar\<Plug>(vsnip-assert)"
|
||||
function g:vsnip_assert.step2()
|
||||
call s:expect(getbufline('%', '^', '$')).to_equal([
|
||||
\ 'foobar, ____foobar____'
|
||||
\ ])
|
||||
endfunction
|
||||
|
||||
" edit $1's follower
|
||||
let l:sequence .= "\<Esc>1G16|dt_ibaz\<Plug>(vsnip-assert)"
|
||||
function g:vsnip_assert.step3()
|
||||
call s:expect(getbufline('%', '^', '$')).to_equal([
|
||||
\ 'foobar, ____foobaz____'
|
||||
\ ])
|
||||
endfunction
|
||||
|
||||
" edit $1 again
|
||||
let l:sequence .= "\<Esc>1G1|dt,imodified\<Plug>(vsnip-assert)"
|
||||
function g:vsnip_assert.step4()
|
||||
call s:expect(getbufline('%', '^', '$')).to_equal([
|
||||
\ 'modified, ____foobaz____'
|
||||
\ ])
|
||||
endfunction
|
||||
|
||||
" can jump to $2
|
||||
let l:sequence .= "\<Tab>\<Plug>(vsnip-assert)"
|
||||
function g:vsnip_assert.step5()
|
||||
call s:expect_selection([1, 11], [1, 24])
|
||||
endfunction
|
||||
|
||||
" can jump to $3
|
||||
let l:sequence .= "\<Tab>\<Plug>(vsnip-assert)"
|
||||
function g:vsnip_assert.step6()
|
||||
call s:expect_selection([1, 12], [1, 23])
|
||||
endfunction
|
||||
|
||||
call feedkeys(l:sequence, 'x')
|
||||
End
|
||||
|
||||
End
|
||||
|
||||
Context issue
|
||||
|
||||
It should work issue82
|
||||
enew!
|
||||
set filetype=integration
|
||||
call setline(1, "'")
|
||||
call cursor([1, 1])
|
||||
|
||||
let g:vsnip_assert = {}
|
||||
function g:vsnip_assert.step1()
|
||||
call s:expect(getcurpos()[1 : 2]).to_equal([1, 2])
|
||||
call s:expect(getbufline('%', '^', '$')).to_equal(["''"])
|
||||
endfunction
|
||||
call feedkeys("a\<C-j>\<Plug>(vsnip-assert)", 'x')
|
||||
End
|
||||
|
||||
It should work issue85
|
||||
enew!
|
||||
set filetype=integration
|
||||
call setline(1, 'issue85')
|
||||
call cursor([1, 7])
|
||||
|
||||
let g:vsnip_assert = {}
|
||||
function g:vsnip_assert.step1()
|
||||
call s:expect(getbufline('%', '^', '$')).to_equal(['for i=1,10', ' print(i)'])
|
||||
call s:expect_selection([1, 5], [1, 5])
|
||||
endfunction
|
||||
call feedkeys("a\<C-j>\<Plug>(vsnip-assert)", 'x')
|
||||
End
|
||||
|
||||
It should work issue106
|
||||
enew!
|
||||
set filetype=integration
|
||||
call setline(1, ['foo', 'issue106'])
|
||||
call cursor([2, 8])
|
||||
|
||||
let g:vsnip_assert = {}
|
||||
function g:vsnip_assert.step1()
|
||||
call s:expect(vsnip#get_session()).to_be_empty()
|
||||
endfunction
|
||||
call feedkeys("a\<C-j>\<Esc>gg0i_\<Plug>(vsnip-assert)", 'x')
|
||||
End
|
||||
|
||||
It should work issue122
|
||||
enew!
|
||||
set filetype=integration
|
||||
call setline(1, ['foo', 'issue122>'])
|
||||
call cursor([2, 9])
|
||||
|
||||
let g:vsnip_assert = {}
|
||||
function g:vsnip_assert.step1()
|
||||
call s:expect(getbufline('%', '^', '$')).to_equal(['foo', ''])
|
||||
endfunction
|
||||
call feedkeys("a\<C-j>\<Plug>(vsnip-assert)", 'x')
|
||||
End
|
||||
|
||||
It should work issue129
|
||||
enew!
|
||||
set filetype=integration
|
||||
call setline(1, ['issue129'])
|
||||
call cursor([1, 8])
|
||||
|
||||
let g:vsnip_assert = {}
|
||||
let l:sequence = ''
|
||||
|
||||
" expand
|
||||
let l:sequence .= "a\<C-j>\<Plug>(vsnip-assert)"
|
||||
function g:vsnip_assert.step1()
|
||||
call s:expect(getbufline('%', '^', '$')).to_equal(["console.log('', );"])
|
||||
endfunction
|
||||
|
||||
" modify
|
||||
let l:sequence .= "\<Esc>1G13|dt,iMODIFY\<Plug>(vsnip-assert)"
|
||||
function g:vsnip_assert.step2()
|
||||
call s:expect(getbufline('%', '^', '$')).to_equal(["console.log(MODIFY, );"])
|
||||
endfunction
|
||||
|
||||
" jump
|
||||
let l:sequence .= "\<Tab>\<Plug>(vsnip-assert)"
|
||||
function g:vsnip_assert.step3()
|
||||
call s:expect(getcurpos()[1 : 2]).to_equal([1, 21])
|
||||
endfunction
|
||||
|
||||
call feedkeys(l:sequence, 'x')
|
||||
End
|
||||
|
||||
It should work issue139
|
||||
enew!
|
||||
set filetype=integration
|
||||
call setline(1, ['issue139'])
|
||||
call cursor([1, 8])
|
||||
|
||||
let g:vsnip_assert = {}
|
||||
let l:sequence = ''
|
||||
|
||||
" expand
|
||||
let l:sequence .= "a\<C-j>\<Plug>(vsnip-assert)"
|
||||
function g:vsnip_assert.step1()
|
||||
call s:expect(getbufline('%', '^', '$')).to_equal([
|
||||
\ 'for (size_t i=0; i < count; i++) {',
|
||||
\ ' ',
|
||||
\ '}'
|
||||
\ ])
|
||||
endfunction
|
||||
|
||||
" modify
|
||||
let l:sequence .= "\<BS>\<Tab>variable\<Plug>(vsnip-assert)"
|
||||
function g:vsnip_assert.step2()
|
||||
call s:expect(getbufline('%', '^', '$')).to_equal([
|
||||
\ 'for (variable=0; variable < count; variable++) {',
|
||||
\ ' ',
|
||||
\ '}'
|
||||
\ ])
|
||||
endfunction
|
||||
|
||||
call feedkeys(l:sequence, 'x')
|
||||
End
|
||||
|
||||
It should work issue249
|
||||
enew!
|
||||
set filetype=integration
|
||||
call setline(1, ['issue249'])
|
||||
call cursor([1, 8])
|
||||
|
||||
let g:vsnip_assert = {}
|
||||
let l:sequence = ''
|
||||
|
||||
" expand
|
||||
let l:sequence .= "a\<C-j>\<Plug>(vsnip-assert)"
|
||||
function g:vsnip_assert.step1()
|
||||
call s:expect_selection([1, 1], [1, 3])
|
||||
call s:expect(getbufline('%', '^', '$')).to_equal([
|
||||
\ 'FOO',
|
||||
\ '',
|
||||
\ ])
|
||||
endfunction
|
||||
|
||||
call feedkeys(l:sequence, 'x')
|
||||
End
|
||||
|
||||
End
|
||||
|
||||
End
|
||||
|
||||
45
dot_vim/plugged/vim-vsnip/syntax/snippets.vim
Normal file
45
dot_vim/plugged/vim-vsnip/syntax/snippets.vim
Normal file
@@ -0,0 +1,45 @@
|
||||
" MIT License
|
||||
"
|
||||
" Copyright 2009-2010 Michael Sanders. All rights reserved.
|
||||
|
||||
" 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." From https://github.com/garbas/vim-snipmate
|
||||
|
||||
|
||||
" Syntax highlighting for .snippets files (used for snipMate.vim)
|
||||
" Hopefully this should make snippets a bit nicer to write!
|
||||
syn match snipComment '^#.*'
|
||||
syn match placeHolder '\${\d\+\(:.\{-}\)\=}' contains=snipCommand
|
||||
syn match tabStop '\$\d\+'
|
||||
syn match snipEscape '\\\\\|\\`'
|
||||
syn match snipCommand '\%(\\\@<!\%(\\\\\)*\)\@<=`.\{-}\%(\\\@<!\%(\\\\\)*\)\@<=`'
|
||||
syn match snippet '^snippet.*' contains=multiSnipText,snipKeyword
|
||||
syn match snippet '^extends.*' contains=snipKeyword
|
||||
syn match multiSnipText '\S\+ \zs.*' contained
|
||||
syn match snipKeyword '^(snippet|extends)'me=s+8 contained
|
||||
syn match snipError "^[^#vse\t].*$"
|
||||
|
||||
hi link snippet Identifier
|
||||
hi link snipComment Comment
|
||||
hi link multiSnipText String
|
||||
hi link snipKeyword Keyword
|
||||
hi link snipEscape SpecialChar
|
||||
hi link placeHolder Special
|
||||
hi link tabStop Special
|
||||
hi link snipCommand String
|
||||
hi link snipError Error
|
||||
Reference in New Issue
Block a user