Apply chunks from bottom to top

This commit is contained in:
micbou 2018-02-10 14:10:44 +01:00
parent 26a5e3cbc4
commit c692b48bc6
No known key found for this signature in database
GPG Key ID: C7E8FD1F3BDA1E05
2 changed files with 328 additions and 538 deletions

View File

@ -88,379 +88,217 @@ def AssertBuffersAreEqualAsBytes( result_buffer, expected_buffer ):
def ReplaceChunk_SingleLine_Repl_1_test():
# Replace with longer range
result_buffer = [ 'This is a string' ]
start, end = _BuildLocations( 1, 1, 1, 5 )
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start,
end,
'How long',
0,
0,
result_buffer )
result_buffer = VimBuffer( 'buffer', contents = [ 'This is a string' ] )
start, end = _BuildLocations( 1, 11, 1, 17 )
vimsupport.ReplaceChunk( start, end, 'pie', result_buffer )
AssertBuffersAreEqualAsBytes( [ 'How long is a string' ], result_buffer )
eq_( line_offset, 0 )
eq_( char_offset, 4 )
AssertBuffersAreEqualAsBytes( [ 'This is a pie' ], result_buffer )
# and replace again, using delta
# and replace again
start, end = _BuildLocations( 1, 10, 1, 11 )
( new_line_offset, new_char_offset ) = vimsupport.ReplaceChunk(
start,
end,
' piece of ',
line_offset,
char_offset,
result_buffer )
vimsupport.ReplaceChunk( start, end, ' piece of ', result_buffer )
line_offset += new_line_offset
char_offset += new_char_offset
AssertBuffersAreEqualAsBytes( [ 'How long is a piece of string' ],
result_buffer )
eq_( new_line_offset, 0 )
eq_( new_char_offset, 9 )
eq_( line_offset, 0 )
eq_( char_offset, 13 )
AssertBuffersAreEqualAsBytes( [ 'This is a piece of pie' ], result_buffer )
# and once more, for luck
start, end = _BuildLocations( 1, 11, 1, 17 )
( new_line_offset, new_char_offset ) = vimsupport.ReplaceChunk(
start,
end,
'pie',
line_offset,
char_offset,
result_buffer )
line_offset += new_line_offset
char_offset += new_char_offset
start, end = _BuildLocations( 1, 1, 1, 5 )
vimsupport.ReplaceChunk( start, end, 'How long', result_buffer )
AssertBuffersAreEqualAsBytes( [ 'How long is a piece of pie' ],
result_buffer )
eq_( new_line_offset, 0 )
eq_( new_char_offset, -3 )
eq_( line_offset, 0 )
eq_( char_offset, 10 )
def ReplaceChunk_SingleLine_Repl_2_test():
# Replace with shorter range
result_buffer = [ 'This is a string' ]
result_buffer = VimBuffer( 'buffer', contents = [ 'This is a string' ] )
start, end = _BuildLocations( 1, 11, 1, 17 )
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start,
end,
'test',
0,
0,
result_buffer )
vimsupport.ReplaceChunk( start, end, 'test', result_buffer )
AssertBuffersAreEqualAsBytes( [ 'This is a test' ], result_buffer )
eq_( line_offset, 0 )
eq_( char_offset, -2 )
def ReplaceChunk_SingleLine_Repl_3_test():
# Replace with equal range
result_buffer = [ 'This is a string' ]
result_buffer = VimBuffer( 'buffer', contents = [ 'This is a string' ] )
start, end = _BuildLocations( 1, 6, 1, 8 )
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start,
end,
'be',
0,
0,
result_buffer )
vimsupport.ReplaceChunk( start, end, 'be', result_buffer )
AssertBuffersAreEqualAsBytes( [ 'This be a string' ], result_buffer )
eq_( line_offset, 0 )
eq_( char_offset, 0 )
def ReplaceChunk_SingleLine_Add_1_test():
# Insert at start
result_buffer = [ 'is a string' ]
result_buffer = VimBuffer( 'buffer', contents = [ 'is a string' ] )
start, end = _BuildLocations( 1, 1, 1, 1 )
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start,
end,
'This ',
0,
0,
result_buffer )
vimsupport.ReplaceChunk( start, end, 'This ', result_buffer )
AssertBuffersAreEqualAsBytes( [ 'This is a string' ], result_buffer )
eq_( line_offset, 0 )
eq_( char_offset, 5 )
def ReplaceChunk_SingleLine_Add_2_test():
# Insert at end
result_buffer = [ 'This is a ' ]
result_buffer = VimBuffer( 'buffer', contents = [ 'This is a ' ] )
start, end = _BuildLocations( 1, 11, 1, 11 )
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start,
end,
'string',
0,
0,
result_buffer )
vimsupport.ReplaceChunk( start, end, 'string', result_buffer )
AssertBuffersAreEqualAsBytes( [ 'This is a string' ], result_buffer )
eq_( line_offset, 0 )
eq_( char_offset, 6 )
def ReplaceChunk_SingleLine_Add_3_test():
# Insert in the middle
result_buffer = [ 'This is a string' ]
result_buffer = VimBuffer( 'buffer', contents = [ 'This is a string' ] )
start, end = _BuildLocations( 1, 8, 1, 8 )
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start,
end,
' not',
0,
0,
result_buffer )
vimsupport.ReplaceChunk( start, end, ' not', result_buffer )
AssertBuffersAreEqualAsBytes( [ 'This is not a string' ], result_buffer )
eq_( line_offset, 0 )
eq_( char_offset, 4 )
def ReplaceChunk_SingleLine_Del_1_test():
# Delete from start
result_buffer = [ 'This is a string' ]
result_buffer = VimBuffer( 'buffer', contents = [ 'This is a string' ] )
start, end = _BuildLocations( 1, 1, 1, 6 )
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start,
end,
'',
0,
0,
result_buffer )
vimsupport.ReplaceChunk( start, end, '', result_buffer )
AssertBuffersAreEqualAsBytes( [ 'is a string' ], result_buffer )
eq_( line_offset, 0 )
eq_( char_offset, -5 )
def ReplaceChunk_SingleLine_Del_2_test():
# Delete from end
result_buffer = [ 'This is a string' ]
result_buffer = VimBuffer( 'buffer', contents = [ 'This is a string' ] )
start, end = _BuildLocations( 1, 10, 1, 18 )
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start,
end,
'',
0,
0,
result_buffer )
vimsupport.ReplaceChunk( start, end, '', result_buffer )
AssertBuffersAreEqualAsBytes( [ 'This is a' ], result_buffer )
eq_( line_offset, 0 )
eq_( char_offset, -8 )
def ReplaceChunk_SingleLine_Del_3_test():
# Delete from middle
result_buffer = [ 'This is not a string' ]
result_buffer = VimBuffer( 'buffer', contents = [ 'This is not a string' ] )
start, end = _BuildLocations( 1, 9, 1, 13 )
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start,
end,
'',
0,
0,
result_buffer )
vimsupport.ReplaceChunk( start, end, '', result_buffer )
AssertBuffersAreEqualAsBytes( [ 'This is a string' ], result_buffer )
eq_( line_offset, 0 )
eq_( char_offset, -4 )
def ReplaceChunk_SingleLine_Unicode_ReplaceUnicodeChars_test():
# Replace Unicode characters.
result_buffer = [ 'This Uniçø∂‰ string is in the middle' ]
result_buffer = VimBuffer(
'buffer', contents = [ 'This Uniçø∂‰ string is in the middle' ] )
start, end = _BuildLocations( 1, 6, 1, 20 )
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start,
end,
'Unicode ',
0,
0,
result_buffer )
vimsupport.ReplaceChunk( start, end, 'Unicode ', result_buffer )
AssertBuffersAreEqualAsBytes( [ 'This Unicode string is in the middle' ],
result_buffer )
eq_( line_offset, 0 )
eq_( char_offset, -6 )
def ReplaceChunk_SingleLine_Unicode_ReplaceAfterUnicode_test():
# Replace ASCII characters after Unicode characters in the line.
result_buffer = [ 'This Uniçø∂‰ string is in the middle' ]
result_buffer = VimBuffer(
'buffer', contents = [ 'This Uniçø∂‰ string is in the middle' ] )
start, end = _BuildLocations( 1, 30, 1, 43 )
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start,
end,
'fåke',
0,
0,
result_buffer )
vimsupport.ReplaceChunk( start, end, 'fåke', result_buffer )
AssertBuffersAreEqualAsBytes( [ 'This Uniçø∂‰ string is fåke' ],
result_buffer )
eq_( line_offset, 0 )
eq_( char_offset, -8 )
def ReplaceChunk_SingleLine_Unicode_Grown_test():
# Replace ASCII characters after Unicode characters in the line.
result_buffer = [ 'a' ]
result_buffer = VimBuffer( 'buffer', contents = [ 'a' ] )
start, end = _BuildLocations( 1, 1, 1, 2 )
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start,
end,
'å',
0,
0,
result_buffer )
vimsupport.ReplaceChunk( start, end, 'å', result_buffer )
AssertBuffersAreEqualAsBytes( [ 'å' ], result_buffer )
eq_( line_offset, 0 )
eq_( char_offset, 1 ) # Note: byte difference (a = 1 byte, å = 2 bytes)
def ReplaceChunk_RemoveSingleLine_test():
result_buffer = [ 'aAa',
result_buffer = VimBuffer( 'buffer', contents = [ 'aAa',
'aBa',
'aCa' ]
'aCa' ] )
start, end = _BuildLocations( 2, 1, 3, 1 )
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start, end, '',
0, 0, result_buffer )
vimsupport.ReplaceChunk( start, end, '', result_buffer )
# First line is not affected.
expected_buffer = [ 'aAa',
'aCa' ]
AssertBuffersAreEqualAsBytes( expected_buffer, result_buffer )
eq_( line_offset, -1 )
eq_( char_offset, 0 )
AssertBuffersAreEqualAsBytes( [ 'aAa',
'aCa' ], result_buffer )
def ReplaceChunk_SingleToMultipleLines_test():
result_buffer = [ 'aAa',
result_buffer = VimBuffer( 'buffer', contents = [ 'aAa',
'aBa',
'aCa' ]
start, end = _BuildLocations( 2, 2, 2, 2 )
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start, end, 'Eb\nbF',
0, 0, result_buffer )
expected_buffer = [ 'aAa',
'aEb',
'bFBa',
'aCa' ]
AssertBuffersAreEqualAsBytes( expected_buffer, result_buffer )
eq_( line_offset, 1 )
eq_( char_offset, 1 )
# now make another change to the "2nd" line
'aCa' ] )
start, end = _BuildLocations( 2, 3, 2, 4 )
( new_line_offset, new_char_offset ) = vimsupport.ReplaceChunk(
start,
end,
'cccc',
line_offset,
char_offset,
result_buffer )
vimsupport.ReplaceChunk( start, end, 'cccc', result_buffer )
line_offset += new_line_offset
char_offset += new_char_offset
AssertBuffersAreEqualAsBytes( [ 'aAa',
'aBcccc',
'aCa' ], result_buffer )
# now make another change to the second line
start, end = _BuildLocations( 2, 2, 2, 2 )
vimsupport.ReplaceChunk( start, end, 'Eb\nbF', result_buffer )
AssertBuffersAreEqualAsBytes( [ 'aAa',
'aEb',
'bFBcccc',
'aCa' ], result_buffer )
eq_( line_offset, 1 )
eq_( char_offset, 4 )
def ReplaceChunk_SingleToMultipleLines2_test():
result_buffer = [ 'aAa', 'aBa', 'aCa' ]
result_buffer = VimBuffer( 'buffer', contents = [ 'aAa',
'aBa',
'aCa' ] )
start, end = _BuildLocations( 2, 2, 2, 2 )
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start,
end,
'Eb\nbFb\nG',
0,
0,
result_buffer )
expected_buffer = [ 'aAa',
vimsupport.ReplaceChunk( start, end, 'Eb\nbFb\nG', result_buffer )
AssertBuffersAreEqualAsBytes( [ 'aAa',
'aEb',
'bFb',
'GBa',
'aCa' ]
AssertBuffersAreEqualAsBytes( expected_buffer, result_buffer )
eq_( line_offset, 2 )
eq_( char_offset, 0 )
'aCa' ], result_buffer )
def ReplaceChunk_SingleToMultipleLines3_test():
result_buffer = [ 'aAa', 'aBa', 'aCa' ]
result_buffer = VimBuffer( 'buffer', contents = [ 'aAa',
'aBa',
'aCa' ] )
start, end = _BuildLocations( 2, 2, 2, 2 )
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start,
end,
'Eb\nbFb\nbGb',
0,
0,
result_buffer )
expected_buffer = [ 'aAa',
vimsupport.ReplaceChunk( start, end, 'Eb\nbFb\nbGb', result_buffer )
AssertBuffersAreEqualAsBytes( [ 'aAa',
'aEb',
'bFb',
'bGbBa',
'aCa' ]
AssertBuffersAreEqualAsBytes( expected_buffer, result_buffer )
eq_( line_offset, 2 )
eq_( char_offset, 2 )
'aCa' ], result_buffer )
def ReplaceChunk_SingleToMultipleLinesReplace_test():
result_buffer = [ 'aAa', 'aBa', 'aCa' ]
result_buffer = VimBuffer( 'buffer', contents = [ 'aAa',
'aBa',
'aCa' ] )
start, end = _BuildLocations( 1, 2, 1, 4 )
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start,
end,
'Eb\nbFb\nbGb',
0,
0,
result_buffer )
expected_buffer = [ 'aEb',
vimsupport.ReplaceChunk( start, end, 'Eb\nbFb\nbGb', result_buffer )
AssertBuffersAreEqualAsBytes( [ 'aEb',
'bFb',
'bGb',
'aBa',
'aCa' ]
AssertBuffersAreEqualAsBytes( expected_buffer, result_buffer )
eq_( line_offset, 2 )
eq_( char_offset, 0 )
'aCa' ], result_buffer )
def ReplaceChunk_SingleToMultipleLinesReplace_2_test():
result_buffer = [ 'aAa',
result_buffer = VimBuffer( 'buffer', contents = [ 'aAa',
'aBa',
'aCa' ]
start, end = _BuildLocations( 1, 2, 1, 4 )
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start,
end,
'Eb\nbFb\nbGb',
0,
0,
result_buffer )
expected_buffer = [ 'aEb',
'bFb',
'bGb',
'aBa',
'aCa' ]
AssertBuffersAreEqualAsBytes( expected_buffer, result_buffer )
eq_( line_offset, 2 )
eq_( char_offset, 0 )
# now do a subsequent change (insert at end of line "1")
'aCa' ] )
start, end = _BuildLocations( 1, 4, 1, 4 )
( new_line_offset, new_char_offset ) = vimsupport.ReplaceChunk(
start,
end,
'cccc',
line_offset,
char_offset,
result_buffer )
vimsupport.ReplaceChunk( start, end, 'cccc', result_buffer )
line_offset += new_line_offset
char_offset += new_char_offset
AssertBuffersAreEqualAsBytes( [ 'aAacccc',
'aBa',
'aCa', ], result_buffer )
# now do a subsequent change (insert in the middle of the first line)
start, end = _BuildLocations( 1, 2, 1, 4 )
vimsupport.ReplaceChunk( start, end, 'Eb\nbFb\nbGb', result_buffer )
AssertBuffersAreEqualAsBytes( [ 'aEb',
'bFb',
@ -468,248 +306,146 @@ def ReplaceChunk_SingleToMultipleLinesReplace_2_test():
'aBa',
'aCa' ], result_buffer )
eq_( line_offset, 2 )
eq_( char_offset, 4 )
def ReplaceChunk_MultipleLinesToSingleLine_test():
result_buffer = [ 'aAa', 'aBa', 'aCaaaa' ]
start, end = _BuildLocations( 2, 2, 3, 2 )
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start, end, 'E',
0, 0, result_buffer )
expected_buffer = [ 'aAa', 'aECaaaa' ]
AssertBuffersAreEqualAsBytes( expected_buffer, result_buffer )
eq_( line_offset, -1 )
eq_( char_offset, 1 )
result_buffer = VimBuffer( 'buffer', contents = [ 'aAa',
'aBa',
'aCaaaa' ] )
start, end = _BuildLocations( 3, 4, 3, 5 )
vimsupport.ReplaceChunk( start, end, 'dd\ndd', result_buffer )
AssertBuffersAreEqualAsBytes( [ 'aAa',
'aBa',
'aCadd',
'ddaa' ], result_buffer )
# make another modification applying offsets
start, end = _BuildLocations( 3, 3, 3, 4 )
( new_line_offset, new_char_offset ) = vimsupport.ReplaceChunk(
start,
end,
'cccc',
line_offset,
char_offset,
result_buffer )
line_offset += new_line_offset
char_offset += new_char_offset
vimsupport.ReplaceChunk( start, end, 'cccc', result_buffer )
AssertBuffersAreEqualAsBytes( [ 'aAa',
'aECccccaaa' ], result_buffer )
eq_( line_offset, -1 )
eq_( char_offset, 4 )
'aBa',
'aCccccdd',
'ddaa' ], result_buffer )
# and another, for luck
start, end = _BuildLocations( 3, 4, 3, 5 )
( new_line_offset, new_char_offset ) = vimsupport.ReplaceChunk(
start,
end,
'dd\ndd',
line_offset,
char_offset,
result_buffer )
line_offset += new_line_offset
char_offset += new_char_offset
start, end = _BuildLocations( 2, 2, 3, 2 )
vimsupport.ReplaceChunk( start, end, 'E', result_buffer )
AssertBuffersAreEqualAsBytes( [ 'aAa',
'aECccccdd',
'ddaa' ], result_buffer )
eq_( line_offset, 0 )
eq_( char_offset, -2 )
def ReplaceChunk_MultipleLinesToSameMultipleLines_test():
result_buffer = [ 'aAa',
result_buffer = VimBuffer( 'buffer', contents = [ 'aAa',
'aBa',
'aCa',
'aDe' ]
'aDe' ] )
start, end = _BuildLocations( 2, 2, 3, 2 )
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start, end, 'Eb\nbF',
0, 0, result_buffer )
expected_buffer = [ 'aAa',
vimsupport.ReplaceChunk( start, end, 'Eb\nbF', result_buffer )
AssertBuffersAreEqualAsBytes( [ 'aAa',
'aEb',
'bFCa',
'aDe' ]
AssertBuffersAreEqualAsBytes( expected_buffer, result_buffer )
eq_( line_offset, 0 )
eq_( char_offset, 1 )
'aDe' ], result_buffer )
def ReplaceChunk_MultipleLinesToMoreMultipleLines_test():
result_buffer = [ 'aAa',
result_buffer = VimBuffer( 'buffer', contents = [ 'aAa',
'aBa',
'aCa',
'aDe' ]
'aDe' ] )
start, end = _BuildLocations( 2, 2, 3, 2 )
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start,
end,
'Eb\nbFb\nbG',
0,
0,
result_buffer )
expected_buffer = [ 'aAa',
vimsupport.ReplaceChunk( start, end, 'Eb\nbFb\nbG', result_buffer )
AssertBuffersAreEqualAsBytes( [ 'aAa',
'aEb',
'bFb',
'bGCa',
'aDe' ]
AssertBuffersAreEqualAsBytes( expected_buffer, result_buffer )
eq_( line_offset, 1 )
eq_( char_offset, 1 )
'aDe' ], result_buffer )
def ReplaceChunk_MultipleLinesToLessMultipleLines_test():
result_buffer = [ 'aAa',
result_buffer = VimBuffer( 'buffer', contents = [ 'aAa',
'aBa',
'aCa',
'aDe' ]
'aDe' ] )
start, end = _BuildLocations( 1, 2, 3, 2 )
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start, end, 'Eb\nbF',
0, 0, result_buffer )
expected_buffer = [ 'aEb', 'bFCa', 'aDe' ]
AssertBuffersAreEqualAsBytes( expected_buffer, result_buffer )
eq_( line_offset, -1 )
eq_( char_offset, 1 )
vimsupport.ReplaceChunk( start, end, 'Eb\nbF', result_buffer )
AssertBuffersAreEqualAsBytes( [ 'aEb',
'bFCa',
'aDe' ], result_buffer )
def ReplaceChunk_MultipleLinesToEvenLessMultipleLines_test():
result_buffer = [ 'aAa',
result_buffer = VimBuffer( 'buffer', contents = [ 'aAa',
'aBa',
'aCa',
'aDe' ]
'aDe' ] )
start, end = _BuildLocations( 1, 2, 4, 2 )
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start, end, 'Eb\nbF',
0, 0, result_buffer )
expected_buffer = [ 'aEb', 'bFDe' ]
AssertBuffersAreEqualAsBytes( expected_buffer, result_buffer )
eq_( line_offset, -2 )
eq_( char_offset, 1 )
vimsupport.ReplaceChunk( start, end, 'Eb\nbF', result_buffer )
AssertBuffersAreEqualAsBytes( [ 'aEb',
'bFDe' ], result_buffer )
def ReplaceChunk_SpanBufferEdge_test():
result_buffer = [ 'aAa',
result_buffer = VimBuffer( 'buffer', contents = [ 'aAa',
'aBa',
'aCa' ]
'aCa' ] )
start, end = _BuildLocations( 1, 1, 1, 3 )
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start, end, 'bDb',
0, 0, result_buffer )
expected_buffer = [ 'bDba',
vimsupport.ReplaceChunk( start, end, 'bDb', result_buffer )
AssertBuffersAreEqualAsBytes( [ 'bDba',
'aBa',
'aCa' ]
AssertBuffersAreEqualAsBytes( expected_buffer, result_buffer )
eq_( line_offset, 0 )
eq_( char_offset, 1 )
'aCa' ], result_buffer )
def ReplaceChunk_DeleteTextInLine_test():
result_buffer = [ 'aAa',
result_buffer = VimBuffer( 'buffer', contents = [ 'aAa',
'aBa',
'aCa' ]
'aCa' ] )
start, end = _BuildLocations( 2, 2, 2, 3 )
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start, end, '',
0, 0, result_buffer )
expected_buffer = [ 'aAa',
vimsupport.ReplaceChunk( start, end, '', result_buffer )
AssertBuffersAreEqualAsBytes( [ 'aAa',
'aa',
'aCa' ]
AssertBuffersAreEqualAsBytes( expected_buffer, result_buffer )
eq_( line_offset, 0 )
eq_( char_offset, -1 )
'aCa' ], result_buffer )
def ReplaceChunk_AddTextInLine_test():
result_buffer = [ 'aAa',
result_buffer = VimBuffer( 'buffer', contents = [ 'aAa',
'aBa',
'aCa' ]
'aCa' ] )
start, end = _BuildLocations( 2, 2, 2, 2 )
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start, end, 'bDb',
0, 0, result_buffer )
expected_buffer = [ 'aAa',
vimsupport.ReplaceChunk( start, end, 'bDb', result_buffer )
AssertBuffersAreEqualAsBytes( [ 'aAa',
'abDbBa',
'aCa' ]
AssertBuffersAreEqualAsBytes( expected_buffer, result_buffer )
eq_( line_offset, 0 )
eq_( char_offset, 3 )
'aCa' ], result_buffer )
def ReplaceChunk_ReplaceTextInLine_test():
result_buffer = [ 'aAa',
result_buffer = VimBuffer( 'buffer', contents = [ 'aAa',
'aBa',
'aCa' ]
'aCa' ] )
start, end = _BuildLocations( 2, 2, 2, 3 )
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start, end, 'bDb',
0, 0, result_buffer )
expected_buffer = [ 'aAa',
vimsupport.ReplaceChunk( start, end, 'bDb', result_buffer )
AssertBuffersAreEqualAsBytes( [ 'aAa',
'abDba',
'aCa' ]
AssertBuffersAreEqualAsBytes( expected_buffer, result_buffer )
eq_( line_offset, 0 )
eq_( char_offset, 2 )
'aCa' ], result_buffer )
def ReplaceChunk_SingleLineOffsetWorks_test():
result_buffer = [ 'aAa',
'aBa',
'aCa' ]
start, end = _BuildLocations( 1, 1, 1, 2 )
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start, end, 'bDb',
1, 1, result_buffer )
expected_buffer = [ 'aAa',
'abDba',
'aCa' ]
AssertBuffersAreEqualAsBytes( expected_buffer, result_buffer )
eq_( line_offset, 0 )
eq_( char_offset, 2 )
def ReplaceChunk_NewlineChunk_test():
result_buffer = VimBuffer( 'buffer', contents = [ 'first line',
'second line' ] )
start, end = _BuildLocations( 1, 11, 2, 1 )
vimsupport.ReplaceChunk( start, end, '\n', result_buffer )
def ReplaceChunk_SingleLineToMultipleLinesOffsetWorks_test():
result_buffer = [ 'aAa',
'aBa',
'aCa' ]
start, end = _BuildLocations( 1, 1, 1, 2 )
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start, end, 'Db\nE',
1, 1, result_buffer )
expected_buffer = [ 'aAa',
'aDb',
'Ea',
'aCa' ]
AssertBuffersAreEqualAsBytes( expected_buffer, result_buffer )
eq_( line_offset, 1 )
eq_( char_offset, -1 )
def ReplaceChunk_MultipleLinesToSingleLineOffsetWorks_test():
result_buffer = [ 'aAa',
'aBa',
'aCa' ]
start, end = _BuildLocations( 1, 1, 2, 2 )
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start, end, 'bDb',
1, 1, result_buffer )
expected_buffer = [ 'aAa',
'abDbCa' ]
AssertBuffersAreEqualAsBytes( expected_buffer, result_buffer )
eq_( line_offset, -1 )
eq_( char_offset, 3 )
def ReplaceChunk_MultipleLineOffsetWorks_test():
result_buffer = [ 'aAa',
'aBa',
'aCa' ]
start, end = _BuildLocations( 3, 1, 4, 3 )
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start,
end,
'bDb\nbEb\nbFb',
-1,
1,
result_buffer )
expected_buffer = [ 'aAa',
'abDb',
'bEb',
'bFba' ]
AssertBuffersAreEqualAsBytes( expected_buffer, result_buffer )
eq_( line_offset, 1 )
eq_( char_offset, 1 )
AssertBuffersAreEqualAsBytes( [ 'first line',
'second line' ], result_buffer )
def _BuildLocations( start_line, start_column, end_line, end_column ):
@ -728,11 +464,10 @@ def ReplaceChunksInBuffer_SortedChunks_test():
_BuildChunk( 1, 11, 1, 11, ')' )
]
result_buffer = [ 'CT<10 >> 2> ct' ]
vimsupport.ReplaceChunksInBuffer( chunks, result_buffer, None )
result_buffer = VimBuffer( 'buffer', contents = [ 'CT<10 >> 2> ct' ] )
vimsupport.ReplaceChunksInBuffer( chunks, result_buffer )
expected_buffer = [ 'CT<(10 >> 2)> ct' ]
AssertBuffersAreEqualAsBytes( expected_buffer, result_buffer )
AssertBuffersAreEqualAsBytes( [ 'CT<(10 >> 2)> ct' ], result_buffer )
def ReplaceChunksInBuffer_UnsortedChunks_test():
@ -741,11 +476,78 @@ def ReplaceChunksInBuffer_UnsortedChunks_test():
_BuildChunk( 1, 4, 1, 4, '(' )
]
result_buffer = [ 'CT<10 >> 2> ct' ]
vimsupport.ReplaceChunksInBuffer( chunks, result_buffer, None )
result_buffer = VimBuffer( 'buffer', contents = [ 'CT<10 >> 2> ct' ] )
vimsupport.ReplaceChunksInBuffer( chunks, result_buffer )
expected_buffer = [ 'CT<(10 >> 2)> ct' ]
AssertBuffersAreEqualAsBytes( expected_buffer, result_buffer )
AssertBuffersAreEqualAsBytes( [ 'CT<(10 >> 2)> ct' ], result_buffer )
def ReplaceChunksInBuffer_LineOverlappingChunks_test():
chunks = [
_BuildChunk( 1, 11, 2, 1, '\n ' ),
_BuildChunk( 2, 12, 3, 1, '\n ' ),
_BuildChunk( 3, 11, 4, 1, '\n ' )
]
result_buffer = VimBuffer( 'buffer', contents = [ 'first line',
'second line',
'third line',
'fourth line' ] )
vimsupport.ReplaceChunksInBuffer( chunks, result_buffer )
AssertBuffersAreEqualAsBytes( [ 'first line',
' second line',
' third line',
' fourth line' ], result_buffer )
def ReplaceChunksInBuffer_OutdentChunks_test():
chunks = [
_BuildChunk( 1, 1, 1, 5, ' ' ),
_BuildChunk( 1, 15, 2, 9, '\n ' ),
_BuildChunk( 2, 20, 3, 3, '\n' )
]
result_buffer = VimBuffer( 'buffer', contents = [ ' first line',
' second line',
' third line' ] )
vimsupport.ReplaceChunksInBuffer( chunks, result_buffer )
AssertBuffersAreEqualAsBytes( [ ' first line',
' second line',
' third line' ], result_buffer )
def ReplaceChunksInBuffer_OneLineIndentingChunks_test():
chunks = [
_BuildChunk( 1, 8, 2, 1, '\n ' ),
_BuildChunk( 2, 9, 2, 10, '\n ' ),
_BuildChunk( 2, 19, 2, 20, '\n ' )
]
result_buffer = VimBuffer( 'buffer', contents = [ 'class {',
'method { statement }',
'}' ] )
vimsupport.ReplaceChunksInBuffer( chunks, result_buffer )
AssertBuffersAreEqualAsBytes( [ 'class {',
' method {',
' statement',
' }',
'}' ], result_buffer )
def ReplaceChunksInBuffer_SameLocation_test():
chunks = [
_BuildChunk( 1, 1, 1, 1, 'this ' ),
_BuildChunk( 1, 1, 1, 1, 'is ' ),
_BuildChunk( 1, 1, 1, 1, 'pure ' )
]
result_buffer = VimBuffer( 'buffer', contents = [ 'folly' ] )
vimsupport.ReplaceChunksInBuffer( chunks, result_buffer )
AssertBuffersAreEqualAsBytes( [ 'this is pure folly' ], result_buffer )
@patch( 'ycm.vimsupport.VariableExists', return_value = False )

View File

@ -711,15 +711,14 @@ def ReplaceChunks( chunks ):
If for some reason a file could not be opened or changed, raises RuntimeError.
Otherwise, returns no meaningful value."""
# We apply the edits file-wise for efficiency, and because we must track the
# file-wise offset deltas (caused by the modifications to the text).
# We apply the edits file-wise for efficiency.
chunks_by_file = _SortChunksByFile( chunks )
# We sort the file list simply to enable repeatable testing
# We sort the file list simply to enable repeatable testing.
sorted_file_list = sorted( iterkeys( chunks_by_file ) )
# Make sure the user is prepared to have her screen mutilated by the new
# buffers
# buffers.
num_files_to_open = _GetNumNonVisibleFiles( sorted_file_list )
if num_files_to_open > 0:
@ -732,11 +731,10 @@ def ReplaceChunks( chunks ):
locations = []
for filepath in sorted_file_list:
( buffer_num, close_window ) = _OpenFileInSplitIfNeeded( filepath )
buffer_num, close_window = _OpenFileInSplitIfNeeded( filepath )
ReplaceChunksInBuffer( chunks_by_file[ filepath ],
vim.buffers[ buffer_num ],
locations )
locations.extend( ReplaceChunksInBuffer( chunks_by_file[ filepath ],
vim.buffers[ buffer_num ] ) )
# When opening tons of files, we don't want to have a split for each new
# file, as this simply does not scale, so we open the window, make the
@ -760,90 +758,83 @@ def ReplaceChunks( chunks ):
warning = False )
def ReplaceChunksInBuffer( chunks, vim_buffer, locations ):
"""Apply changes in |chunks| to the buffer-like object |buffer|. Append each
chunk's start to the list |locations|"""
def ReplaceChunksInBuffer( chunks, vim_buffer ):
"""Apply changes in |chunks| to the buffer-like object |buffer| and return the
locations for that buffer."""
# We need to track the difference in length, but ensuring we apply fixes
# in ascending order of insertion point.
# We apply the chunks from the bottom to the top of the buffer so that we
# don't need to adjust the position of the remaining chunks due to text
# changes. This assumes that chunks are not overlapping. However, we still
# allow multiple chunks to share the same starting position (because of the
# language server protocol specs). These chunks must be applied in their order
# of appareance. Since Python sorting is stable, if we sort the whole list in
# reverse order of location, these chunks will be reversed. Therefore, we
# need to fully reverse the list then sort it on the starting position in
# reverse order.
chunks.reverse()
chunks.sort( key = lambda chunk: (
chunk[ 'range' ][ 'start' ][ 'line_num' ],
chunk[ 'range' ][ 'start' ][ 'column_num' ]
) )
), reverse = True )
# Remember the line number we're processing. Negative line number means we
# haven't processed any lines yet (by nature of being not equal to any
# real line number).
last_line = -1
line_delta = 0
for chunk in chunks:
if chunk[ 'range' ][ 'start' ][ 'line_num' ] != last_line:
# If this chunk is on a different line than the previous chunk,
# then ignore previous deltas (as offsets won't have changed).
last_line = chunk[ 'range' ][ 'end' ][ 'line_num' ]
char_delta = 0
( new_line_delta, new_char_delta ) = ReplaceChunk(
chunk[ 'range' ][ 'start' ],
# However, we still want to display the locations from the top of the buffer
# to its bottom.
return reversed( [ ReplaceChunk( chunk[ 'range' ][ 'start' ],
chunk[ 'range' ][ 'end' ],
chunk[ 'replacement_text' ],
line_delta, char_delta,
vim_buffer,
locations )
line_delta += new_line_delta
char_delta += new_char_delta
vim_buffer )
for chunk in chunks ] )
def SplitLines( contents ):
"""Return a list of each of the lines in the byte string |contents|.
Behavior is equivalent to str.splitlines with the following exceptions:
- empty strings are returned as [ '' ];
- a trailing newline is not ignored (i.e. SplitLines( '\n' )
returns [ '', '' ], not [ '' ] )."""
if contents == b'':
return [ b'' ]
lines = contents.splitlines()
if contents.endswith( b'\r' ) or contents.endswith( b'\n' ):
lines.append( b'' )
return lines
# Replace the chunk of text specified by a contiguous range with the supplied
# text.
# text and return the location.
# * start and end are objects with line_num and column_num properties
# * the range is inclusive
# * indices are all 1-based
# * the returned character delta is the delta for the last line
#
# returns the delta (in lines and characters) that any position after the end
# needs to be adjusted by.
#
# NOTE: Works exclusively with bytes() instances and byte offsets as returned
# by ycmd and used within the Vim buffers
def ReplaceChunk( start, end, replacement_text, line_delta, char_delta,
vim_buffer, locations = None ):
def ReplaceChunk( start, end, replacement_text, vim_buffer ):
# ycmd's results are all 1-based, but vim's/python's are all 0-based
# (so we do -1 on all of the values)
start_line = start[ 'line_num' ] - 1 + line_delta
end_line = end[ 'line_num' ] - 1 + line_delta
start_line = start[ 'line_num' ] - 1
end_line = end[ 'line_num' ] - 1
source_lines_count = end_line - start_line + 1
start_column = start[ 'column_num' ] - 1 + char_delta
start_column = start[ 'column_num' ] - 1
end_column = end[ 'column_num' ] - 1
if source_lines_count == 1:
end_column += char_delta
# NOTE: replacement_text is unicode, but all our offsets are byte offsets,
# so we convert to bytes
replacement_lines = ToBytes( replacement_text ).splitlines( False )
if not replacement_lines:
replacement_lines = [ bytes( b'' ) ]
replacement_lines_count = len( replacement_lines )
replacement_lines = SplitLines( ToBytes( replacement_text ) )
# NOTE: Vim buffers are a list of byte objects on Python 2 but unicode
# objects on Python 3.
end_existing_text = ToBytes( vim_buffer[ end_line ] )[ end_column : ]
start_existing_text = ToBytes( vim_buffer[ start_line ] )[ : start_column ]
new_char_delta = ( len( replacement_lines[ -1 ] )
- ( end_column - start_column ) )
if replacement_lines_count > 1:
new_char_delta -= start_column
end_existing_text = ToBytes( vim_buffer[ end_line ] )[ end_column : ]
replacement_lines[ 0 ] = start_existing_text + replacement_lines[ 0 ]
replacement_lines[ -1 ] = replacement_lines[ -1 ] + end_existing_text
vim_buffer[ start_line : end_line + 1 ] = replacement_lines[:]
if locations is not None:
locations.append( {
return {
'bufnr': vim_buffer.number,
'filename': vim_buffer.name,
# line and column numbers are 1-based in qflist
@ -851,10 +842,7 @@ def ReplaceChunk( start, end, replacement_text, line_delta, char_delta,
'col': start_column + 1,
'text': replacement_text,
'type': 'F',
} )
new_line_delta = replacement_lines_count - source_lines_count
return ( new_line_delta, new_char_delta )
}
def InsertNamespace( namespace ):
@ -871,9 +859,9 @@ def InsertNamespace( namespace ):
if line:
existing_line = LineTextInCurrentBuffer( line )
existing_indent = re.sub( r"\S.*", "", existing_line )
new_line = "{0}using {1};\n\n".format( existing_indent, namespace )
new_line = "{0}using {1};\n".format( existing_indent, namespace )
replace_pos = { 'line_num': line + 1, 'column_num': 1 }
ReplaceChunk( replace_pos, replace_pos, new_line, 0, 0, vim.current.buffer )
ReplaceChunk( replace_pos, replace_pos, new_line, vim.current.buffer )
PostVimMessage( 'Add namespace: {0}'.format( namespace ), warning = False )