I broke up with neovim....vim is my best friend now

This commit is contained in:
LinlyBoi
2023-04-30 08:14:07 +03:00
parent 0d185449c5
commit 4a4a6b1e81
5245 changed files with 468325 additions and 25 deletions

View 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

View 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

View File

@@ -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

View 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