def should_not_validate_after_closing_bracket(self, vh): vh.set_line('require ("require("../package").subPackage'); vh.move_cursor(0, 35) print(get_context(vh.view)) result = get_context(vh.view).get("valid_needle") self.assert_equal(result, False)
def should_not_validate_after_closing_bracket(self, vh): vh.set_line('require ("require("../package").subPackage') vh.move_cursor(0, 35) print(get_context(vh.view)) result = get_context(vh.view).get("valid_needle") self.assert_equal(result, False)
def should_return_style_in_quotes(self, vh): vh.set_line('"background": prefix(test)') vh.move_cursor(0, 23) result = get_context(vh.view).get("style") self.assert_equal(result, 'background')
def should_return_prefix_before_colon(self, viewHelper): viewHelper.set_line('prefix:file') viewHelper.move_cursor(0, 10) result = get_context(viewHelper.view).get("prefix") self.assert_equal(result, 'prefix')
def should_return_word_as_needle(self, viewHelper): viewHelper.set_line('result = path') viewHelper.move_cursor(0, 12) needle = get_context(viewHelper.view).get("needle") self.assert_equal(needle, 'path')
def should_return_tagName(self, vh): vh.set_line('<div id') vh.move_cursor(0, 10) result = get_context(vh.view).get("tagName") self.assert_equal(result, 'div')
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 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 run(self, edit): context = Context.get_context(self.view) current_scope = self.view.scope_name(Selection.get_position(self.view)) trigger = resolve_trigger(self.view, Query) print("FOUND TRIGGER", trigger) self.content = "<h4>FuzzyFilepath - context evaluation</h4>" self.add("filepath valid", context.get("valid_needle")) self.add("context valid", context.get("is_valid")) self.content += "<br>" self.add("path", context.get("needle")) self.add("prefix", context.get("prefix")) self.add("property", context.get("style")) self.add("tag", context.get("tagName")) self.add("word", context.get("word")) self.content += "<br>" self.add("scope", current_scope) self.content += "<br>" self.content += "<h5>Trigger</h5>" if trigger is False: self.content += "no trigger could be found matching the given context" else: for key in trigger: self.add(key, trigger.get(key)) self.show()
def should_return_line_as_needle(self, viewHelper): viewHelper.set_line('../line/as/path') viewHelper.move_cursor(0, 12) needle = get_context(viewHelper.view).get("needle") self.assert_equal(needle, '../line/as/path')
def should_return_style_in_tag(self, vh): vh.set_line('<h1 style=\"\'background\': prefix(\'test\')\"') vh.move_cursor(0, 36) result = get_context(vh.view) self.assert_equal(result.get("tagName"), 'h1') self.assert_equal(result.get("style"), 'background')
def should_identify_hbs_partials(self, viewHelper): viewHelper.set_line('{{> src/to/folder/file.hbs}}') viewHelper.move_cursor(0, 10) context = get_context(viewHelper.view) self.assert_equal(context.get("needle"), 'src/to/folder/file.hbs') self.assert_equal(context.get("region").a, 4)
def start_tracking(self, view, command_name=None): self.track_insert["active"] = True self.track_insert["start_line"] = Selection.get_line(view) """ - sublime inserts completions by replacing the current word - this results in wrong path insertions if the query contains word_separators like slashes - thus the path until current word has to be removed after insertion - ... and possibly afterwards """ context = Context.get_context(view) needle = context.get("needle") word = re.escape(Selection.get_word(view)) self.post_remove = re.sub(word + "$", "", needle) verbose(ID, "start tracking", self.post_remove)
def resolve_trigger(view, query): global start_expression # parse current context, may contain 'is_valid: False' start_expression = Context.get_context(view) if start_expression["error"] and not query.by_command(): verbose(ID, "abort - not a valid context") return False current_scope = Selection.get_scope(view) trigger = find_trigger(current_scope, start_expression, query.by_command()) # currently trigger is required in Query.build if trigger is False: verbose(ID, "abort - no trigger found") return False return trigger
def run(self, edit): print("show context") context = Context.get_context(self.view) current_scope = self.view.scope_name(Selection.get_position(self.view)) self.content = "<h4>FuzzyFilepath - context evaluation</h4>" self.add("filepath valid", context.get("valid_needle")) self.add("context valid", context.get("is_valid")) self.content += "<br>" self.add("path", context.get("needle")) self.add("prefix", context.get("prefix")) self.add("property", context.get("style")) self.add("tag", context.get("tagName")) self.add("word", context.get("word")) self.content += "<br>" self.add("scope", current_scope) self.show()
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)
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)
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