Skip to content

Instantly share code, notes, and snippets.

@jbjornson
Last active September 26, 2015 23:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jbjornson/1178613 to your computer and use it in GitHub Desktop.
Save jbjornson/1178613 to your computer and use it in GitHub Desktop.
Display a quick panel with the other files in the directory of the current file
'''
@author Josh Bjornson
This work is licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported License.
To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/3.0/
or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA.
'''
import sublime, sublime_plugin
import glob, os
# Display a quick panel with the other files in the directory of the current file
# { "keys": ["ctrl+shift+o"], "command": "open_file_in_folder"}
# https://gist.github.com/jbjornson/1178613
class OpenFileInFolderCommand(sublime_plugin.WindowCommand):
def run(self):
self.calling_view = self.window.active_view()
if not hasattr(self, 'excluded_extensions'):
settings = sublime.load_settings('Preferences.sublime-settings')
self.excluded_extensions = settings.get('binary_file_patterns') + settings.get('file_exclude_patterns')
# get the path of the file in the active view
current_file = self.window.active_view().file_name()
if not current_file:
current_file = os.getcwd()
self.stack = {}
self.navigate(current_file)
def get_directory(self, current_file):
path = os.path.dirname(current_file) if os.path.isfile(current_file) else current_file
return os.path.normpath(path)
def navigate(self, current_file):
# Iterate over the list of files and add them to the display list
path = self.get_directory(current_file)
dir_listing = glob.glob(os.path.join(path, '*'))
# Filter out the binary and ignored file extensions
for file_path in dir_listing:
extension = '*' + os.path.splitext(file_path)[1].lower()
if extension in self.excluded_extensions:
dir_listing.remove(file_path)
# Build up the file list for display
self.stack[current_file] = []
# Add the parent directory
parent = os.path.abspath(os.path.join(path, os.pardir))
if not os.path.samefile(path, parent):
self.stack[current_file].append([os.pardir, parent])
# Add all the files (aside from the current) in other files in this directory
for (index, file_path) in enumerate(dir_listing):
if self.skip_file(file_path, current_file):
continue
# If this is a sub-folder then decorate the name with an ellipsis
label = os.path.basename(file_path)
if os.path.isdir(file_path):
label += '/'
self.stack[current_file].append([label, file_path])
on_done = lambda i, cwd=path: self.open_selected_file(current_file, i)
on_selected = lambda i, cwd=path: self.show_preview(current_file, i)
self.window.show_quick_panel(self.stack[current_file], on_done, sublime.MONOSPACE_FONT, 0, on_selected)
# os.access blatantly lies and os.stat throws an exception rather than telling me I have no permission
# Apparently is is easier to catch failed access than check the permissions (especially on windows)
def skip_file(self, file_path, current_file):
skip = False
try:
if os.path.samefile(file_path, current_file):
skip = True
except OSError:
skip = True
return skip
def open_selected_file(self, path, selected_index):
if selected_index < 0:
# The user cancelled the action - give the focus back to the "calling" view
self.window.focus_view(self.calling_view)
self.calling_view = None
else:
# If the selected item is a file then open it, otherwise recursively navigate the selected directory
file_path = self.stack[path][selected_index][1]
if os.path.isfile(file_path):
# Open the selected file
self.window.open_file(file_path)
else:
# Navigate the selected directory
sublime.set_timeout_async(lambda s=file_path: self.navigate(s), 0)
def show_preview(self, path, selected_index):
if selected_index >= 0:
file_path = self.stack[path][selected_index][1]
if os.path.isfile(file_path):
self.window.open_file(file_path, sublime.TRANSIENT)
else:
self.window.focus_view(self.calling_view)
@FichteFoll
Copy link

What about a directorys=True option which will display all the directories in the file (at the top, with a trailing "/") and only when True (because now they are alreadylisted but you can't actually open a directory into a view). With "../" to go up a level.
And then reopening the popup with the "new dir" as base.

And what about an option to recursively list all the files from the current directory (the file is in)?

(And what happens when view.file_name() == None? Well, besides the exception that is being raised.)

@jbjornson
Copy link
Author

Added support for recursing into directories and the parent

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment