Repository: sagold/FuzzyFilePath Branch: master Commit: 5c50ecdc2af2 Files: 77 Total size: 90.1 KB Directory structure: gitextract_1a51ib0w/ ├── .gitignore ├── .npmignore ├── CHANGES.md ├── Default (Linux).sublime-keymap ├── Default (OSX).sublime-keymap ├── Default (Windows).sublime-keymap ├── Default.sublime-commands ├── Default.sublime-keymap ├── FuzzyFilePath.md ├── FuzzyFilePath.sublime-settings ├── LICENSE ├── Main.sublime-menu ├── ProjectListener.py ├── QueryCompletionListener.py ├── README.md ├── TestRunner.py ├── ViewListener.py ├── command_goto_file.py ├── command_insert_path.py ├── command_rebuild_cache.py ├── command_replace_region.py ├── command_show_context.py ├── command_show_current_settings.py ├── command_show_info.py ├── common/ │ ├── __init__.py │ ├── config.py │ ├── path.py │ ├── selection.py │ ├── settings.py │ ├── string.py │ └── verbose.py ├── completion.py ├── controller.py ├── current_state.py ├── expression.py ├── project/ │ ├── FileCache.py │ ├── FileCacheWorker.py │ ├── __init__.py │ └── validate.py ├── query.py └── test/ ├── __init__.py ├── integration/ │ ├── __init__.py │ ├── get_context_test.py │ ├── tests.py │ └── tools.py ├── mock/ │ └── project/ │ ├── app/ │ │ ├── boot.js │ │ ├── index.html │ │ ├── latex.tex │ │ ├── src/ │ │ │ ├── coffee/ │ │ │ │ ├── coffee.coffee │ │ │ │ ├── module.coffee │ │ │ │ └── other.coffee │ │ │ ├── common.js │ │ │ ├── main.js │ │ │ ├── tools.js │ │ │ └── ts/ │ │ │ ├── another.ts │ │ │ ├── module.ts │ │ │ ├── other.ts │ │ │ ├── tsconfig.json │ │ │ └── typescript.ts │ │ └── styles/ │ │ ├── index.css │ │ ├── partials/ │ │ │ ├── common.scss │ │ │ └── media.scss │ │ └── styles.css │ └── bower_components/ │ ├── angular/ │ │ └── index.js │ └── lib/ │ ├── component/ │ │ ├── component.html │ │ ├── component.scss │ │ ├── componentCtrl.js │ │ └── componentModel.js │ ├── css/ │ │ ├── index.css │ │ └── styles.css │ └── index.js ├── tools.py └── unit/ ├── __init__.py ├── debug_test.py ├── get_closest_folder_test.py ├── query_test.py └── tests.py ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ /temp *.pyc *.psd FuzzyFilePath.sublime-workspace FuzzyFilePath.sublime-project ================================================ FILE: .npmignore ================================================ /test *.gif ================================================ FILE: CHANGES.md ================================================ 19/04/03 - Update triggers for sass, js and ts 18/05/06 - Add `additional_scopes` list for custom scope extension - Update edit_settings command - Add json as valid js extension 17/04/01 - fixed an error while post-replacing inserted filepath, which exited with a broken result CHANGES - improved goto-file command by quering a simplified path (webpack ~) - improved goto-file command to open uncached files if filepath does exist - filecache worker now includes subfolders defined as project-folder, even if exclude_folders does match them 16/09/10 - support for multiple folders - bugfixes - major code simplifications 15/06/07 - fixed project settings to be added on top of default settings - fixed update settings for modified user settings - fixed an issue on windows where paths were not inserted relative 15/03 - major refactoring and bugfixes FEATURES - open path under cursor - show popup containing context evaluation information, required to setup triggers (requires Sublime Text build 3073) - set project specifiv project_directory via command palette - after completion insertion, move to beginning of next word - support multiple opened projects (in separate windows) CHANGES - improve update of caching - update cache on project change - update cache window focus - add command to rebiuld cache manually - update cache if a new file is saved - improve replacement of current path fragments - display of file path suggestions will not separate file extension. this allows querying filetype 14/11/23 BREAKING CHANGES - **change** `exclude_folders` items to be matched as regex - **remove** `extensionsToSuggest`, now being retrieved from scope settings - **remove** shortcut `super+ctrl+space` - **remove** option `auto_trigger` - **remove** option `insertExtension`. Should now be done by `replace_on_insert` - **change** and extend default scope rules - **change** absolute paths to start with "/name" - **change** path prefix (./, ../, /) now overwrites scope settings CHANGES - extend insert\_path command (shortcut) with base\_directory and extensions - add support for base_directory - extend scope-rules by tagName, style and prefix - analyse context of cursor to retrieve tagName, style and prefix - improve retrieval of query in view - fix path replacement for files being in root - stability improvements - refactorings 14/11/02 - fix bug in instant completions (missing string-cleanup method) - fix trigger to update cached files - remove bugged merge of exlude\_folder\_patterns and exlude\_folders. Thus exlude\_folders are always applied - fix bug in updating cache (triggered for invalid file extensions) - refactorings 14/10/03 - extend insert\_path command by replace\_on\_insert - add FuzzyFilePath Package Settings to Sublime Text Menu - setting replace\_on\_insert - setting disable\_keymap\_actions - setting disable_autocompletions - add integration tests ================================================ FILE: Default (Linux).sublime-keymap ================================================ [ { "keys": ["ctrl+alt+space"], "command": "insert_path", "args": { "type": "relative" } }, { "keys": ["ctrl+shift+space"], "command": "insert_path", "args": { "type": "absolute" } }, { "keys": ["alt+enter"], "command": "ffp_goto_file" } ] ================================================ FILE: Default (OSX).sublime-keymap ================================================ [ { "keys": ["ctrl+alt+space"], "command": "insert_path", "args": { "type": "relative" } }, { "keys": ["ctrl+shift+space"], "command": "insert_path", "args": { "type": "absolute" } }, { "keys": ["alt+enter"], "command": "ffp_goto_file" } ] ================================================ FILE: Default (Windows).sublime-keymap ================================================ [ { "keys": ["ctrl+alt+space"], "command": "insert_path", "args": { "type": "relative" } }, { "keys": ["ctrl+shift+space"], "command": "insert_path", "args": { "type": "absolute" } }, { "keys": ["alt+enter"], "command": "ffp_goto_file" } ] ================================================ FILE: Default.sublime-commands ================================================ [ { "caption": "FuzzyFilePath: Rebuild cache", "command": "ffp_update_cache" }, { "caption": "FuzzyFilePath: Show info", "command": "ffp_show_info" }, { "caption": "FuzzyFilePath: Set project directory", "command": "ffp_set_project_directory" }, { "caption": "FuzzyFilePath: Show current settings", "command": "ffp_show_current_settings" }, { "caption": "FuzzyFilePath: Goto File", "command": "ffp_goto_file"}, { "caption": "FuzzyFilePath: Insert Relative Path", "command": "insert_path", "args": { "type": "relative" } }, { "caption": "FuzzyFilePath: Insert Absolute Path", "command": "insert_path", "args": { "type": "absolute" } } ] ================================================ FILE: Default.sublime-keymap ================================================ [ { "keys": ["ctrl+alt+space"], "command": "insert_path", "args": { "type": "relative" } }, { "keys": ["ctrl+shift+space"], "command": "insert_path", "args": { "type": "absolute" } }, { "keys": ["alt+enter"], "command": "ffp_goto_file" } ] ================================================ FILE: FuzzyFilePath.md ================================================ # FuzzyFilePath - autocomplete filepaths @version 0.6.1 @author Sascha Goldhofer ## tasks - possibly create file caches of all project directories simultaneously - Cleanup @TODO flags - suddenly Testrunner causes plugin host to expire ### bugs - Initial opened view may be falsely recognised as "not within project" ### release - WIP: Test changes - DONE: Test windows paths - Add documentation for multiple folder support ### performance - searching in large folders, where the query matches a folder containing many files, are very slow. i.e. searching for "node_modules/path/to/package" is much slower than searching for "path/to/package" (filecount 10k+) - current workaround fast_query option in default settings - so far the regex can not be improved to be faster and still return the same results, the first step should be to exclude unused folders which (may require an option for folder whitelisting) i.e. "node_modules/(?!szig).*" ### features - growing list of triggers is getting unmaintainable - Probably group by main-scope in object for faster retrieval and namespacing - create an object with ids for a specific trigger and use a list of ids for triggers to use (selecting object) - further support trigger objects in the scope-list - add custom triggers without overriding the default scopes ### ideas - maybe support different triggers based on inserted filepath? (i.e. absolute if matches node_mod...) - possibly send ffp states to serve for better debugging ================================================ FILE: FuzzyFilePath.sublime-settings ================================================ { // set project_directory relative to sublime project directory "project_directory": "", // base directory for paths relative to project_directory. Used if scope-trigger contains "base_directory": true // watch out for side effects with project directory (if base_directory is not within project_directory) "base_directory": false, // disable automatic path completions "disable_autocompletions": false, // disable keymaps "disable_keymap_actions": false, // ignore folders that match following regular expressions "exclude_folders": ["node_modules", "bower_components"], // logs scope evaluation to console to debug configuration "log": false, // LIST OF TRIGGERS FOR AUTO COMPLETION // - setting "scopes" in user settings will override all other scopes. // - create "additional_scopes" in user settings to add more scopes instead. // they will be added after the existing scopes. // - triggers are evaluated in given order. First match wins // - specialize trigger by 1. scope 2. prefix, style and/or tagname // - command (insert_path) still requires a trigger "scopes": [ // MINIMAL AUTO TRIGGER - NOT RECOMMENDED // will always query files for auto completions // { // "scope": ".", // "extensions": ["*"], // "auto": true // }, /* Javascript */ { // js: require() "scope": "\\.(js|ts)\\s", // 1. ignore if scope at cursor does not match expression (super+alt+p) "prefix": ["require", "define"], // 2. trigger only if: require(, define([ // if 1 & 2 are true: "auto": true, "relative": true, // insert absolute "base_directory": false, // insert absolute from the set base directory (above) "extensions": ["ts", "js", "html", "scss", "json"], // show only .js, .html and .scss files "replace_on_insert": [ ["\\.(js|ts)$", ""], // after insertion, remove .js from path ["([^.])\\/index$", "\\1"], // nodejs will load index.js by default => also remove index // remove path to module-folder, since our build tool resolves this path automatically ["^([\\/.]+)?\\/(bower_components|node_modules)\\/", ""] ] }, { // es6 import from/import "*" "scope": "string.*\\.(js|ts)\\s", "auto": true, "relative": true, "base_directory": false, "prefix": ["from", "import"], "extensions": ["ts", "js", "html", "scss", "json"], "replace_on_insert": [ ["\\.(js|ts)$", ""], ["([^.])\\/index$", "\\1"], ["^([\\/.]+)?\\/(bower_components|node_modules)\\/", ""] ] }, { // Typescript // "scope": "source\\.ts\\scomment", "auto": true, "relative": true, "base_directory": false, "prefix": ["path"], "tagName": ["reference"], "extensions": ["ts", "js"], "replace_on_insert": [] }, { // Typescript es6 import from/import "*" "scope": "string[^\\s]*\\.ts\\s", "auto": true, "relative": true, "base_directory": false, "prefix": ["from", "import"], "extensions": ["js", "ts"], "replace_on_insert": [ ["(\\.js|\\.ts)$", ""], ["([^.])\\/index$", "\\1"], ["^(\\/.+)?\\/(bower_components|node_modules)\\/", ""] ] }, { // Coffeescript es6 import from/import "*" and require "scope": "string[^\\s]*\\.coffee\\s", "auto": true, "relative": true, "base_directory": false, "prefix": ["from", "import", "require"], "extensions": ["coffee"], "replace_on_insert": [] }, { // js - *.src = "" "scope": "source\\.js.*string", "prefix": ["src"], "auto": true, "base_directory": true, "extensions": ["png", "gif", "jpg", "jpeg"], "relative": true }, /* CSS */ { // import "" "scope": "source\\.(css|sass|scss|less)", "auto": true, "prefix": ["import"], "relative": true, "extensions": ["css", "sass", "scss", "less"], "replace_on_insert": [ ["\\.(css|scss)$", ""], ["^(\\/.+)?\\/(bower_components|node_modules)\\/", ""] ] }, { // *: url() "scope": "source\\.(css|sass|less)", "prefix": ["url"], "auto": true, "relative": true, "base_directory": true, "extensions": ["png", "gif", "jpeg", "jpg", "woff", "ttf", "svg", "otf"], "replace_on_insert": [ ["\\.(css|scss)$", ""], ["^(\\/.+)?\\/(bower_components|node_modules)\\/", ""] ] }, /* HTML */ { // html -
================================================ FILE: test/mock/project/app/latex.tex ================================================ \input{"./assets/header.png"} ================================================ FILE: test/mock/project/app/src/coffee/coffee.coffee ================================================ require("./module.coffee"); `import "./module.coffee"` ================================================ FILE: test/mock/project/app/src/coffee/module.coffee ================================================ ================================================ FILE: test/mock/project/app/src/coffee/other.coffee ================================================ ================================================ FILE: test/mock/project/app/src/common.js ================================================ ================================================ FILE: test/mock/project/app/src/main.js ================================================ // main var tools = require("./tools"); var media = require("../styles/partials/media.scss"); ================================================ FILE: test/mock/project/app/src/tools.js ================================================ ================================================ FILE: test/mock/project/app/src/ts/another.ts ================================================ ================================================ FILE: test/mock/project/app/src/ts/module.ts ================================================ ================================================ FILE: test/mock/project/app/src/ts/other.ts ================================================ ================================================ FILE: test/mock/project/app/src/ts/tsconfig.json ================================================ { "compilerOptions": { "out": "built/out.js", "sourceMap": true, "target": "es5" }, "files": [] } ================================================ FILE: test/mock/project/app/src/ts/typescript.ts ================================================ import * from ./other.ts import {test} from "../../../bower_components/angular" from "./another.ts" import "./typescript"; // ================================================ FILE: test/mock/project/app/styles/index.css ================================================ .issue13 { composes: label from './styles.css' composes: label from "sty"; background-color: rgba(0, 0, 0, 0.2); } ================================================ FILE: test/mock/project/app/styles/partials/common.scss ================================================ @import ./component.scss ================================================ FILE: test/mock/project/app/styles/partials/media.scss ================================================ // SASS @import "../../../bower_components/lib/component/component" @import "/test/mock/project/bower_components/lib/component/component" @import "./common" ================================================ FILE: test/mock/project/app/styles/styles.css ================================================ * { background-image: url("./assets/header.png"); } @font-face { font-family: "icon"; src: url(./assets/fonts/glyph.ttf) format("truetype"), url(./assets/fonts/glyph.svg) format("svg"); } ================================================ FILE: test/mock/project/bower_components/angular/index.js ================================================ // angular/index.js ================================================ FILE: test/mock/project/bower_components/lib/component/component.html ================================================ ================================================ FILE: test/mock/project/bower_components/lib/component/component.scss ================================================ ================================================ FILE: test/mock/project/bower_components/lib/component/componentCtrl.js ================================================ ================================================ FILE: test/mock/project/bower_components/lib/component/componentModel.js ================================================ ================================================ FILE: test/mock/project/bower_components/lib/css/index.css ================================================ ================================================ FILE: test/mock/project/bower_components/lib/css/styles.css ================================================ ================================================ FILE: test/mock/project/bower_components/lib/index.js ================================================ ================================================ FILE: test/tools.py ================================================ import inspect """ Inherit from TestCase to run tests receiving argument `ViewHelper` Convention: for a test to be executed/recognized its name must contains "should" """ class TestCase: unit_test = False def __init__(self, name): self.name = name self.tests = self.get_tests() self.length = len(self.tests) def get_tests(self): tests = [] methods = inspect.getmembers(self, predicate=inspect.ismethod) for name, descr in methods: if "should" in name: tests.append(name) return tests def assert_equal(self, expect, value): assert expect == value, "expected '{0}' to equal '{1}'".format(expect, value) ================================================ FILE: test/unit/__init__.py ================================================ ================================================ FILE: test/unit/debug_test.py ================================================ """ get word at cursor """ from FuzzyFilePath.test.tools import TestCase import FuzzyFilePath.query as Query valid_trigger = False class Test(TestCase): def should_set_basepath_to_current_folder(self): Query.reset() Query.build("", { "relative": True, "auto": True }, "current_folder") self.assert_equal(Query.get_base_path(), "current_folder") def should_not_set_basepath_for_absolute_queries(self): Query.reset() Query.build("", { "relative": False, "auto": True }, "current_folder") self.assert_equal(Query.get_base_path(), False) ================================================ FILE: test/unit/get_closest_folder_test.py ================================================ from FuzzyFilePath.test.tools import TestCase from FuzzyFilePath.current_state import get_closest_folder class FolderMock: def __init__(self, directory): self.directory = directory class Test(TestCase): def should_return_nearest_folder(self): folders = [FolderMock("/Users/Spock"), FolderMock("/Users/Spock/Pictures")] result = get_closest_folder("/Users/Spock/Pictures/Uhura", folders) self.assert_equal(result.directory, "/Users/Spock/Pictures") def should_return_valid_folders_only(self): folders = [FolderMock("/Lib"), FolderMock("/Users"), FolderMock("/Users/Spock/Lib")] result = get_closest_folder("/Users/Spock", folders) self.assert_equal(result.directory, "/Users") def should_return_false_if_no_directory_found(self): folders = [FolderMock("/Lib"), FolderMock("/Users/Spock"), FolderMock("/Users/Spock/Lib")] result = get_closest_folder("/Users/Kirk", folders) self.assert_equal(result, False) ================================================ FILE: test/unit/query_test.py ================================================ """ get word at cursor """ from FuzzyFilePath.test.tools import TestCase import FuzzyFilePath.query as Query valid_trigger = False class Test(TestCase): def before_each(self): global valid_trigger Query.reset() valid_trigger = { "auto": True } #validation def should_abort_on_empty_values(self): needle = "" current_folder = "" trigger = {} valid = Query.build(needle, trigger, current_folder) self.assert_equal(valid, False) def should_be_valid_for_auto(self): valid = bool(Query.build("", valid_trigger, "")) self.assert_equal(valid, True) #base path def should_set_basepath_to_current_folder(self): valid_trigger["relative"] = True Query.build("", valid_trigger, "current_folder") self.assert_equal(Query.get_base_path(), "current_folder") def should_set_base_path_for_relative_queries(self): valid_trigger["relative"] = True # !Potential problem: path requires a trailing slash (os.path.dirname) valid_trigger["base_path"] = "base_path/" Query.build("", valid_trigger, "current_folder") self.assert_equal(Query.get_base_path(), "base_path") def should_not_set_basepath_for_absolute_queries(self): valid_trigger["relative"] = False Query.build("", valid_trigger, "current_folder") self.assert_equal(Query.get_base_path(), False) #basepath override by needle def should_prefer_needletype_over_relative_setting_01(self): valid_trigger["relative"] = True Query.build("/absolute", valid_trigger, "current_folder") self.assert_equal(Query.get_base_path(), False) def should_prefer_needletype_over_relative_setting_02(self): valid_trigger["relative"] = False Query.build("../relative", valid_trigger, "current_folder") self.assert_equal(Query.get_base_path(), "current_folder") #basepath override by command def should_prefer_command_over_rel(self): valid_trigger["relative"] = True Query.override_trigger_setting("filepath_type", "absolute") Query.build("../relative", valid_trigger, "current_folder") self.assert_equal(Query.get_base_path(), False) def should_prefer_command_over_abs(self): valid_trigger["relative"] = False Query.override_trigger_setting("filepath_type", "relative") Query.build("/absolute", valid_trigger, "current_folder") self.assert_equal(Query.get_base_path(), "current_folder") #swap rel <-> abs def should_transform_rel_to_abs_query(self): Query.override_trigger_setting("filepath_type", "absolute") # set query to be absolute Query.build("../folder/sub", valid_trigger, "current_folder") # but insert relative path self.assert_equal(Query.get_needle(), "folder/sub") self.assert_equal(Query.get_base_path(), False) def should_transform_abs_to_rel_query(self): Query.override_trigger_setting("filepath_type", "relative") # set query to be relative Query.build("/folder/sub", valid_trigger, "current_folder") # but insert absolute path self.assert_equal(Query.get_needle(), "folder/sub") self.assert_equal(Query.get_base_path(), "current_folder") ================================================ FILE: test/unit/tests.py ================================================ """ Loads all integration tests within this folder - In order to be loaded each test-file must have "_test" appended - Tests are stored and dumped by the file name (without test) """ import os import glob import importlib tests = [] modules = glob.glob(os.path.dirname(__file__) + "/*_test.py") modules = [os.path.basename(f)[:-3] for f in modules] for f in modules: lib = importlib.import_module("FuzzyFilePath.test.unit." + f) tests.append(lib.Test(f[:-5]))