def filter_top_level_completions (offset_char, all_comps): log("number of top level completions all:" + str(len(all_comps))) comps = [] is_lower = offset_char in "abcdefghijklmnopqrstuvwxyz" is_upper = offset_char in "ABCDEFGHIJKLMNOPQRSTUVWXYZ" is_digit = offset_char in "0123456789" is_special = offset_char in "$_#" offset_upper = offset_char.upper() offset_lower = offset_char.lower() if is_lower or is_upper or is_digit or is_special: for c in all_comps: id = c[1] if (offset_char in id or (is_upper and offset_lower in id) or (is_lower and offset_upper in id)): comps.append(c) else: comps = all_comps log("number of top level completions filtered" + str(len(comps))) return comps
def set_current_build( self, view , id , force_panel ) : log( "set_current_build") if id < 0 or id >= len(self.builds) : id = 0 view.settings().set( "haxe-build-id" , id ) if len(self.builds) > 0 : self.current_build = self.builds[id] #log( "set_current_build - 2") hxpanel.default_panel().writeln( "building " + self.current_build.to_string() ) else: hxpanel.default_panel().writeln( "No build found/selected" ) self.selecting_build = False if force_panel and self.current_build is not None: # choose NME target if self.current_build.nmml is not None: sublime.status_message("Please select a NME target") nme_targets = [] for t in hxbuild.HaxeBuild.nme_targets : nme_targets.append( t[0] ) view.window().show_quick_panel(nme_targets, lambda i : select_nme_target(self.current_build, i, view))
def get_completion_info (view, offset, src, prev): commas = 0 toplevel_complete = False complete_offset = offset is_new = False if (prev == " " and (offset-4 >= 0) and src[offset-4:offset-1] == "new"): is_new = True elif prev not in "(." : fragment = view.substr(sublime.Region(0,offset)) prev_dot = fragment.rfind(".") prev_par = fragment.rfind("(") prev_comma = fragment.rfind(",") prev_colon = fragment.rfind(":") prev_brace = fragment.rfind("{") prev_symbol = max(prev_dot,prev_par,prev_comma,prev_brace,prev_colon) if prev_symbol == prev_comma: commas, complete_offset = count_commas_and_complete_offset(src, prev_comma, complete_offset) log("commas: " + str(commas)) #print("closedBrackets : " + str(closedBrackets)) else : complete_offset = max( prev_dot + 1, prev_par + 1 , prev_colon + 1 ) skipped = src[complete_offset:offset] toplevel_complete = hxsrctools.skippable.search( skipped ) is None and hxsrctools.in_anonymous.search( skipped ) is None return (commas, complete_offset, toplevel_complete, is_new)
def run( self ) : log("run HaxeRestartServerCommand") view = sublime.active_window().active_view() project = hxproject.current_project(view) project.server.stop() project.start_server( view )
def update_types(self): #haxe.output_panel.HaxePanel.status("haxe-debug", "updating types") log("update types for " + str(self.classpaths)) classes, packages = hxtypes.find_types(self.classpaths, self.libs, os.path.dirname( self.hxml ), [], [], include_private_types = False ) self.classes = classes; self.packages = packages;
def run( self , edit ) : log("run HaxeInsertCompletion") view = self.view view.run_command( "insert_best_completion" , { "default" : ".", "exact" : True } )
def get_compiler_info_env (project_path): lib_path = hxsettings.haxe_library_path(); env = os.environ.copy() if lib_path != None : abs_lib_path = path_tools.join_norm(project_path, lib_path) env["HAXE_LIBRARY_PATH"] = abs_lib_path log("export HAXE_LIBRARY_PATH=" + abs_lib_path) return env
def __init__ (self, panel, view): log( "construct") self.view = view log(str(self.view)) self.panel = panel self.start = None self.size = None self.cname = None
def parse_completion_output(temp_file, orig_file, output): try: x = "<root>" + output.encode("utf-8") + "</root>" tree = ElementTree.XML(x) except Exception, e: tree = None log("invalid xml - error: " + str(e))
def run( self , edit ) : view = self.view log("run HaxeRunBuildCommand") project = hxproject.current_project(self.view) if len(project.builds) == 0: log("no builds available") project.extract_build_args(view, True); else: project.run_sublime_build( view )
def get_build( self, view ) : if self.current_build is None and view.score_selector(0,"source.haxe.2") > 0 : fn = view.file_name() src_dir = os.path.dirname( fn ) src = view.substr(sublime.Region(0, view.size())) build = hxbuild.HaxeBuild() build.target = "js" folder = os.path.dirname(fn) folders = view.window().folders() for f in folders: if f in fn : folder = f pack = [] for ps in hxsrctools.package_line.findall( src ) : if ps == "": continue pack = ps.split(".") for p in reversed(pack) : spl = os.path.split( src_dir ) if( spl[1] == p ) : src_dir = spl[0] cl = os.path.basename(fn) cl = cl.encode('ascii','ignore') cl = cl[0:cl.rfind(".")] main = pack[0:] main.append( cl ) build.main = ".".join( main ) build.output = os.path.join(folder,build.main.lower() + ".js") log( "add cp: " + src_dir) build.args.append( ("-cp" , src_dir) ) #build.args.append( ("-main" , build.main ) ) build.args.append( ("-js" , build.output ) ) #build.args.append( ("--no-output" , "-v" ) ) build.hxml = os.path.join( src_dir , "build.hxml") #build.hxml = os.path.join( src_dir , "build.hxml") self.current_build = build return self.current_build.copy()
def run( self , edit ) : log("run HaxeHintCommand") view = self.view view.run_command( "auto_complete" , { "api_completions_only" : True, "disable_auto_insert" : True, "next_completion_if_showing" : True, 'auto_complete_commit_on_tab': True } )
def _get_project_file(win_id = None): global _last_project global _last_modification_time log( "try getting project file") if win_id == None: win_id = sublime.active_window().id() project = None reg_session = os.path.join(sublime.packages_path(), "..", "Settings", "Session.sublime_session") auto_save = os.path.join(sublime.packages_path(), "..", "Settings", "Auto Save Session.sublime_session") session = auto_save if os.path.exists(auto_save) else reg_session if not os.path.exists(session) or win_id == None: return project mtime = os.path.getmtime(session) if (_last_modification_time is not None and mtime == _last_modification_time and _last_project != None): _last_modification_time = mtime log( "cached project id") return _last_project else: _last_modification_time = mtime try: with open(session, 'r') as f: # Tabs in strings messes things up for some reason j = json.JSONDecoder(strict=False).decode(f.read()) for w in j['windows']: if w['window_id'] == win_id: if "workspace_name" in w: if sublime.platform() == "windows": # Account for windows specific formatting project = os.path.normpath(w["workspace_name"].lstrip("/").replace("/", ":/", 1)) else: project = w["workspace_name"] break except: pass # Throw out empty project names if project == None or re.match(".*\\.sublime-project", project) == None or not os.path.exists(project): project = None _last_project = project return project
def on_post_save(self, view): log("on_post_save") if view is not None and view.file_name() is not None: if view_tools.is_supported(view) or view.file_name().endswith(".erazor.html"): if (hxsettings.build_on_save()): project = hxproject.current_project(view) if len(project.builds) > 0: project.run_sublime_build( view ) else: project.extract_build_args(view, False) build = project.get_build(view) if (build != None): project.run_sublime_build( view )
def run( self , edit ) : log("run HaxeDisplayMacroCompletion") view = self.view project = hxproject.current_project(view) project.completion_context.set_manual_trigger(view, True) view.run_command( "auto_complete" , { "api_completions_only" : True, "disable_auto_insert" : True, "next_completion_if_showing" : True, 'auto_complete_commit_on_tab': True } )
def cb (out, err): log("-------------------------------------") log("out:" + out) log("err:" + err) log("---------compiler-output-------------") if nekox_file_name is not None: self.run_neko_x(build_folder, nekox_file_name) callback(out, err)
def make_hint_comp (h): is_only_type = len(h) == 1 res = None if is_only_type: res = (h[0] + " - No Completion", "${}") else: only_next = hxsettings.smarts_hints_only_next() params = h[0:len(h)-1]; params2 = params if not only_next else h[0:1] ret = h[len(h)-1]; show = "__(" + ",".join([param for param in params]) + "):" + ret insert = ",".join(["${" + str(index+1) + ":" + param + "}" for index, param in enumerate(params2)]) log(insert) res = (show, insert) return res
def run (self, haxe_exec, env, server_mode, view, project): cmd, build_folder, nekox_file_name = self.prepare_run(haxe_exec, server_mode, view, project) out, err = run_cmd( args=cmd, input="", cwd=build_folder, env=env ) log("-------------------------------------") log("out:" + out) log("err:" + err) log("---------compiler-output-------------") # execute compiled file if hxml/build has -x target if nekox_file_name is not None: self.run_neko_x(build_folder, nekox_file_name) return out,err
def start( self , haxe_path, cwd = None, env = None, retries = 10 ) : if self._server_proc is None : try: cmd = [haxe_path , "--wait" , str(self._server_port) ] if env == None: env = os.environ.copy() self._server_proc = Popen(cmd, cwd=cwd, env = env, stdout=PIPE, stderr=PIPE, startupinfo=STARTUP_INFO) poll_res = self._server_proc.poll() log("server started at port: " + str(self._server_port)) except(OSError, ValueError) as e: err = u'Error starting server %s: %s' % (" ".join(cmd), e) sublime.error_message(err) if (retries > 0): self.stop(); self._server_port += 1 log("retry starting server at port: " + str(self._server_port)) self.start(haxe_path, cwd, env, retries-1) else: msg = "Cannot start haxe compilation server on ports {0}-{1}" msg = msg.format((self._orig_server_port, self._server_port)) log("Server starting error") hxpanel.default_panel().writeln(msg) sublime.error_message(msg)
def auto_complete (project, view, prefix, locations): start_time = time.time() pos = locations[0] offset = pos - len(prefix) comps = [] if offset == 0 : return comps scopes = view_tools.get_scopes_at(view, pos) if (scope_tools.contains_string_or_comment(scopes)): return comps if hxconfig.SOURCE_HXML in scopes: comps = hxml_auto_complete( project, view , offset ) if hxconfig.SOURCE_HAXE in scopes : if view_tools.is_hxsl(view) : comps = hxsl_auto_complete( project, view , offset ) else : log("run hx auto complete") comps = hx_auto_complete( project, view, offset ) end_time = time.time() log("on_query_completion time: " + str(end_time-start_time)) log("number of completions: " + str(len(comps))) return comps
def prepare_run (self, haxe_exec, server_mode, view, project): b = self.copy() nekox_file_name = None for i in range(0, len(b.args)): if b.args[i][0] == "-x": nekox_file_name = b.args[i][1] + ".n" b.args[i] = ("-neko", nekox_file_name) if server_mode: project.start_server( view ) b.set_server_mode(project.server.get_server_port()) b.set_build_cwd() cmd = b.get_command_args(haxe_exec) log("cmd : " + " ".join(cmd)) return (cmd, self.get_build_folder(), nekox_file_name)
def extract_errors(str): errors = [] for infos in compiler_output.findall(str): infos = list(infos) f = infos.pop(0) l = int(infos.pop(0)) - 1 left = int(infos.pop(0)) right = infos.pop(0) if right != "": right = int(right) else: right = left + 1 m = infos.pop(0) errors.append({"file": f, "line": l, "from": left, "to": right, "message": m}) # print(errors) if len(errors) > 0: log("should show panel") hxpanel.slide_panel().writeln(errors[0]["message"]) sublime.status_message(errors[0]["message"]) return errors
def get_types( self ) : now = time.time() log("get_types" + str(now)) log("get_types" + str(self.update_time)) if self.classes is None or self.packages is None or self.update_time is None or (now - self.update_time) > 10: log("update types") self.update_time = now self.update_types() return self.classes, self.packages
def in_main (ret_, err_): hints, comps_, status_, errors = get_completion_output(temp_file, orig_file, err_, commas) comps_ = [(t[0], t[1]) for t in comps_] log("background completion time: " + str(time.time() - timer)) project.completion_context.set_errors(errors) highlight_errors( errors, view ) hxtemp.remove_path(temp_path) comps.extend(comps_) if completion_id == project.completion_context.current_id: cache["output"] = (ret_,comps_,status_, hints) cache["input"] = current_input else: log("ignored completion") # do we still need this completion, or is it old has_new_comps = len(comps) > len(basic_comps) has_hints = len(hints) > 0 if completion_id == project.completion_context.current_id and (has_new_comps or hxsettings.only_delayed_completions() or has_hints): project.completion_context.delayed.insert(view_id, (comps, hints)) if only_delayed: log("trigger_auto_complete") trigger_manual_completion(view,macro_completion) #view.run_command('auto_complete', {'disable_auto_insert': True}) else: view.run_command('hide_auto_complete') sublime.set_timeout(lambda : trigger_manual_completion(view,macro_completion), show_delay) #sublime.set_timeout(lambda : view.run_command('auto_complete', {'disable_auto_insert': True}), show_delay) else: log("ignore background completion") project.completion_context.running.delete(completion_id)
def run_sublime_build( self, view ) : if view is None: view = sublime.active_window().active_view() log("start sublime build") haxe_exec = self.haxe_exec(view) env = self.haxe_build_env(view) if (self.has_build()): build = self.get_build(view) else: self.extract_build_args(view) build = self.get_build(view) cmd, build_folder, nekox_file_name = build.prepare_run(haxe_exec, self.serverMode, view, self) log(env) log(cmd) win = view.window() if win is None: win = sublime.active_window() win.run_command("haxe_exec", { "cmd": cmd, "working_dir": build_folder, "file_regex": haxe_file_regex, "env" : env })
def on_data(self, proc, data): sublime.set_timeout(lambda : log(data), 0) sublime.set_timeout(functools.partial(self.append_data, proc, data), 0)
def run(self, cmd = [], file_regex = "", line_regex = "", working_dir = "", encoding = "utf-8", env = {}, quiet = False, kill = False, # Catches "path" and "shell" **kwargs): log("run haxe exec") if kill: if self.proc: self.proc.kill() self.proc = None self.append_data(None, "[Cancelled]") return if not hasattr(self, 'output_view'): # Try not to call get_output_panel until the regexes are assigned self.output_view = self.window.get_output_panel("exec") self.output_view.settings().set('word_wrap', True) # Default the to the current files directory if no working directory was given if (working_dir == "" and self.window.active_view() and self.window.active_view().file_name()): working_dir = os.path.dirname(self.window.active_view().file_name()) self.output_view.settings().set("result_file_regex", file_regex) self.output_view.settings().set("result_line_regex", line_regex) self.output_view.settings().set("result_base_dir", working_dir) # Call get_output_panel a second time after assigning the above # settings, so that it'll be picked up as a result buffer self.window.get_output_panel("exec") self.encoding = encoding self.quiet = quiet self.proc = None if not self.quiet: print "Running " + " ".join(cmd) sublime.status_message("Building") show_panel_on_build = sublime.load_settings("Preferences.sublime-settings").get("show_panel_on_build", True) if show_panel_on_build: self.window.run_command("show_panel", {"panel": "output.exec"}) merged_env = env.copy() if self.window.active_view(): user_env = self.window.active_view().settings().get('build_env') if user_env: merged_env.update(user_env) # Change to the working dir, rather than spawning the process with it, # so that emitted working dir relative path names make sense if working_dir != "": os.chdir(working_dir) err_type = OSError if os.name == "nt": err_type = WindowsError try: # Forward kwargs to AsyncProcess self.proc = AsyncProcess(cmd, merged_env, self, **kwargs) self.append_data(self.proc, "Running " + " ".join(cmd) + "\n") except err_type as e: self.append_data(None, str(e) + "\n") self.append_data(None, "[cmd: " + str(cmd) + "]\n") self.append_data(None, "[dir: " + str(os.getcwdu()) + "]\n") if "PATH" in merged_env: self.append_data(None, "[path: " + str(merged_env["PATH"]) + "]\n") else: self.append_data(None, "[path: " + str(os.environ["PATH"]) + "]\n") if not self.quiet: self.append_data(None, "[Finished]")
def on_change( self , inp ) : #sublime.status_message( "Current classpath : " + self.classpath ) log( inp )
def run( self , paths = [] , t = "class" ) : log("createtype") win = self.win view = win.active_view() project = hxproject.current_project(view) builds = project.builds #scopes = view.scope_name(view.sel()[0].end()).split() pack = []; if len(builds) == 0 and view != None and view.file_name() != None: print view.file_name() project.extract_build_args(view) builds = project.builds if len(paths) == 0 and view != None: fn = view.file_name() paths.append(fn) for path in paths : if os.path.isfile( path ) : path = os.path.dirname( path ) if self.classpath is None : self.classpath = path for b in builds : found = False for cp in b.classpaths : if path.startswith( cp ) : self.classpath = path[0:len(cp)] for p in path[len(cp):].split(os.sep) : if "." in p : break elif p : pack.append(p) found = True if found: break if found: break if found: break if self.classpath is None : if len(builds) > 0 : self.classpath = builds[0].classpaths[0] # so default text ends with . if len(pack) > 0 : pack.append("") sublime.status_message( "Current classpath : " + self.classpath ) win.show_input_panel("Enter "+t+" name : " , ".".join(pack) , lambda inp: self.on_done(inp, t) , self.on_change , self.on_cancel )
def run( self, edit ) : log("run HaxeGenerateImportCommand") haxe.codegen.generate_import(self.view, edit)