Example #1
0
def cleanup_completion(view, post_remove):
    expression = Context.get_context(view)
    # remove path query completely
    final_path = Completion.get_final_path(expression["needle"], post_remove)
    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 })
Example #2
0
    def get_final_path(path, path_needle):
        # print("cleanup path", path, "needle:", path_needle)
        #st2 - remove path_needle fragments
        #remove anything before last word separator?
        part_to_remove = re.escape(re.sub("[^\/]*$", "", path_needle))
        # print("remove:", part_to_remove)
        path = re.sub("^" + part_to_remove, "", path)
        # print("cleanup #1", path)

        # st2 - sanitize
        if re.search("\/\.\/", path):
            path = re.sub("^(\.\.\/)*", "", path)

        path = re.sub("^(\.\/)+", "./", path)
        path = re.sub("^(\/\/)+", "/", path)

        # hack reverse
        path = re.sub(config["ESCAPE_DOLLAR"], "$", path)
        for replace in Completion.replaceOnInsert:
            path = re.sub(replace[0], replace[1], path)

        if Completion.base_directory and path.startswith("/"):
            path = re.sub("^\/" + Completion.base_directory, "", path)
            path = Path.sanitize(path)

        log("final filepath: '{0}'".format(path))
        return path
Example #3
0
def update_settings():
    """ restart projectFiles with new plugin and project settings """
    global project_files, scope_cache

    scope_cache.clear()
    settings = sublime.load_settings(config["FFP_SETTINGS_FILE"])

    # st2 - has to check window
    project_settings = False
    current_window = sublime.active_window()
    if current_window:
        project_settings = current_window.active_view().settings().get('FuzzyFilePath', False)

    # sync settings to config
    for key in config:
        config[key] = settings.get(key.lower(), config[key])
    # mapping
    config["TRIGGER"] = settings.get("scopes", config["TRIGGER"])
    # merge project settings stored in "settings: { FuzzyFilePath: ..."
    if project_settings:
        # mapping
        config["TRIGGER"] = project_settings.get("scopes", config["TRIGGER"])
        for key in config:
            config[key] = project_settings.get(key.lower(), config[key])
    # build extensions to suggest
    extensionsToSuggest = []
    for scope in config["TRIGGER"]:
        ext = scope.get("extensions", [])
        extensionsToSuggest += ext
    # remove duplicates
    extensionsToSuggest = list(set(extensionsToSuggest))

    project_files = ProjectFiles()
    project_files.update_settings(extensionsToSuggest, config["EXCLUDE_FOLDERS"])
    # validate directories
    if config["BASE_DIRECTORY"]:
        config["BASE_DIRECTORY"] = Path.sanitize_base_directory(config["BASE_DIRECTORY"])
    if config["PROJECT_DIRECTORY"]:
        config["PROJECT_DIRECTORY"] = Path.sanitize_base_directory(config["PROJECT_DIRECTORY"])

    log("logging enabled")
    log("project base directory set to '{0}'".format(config["BASE_DIRECTORY"]))
    log("{0} scope triggers loaded".format(len(config["TRIGGER"])))
Example #4
0
def 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):
        log("abort query, no valid scope-regex for current context")
        return False

    # parse current context, may contain 'is_valid: False'
    expression = Context.get_context(view)
    # check if there is a trigger for the current expression
    trigger = Context.find_trigger(expression, current_scope, triggers)

    # 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:
        log("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)
        log("changed invalid needle to {0}".format(expression["needle"]))
    else:
        log("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
        log("abort valid query: auto trigger disabled")
        return False

    if Query.base_path:
        Query.base_path = str(Query.base_path)


    completions = project_files.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
Example #5
0
    def build(needle, trigger, current_folder, project_folder):
        force_type = Query.get("filepath_type", False)
        triggered = Query.by_command()
        filepath_type = "relative"
        needle = Path.sanitize(needle)
        needle_is_absolute = Path.is_absolute(needle)
        needle_is_relative = Path.is_relative(needle)
        needle_is_path = needle_is_absolute or needle_is_relative
        # abort if autocomplete is not available
        if not triggered and trigger.get("auto", False) is False and needle_is_path is False:
            return False
        # test path to trigger auto-completion by needle
        if not triggered and trigger["auto"] is False and config["AUTO_TRIGGER"] and needle_is_absolute:
            force_type = "absolute"
        # base_directory: override - trigger - False
        base_directory = trigger.get("base_directory", False)
        base_directory = Query.get("base_directory", base_directory)
        #
        # set current directory by force, else by trigger:
        #
        # trigger       |
        # --------------|--------------------
        # False         | use current file's directory
        # True          | use settings: base_directory
        # String        | use string as base_directory
        # change base folder to base directory
        #
        # st2? - fix missing or bugged base_directory
        adjusted_basepath = current_folder
        if base_directory is True:
            adjusted_basepath = config["BASE_DIRECTORY"]
        elif base_directory:
            adjusted_basepath = Path.sanitize_base_directory(base_directory)
        # notify completion to replace path
        if base_directory and needle_is_absolute:
            Completion.base_directory = current_folder
        # st2? - fix missing or bugged base_directory
        if adjusted_basepath is False:
            adjusted_basepath = current_folder
        #
        # filepath_type
        #
        # needle    | trigger rel   | force     | RESULT
        # ----------|---------------|-----------|---------
        # ?         | relative      | False     | relative
        # ?         | absolute      | False     | absolute
        # absolute  | *             | False     | absolute
        # relative  | *             | False     | relative
        # *         | *             | relative  | relative
        # *         | *             | absolute  | absolute
        #
        if force_type:
            filepath_type = force_type
        elif needle_is_absolute:
            filepath_type = "absolute"
        elif needle_is_relative:
            filepath_type = "relative"
        elif trigger.get("relative") is True:
            filepath_type = "relative"
        elif trigger.get("relative") is False:
            filepath_type = "absolute"

        Query.base_path = current_folder if filepath_type == "relative" else False
        # replacements: override - trigger - None
        Query.replace_on_insert = trigger.get("replace_on_insert", [])
        Query.replace_on_insert = Query.get("replace_on_insert", Query.replace_on_insert)
        # extensions: override - trigger - "js"
        Query.extensions = trigger.get("extensions", ["*"])
        Query.extensions = Query.get("extensions", Query.extensions)
        Query.needle = Query.build_needle_query(needle, current_folder)
        log("\nfilepath type\n--------")
        log("type:", filepath_type)
        log("base_path:", Query.base_path)
        log("needle:", Query.needle)
        log("current folder", current_folder)
        return triggered or (config["AUTO_TRIGGER"] if needle_is_path else trigger.get("auto", config["AUTO_TRIGGER"]))