Beispiel #1
0
def update_inserted_filepath(view, post_remove):
    """ post completion: adjusts inserted filepath """
    expression = Context.get_context(view)
    # diff of previous needle and inserted needle
    diff = get_diff(post_remove, expression["needle"])
    # cleanup string
    result = re.sub("^" + diff["start"], "", expression["needle"])
    # do not replace current word
    if diff["end"] != start_expression["word"]:
        result = re.sub(diff["end"] + "$", "", result)

    # remove path query completely
    result = apply_post_replacements(result, state.get("base_directory"),
                                     state.get("replace_on_insert"))
    log("post cleanup path:'", expression.get("needle"), "' ~~> '", result,
        "'")

    # replace current query with final path
    view.run_command(
        "ffp_replace_region", {
            "a": expression["region"].a,
            "b": expression["region"].b,
            "string": result,
            "move_cursor": True
        })
    def on_post_insert_completion(view, post_remove):
        start_expression = FuzzyFilePath.start_expression
        expression = Context.get_context(view)

        # diff of previous needle and inserted needle
        diff = get_diff(post_remove, expression["needle"])
        # cleanup string
        final_path = re.sub("^" + diff["start"], "", expression["needle"])
        # do not replace current word
        if diff["end"] != start_expression["word"]:
            final_path = re.sub(diff["end"] + "$", "", final_path)

        # remove path query completely
        final_path = Completion.get_final_path(final_path)
        log("post cleanup path:'", expression.get("needle"), "' ~~> '",
            final_path, "'")

        # replace current query with final path
        view.run_command(
            "ffp_replace_region", {
                "a": expression["region"].a,
                "b": expression["region"].b,
                "string": final_path,
                "move_cursor": True
            })
Beispiel #3
0
def update():
    """ call me anytime a new view has gained focus. This includes activation of a new window, which should have an
		active view
	"""
    global valid, is_enabled

    if not is_enabled:
        return False

    temp = False
    window = sublime.active_window()
    if window is None:
        logger.log(ID, "Abort -- no active window")
        valid = False
        return valid
    view = window.active_view()
    if view is None:
        logger.log(ID, "Abort -- no active view")
        valid = False
        return valid
    file = Path.posix(view.file_name())
    if not file:
        logger.log(ID, "Abort -- view has not yet been saved to file")
        temp = True
        return valid
    if state.get("file") == file:
        logger.log(ID, "Abort -- view already updated")
        return valid

    folders = list(map(lambda f: Path.posix(f), window.folders()))
    project_folder = get_closest_folder(file, folders)

    if project_folder is False:
        logger.log(ID, "Abort -- file not part of a project (folder)")
        valid = False
        return valid

    # notify settings of new project folder
    if state.get("project_folder") != project_folder:
        settings.update_project_settings()
    settings.update_project_folder_settings(project_folder)

    valid = True

    # @TODO cache
    state["file"] = file
    state["directory"] = sanitize_directory(file, project_folder)
    state["folders"] = folders
    state["project_folder"] = project_folder
    state["cache"] = get_file_cache(project_folder)

    logger.start_block()
    logger.verbose(ID, "Updated", state)

    return valid
Beispiel #4
0
def get_filepaths(view, query):
    global start_expression

    trigger = resolve_trigger(view, query)
    log(ID_TRIGGER, trigger)
    if query.build(start_expression.get("needle"), trigger,
                   current_state.get_directory()) is False:
        # query is valid, but may not be triggered: not forced, no auto-options
        verbose(ID, "abort - no auto trigger found")
        return False

    # remembed the path for `update_inserted_filepath`, query will be reset...
    state["base_directory"] = query.get_post_remove_path()

    return current_state.search_completions(
        query.get_needle(), current_state.get_project_directory(),
        query.get_extensions(), query.get_base_path())
Beispiel #5
0
def rebuild_filecache(folder=None):
    if not folder:
        if state.get("cache"):
            logger.verbose(
                ID, "rebuild current filecache of folder " +
                state.get("project_folder"))
            state.get("cache").rebuild()
        return

    folder = Path.posix(folder)
    if not folder in file_caches:
        logger.log(
            ID, "Abort rebuild filecache -- folder " + folder + " not cached")
        return False

    logger.verbose(ID, "rebuild current filecache of folder " + folder)
    file_caches.get(folder).rebuild()
Beispiel #6
0
    def run(self, edit):
        current_directory = os.path.dirname(self.view.file_name())
        context = Context.get_context(self.view)
        if context.get("valid") is False:
            return log(ID, "abort, no valid path given:", context.get("needle"))

        path = context.get("needle")
        project_folder = state.get_project_directory()

        if not (path and project_folder):
            return log(ID, "path or project invalid", path, project_folder)

        is_relative = Path.is_relative(path)
        if is_relative:
            path = Path.get_absolute_path(current_directory, path)
            path = re.sub(project_folder, "", path)


        path = re.sub("^[\\\\/\.]", "", path)
        realpath = path
        # cleanup string, in case there are special characters for a path
        # e.g. webpack uses ~, which is not part of path
        path = re.sub("[^A-Za-z0-9 \-_\\\\/.%?#]*", "", path)
        files = state.find_file(path)

        if len(files) == 0:
            # it may be an uncached file, try to open it by using the real path
            if self.filepath_exists(os.path.join(project_folder, realpath)):
                return self.open_file(project_folder, realpath)
            return log(ID, "failed finding file", path, "it is not within the cache and not a realpath")

        if len(files) == 1:
            self.open_file(project_folder, files[0])
        else:
            # if javascript, search for index.js
            current_scope = self.view.scope_name(Selection.get_position(self.view))
            if re.search("\.js ", current_scope):
                for file in files:
                    if "index.js" in file:
                        return self.open_file(project_folder, file)

            self.files = files
            self.project_folder = project_folder
            self.view.show_popup_menu(files, self.select_file)
Beispiel #7
0
def get_filepath_completions(view):
    if not state.is_valid():
        Query.reset()
        return False

    verbose(ID, "get filepath completions")
    completions = Completion.get_filepaths(view, Query)

    if completions and len(completions[0]) > 0:
        Completion.start(Query.get_replacements())
        view.run_command('_enter_insert_mode') # vintageous
        log("{0} completions found".format(len(completions)))
    else:
        if Query.get_needle() is not None:
            sublime.status_message("FFP no filepaths found for '" + Query.get_needle() + "'")
        Completion.stop()

    Query.reset()
    return completions
Beispiel #8
0
    def run(self, edit):
        current_directory = os.path.dirname(self.view.file_name())
        context = Context.get_context(self.view)
        if context.get("valid") is False:
            return log(ID, "abort, no valid path given:",
                       context.get("needle"))

        path = context.get("needle")
        project_folder = state.get_project_directory()

        if not (path and project_folder):
            return log(ID, "path or project invalid", path, project_folder)

        is_relative = Path.is_relative(path)
        if is_relative:
            path = Path.get_absolute_path(current_directory, path)
            path = re.sub(project_folder, "", path)

        path = re.sub("^[\\\\/\.]", "", path)
        files = state.find_file(path)

        if len(files) == 0:
            return log(ID, "failed finding file", path)

        if len(files) == 1:
            self.open_file(project_folder, files[0])
        else:
            # if javascript, search for index.js
            current_scope = self.view.scope_name(
                Selection.get_position(self.view))
            if re.search("\.js ", current_scope):
                for file in files:
                    if "index.js" in file:
                        return self.open_file(project_folder, file)

            self.files = files
            self.project_folder = project_folder
            self.view.show_popup_menu(files, self.select_file)
    def on_post_insert_completion(view, post_remove):
        start_expression = FuzzyFilePath.start_expression
        expression = Context.get_context(view)

        # diff of previous needle and inserted needle
        diff = get_diff(post_remove, expression["needle"])
        # cleanup string
        final_path = re.sub("^" + diff["start"], "", expression["needle"])
        # do not replace current word
        if diff["end"] != start_expression["word"]:
            final_path = re.sub(diff["end"] + "$", "", final_path)

        # remove path query completely
        final_path = Completion.get_final_path(final_path)
        log("post cleanup path:'", expression.get("needle"), "' ~~> '", final_path, "'")

        # replace current query with final path
        view.run_command("ffp_replace_region", {
            "a": expression["region"].a,
            "b": expression["region"].b,
            "string": final_path,
            "move_cursor": True
        })
    def run(self, edit):
        current_directory = os.path.dirname(self.view.file_name())

        context = Context.get_context(self.view)
        if context.get("valid") is False:
            return log(ID, "abort, no valid path given:", context.get("needle"))

        path = context.get("needle")
        project = ProjectManager.get_current_project()

        if not (path and project):
            return log(ID, "path or project invalid", path, project)

        is_relative = Path.is_relative(path)
        if is_relative:
            path = Path.get_absolute_path(current_directory, path)
            path = re.sub(project.get_directory(), "", path)

        path = re.sub("^[\\\\/\.]", "", path)
        files = project.find_file(path)

        if len(files) == 0:
            return log(ID, "failed finding file", path)

        if len(files) == 1:
            self.open_file(project.get_directory(), files[0])
        else:
            # if javascript, search for index.js
            current_scope = self.view.scope_name(Selection.get_position(self.view))
            if re.search("\.js ", current_scope):
                for file in files:
                    if "index.js" in file:
                        return self.open_file(project.get_directory(), file)

            self.files = files
            self.project_folder = project.get_directory()
            self.view.show_popup_menu(files, self.select_file)
Beispiel #11
0
def sanitize_base_directory(base_directory, project_directory,
                            base_project_directory):
    """
        validate possible base directory
    """
    if not base_directory:
        return ""

    base_directory = get_valid_path(base_directory)
    # base_project_directory    | /path/to/sublime/project
    # project_directory         | /path/to/sublime/project/project_directory
    # - path_to_base_directory  | /path/to/sublime/project/base_directory
    # + path_to_base_directory  | /path/to/sublime/project/project_directory/base_directory
    path_to_base_directory = os.path.join(project_directory, base_directory)
    if not os.path.isdir(path_to_base_directory):
        # BASE_DIRECTORY is NOT a valid folder relative to (possibly modified) project_directory
        path_to_base_directory = os.path.join(base_project_directory,
                                              base_directory)

        if not os.path.isdir(path_to_base_directory):
            log("Error: setting's base_directory is not a valid directory in project"
                )
            log("=> changing base_directory {0} to ''".format(base_directory))
            return ""

        elif path_to_base_directory in project_directory:
            # change BASE_DIRECTORY to be '' since its outside of project directory
            log("Error: setting's base_directory is within project directory")
            log("=> changing base_directory {0} to ''".format(base_directory))
            return ""

        else:
            # change BASE_DIRECTORY to be relative to modified project directory
            path_to_base_directory = path_to_base_directory.replace(
                project_directory, "")
            log("Error: setting's base_directory is not relative to project directory"
                )
            log("=> changing base_directory '{0}' to '{1}'".format(
                base_directory, path_to_base_directory))
            return get_valid_path(path_to_base_directory)

    return base_directory
    def on_query_completions(view, project_folder, current_folder):
        global Context, Selection

        current_scope = Selection.get_scope(view)

        if not Query.by_command():
            triggers = get_matching_autotriggers(current_scope, config["TRIGGER"])
        else:
            triggers = config["TRIGGER"]

        if not bool(triggers):
            verbose(ID, "abort query, no valid scope-regex for current context")
            return False

        # parse current context, may contain 'is_valid: False'
        expression = Context.get_context(view)
        if expression["error"] and not Query.by_command():
            verbose(ID, "abort not a valid context")
            return False

        # check if there is a trigger for the current expression
        trigger = Context.find_trigger(expression, current_scope, triggers)
        # verbose("trigger", trigger)

        # expression | trigger  | force | ACTION            | CURRENT
        # -----------|----------|-------|-------------------|--------
        # invalid    | False    | False | abort             | abort
        # invalid    | False    | True  | query needle      | abort
        # invalid    | True     | False | query             |
        # invalid    | True     | True  | query +override   |
        # valid      | False    | False | abort             | abort
        # valid      | False    | True  | query needle      | abort
        # valid      | True     | False | query             |
        # valid      | True     | True  | query +override   |

        # currently trigger is required in Query.build
        if trigger is False:
            verbose(ID, "abort completion, no trigger found")
            return False

        if not expression["valid_needle"]:
            word = Selection.get_word(view)
            expression["needle"] = re.sub("[^\.A-Za-z0-9\-\_$]", "", word)
            verbose(ID, "changed invalid needle to {0}".format(expression["needle"]))
        else:
            verbose(ID, "context evaluation {0}".format(expression))

        if Query.build(expression.get("needle"), trigger, current_folder, project_folder) is False:
            # query is valid, but may not be triggered: not forced, no auto-options
            verbose(ID, "abort valid query: auto trigger disabled")
            return False

        verbose(ID, ".───────────────────────────────────────────────────────────────")
        verbose(ID, "| scope settings: {0}".format(trigger))
        verbose(ID, "| search needle: '{0}'".format(Query.needle))
        verbose(ID, "| in base path: '{0}'".format(Query.base_path))

        FuzzyFilePath.start_expression = expression
        completions = ProjectManager.search_completions(Query.needle, project_folder, Query.extensions, Query.base_path)

        if completions and len(completions[0]) > 0:
            Completion.start(Query.replace_on_insert)
            view.run_command('_enter_insert_mode') # vintageous
            log("| => {0} completions found".format(len(completions)))
        else:
            sublime.status_message("FFP no filepaths found for '" + Query.needle + "'")
            Completion.stop()
            log("| => no valid files found for needle: {0}".format(Query.needle))

        log("")

        Query.reset()
        return completions
    def on_query_completions(view, project_folder, current_folder):
        global Context, Selection

        current_scope = Selection.get_scope(view)

        if not Query.by_command():
            triggers = get_matching_autotriggers(current_scope,
                                                 config["TRIGGER"])
        else:
            triggers = config["TRIGGER"]

        if not bool(triggers):
            verbose(ID,
                    "abort query, no valid scope-regex for current context")
            return False

        # parse current context, may contain 'is_valid: False'
        expression = Context.get_context(view)
        if expression["error"] and not Query.by_command():
            verbose(ID, "abort not a valid context")
            return False

        # check if there is a trigger for the current expression
        trigger = Context.find_trigger(expression, current_scope, triggers)
        # verbose("trigger", trigger)

        # expression | trigger  | force | ACTION            | CURRENT
        # -----------|----------|-------|-------------------|--------
        # invalid    | False    | False | abort             | abort
        # invalid    | False    | True  | query needle      | abort
        # invalid    | True     | False | query             |
        # invalid    | True     | True  | query +override   |
        # valid      | False    | False | abort             | abort
        # valid      | False    | True  | query needle      | abort
        # valid      | True     | False | query             |
        # valid      | True     | True  | query +override   |

        # currently trigger is required in Query.build
        if trigger is False:
            verbose(ID, "abort completion, no trigger found")
            return False

        if not expression["valid_needle"]:
            word = Selection.get_word(view)
            expression["needle"] = re.sub("[^\.A-Za-z0-9\-\_$]", "", word)
            verbose(
                ID,
                "changed invalid needle to {0}".format(expression["needle"]))
        else:
            verbose(ID, "context evaluation {0}".format(expression))

        if Query.build(expression.get("needle"), trigger, current_folder,
                       project_folder) is False:
            # query is valid, but may not be triggered: not forced, no auto-options
            verbose(ID, "abort valid query: auto trigger disabled")
            return False

        verbose(
            ID,
            ".───────────────────────────────────────────────────────────────")
        verbose(ID, "| scope settings: {0}".format(trigger))
        verbose(ID, "| search needle: '{0}'".format(Query.needle))
        verbose(ID, "| in base path: '{0}'".format(Query.base_path))

        FuzzyFilePath.start_expression = expression
        completions = ProjectManager.search_completions(
            Query.needle, project_folder, Query.extensions, Query.base_path)

        if completions and len(completions[0]) > 0:
            Completion.start(Query.replace_on_insert)
            view.run_command('_enter_insert_mode')  # vintageous
            log("| => {0} completions found".format(len(completions)))
        else:
            sublime.status_message("FFP no filepaths found for '" +
                                   Query.needle + "'")
            Completion.stop()
            log("| => no valid files found for needle: {0}".format(
                Query.needle))

        log("")

        Query.reset()
        return completions