aboutsummaryrefslogtreecommitdiff
path: root/vim/bundle/YouCompleteMe/python/ycm/base.py
diff options
context:
space:
mode:
Diffstat (limited to 'vim/bundle/YouCompleteMe/python/ycm/base.py')
-rw-r--r--vim/bundle/YouCompleteMe/python/ycm/base.py175
1 files changed, 175 insertions, 0 deletions
diff --git a/vim/bundle/YouCompleteMe/python/ycm/base.py b/vim/bundle/YouCompleteMe/python/ycm/base.py
new file mode 100644
index 0000000..4de4c0b
--- /dev/null
+++ b/vim/bundle/YouCompleteMe/python/ycm/base.py
@@ -0,0 +1,175 @@
+# Copyright (C) 2011, 2012 Google Inc.
+#
+# This file is part of YouCompleteMe.
+#
+# YouCompleteMe is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# YouCompleteMe is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>.
+
+from __future__ import unicode_literals
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+from future import standard_library
+standard_library.install_aliases()
+from builtins import * # noqa
+
+from future.utils import iteritems
+from ycm import vimsupport
+from ycmd import user_options_store
+from ycmd import request_wrap
+from ycmd import identifier_utils
+
+YCM_VAR_PREFIX = 'ycm_'
+
+
+def BuildServerConf():
+ """Builds a dictionary mapping YCM Vim user options to values. Option names
+ don't have the 'ycm_' prefix."""
+ # We only evaluate the keys of the vim globals and not the whole dictionary
+ # to avoid unicode issues.
+ # See https://github.com/Valloric/YouCompleteMe/pull/2151 for details.
+ keys = vimsupport.GetVimGlobalsKeys()
+ server_conf = {}
+ for key in keys:
+ if not key.startswith( YCM_VAR_PREFIX ):
+ continue
+ new_key = key[ len( YCM_VAR_PREFIX ): ]
+ new_value = vimsupport.VimExpressionToPythonType( 'g:' + key )
+ server_conf[ new_key ] = new_value
+
+ return server_conf
+
+
+def LoadJsonDefaultsIntoVim():
+ defaults = user_options_store.DefaultOptions()
+ for key, value in iteritems( defaults ):
+ new_key = 'g:ycm_' + key
+ if not vimsupport.VariableExists( new_key ):
+ vimsupport.SetVariableValue( new_key, value )
+
+
+def CompletionStartColumn():
+ return ( request_wrap.CompletionStartColumn(
+ vimsupport.CurrentLineContents(),
+ vimsupport.CurrentColumn() + 1,
+ vimsupport.CurrentFiletypes()[ 0 ] ) - 1 )
+
+
+def CurrentIdentifierFinished():
+ current_column = vimsupport.CurrentColumn()
+ previous_char_index = current_column - 1
+ if previous_char_index < 0:
+ return True
+ line = vimsupport.CurrentLineContents()
+ filetype = vimsupport.CurrentFiletypes()[ 0 ]
+ regex = identifier_utils.IdentifierRegexForFiletype( filetype )
+
+ for match in regex.finditer( line ):
+ if match.end() == previous_char_index:
+ return True
+ # If the whole line is whitespace, that means the user probably finished an
+ # identifier on the previous line.
+ return line[ : current_column ].isspace()
+
+
+def LastEnteredCharIsIdentifierChar():
+ current_column = vimsupport.CurrentColumn()
+ if current_column - 1 < 0:
+ return False
+ line = vimsupport.CurrentLineContents()
+ filetype = vimsupport.CurrentFiletypes()[ 0 ]
+ return (
+ identifier_utils.StartOfLongestIdentifierEndingAtIndex(
+ line, current_column, filetype ) != current_column )
+
+
+def AdjustCandidateInsertionText( candidates ):
+ """This function adjusts the candidate insertion text to take into account the
+ text that's currently in front of the cursor.
+
+ For instance ('|' represents the cursor):
+ 1. Buffer state: 'foo.|bar'
+ 2. A completion candidate of 'zoobar' is shown and the user selects it.
+ 3. Buffer state: 'foo.zoobar|bar' instead of 'foo.zoo|bar' which is what the
+ user wanted.
+
+ This function changes candidates to resolve that issue.
+
+ It could be argued that the user actually wants the final buffer state to be
+ 'foo.zoobar|' (the cursor at the end), but that would be much more difficult
+ to implement and is probably not worth doing.
+ """
+
+ 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
+
+ text_after_cursor = vimsupport.TextAfterCursor()
+ if not text_after_cursor:
+ return candidates
+
+ new_candidates = []
+ for candidate in candidates:
+ if isinstance( candidate, dict ):
+ new_candidate = candidate.copy()
+
+ if 'abbr' not in new_candidate:
+ new_candidate[ 'abbr' ] = new_candidate[ 'word' ]
+
+ new_candidate[ 'word' ] = NewCandidateInsertionText(
+ new_candidate[ 'word' ],
+ text_after_cursor )
+
+ new_candidates.append( new_candidate )
+
+ elif isinstance( candidate, str ) or isinstance( candidate, bytes ):
+ new_candidates.append(
+ { 'abbr': candidate,
+ '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