Beispiel #1
0
    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")
Beispiel #2
0
 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)
Beispiel #3
0
    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")
Beispiel #4
0
 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")
Beispiel #5
0
 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)
Beispiel #7
0
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)
Beispiel #8
0
    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)
Beispiel #10
0
 def initialize(self):
     self.load_completions(
         _corona_utils.GetSetting("corona_sdk_use_docset", "public"))
Beispiel #11
0
    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
Beispiel #12
0
    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
Beispiel #13
0
    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)