├── .gitignore ├── Default (Linux).sublime-keymap ├── Default (OSX).sublime-keymap ├── Default (Windows).sublime-keymap ├── Default.sublime-commands ├── File Navigator.py ├── File Navigator.sublime-settings ├── Readme.md └── file_navigator ├── __init__.py └── tools.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *.DS_Store 3 | 4 | .build -------------------------------------------------------------------------------- /Default (Linux).sublime-keymap: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "keys": ["ctrl+shift+o"], 4 | "command": "file_navigator" 5 | }, 6 | { 7 | "keys": ["tab"], 8 | "command": "file_navigator_do_directory", 9 | "context": [{"key": "file_navigator_do_directory"}] 10 | }, 11 | { 12 | "keys": ["ctrl+."], 13 | "command": "file_navigator_toggel_hidden_files", 14 | "context": [{"key": "file_navigator_toggel_hidden_files"}] 15 | } 16 | ] 17 | -------------------------------------------------------------------------------- /Default (OSX).sublime-keymap: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "keys": ["super+shift+o"], 4 | "command": "file_navigator" 5 | }, 6 | { 7 | "keys": ["tab"], 8 | "command": "file_navigator_do_directory", 9 | "context": [{"key": "file_navigator_do_directory"}] 10 | }, 11 | { 12 | "keys": ["super+."], 13 | "command": "file_navigator_toggel_hidden_files", 14 | "context": [{"key": "file_navigator_toggel_hidden_files"}] 15 | } 16 | ] 17 | -------------------------------------------------------------------------------- /Default (Windows).sublime-keymap: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "keys": ["ctrl+shift+o"], 4 | "command": "file_navigator" 5 | }, 6 | { 7 | "keys": ["tab"], 8 | "command": "file_navigator_do_directory", 9 | "context": [{"key": "file_navigator_do_directory"}] 10 | }, 11 | { 12 | "keys": ["ctrl+."], 13 | "command": "file_navigator_toggel_hidden_files", 14 | "context": [{"key": "file_navigator_toggel_hidden_files"}] 15 | } 16 | ] 17 | -------------------------------------------------------------------------------- /Default.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "File Navigator: Open", 4 | "command": "file_navigator" 5 | }, 6 | { 7 | "caption": "File Navigator: Reset History", 8 | "command": "file_navigator_reset_history" 9 | } 10 | ] 11 | -------------------------------------------------------------------------------- /File Navigator.py: -------------------------------------------------------------------------------- 1 | import sublime, sublime_plugin 2 | 3 | import time, os.path, shutil, subprocess 4 | 5 | try: 6 | from Default.send2trash import send2trash 7 | from .file_navigator.tools import history_items, list_items, show_input_panel, show_quick_panel 8 | except (ImportError, ValueError): 9 | from file_navigator.tools import history_items, list_items, show_input_panel, show_quick_panel 10 | 11 | import sys 12 | package_dir = sublime.packages_path() + os.sep + "Default" 13 | if package_dir not in sys.path: 14 | sys.path += [package_dir] 15 | from send2trash import send2trash 16 | 17 | CHOOSE_ROOT = 0 18 | NAVIGATOR = 1 19 | NAVIGATOR_PASTE = 2 20 | DO_FILE = 3 21 | DO_DIR = 4 22 | 23 | class FileNavigatorListener(sublime_plugin.EventListener): 24 | 25 | def on_activated(self, view): 26 | 27 | if FileNavigatorCommand.active and view.window() and view.window().id() != FileNavigatorCommand.window_id: 28 | FileNavigatorCommand.reset() 29 | 30 | if FileNavigatorCommand.active and FileNavigatorCommand.view_id != view.id(): 31 | FileNavigatorCommand.view_id = view.id() 32 | 33 | def on_query_context(self, view, key, operator, operand, match_all): 34 | 35 | # Check if file navigator is active 36 | if FileNavigatorCommand.active and FileNavigatorCommand.view_id == view.id(): 37 | if key in ["file_navigator_do_directory", "file_navigator_toggel_hidden_files"]: 38 | return True 39 | 40 | 41 | class FileNavigatorCommand(sublime_plugin.WindowCommand): 42 | 43 | active = False 44 | cwd = None 45 | view_id = None 46 | window_id = None 47 | 48 | navigator_status = None 49 | 50 | block_do_directory = False 51 | keep_settings = False 52 | show_hidden_files = False 53 | 54 | @classmethod 55 | def reset(self): 56 | self.active = False 57 | cwd = None 58 | view_id = None 59 | window_id = None 60 | 61 | def run(self, path = None, do_dir = None): 62 | 63 | # Hide overlay before the next run 64 | self.window.run_command("hide_overlay") 65 | 66 | self.cls = FileNavigatorCommand 67 | self.cls.active = True 68 | self.cls.window_id = self.window.id() 69 | 70 | self.item_buffer = [] 71 | 72 | if not path: 73 | self.choose_root() 74 | elif do_dir: 75 | self.do_dictionary(path) 76 | else: 77 | self.navigator(path) 78 | 79 | def choose_root(self, roots = None): 80 | 81 | # Set navigator status 82 | self.cls.navigator_status = CHOOSE_ROOT 83 | 84 | # Find roots 85 | roots = roots if roots else self.find_root() 86 | 87 | # Sort roots 88 | roots = sorted(roots) 89 | 90 | # Find command prefix 91 | prefix = os.path.commonprefix(roots).rpartition(os.sep)[0] 92 | items = [[item[len(prefix)+1:], os.path.dirname(item)] for item in roots] 93 | # items = [[os.path.basename(item), os.path.dirname(item)] for item in roots] 94 | 95 | def on_done(i): 96 | if i < 0: 97 | self.cls.reset() 98 | else: 99 | self.navigator(roots[i]) 100 | 101 | if not items: 102 | sublime.status_message("No Root Elements") 103 | elif len(items) == 1: 104 | on_done(0) 105 | else: 106 | show_quick_panel(self.window, items, on_done) 107 | 108 | def find_root(self): 109 | items = [] 110 | 111 | # Search for root of the different views 112 | for view in self.window.views(): 113 | if view.file_name(): 114 | item = os.path.dirname(view.file_name()) 115 | if os.path.isdir(item) and item not in items: 116 | items += [item] 117 | 118 | # Search for the root for the window 119 | for item in self.window.folders(): 120 | if item and os.path.isdir(item) and item not in items: 121 | items += [item] 122 | 123 | return items 124 | 125 | def navigator(self, path): 126 | 127 | items = [{"name": ".."}] 128 | if self.item_buffer: 129 | items += [{"name": "Paste"}] 130 | if len(self.item_buffer) == 1: 131 | items += [{"name": "Paste As ..."}] 132 | 133 | # List items in folder 134 | items += list_items(path, len(self.item_buffer) > 0, self.cls.show_hidden_files) 135 | 136 | # block_do_directory on paste 137 | if self.item_buffer: 138 | self.cls.navigator_status = NAVIGATOR_PASTE 139 | else: 140 | self.cls.navigator_status = NAVIGATOR 141 | 142 | # Set current working directory 143 | self.cls.cwd = path 144 | 145 | def on_done(i): 146 | if i < 0: 147 | if not self.cls.keep_settings: 148 | self.cls.reset() 149 | self.cls.keep_settings = False 150 | # Enclosing Directory 151 | elif i == 0: 152 | self.navigator(os.path.dirname(path)) 153 | # Paste item if item buffer 154 | elif i == 1 and self.item_buffer: 155 | self.do_paste(path); 156 | elif i == 2 and len(self.item_buffer) == 1: 157 | self.do_paste_as(path); 158 | # Restart navigator if the selected item is a dir, or file action on selecting a file 159 | elif items[i]["is_dir"]: 160 | self.navigator(items[i]["path"]) 161 | else: 162 | self.do_file(items[i]["path"]) 163 | 164 | if items: 165 | show_quick_panel(self.window, [item["name"] for item in items], on_done) 166 | else: 167 | sublime.status_message("No Items in %s!!!" % path) 168 | 169 | def do_dictionary(self, path): 170 | 171 | # Set navigator status 172 | self.cls.navigator_status = DO_DIR 173 | 174 | def on_done(i): 175 | if i < 0: 176 | if not self.cls.keep_settings: 177 | self.cls.reset() 178 | self.cls.keep_settings = False 179 | # Go back to directory 180 | elif i == 0: 181 | self.navigator(path) 182 | elif i == 1: 183 | self.do_new_directory(path) 184 | elif i == 2: 185 | self.do_new_file(path) 186 | elif i == 3: 187 | self.do_open_folder(path) 188 | elif i == 4: 189 | self.do_rename(path) 190 | elif i == 5: 191 | self.do_copy(path) 192 | elif i == 6: 193 | self.do_move(path) 194 | elif i == 7: 195 | self.do_delete(path) 196 | 197 | # Save dir_name 198 | dir_name = os.path.basename(path) 199 | 200 | items = [["Back", "Go back to Directory content"]] 201 | items += [["New Directory", "Create a new Directory in \"%s\"" % dir_name]] 202 | 203 | items += [["New File", "Create a new File in \"%s\"" % dir_name]] 204 | items += [["Open", "Open \"%s\" outside of Sublime Text" % dir_name]] 205 | items += [["Rename", "Rename \"%s\"" % dir_name]] 206 | items += [["Copy To ...", "Copy \"%s\" to a different location" % dir_name]] 207 | items += [["Move To ...", "Move \"%s\" to a different location" % dir_name]] 208 | items += [["Delete", "Delete \"%s\"" % dir_name]] 209 | show_quick_panel(self.window, items, on_done) 210 | 211 | def do_new_file(self, path): 212 | 213 | # Reset FileNavigatorCommand 214 | self.cls.reset() 215 | 216 | def on_done(file_name): 217 | file_path = os.path.join(path, file_name) 218 | if os.path.exists(file_path): 219 | sublime.error_message('File already exists:\n%s' % file_path) 220 | else: 221 | with open(file_path, 'w') as f: 222 | pass 223 | self.window.open_file(file_path) 224 | 225 | show_input_panel(self.window, "New file name:", '', on_done) 226 | 227 | def do_new_directory(self, path): 228 | 229 | # Reset FileNavigatorCommand 230 | self.cls.reset() 231 | 232 | def on_done(dir_name): 233 | # Reset FileNavigatorCommand 234 | FileNavigatorCommand.reset() 235 | 236 | dir_path = os.path.join(path, dir_name) 237 | if os.path.exists(dir_path): 238 | sublime.error_message('Directory already exists:\n%s' % dir_path) 239 | else: 240 | os.mkdir(dir_path) 241 | 242 | show_input_panel(self.window, "New directory name:", '', on_done) 243 | 244 | def do_file(self, path): 245 | 246 | # Set navigator status 247 | self.cls.navigator_status = DO_FILE 248 | 249 | def on_done(i): 250 | if i < 0: 251 | if not self.cls.keep_settings: 252 | self.cls.reset() 253 | self.cls.keep_settings = False 254 | # Go back to directory 255 | elif i == 0: 256 | self.navigator(os.path.dirname(path)) 257 | elif i == 1: 258 | self.do_open(path) 259 | elif i == 2: 260 | self.do_rename(path) 261 | elif i == 3: 262 | self.do_copy(path) 263 | elif i == 4: 264 | self.do_move(path) 265 | elif i == 5: 266 | self.do_delete(path) 267 | 268 | # Save dir_name 269 | file_name = os.path.basename(path) 270 | 271 | items = [["..", "Enclosing Folder"]] 272 | 273 | items += [["Open", "Open \"%s\" in Sublime Text" % file_name]] 274 | items += [["Rename", "Rename \"%s\"" % file_name]] 275 | items += [["Copy To ...", "Copy \"%s\" to a different location" % file_name]] 276 | items += [["Move To ...", "Move \"%s\" to a different location" % file_name]] 277 | items += [["Delete", "Delete \"%s\"" % file_name]] 278 | 279 | show_quick_panel(self.window, items, on_done) 280 | 281 | def do_open(self, path): 282 | 283 | # Reset FileNavigatorCommand 284 | self.cls.reset() 285 | 286 | self.window.open_file(path) 287 | 288 | def do_open_folder(self, path): 289 | 290 | # Reset FileNavigatorCommand 291 | self.cls.reset() 292 | 293 | if sublime.platform() == "windows": 294 | subprocess.call(["explorer", path]) 295 | elif sublime.platform() == "osx": 296 | subprocess.call(["open", path]) 297 | elif sublime.platform() == "linux": 298 | subprocess.call(["xdg-open", path]) 299 | 300 | def do_rename(self, path): 301 | 302 | # Reset FileNavigatorCommand 303 | self.cls.reset() 304 | 305 | # Save source name 306 | source_name = os.path.basename(path) 307 | 308 | def on_done(target_name): 309 | target_path = path[:-len(source_name)] + target_name 310 | shutil.move(path, target_path) 311 | sublime.status_message("%s renamed to %s" % (source_name, target_name)) 312 | 313 | show_input_panel(self.window, "Rename:", source_name, on_done) 314 | 315 | def do_delete(self, path): 316 | 317 | # Reset FileNavigatorCommand 318 | self.cls.reset() 319 | 320 | # Save source name 321 | source_name = os.path.basename(path) 322 | 323 | if sublime.ok_cancel_dialog("Delete %s?" % source_name, "Delete"): 324 | send2trash(path) 325 | sublime.status_message("%s deleted" % source_name) 326 | 327 | 328 | def do_move(self, path): 329 | roots = self.find_root() 330 | 331 | # add history_items 332 | roots += [item["path"] for item in history_items()] 333 | 334 | self.item_buffer = [{"file_path": path, "file_name": os.path.basename(path), "type": "move"}] 335 | self.choose_root(list(set(roots))) 336 | 337 | def do_copy(self, path): 338 | roots = self.find_root() 339 | 340 | # add history_items 341 | roots += [item["path"] for item in history_items()] 342 | 343 | self.item_buffer = [{"file_path": path, "file_name": os.path.basename(path), "type": "copy"}] 344 | self.choose_root(list(set(roots))) 345 | 346 | def do_paste_as(self, path): 347 | 348 | # Save source name 349 | source_name = self.item_buffer[0]["file_name"] 350 | 351 | def on_done(target_name): 352 | self.item_buffer[0]["file_name"] = target_name 353 | self.do_paste(path) 354 | 355 | show_input_panel(self.window, "Paste As:", source_name, on_done) 356 | 357 | def do_paste(self, path): 358 | 359 | # Reset FileNavigatorCommand 360 | self.cls.reset() 361 | 362 | # Load settings 363 | s = sublime.load_settings("File Navigator.sublime-settings") 364 | cache_timeout = s.get("cache_timeout", 24) 365 | 366 | # add history_items 367 | items = history_items() 368 | items += [{"path": path, "rtime": int(time.time())}] 369 | 370 | # Add history items 371 | s = sublime.load_settings("File Navigator.history") 372 | s.set("items", items) 373 | sublime.save_settings("File Navigator.history") 374 | 375 | for item in self.item_buffer: 376 | try: 377 | if item["type"] == "move": 378 | shutil.move(item["file_path"], os.path.join(path, item["file_name"])) 379 | elif item["type"] == "copy": 380 | if os.path.isdir(item["file_path"]): 381 | shutil.copytree(item["file_path"], os.path.join(path, item["file_name"])) 382 | else: 383 | shutil.copy(item["file_path"], os.path.join(path, item["file_name"])) 384 | except Exception as e: 385 | pass 386 | 387 | sublime.status_message("%d paste in %s" % (len(self.item_buffer), path)) 388 | 389 | 390 | class FileNavigatorToggelHiddenFilesCommand(sublime_plugin.WindowCommand): 391 | 392 | def run(self): 393 | 394 | if FileNavigatorCommand.navigator_status == NAVIGATOR: 395 | # Set show_hidden_files for the next run 396 | FileNavigatorCommand.show_hidden_files = not FileNavigatorCommand.show_hidden_files 397 | sublime.status_message("Show all available files" if FileNavigatorCommand.show_hidden_files else "Hide system/hidden files") 398 | 399 | FileNavigatorCommand.keep_settings = True 400 | self.window.run_command("file_navigator", {"path": FileNavigatorCommand.cwd}) 401 | 402 | 403 | class FileNavigatorDoDirectory(sublime_plugin.WindowCommand): 404 | 405 | def run(self): 406 | 407 | if FileNavigatorCommand.navigator_status == CHOOSE_ROOT: 408 | pass 409 | 410 | elif FileNavigatorCommand.navigator_status == NAVIGATOR: 411 | FileNavigatorCommand.keep_settings = True 412 | self.window.run_command("file_navigator", {"do_dir": True, "path": FileNavigatorCommand.cwd}) 413 | 414 | elif FileNavigatorCommand.navigator_status in [DO_DIR, DO_FILE]: 415 | FileNavigatorCommand.keep_settings = True 416 | self.window.run_command("file_navigator", {"path": FileNavigatorCommand.cwd}) 417 | 418 | class FileNavigatorResetHistory(sublime_plugin.WindowCommand): 419 | 420 | def is_enabled(self): 421 | try: 422 | return os.path.isfile(os.path.join(os.path.join(sublime.cache_path(), "File Navigator", "History.json"))) 423 | except Exception as e: 424 | return False 425 | 426 | def run(self): 427 | try: 428 | if sublime.ok_cancel_dialog("Delete File Navigator History?", "Delete"): 429 | os.remove(os.path.join(sublime.cache_path(), "FileNavigator", "History.json")) 430 | except Exception as e: 431 | pass 432 | -------------------------------------------------------------------------------- /File Navigator.sublime-settings: -------------------------------------------------------------------------------- 1 | { 2 | // Patterns of files to exclude at all 3 | "exclude_patterns": [ ".DS_Store" ], 4 | 5 | // By default, files hidden by the system are hidden in as well (files that 6 | // start with "." in Linux\Unix and files with the hidden attribute on windows) 7 | "show_hidden_files": false, 8 | 9 | // Patterns of files to consider it as hidden files 10 | "hidden_patterns": [".git", ".gitignore", ".svn"], 11 | 12 | // By default File Navigator uses a cache to save the most recent used folders 13 | // after moving/copying a file. Here you can define a certain time for it (in hours) 14 | "cache_timeout": 24 15 | } -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # File Navigator for Sublime Text 2/3 2 | 3 | This plugin lets You quickly navigate through your project and perform basic file operations just using your keyboard (something that many of us missed when moving from VIM). 4 | 5 | Things you can do with this plugin are: 6 | 7 | - create new files and directories 8 | - copy/move/paste existing files/directories 9 | - rename existing files 10 | - delete existing files 11 | 12 | All of the operations above are done using the excellent sublime quick panel window. This means you get all the usual benefits of that including fuzzy name matching. 13 | 14 | ## Usage 15 | 16 | * `super+shift+o` on OSX or `ctrl+shift+o` on Windows/Linux shows a quick panel with directories related to the current open files or window. 17 | 18 | * `tab` shows the directory actions for the current selected folder 19 | 20 | * `super+.` on OSX or `ctrl+.` on Windows/Linux hide/shows the hidden files temporary, just can adjust this in the settings. 21 | 22 | ## Screenshots 23 | 24 | ![Navigator](https://raw.github.com/wiki/Chris---/SublimeText-File-Navigator/navigator.jpg) 25 | 26 | ![Navigator - File Actions](https://raw.github.com/wiki/Chris---/SublimeText-File-Navigator/file.jpg) 27 | 28 | ![Navigator - Directory Actions](https://raw.github.com/wiki/Chris---/SublimeText-File-Navigator/directory.jpg) 29 | 30 | ![Navigator - Paste](https://raw.github.com/wiki/Chris---/SublimeText-File-Navigator/paste.jpg) 31 | 32 | ## Installation 33 | 34 | ### Using Package Control: 35 | 36 | * Bring up the Command Palette (Command+Shift+P on OS X, Control+Shift+P on Linux/Windows). 37 | * Select Package Control: Install Package. 38 | * Select File Navigator to install. 39 | 40 | ### Not using Package Control: 41 | 42 | * Save files to the `Packages/File Navigator` directory, then relaunch Sublime: 43 | * Linux: `~/.config/sublime-text-2|3/Packages/File Navigator` 44 | * Mac: `~/Library/Application Support/Sublime Text 2|3/Packages/File Navigator` 45 | * Windows: `%APPDATA%/Sublime Text 2|3/Packages/File Navigator` 46 | 47 | ## Donating 48 | 49 | Support this project via [gittip][] or [paypal][]. 50 | 51 | [![Support via Gittip](https://rawgithub.com/chris---/Donation-Badges/master/gittip.jpeg)][gittip] [![Support via PayPal](https://rawgithub.com/chris---/Donation-Badges/master/paypal.jpeg)][paypal] 52 | 53 | [gittip]: https://www.gittip.com/Chris--- 54 | [paypal]: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=ZWZCJPFSZNXEW 55 | 56 | ## Code base 57 | The initial idea of this package came from by Tomasz Grabowski. Thanks for that :) 58 | 59 | ## License 60 | 61 | All files in this package is licensed under the MIT license. 62 | 63 | Copyright (c) 2013 Chris 64 | 65 | Permission is hereby granted, free of charge, to any person obtaining a copy 66 | of this software and associated documentation files (the "Software"), to deal 67 | in the Software without restriction, including without limitation the rights 68 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 69 | copies of the Software, and to permit persons to whom the Software is 70 | furnished to do so, subject to the following conditions: 71 | 72 | The above copyright notice and this permission notice shall be included in 73 | all copies or substantial portions of the Software. 74 | 75 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 76 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 77 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 78 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 79 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 80 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 81 | THE SOFTWARE. -------------------------------------------------------------------------------- /file_navigator/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csch0/SublimeText-File-Navigator/d41ee128109318b19204214ba1e7d40dd22c4423/file_navigator/__init__.py -------------------------------------------------------------------------------- /file_navigator/tools.py: -------------------------------------------------------------------------------- 1 | import sublime, sublime_plugin 2 | 3 | import time, fnmatch, os 4 | 5 | if sublime.platform() == "windows": 6 | import ctypes 7 | 8 | def list_items(path, dirs_only = False, show_hidden_files = False): 9 | s = sublime.load_settings("File Navigator.sublime-settings") 10 | exclude_patterns = s.get("exclude_patterns", []) 11 | hidden_patterns = s.get("hidden_patterns", []) 12 | show_hidden_files = show_hidden_files if show_hidden_files else s.get("show_hidden_files", False) 13 | # 14 | items = [] 15 | for item in os.listdir(path): 16 | # Build path of file 17 | item_path = os.path.join(path, item) 18 | 19 | # Check file_exclude_patterns and folder_exclude_patterns 20 | if any([fnmatch.fnmatch(item.lower(), p.lower()) for p in exclude_patterns]): 21 | continue 22 | 23 | # Check hidden files 24 | if not show_hidden_files: 25 | 26 | if any([fnmatch.fnmatch(item.lower(), p.lower()) for p in hidden_patterns]): 27 | continue 28 | 29 | # Check for hidden attribute etc 30 | if sublime.platform() in ["osx", "linux"] and item[0] == ".": 31 | continue 32 | elif sublime.platform() == "windows": 33 | attrs = ctypes.windll.kernel32.GetFileAttributesW(item_path) 34 | if attrs != -1 and bool(attrs & 2): 35 | continue 36 | 37 | if os.path.isdir(item_path): 38 | items += [{"name":item + "/", "desciption": "Open Directory", "path": item_path, "is_dir": True}] 39 | else: 40 | items += [{"name":item, "desciption": "Rename/Delete/Copy/Move File", "path": item_path, "is_dir": False}] 41 | 42 | # Filter dirs, if required 43 | if dirs_only: 44 | items = [item for item in items if item["is_dir"]] 45 | return items 46 | 47 | 48 | def show_input_panel(window, caption, initial_text, on_done, on_change = None, on_cancel = None): 49 | sublime.set_timeout(lambda: window.show_input_panel(caption, initial_text, on_done, on_change, on_cancel), 0) 50 | 51 | 52 | def show_quick_panel(window, items, on_done, selected_index = -1): 53 | sublime.set_timeout(lambda: window.show_quick_panel(items, on_done, sublime.MONOSPACE_FONT, selected_index), 0) 54 | 55 | 56 | def history_items(): 57 | # Load settings 58 | s = sublime.load_settings("File Navigator.sublime-settings") 59 | cache_timeout = s.get("cache_timeout", 24) 60 | 61 | s = sublime.load_settings("File Navigator.history") 62 | 63 | # Check for cache_timeout 64 | now = time.time() 65 | items = [] 66 | for item in s.get("items", []): 67 | try: 68 | if now - int(item["rtime"]) < cache_timeout * 3600: 69 | items += [item] 70 | except Exception: 71 | pass 72 | return items --------------------------------------------------------------------------------