Candidate overlap with buffer text improved
Now, "foobar.h" will be changed to insert "foo" if the text after the cursor is "bar.h". This already worked for "foobar" and "bar", but the overlap search would stop before a non-word character. This has now been resolved.
This commit is contained in:
parent
df161cff52
commit
a18807d31e
@ -17,7 +17,6 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import re
|
||||
import vim
|
||||
from ycm import vimsupport
|
||||
from ycm import utils
|
||||
@ -124,18 +123,14 @@ def AdjustCandidateInsertionText( candidates ):
|
||||
to implement and is probably not worth doing.
|
||||
"""
|
||||
|
||||
def NewCandidateInsertionText( to_insert, word_after_cursor ):
|
||||
if to_insert.endswith( word_after_cursor ):
|
||||
return to_insert[ : - len( word_after_cursor ) ]
|
||||
def NewCandidateInsertionText( to_insert, text_after_cursor ):
|
||||
overlap_len = OverlapLength( to_insert, text_after_cursor )
|
||||
if overlap_len:
|
||||
return to_insert[ :-overlap_len ]
|
||||
return to_insert
|
||||
|
||||
match = re.search( r'^(\w+)', vimsupport.TextAfterCursor() )
|
||||
if not match:
|
||||
return candidates
|
||||
|
||||
new_candidates = []
|
||||
|
||||
word_after_cursor = match.group( 1 )
|
||||
text_after_cursor = vimsupport.TextAfterCursor()
|
||||
for candidate in candidates:
|
||||
if type( candidate ) is dict:
|
||||
new_candidate = candidate.copy()
|
||||
@ -145,17 +140,51 @@ def AdjustCandidateInsertionText( candidates ):
|
||||
|
||||
new_candidate[ 'word' ] = NewCandidateInsertionText(
|
||||
new_candidate[ 'word' ],
|
||||
word_after_cursor )
|
||||
text_after_cursor )
|
||||
|
||||
new_candidates.append( new_candidate )
|
||||
|
||||
elif type( candidate ) is str:
|
||||
new_candidates.append(
|
||||
{ 'abbr': candidate,
|
||||
'word': NewCandidateInsertionText( candidate, word_after_cursor ) } )
|
||||
'word': NewCandidateInsertionText( candidate, text_after_cursor ) } )
|
||||
return new_candidates
|
||||
|
||||
|
||||
def OverlapLength( left_string, right_string ):
|
||||
"""Returns the length of the overlap between two strings.
|
||||
Example: "foo baro" and "baro zoo" -> 4
|
||||
"""
|
||||
left_string_length = len( left_string )
|
||||
right_string_length = len( right_string )
|
||||
|
||||
if not left_string_length or not right_string_length:
|
||||
return 0
|
||||
|
||||
# Truncate the longer string.
|
||||
if left_string_length > right_string_length:
|
||||
left_string = left_string[ -right_string_length: ]
|
||||
elif left_string_length < right_string_length:
|
||||
right_string = right_string[ :left_string_length ]
|
||||
|
||||
if left_string == right_string:
|
||||
return min( left_string_length, right_string_length )
|
||||
|
||||
# Start by looking for a single character match
|
||||
# and increase length until no match is found.
|
||||
best = 0
|
||||
length = 1
|
||||
while True:
|
||||
pattern = left_string[ -length: ]
|
||||
found = right_string.find( pattern )
|
||||
if found < 0:
|
||||
return best
|
||||
length += found
|
||||
if left_string[ -length: ] == right_string[ :length ]:
|
||||
best = length
|
||||
length += 1
|
||||
|
||||
|
||||
COMPATIBLE_WITH_CORE_VERSION = 7
|
||||
|
||||
def CompatibleWithYcmCore():
|
||||
|
@ -49,6 +49,16 @@ def AdjustCandidateInsertionText_WhitespaceInTextAfterCursor_test():
|
||||
base.AdjustCandidateInsertionText( [ 'foobar' ] ) )
|
||||
|
||||
|
||||
def AdjustCandidateInsertionText_MoreThanWordMatchingAfterCursor_test():
|
||||
vimsupport.TextAfterCursor = MagicMock( return_value = 'bar.h' )
|
||||
eq_( [ { 'abbr': 'foobar.h', 'word': 'foo' } ],
|
||||
base.AdjustCandidateInsertionText( [ 'foobar.h' ] ) )
|
||||
|
||||
vimsupport.TextAfterCursor = MagicMock( return_value = 'bar(zoo' )
|
||||
eq_( [ { 'abbr': 'foobar(zoo', 'word': 'foo' } ],
|
||||
base.AdjustCandidateInsertionText( [ 'foobar(zoo' ] ) )
|
||||
|
||||
|
||||
def AdjustCandidateInsertionText_NotSuffix_test():
|
||||
vimsupport.TextAfterCursor = MagicMock( return_value = 'bar' )
|
||||
eq_( [ { 'abbr': 'foofoo', 'word': 'foofoo' } ],
|
||||
@ -57,8 +67,8 @@ def AdjustCandidateInsertionText_NotSuffix_test():
|
||||
|
||||
def AdjustCandidateInsertionText_NothingAfterCursor_test():
|
||||
vimsupport.TextAfterCursor = MagicMock( return_value = '' )
|
||||
eq_( [ 'foofoo',
|
||||
'zobar' ],
|
||||
eq_( [ { 'abbr': 'foofoo', 'word': 'foofoo' },
|
||||
{ 'abbr': 'zobar', 'word': 'zobar' }, ],
|
||||
base.AdjustCandidateInsertionText( [ 'foofoo',
|
||||
'zobar' ] ) )
|
||||
|
||||
@ -88,3 +98,37 @@ def AdjustCandidateInsertionText_DontTouchAbbr_test():
|
||||
eq_( [ { 'abbr': '1234', 'word': 'foo' } ],
|
||||
base.AdjustCandidateInsertionText(
|
||||
[ { 'abbr': '1234', 'word': 'foobar' } ] ) )
|
||||
|
||||
|
||||
def OverlapLength_Basic_test():
|
||||
eq_( 3, base.OverlapLength( 'foo bar', 'bar zoo' ) )
|
||||
eq_( 3, base.OverlapLength( 'foobar', 'barzoo' ) )
|
||||
|
||||
|
||||
def OverlapLength_OneCharOverlap_test():
|
||||
eq_( 1, base.OverlapLength( 'foo b', 'b zoo' ) )
|
||||
|
||||
|
||||
def OverlapLength_SameStrings_test():
|
||||
eq_( 6, base.OverlapLength( 'foobar', 'foobar' ) )
|
||||
|
||||
|
||||
def OverlapLength_Substring_test():
|
||||
eq_( 6, base.OverlapLength( 'foobar', 'foobarzoo' ) )
|
||||
eq_( 6, base.OverlapLength( 'zoofoobar', 'foobar' ) )
|
||||
|
||||
|
||||
def OverlapLength_LongestOverlap_test():
|
||||
eq_( 7, base.OverlapLength( 'bar foo foo', 'foo foo bar' ) )
|
||||
|
||||
|
||||
def OverlapLength_EmptyInput_test():
|
||||
eq_( 0, base.OverlapLength( '', 'goobar' ) )
|
||||
eq_( 0, base.OverlapLength( 'foobar', '' ) )
|
||||
eq_( 0, base.OverlapLength( '', '' ) )
|
||||
|
||||
|
||||
def OverlapLength_NoOverlap_test():
|
||||
eq_( 0, base.OverlapLength( 'foobar', 'goobar' ) )
|
||||
eq_( 0, base.OverlapLength( 'foobar', '(^($@#$#@' ) )
|
||||
eq_( 0, base.OverlapLength( 'foo bar zoo', 'foo zoo bar' ) )
|
||||
|
Loading…
x
Reference in New Issue
Block a user