def on_load(self, view): use_corona_sdk_completion = _corona_utils.GetSetting( "corona_sdk_completion", True) if use_corona_sdk_completion and self.is_lua_file(view): use_periods_in_completion = _corona_utils.GetSetting( "corona_sdk_complete_periods", True) # Completion behavior is improved if periods are included in the completion process if use_periods_in_completion: # If "auto_complete_triggers" for periods is not set for this buffer, set it auto_complete_triggers = view.settings().get( "auto_complete_triggers") self.periods_set[view.file_name()] = False for act in auto_complete_triggers: if "source.lua.corona" in act["selector"] and "." in act[ "characters"]: self.periods_set[view.file_name()] = True break if not self.periods_set.get(view.file_name(), False): auto_complete_triggers.append({ "selector": "source.lua.corona", "characters": "." }) view.settings().set("auto_complete_triggers", auto_complete_triggers) self.periods_set[view.file_name()] = True _corona_utils.debug( "on_load view: ", view.file_name(), "periods_set" if self.periods_set.get(view.file_name(), False) else "not set")
def __init__(self): _corona_utils.debug("CoronaLabs: __init__") global CoronaCompletions CoronaCompletions = self # Use fuzzy completions (essentially search for the characters in the target even if separated) self._use_fuzzy_completion = _corona_utils.GetSetting( "corona_sdk_use_fuzzy_completion", True) # Remove whitespace in completions to match some coding styles self._strip_white_space = _corona_utils.GetSetting( "corona_sdk_completions_strip_white_space", False)
def on_post_save(self, view): if self.is_lua_file(view): auto_build = _corona_utils.GetSetting("corona_sdk_auto_build", default=False) if auto_build: _corona_utils.debug("Corona Editor: auto build triggered") view.window().run_command("build") if view.file_name().lower().endswith( ".lua") and _corona_utils.GetSetting( "corona_sdk_default_new_file_to_corona_lua", default=True): view.set_syntax_file( "Packages/CoronaSDK-SublimeText/CoronaSDKLua.tmLanguage")
def on_post_save(self, view): if self.is_lua_file(view): auto_build = _corona_utils.GetSetting("corona_sdk_auto_build", False) if auto_build: _corona_utils.debug("Corona Editor: auto build triggered") view.window().run_command("build")
def is_lua_file(self, view): # Fairly rigorous test for being a Corona Lua file # If the file has not been saved optionally default to being a Corona Lua file return view.match_selector( view.sel()[0].a, "source.lua.corona") if view.file_name( ) else _corona_utils.GetSetting( "corona_sdk_default_new_file_to_corona_lua", True)
def run(self, edit): s = self.view.sel()[0] # Expand selection to current "word" start = s.a end = s.b view_size = self.view.size() terminator = ['\t', ' ', '\"', '\'', '(', '='] while (start > 0 and not self.view.substr(start - 1) in terminator and self.view.classify(start) & sublime.CLASS_LINE_START == 0): start -= 1 while (end < view_size and not self.view.substr(end) in terminator and self.view.classify(end) & sublime.CLASS_LINE_END == 0): end += 1 # Note if the current point is on a Lua keyword (according to # the .tmLanguage definition) isLuaKeyword = self.view.match_selector(start, "keyword.control.lua, support.function.lua, support.function.library.lua") use_docset = _corona_utils.GetSetting("corona_sdk_use_docset", "public") if use_docset in ['legacy', 'daily']: docset = use_docset + "/" else: docset = "" # Convert "word" under cursor to Corona Docs link, or a Lua docs link page = self.view.substr(sublime.Region(start, end)) page = page.strip(string.punctuation) # Look for an embedded period which, if the class name is one of ours, # indicates we should look it up in the "library" section of the docs # (unless the class member doesn't start with a lowercase letter in which # case it's a constant and we'll have to just default to searching for it) if page is None or page == "": # Nothing is selected, take them to API home docUrl = "http://docs.coronalabs.com/" + docset + "api/index.html" elif (re.search("\w+\.[a-z]", page) is not None and page.partition(".")[0] in LIBRARY_APIS): page = page.replace(".", "/") docUrl = "http://docs.coronalabs.com/" + docset + "api/library/" + page + ".html" elif isLuaKeyword: # Unfortunately, there's no search on the Lua docs site so we need to guess at # an anchor (if it's not there, you go to the top of the page) docUrl = "http://www.lua.org/manual/5.1/manual.html#pdf-" + page else: # We don't know what we're on, send them to the Corona Docs search page page = UrlEncode(page) docUrl = SEARCH_URL.format(search_term=page) # print("docURL : " + docUrl) webbrowser.open_new_tab(docUrl)
def debug(s): global debugFP try: if not debugFP and _corona_utils.GetSetting("corona_sdk_debug", False): if not os.path.isdir(_corona_utils.PACKAGE_USER_DIR): os.makedirs(_corona_utils.PACKAGE_USER_DIR) debugFP = open( os.path.normpath( os.path.join(_corona_utils.PACKAGE_USER_DIR, "debug.log")), "w", 1) except: pass # <CoronaDebuggerThread(Thread-5, started 4583960576)> thread_id = re.sub(r'.*\(([^,]*),.*', r'\1', str(threading.current_thread())) log_line = str( datetime.datetime.now()) + " (" + str(thread_id) + "): " + str(s) if debugFP: debugFP.write(log_line + "\n") _corona_utils.debug(log_line)
def on_query_completions(self, view, prefix, locations): use_corona_sdk_completion = _corona_utils.GetSetting( "corona_sdk_completion", True) if self._first_time and use_corona_sdk_completion: if not self.is_lua_file(view) and view.file_name().lower( ).endswith(".lua"): msg = "Corona Editor: syntax is not set to 'Corona Lua' so completion is inactive" sublime.status_message(msg) print(msg) self._first_time = False _corona_utils.debug( "on_query_completions: ", "use_corona_sdk_completion: ", use_corona_sdk_completion, "source.lua.corona - entity: ", view.match_selector(locations[0], "source.lua.corona - entity")) if use_corona_sdk_completion and view.match_selector( locations[0], "source.lua.corona - entity"): comps = self.find_completions(view, prefix) flags = 0 # sublime.INHIBIT_EXPLICIT_COMPLETIONS | sublime.INHIBIT_WORD_COMPLETIONS return (comps, flags) else: return []
# determine if 'obj' is a string in both Python 2.x and 3.x def is_string_instance(obj): try: return isinstance(obj, basestring) except NameError: return isinstance(obj, str) statusRegion = None # We change our behavior to avoid complications with certain CoronaSDK releases corona_sdk_version = None # Getting settings in certain threads locks up Sublime Text so do it just once corona_sdk_debug = _corona_utils.GetSetting("corona_sdk_debug", False) debugFP = None def debug(s): global debugFP global corona_sdk_debug try: if not debugFP and corona_sdk_debug: if not os.path.isdir(_corona_utils.PACKAGE_USER_DIR): os.makedirs(_corona_utils.PACKAGE_USER_DIR) debugFP = open( os.path.normpath( os.path.join(_corona_utils.PACKAGE_USER_DIR, "debug.log")), "w", 1)
def initialize(self): self.load_completions( _corona_utils.GetSetting("corona_sdk_use_docset", "public"))
def find_completions(self, view, prefix): self.load_completions( _corona_utils.GetSetting("corona_sdk_use_docset", "public")) completion_target = self.current_word(view) # Because we adjust the prefix to make completions with periods in them work better we may need to # trim the part before the period from the returned string (or it will appear to be doubled) completion_adjustment = "" if "." not in completion_target else completion_target.partition( '.')[0] + '.' # _corona_utils.debug('prefix: ', prefix, 'completion_target: ', completion_target, "; completion_adjustment: ", completion_adjustment, "; corona_sdk_complete_periods: ", _corona_utils.GetSetting("corona_sdk_complete_periods", True) ) self.setupFuzzyMatch(completion_target) # Sample: # { "trigger": "audio.stopWithDelay()", "contents": "audio.stopWithDelay( ${1:duration}, ${2:[, options ]} )"}, # "audio.totalChannels ", # This is horrible on a variety of levels but is brought upon us by the fact that # ST completion files contain an array that is a mixture of strings and dicts comps = [] for c in self._completions['completions']: trigger = "" contents = "" if isinstance(c, dict): if self.fuzzyMatchString(c['trigger'], self._use_fuzzy_completion): trigger = c['trigger'] contents = c['contents'] elif is_string_instance(c): if self.fuzzyMatchString(c, self._use_fuzzy_completion): _corona_utils.debug("String match: ", c) trigger = c contents = c if trigger is not "": if self._strip_white_space and contents is not "": contents = self._findWhiteSpace.sub("\\1", contents) # If we do the completion adjustment on completions that aren't functions # ST somehow erases the text before the period from the document leaving # just the piece after it (it makes no sense). This fixes that but will # almost certainly have to be changed when ST's behavior changes. if "(" in contents: comps.append( (trigger, contents.replace(completion_adjustment, ''))) else: comps.append((trigger, contents)) # _corona_utils.debug("extract_completions: ", view.extract_completions(completion_target)) # Add textual completions from the document for c in view.extract_completions(completion_target): comps.append((c, c)) # Reorganize into a list comps = list(set(comps)) comps.sort() # _corona_utils.debug("comps: ", comps) return comps
def find_completions(self, view, prefix): self.load_completions( _corona_utils.GetSetting("corona_sdk_use_docset", default="public")) strip_white_space = _corona_utils.GetSetting( "corona_sdk_completions_strip_white_space", default=False) use_fuzzy_completion = _corona_utils.GetSetting( "corona_sdk_use_fuzzy_completion", default=True) completion_target = self.current_word(view) # Because we adjust the prefix to make completions with periods in them work better we may need to # trim the part before the period from the returned string (or it will appear to be doubled) completion_adjustment = "" if "." not in completion_target else completion_target.partition( '.')[0] + '.' # _corona_utils.debug('prefix: ', prefix, 'completion_target: ', completion_target, "; completion_adjustment: ", completion_adjustment, "; corona_sdk_complete_periods: ", _corona_utils.GetSetting("corona_sdk_complete_periods", True) ) self.setupFuzzyMatch(completion_target) # Sample: # { "trigger": "audio.stopWithDelay()", "contents": "audio.stopWithDelay( ${1:duration}, ${2:[, options ]} )"}, # "audio.totalChannels ", # This is horrible on a variety of levels but is brought upon us by the fact that # ST completion files contain an array that is a mixture of strings and dicts comps = [] # check if text in current line to cursor contains require statement # if so attempt to fill completions with lua formatted file paths textToCursor = _sublime_utils.getTextToCursor(view) completingRequireStatement = self._findRequire.search(textToCursor) inString = self.inString(textToCursor) if completingRequireStatement or inString: extensions = [".lua"] if not completingRequireStatement: extensions = _corona_utils.GetSetting( "corona_sdk_autocomplete_extensions", default=[]) followSymlinks = _corona_utils.GetSetting( "corona_sdk_follow_symlinks", default=False) pathSuggestions = _lua_paths.getFilesAndPaths( view, extensions=extensions, followlinks=followSymlinks, converttoluapaths=completingRequireStatement) for namePath in pathSuggestions: name = namePath[0] luaPath = namePath[1] if self.fuzzyMatchString( name, use_fuzzy_completion) or self.fuzzyMatchString( luaPath, use_fuzzy_completion): comps.append((luaPath, luaPath)) # Add textual completions from the document for c in view.extract_completions(completion_target): comps.append((c, c)) # don't add Corona API completions if editing a require statement or more generally a string # the regex will correctly match multiline strings, but to detect them we need to search more of the document if completingRequireStatement or inString: return list(set(comps)) for c in self._completions['completions']: trigger = "" contents = "" if isinstance(c, dict): if self.fuzzyMatchString(c['trigger'], use_fuzzy_completion): trigger = c['trigger'] contents = c['contents'] elif is_string_instance(c): if self.fuzzyMatchString(c, use_fuzzy_completion): _corona_utils.debug("String match: ", c) trigger = c contents = c if trigger is not "": if strip_white_space and contents is not "": contents = self._findWhiteSpace.sub("\\1", contents) # If we do the completion adjustment on completions that aren't functions # ST somehow erases the text before the period from the document leaving # just the piece after it (it makes no sense). This fixes that but will # almost certainly have to be changed when ST's behavior changes. if "(" in contents: comps.append( (trigger, contents.replace(completion_adjustment, ''))) else: comps.append((trigger, contents)) # _corona_utils.debug("extract_completions: ", view.extract_completions(completion_target)) # Remove duplicates comps = list(set(comps)) # _corona_utils.debug("comps: ", comps) return comps
def run(self, cmd=None, arg_filename=None, arg_lineno=None, arg_toggle=True): debug("CoronaDebuggerCommand: " + cmd) global coronaDbg global corona_sdk_version self.view = self.window.active_view() if self.view is None: sublime.error_message( "Cannot find an active view. You may need to restart Sublime Text." ) return # if we aren't started yet and a step is asked for, do a start if (coronaDbg is None or not coronaDbg.isRunning()) and cmd in ['run', 'step', 'over']: cmd = "start" if cmd == "start": if _corona_utils.GetSetting("corona_sdk_debug", False): # Show Sublime Console self.window.run_command("show_panel", {"panel": "console"}) # sublime.log_commands(True) if coronaDbg is not None: debug("Cleaning up debugger thread") coronaDbg.join() coronaDbg = None self.saved_layout = self.window.get_layout() # Figure out where the PUT and the Simulator are filename = self.window.active_view().file_name() if filename is None or not filename.endswith(".lua"): filename = None # No current .lua file, see if we have one open for view in self.window.views(): if view.file_name() and view.file_name().endswith(".lua"): if filename is None or not filename.endswith( "main.lua" ): # prefer a 'main.lua' if there is one filename = view.file_name() if filename is None: sublime.error_message( "Can't find an open '.lua' file to determine the location of 'main.lua'" ) return mainlua = _corona_utils.ResolveMainLua(filename) if mainlua is None: sublime.error_message( "Can't locate 'main.lua' for this project (try opening it in an editor tab)" ) return self.window.open_file( mainlua ) # make sure main.lua is open as that's the first place we'll stop projectDir = os.path.dirname(mainlua) if not projectDir: sublime.error_message( "Cannot find 'main.lua' for '" + self.view.file_name() + "'. This does not look like a Corona SDK app") return dbg_path, dbg_flags, dbg_version = _corona_utils.GetSimulatorCmd( mainlua, True) dbg_cmd = [dbg_path] dbg_cmd += dbg_flags dbg_cmd.append(mainlua) debug("debugger cmd: " + str(dbg_cmd)) debug("dbg_version: " + str(dbg_version)) if dbg_version: corona_sdk_version = dbg_version.rpartition(".")[2] debug("corona_sdk_version: " + str(corona_sdk_version)) global subProcOutputQ, debuggerCmdQ subProcOutputQ = coronaQueue.Queue() debuggerCmdQ = coronaQueue.Queue() coronaDbg = CoronaDebuggerThread(projectDir, self.debuggerFinished) if coronaDbg.setup(): if self.window.num_groups() == 1: self.initializeWindowPanes() else: # Clear the existing windows variables_output(' ') stack_output(' ') self.window.focus_group(0) RunSubprocess(dbg_cmd, self.window) coronaDbg.start() elif cmd == "restart": if coronaDbg is not None: self.window.run_command("corona_debugger", {"cmd": "exit"}) sublime.set_timeout( lambda: self.window.run_command("corona_debugger", {"cmd": "start"}), 0) elif cmd == "exit": StopSubprocess() if coronaDbg is None: self.closeWindowPanes() else: coronaDbg.doCommand(cmd) coronaDbg.stop() coronaDbg.join() coronaDbg = None elif cmd in ["run", "step", "over"]: coronaDbg.doCommand(cmd) coronaDbg.doCommand('backtrace') if not corona_sdk_version or (int(corona_sdk_version) < 2489 or int(corona_sdk_version) > 2515): coronaDbg.doCommand('locals') elif cmd == "dump": self.dumpVariable() elif cmd == "setb": # toggle a breakpoint at the current cursor position if arg_filename is None: filename = self.view.file_name() (lineno, col) = self.view.rowcol(self.view.sel()[0].begin()) lineno += 1 else: filename = arg_filename lineno = int(arg_lineno) if self.toggle_breakpoint(filename, lineno, arg_toggle): cmd = "setb" else: cmd = "delb" cmd += " " + '"' + filename + '"' cmd += " " + str(lineno) debug("setb: " + cmd) if coronaDbg is not None: coronaDbg.doCommand(cmd) else: print("CoronaDebuggerCommand: Unrecognized command: " + cmd)