574 lines
18 KiB
Plaintext
574 lines
18 KiB
Plaintext
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
|