import sublime import sublime_plugin import json from threading import Thread from ..lib.ycmd_handler import server from ..lib.utils import * from ..lib.msgs import MsgTemplates def create_abbrev(signature): sb = '' startParam = False argumentIndex = 1 for i in range(0, len(signature)): c = signature[i] if c == ',': sb = sb + "}" startParam = True; sb = sb + c elif c == '(': startParam = True; sb = sb + c elif c == ')': if not startParam: # Case of 'f()' - no parameters sb = sb + "}" sb = sb + c elif c == ' ' or c == '\t' or c == '\n': sb = sb + c else: if startParam: startParam = False sb = sb + '${' sb = sb + str(argumentIndex) argumentIndex = argumentIndex + 1 sb = sb + ':' sb = sb + c return sb def complete_func(server, filepath, contents, row, col, callback): ''' Thread that send completion request ''' rst = server.SendCodeCompletionRequest(filepath=filepath, contents=contents, filetype='cpp', line_num=row, column_num=col) if rst == '': return completions = json.loads(rst)['completions'] data = [] for comp in completions: for detailed_info in comp.get('detailed_info', '').strip().split('\n'): insertion_text = comp.get('insertion_text', '') if comp.get('kind', '') == 'FUNCTION': index_of_lbracket = detailed_info.find('(') index_of_rbracket = detailed_info.find(')') if index_of_lbracket >= 0 and index_of_rbracket > index_of_lbracket: insertion_text = insertion_text + create_abbrev(detailed_info[index_of_lbracket:index_of_rbracket + 1]) data.append( ( '{}\t{}'.format(detailed_info, comp.get('kind', '').lower() ), insertion_text ) ) callback(data) class CppYCMCompletionsListener(sublime_plugin.EventListener): def __init__(self): self.completions = [] self.ready_from_defer = False self.view_cache = dict() self.view_line = dict() self.extra_conf_loaded = False def on_query_completions(self, view, prefix, locations): ''' Sublime Text autocompletion event handler. ''' if not is_cpp(view) or view.is_scratch(): return # if completion should begin leftchar = view.substr(locations[0] - 2) thischar = view.substr(locations[0] - 1) if thischar == '>' and leftchar != '-': return if thischar == ':' and leftchar != ':': return print("[C++YouCompleteMe] Start completing.") if self.ready_from_defer is True: cpl = self.completions self.completions = [] self.ready_from_defer = False return (cpl, sublime.INHIBIT_WORD_COMPLETIONS | sublime.INHIBIT_EXPLICIT_COMPLETIONS) filepath = get_file_path(view.file_name()) contents = view.substr(sublime.Region(0, view.size())) # get 1-based location row, col = get_row_col(view, locations[0]) # start code-completion thread t = Thread(None, complete_func, 'CompleteAsync', [server(), filepath, contents, row, col, self._complete]) t.daemon = True t.start() def _complete(self, proposals): if len(proposals): active_view().run_command("hide_auto_complete") self.completions = proposals self.ready_from_defer = True self._run_auto_complete() else: sublime.status_message(MsgTemplates.COMPLETION_NOT_AVAILABLE_MSG) def _run_auto_complete(self): active_view().run_command("auto_complete", { 'disable_auto_insert': True, 'next_completion_if_showing': False, 'auto_complete_commit_on_tab': True, })