Instantly share code, notes, and snippets.
Created
July 13, 2012 20:23
-
Star
0
(0)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
Save liamcain/3107209 to your computer and use it in GitHub Desktop.
FuzzyFileNav
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Show hidden characters
[ | |
{ "caption": "-" }, | |
{ | |
"caption": "Fuzzy Nav", | |
"command": "fuzzy_file_nav", | |
"args": {"regex_exclude": [".*\\.(DS_Store|svn|git)$"]} | |
}, | |
{ | |
"caption": "Fuzzy Nav Here", | |
"command": "fuzzy_start_from_file", | |
"args": {"regex_exclude": [".*\\.(DS_Store|svn|git)$"]} | |
}, | |
{ "caption": "-"} | |
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Fuzzy File Navigation | |
Copyright (c) 2012 Isaac Muse <[email protected]> | |
""" | |
import sublime | |
import sublime_plugin | |
import os | |
import os.path as path | |
import re | |
PLATFORM = sublime.platform() | |
KILO = 1024 | |
MEGA = 1048576 | |
GIGA = 1073741824 | |
TERA = 1099511627776 | |
HOME = "/some/home/here" | |
class FuzzyEventListener(sublime_plugin.EventListener): | |
def on_activated(self, view): | |
# New window gained activation? Reset fuzzy command state | |
if FuzzyFileNavCommand.active and view.window() and view.window().id() != FuzzyFileNavCommand.win_id: | |
FuzzyFileNavCommand.reset() | |
if FuzzyFileNavCommand.active and FuzzyFileNavCommand.view_id != view.id(): | |
FuzzyFileNavCommand.view_id = view.id() | |
def on_modified(self, view): | |
if FuzzyFileNavCommand.active and FuzzyFileNavCommand.view_id and FuzzyFileNavCommand.view_id == view.id(): | |
sel = view.sel()[0] | |
win = view.window() | |
line_text = view.substr(view.line(sel)) | |
# Go Home | |
m = re.match(r"^(?:(~)|\:(mkdir)|\:(mkfile))", line_text) | |
if m: | |
if m.group(1): | |
FuzzyFileNavCommand.fuzzy_relaod = True | |
win.run_command("fuzzy_file_nav", {"start": HOME, "regex_exclude": FuzzyFileNavCommand.regex_exclude}) | |
elif m.group(2): | |
win.run_command("hide_overlay") | |
FuzzyFileNavCommand.reset() | |
win.run_command("fuzzy_folder_create", {"cwd": FuzzyFileNavCommand.cwd}) | |
elif m.group(3): | |
win.run_command("hide_overlay") | |
FuzzyFileNavCommand.reset() | |
win.run_command("fuzzy_file_create", {"cwd": FuzzyFileNavCommand.cwd}) | |
class FuzzyFileCreateCommand(sublime_plugin.WindowCommand): | |
def run(self, cwd): | |
self.cwd = cwd | |
self.window.show_input_panel( | |
"Create File:", | |
"", | |
self.make, | |
None, | |
None | |
) | |
def make(self, value): | |
name = path.join(self.cwd, value) | |
if path.exists(self.cwd) and not path.exists(name): | |
try: | |
with open(name, "a"): | |
pass | |
self.window.open_file(name) | |
except: | |
sublime.error_message("Could not create %d!" % name) | |
class FuzzyFolderCreateCommand(sublime_plugin.WindowCommand): | |
def run(self, cwd): | |
self.cwd = cwd | |
self.window.show_input_panel( | |
"Make Directory:", | |
"", | |
self.make, | |
None, | |
None | |
) | |
def make(self, value): | |
name = path.join(self.cwd, value) | |
if path.exists(self.cwd) and not path.exists(name): | |
try: | |
os.makedirs(name) | |
except: | |
sublime.error_message("Could not create %d!" % name) | |
class FuzzyStartFromFileCommand(sublime_plugin.TextCommand): | |
def run(self, edit, regex_exclude=[]): | |
# Check if you can retrieve a file name (means it exists on disk). | |
name = self.view.file_name() | |
if name: | |
self.view.window().run_command("fuzzy_file_nav", {"start": path.dirname(name), "regex_exclude": regex_exclude}) | |
class FuzzyFileNavCommand(sublime_plugin.WindowCommand): | |
active = False | |
win_id = None | |
view_id = None | |
regex_exclude = [] | |
fuzzy_relaod = False | |
@classmethod | |
def reset(cls): | |
cls.active = False | |
cls.win_id = None | |
cls.view_id = None | |
def run(self, start=None, regex_exclude=[]): | |
if FuzzyFileNavCommand.active: | |
FuzzyFileNavCommand.active = False | |
self.window.run_command("hide_overlay") | |
FuzzyFileNavCommand.active = True | |
FuzzyFileNavCommand.view_id = None | |
FuzzyFileNavCommand.win_id = self.window.id() | |
FuzzyFileNavCommand.regex_exclude = regex_exclude | |
# Check if a start destination has been given | |
# and ensure it is valid. | |
FuzzyFileNavCommand.cwd = self.get_root_path() if start == None or not path.exists(start) or not path.isdir(start) else unicode(start) | |
# Get and display options. | |
try: | |
self.display_files(FuzzyFileNavCommand.cwd) | |
except: | |
FuzzyFileNavCommand.reset() | |
sublime.error_message(FuzzyFileNavCommand.cwd + "is not accessible!") | |
def get_files(self, cwd): | |
# Get files/drives (windows). | |
files = self.get_drives() if PLATFORM == "windows" and cwd == u"" else os.listdir(cwd) | |
folders = [] | |
documents = [] | |
for f in files: | |
valid = True | |
full_path = path.join(cwd, f) | |
# Check exclusion regex to omit files. | |
if valid: | |
for regex in FuzzyFileNavCommand.regex_exclude: | |
if re.match(regex, full_path): | |
valid = False | |
# Store file/folder info. | |
if valid: | |
if not path.isdir(full_path): | |
documents.append(f) | |
else: | |
folders.append(f + ("\\" if PLATFORM == "windows" else "/")) | |
return [u".."] + sorted(folders) + sorted(documents) | |
def get_root_path(self): | |
# Windows doesn't have a root, so just | |
# return an empty string to represent its root. | |
return u"" if PLATFORM == "windows" else u"/" | |
def display_files(self, cwd): | |
FuzzyFileNavCommand.files = self.get_files(cwd) | |
self.window.show_quick_panel(FuzzyFileNavCommand.files, self.check_selection) | |
def back_dir(self, cwd): | |
prev = path.dirname(path.dirname(cwd)) | |
# On windows, if you try and get the | |
# dirname of a drive, you get the drive. | |
# So if the previous directory is the same | |
# as the current, back out of the drive and | |
# list all drives. | |
return self.get_root_path() if prev == cwd else prev | |
def get_drives(self): | |
# Search through valid drive names and see if they exist. | |
return [unicode(d + ":") for d in "ABCDEFGHIJKLMNOPQRSTUVWXYZ" if path.exists(d + ":")] | |
def check_selection(self, selection): | |
if selection > -1: | |
FuzzyFileNavCommand.fuzzy_relaod = False | |
# The first selection is the "go up a directory" option. | |
FuzzyFileNavCommand.cwd = self.back_dir(FuzzyFileNavCommand.cwd) if selection == 0 else path.join(FuzzyFileNavCommand.cwd, FuzzyFileNavCommand.files[selection]) | |
# Check if the option is a folder or if we are at the root (needed for windows) | |
if (path.isdir(FuzzyFileNavCommand.cwd) or FuzzyFileNavCommand.cwd == self.get_root_path()): | |
try: | |
self.display_files(FuzzyFileNavCommand.cwd) | |
except: | |
# Inaccessible folder try backing up | |
sublime.error_message(FuzzyFileNavCommand.cwd + "is not accessible!") | |
FuzzyFileNavCommand.cwd = self.back_dir(FuzzyFileNavCommand.cwd) | |
self.display_files(FuzzyFileNavCommand.cwd) | |
else: | |
try: | |
self.window.open_file(FuzzyFileNavCommand.cwd) | |
FuzzyFileNavCommand.reset() | |
except: | |
FuzzyFileNavCommand.reset() | |
sublime.error_message(FuzzyFileNavCommand.cwd + "is not accessible!") | |
elif not FuzzyFileNavCommand.fuzzy_relaod: | |
FuzzyFileNavCommand.reset() | |
else: | |
FuzzyFileNavCommand.fuzzy_relaod = False | |
def format_size(self, bytes): | |
bytes = float(bytes) | |
if bytes < KILO: | |
return str(bytes) + ' B' | |
elif bytes < MEGA: | |
return str(round(bytes / KILO, 2)) + ' KB' | |
elif bytes < GIGA: | |
return str(round(bytes / MEGA, 2)) + ' MB' | |
elif bytes < TERA: | |
return str(round(bytes / GIGA, 2)) + ' GB' | |
else: | |
return str(round(bytes / TERA, 2)) + ' TB' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment