def _get_pane_info(pane): settings = load_json('Panes.json', default=[]) default = {'show_hidden_files': False} pane_index = pane.window.get_panes().index(pane) for _ in range(pane_index - len(settings) + 1): settings.append(default.copy()) return settings[pane_index]
def open_native_file_manager(dir_path): settings = load_json('Core Settings.json', default={}) app = settings.get('native_file_manager', {}) if app: _run_app_from_setting(app, dir_path) else: xdg_open = which('xdg-open') if xdg_open: app = {'args': [xdg_open, '{curr_dir}']} _run_app_from_setting(app, dir_path) if _is_gnome_based(): try: fpl = \ check_output(['dconf', 'read', _FOCUS_PREVENTION_LEVEL]) except FileNotFoundError as dconf_not_installed: pass else: if fpl in (b'', b'1\n'): show_status_message( 'Hint: If your OS\'s file manager opened in the ' 'background, click ' '<a href="https://askubuntu.com/a/594301">here</a>.', timeout_secs=10 ) else: show_alert( 'Could not determine the Popen(...) arguments for opening the ' 'native file manager. Please configure the ' '"native_file_manager" dictionary in "Core Settings.json" ' 'similarly to what\'s explained ' '<a href="https://fman.io/docs/terminal?s=f">here</a>.' )
def _get_handler_for_archive(self, file_path): settings = load_json('Core Settings.json', default={}) archive_types = sorted(settings.get('archive_handlers', {}).items(), key=lambda tpl: -len(tpl[0])) for suffix, scheme in archive_types: if file_path.lower().endswith(suffix): return scheme
def get_current_tortoisesvnproc_install_path(): settings = load_json(_TORTOISEPROCCONFIGFILE, default={'path': _TORTOISEPROCPATHDEFAULT}) if settings['path'] and exists(as_url(settings['path'])): return settings['path'] else: return _TORTOISEPROCPATHDEFAULT
def get_current_sublime_install_path(): settings = load_json(_SUBLIMETEXTCONFIGFILE, default={'path': _SUBLIMETEXTPATHDEFAULT}) if settings['path'] and exists(as_url(settings['path'])): return settings['path'] else: return _SUBLIMETEXTPATHDEFAULT
def __call__(self): choice = show_alert( 'Are you sure you want to delete the FTP connection history?', buttons=YES | NO, default_button=NO) if choice == YES: history = \ load_json('FTP History.json', default={}, save_on_quit=True) history.clear()
def __call__(self): result = show_quicksearch(self._get_items) if result and result[1]: # Fetch bookmarks to connect to the default path bookmarks = \ load_json('FTP Bookmarks.json', default={}) bookmark = bookmarks[result[1]] url = urlparse(result[1])._replace(path=bookmark[1]).geturl() self.pane.set_path(url)
def _get_bookmark(self, url): u = urlparse(url) url_without_path = u._replace(path='').geturl() bookmarks = \ load_json('FTP Bookmarks.json', default={}) # Replace base URL -if found in bookmarks-, keep the same path if url_without_path in bookmarks: u = urlparse(bookmarks[url_without_path][0])._replace(path=u.path) return u
def __call__(self): result = show_quicksearch(self._get_items) if result and result[1]: choice = show_alert('Are you sure you want to delete "%s"' % (result[1], ), buttons=YES | NO, default_button=NO) if choice == YES: bookmarks = \ load_json('FTP Bookmarks.json', default={}, save_on_quit=True) bookmarks.pop(result[1], None)
def on_path_changed(self): url = self.pane.get_path() if not is_ftp(url): return scheme, path = splitscheme(url) if not path: # XXX avoid storing URLs with empty path return history = \ load_json('FTP History.json', default={}, save_on_quit=True) history[url] = history.get(url, 0) + 1
def _get_items(self, query): bookmarks = \ load_json('FTP Bookmarks.json', default={}) for item in sorted(bookmarks.keys()): try: index = item.lower().index(query) except ValueError: continue else: highlight = range(index, index + len(query)) yield QuicksearchItem(item, highlight=highlight)
def show_selected_files(self, cfg): panes = self.pane.window.get_panes() pane_id = panes.index(self.pane) cfg_show_hidden_files = load_json( 'Panes.json')[pane_id]['show_hidden_files'] selected = self.pane.get_selected_files() dir_folders = 0 dir_files = 0 dir_filesize = 0 if selected: if cfg_show_hidden_files: for f in selected: if is_dir(f): dir_folders += 1 else: dir_files += 1 dir_filesize += query(f, 'size_bytes') else: for f in selected: if not is_hidden(as_path(f)): if is_dir(f): dir_folders += 1 else: dir_files += 1 dir_filesize += query(f, 'size_bytes') bc = ByteConverter(dir_filesize) bcc = str(bc.calc()) jFd = cfg['Justify']['folder'] jFl = cfg['Justify']['file'] jSz = cfg['Justify']['size'] dir_foldK = "{0:,}".format(dir_folders) dir_fileK = "{0:,}".format(dir_files) statusbar = "Selected* " if dir_folders > 0: statusbar += "Dirs: " + dir_foldK.rjust(jFd, ' ') + " " if dir_folders <= 9999: statusbar += " " else: statusbar += " " + ''.rjust(jFd, ' ') + " " if dir_files > 0: statusbar += "Files: " + dir_fileK.rjust(jFl, ' ') + " " if dir_files <= 9999: statusbar += " " else: statusbar += " " + ''.rjust(jFl, ' ') + " " statusbar += "∑ Size: " + bcc.rjust(jSz, ' ') + " " show_status_message(statusbar) else: StatusBarExtended.refresh(self, cfg)
def __call__(self): keybindings_json = load_json('Key Bindings.json') keybindings_output = "" for keybind in keybindings_json: command = str(keybind['command'].capitalize().replace('_', ' ')) key = str(keybind['keys']).replace('[\'', '').replace('\']', '') tab = "\t" tab_num = 1 keybindings_output += key + (tab * tab_num) + " = " + command + "\n" show_alert(keybindings_output)
def _get_default_recipient(self): config = load_json(CONFIG_FILE_NAME, default={}) if config and "default_recipient" in config: return config["default_recipient"] else: default_recipient, ok = show_prompt( 'First run - please enter default recipient') config['default_recipient'] = default_recipient save_json(CONFIG_FILE_NAME, config) return default_recipient
def _GetScriptVars(): # # Get the scripts directory. # scriptVars = load_json("LaunchScript.json") if scriptVars is None: scriptVars = dict() scriptVars['show_output'] = True scriptVars['directory'] = os.path.expanduser('~/bin') scriptVars['local_shell'] = os.path.expanduser('~/.bashrc') scriptVars['command_line_history'] = ['ls -la'] save_json("LaunchScript.json", scriptVars) return(scriptVars)
def _get_items(self, query): bookmarks = \ load_json('FTP History.json', default={}) for item, _ in sorted(bookmarks.items(), key=itemgetter(1), reverse=True): try: index = item.lower().index(query) except ValueError: continue else: highlight = range(index, index + len(query)) yield QuicksearchItem(item, highlight=highlight)
def _get_foobar2000_exe_path(self): config = load_json(CONFIG_FILE_NAME, default={}) if config and "foobar2000_exe_path" in config: return config["foobar2000_exe_path"] selected_foobar2000_exe_path = show_file_open_dialog("First use configuration: Please locate your foobar2000 executable.", DEFAULT_FOOBAR2000_EXECUTABLE_PATH, "*.exe") if selected_foobar2000_exe_path: config['foobar2000_exe_path'] = selected_foobar2000_exe_path save_json(CONFIG_FILE_NAME, config) return selected_foobar2000_exe_path return None
def __call__(self): selected_files = self.pane.get_selected_files() if len(selected_files) >= 1 or (len(selected_files) == 0 and self.get_chosen_files()): if len(selected_files) == 0 and self.get_chosen_files(): selected_files.append(self.get_chosen_files()[0]) file = as_human_readable(selected_files[0]) if(os.path.exists(file)): contents = '' npdata = load_json('CopyToNotePad.json') if npdata is None: npdata = dict() npdata['number'] = 3 npdata['save'] = 'a' save_json('CopyToNotePad.json', npdata) with open(file, 'r') as content_file: contents = content_file.read() headers = {'Content-Type': 'application/json'} requests.put('http://localhost:9978/api/note/' + str(npdata['number']) + '/' + npdata['save'], headers=headers, data=json.dumps({"note": contents}))
def __call__(self): global DBDATA show_status_message('NotePad (A)ppend or Over(w)rite') npdata = load_json('CopyToNotePad.json') if npdata is None: npdata = dict() npdata['number'] = 3 npdata['save'] = 'a' npappend, result = show_prompt( "The 'a'ppend or 'w'rite:") if not npappend: npappend = 'a' npappend = npappend.lower() if (npappend != 'a') and (npappend != 'w'): npappend = 'a' npdata['save'] = npappend save_json('CopyToNotePad.json', npdata) clear_status_message()
def __call__(self): url = self.pane.get_path() if not is_ftp(url): url = 'ftp[s]://user[:password]@other.host[:port]/some_dir' url, ok = show_prompt('New FTP bookmark, please enter the URL', default=url) if not (url and ok): return if not is_ftp(url): show_alert('URL must include any of the following schemes: ' 'ftp://, ftps://') return bookmarks = \ load_json('FTP Bookmarks.json', default={}, save_on_quit=True) # XXX URL is split in `(base, path)` to allow setting a default path u = urlparse(url) base = alias = u._replace(path='').geturl() path = u.path if base in bookmarks: # XXX if base URL points to an alias, resolve to an existing URL base = bookmarks[base][0] if path and path.strip('/'): alias += '-'.join(path.split('/')) alias, ok = show_prompt( 'Please enter an alias (will override aliases with the same name)', default=alias) if not (alias and ok): return if not is_ftp(alias): # XXX alias must include the FTP scheme scheme, _ = splitscheme(base) alias = scheme + alias if urlparse(alias).path: show_alert('Aliases should not include path information') return bookmarks[alias] = (base, path)
def __call__(self): global DBDATA show_status_message('NotePad Number') npdata = load_json('CopyToNotePad.json') if npdata is None: npdata = dict() npdata['number'] = 3 npdata['save'] = 'a' npnum, result = show_prompt( "The NotePad Number to use:") if not npnum: npnum = 3 else: npnum = int(npnum) if npnum < 1: npnum = 1 elif npnum > 9: npnum = 9 npdata['number'] = npnum save_json('CopyToNotePad.json', npdata) clear_status_message()
def open_terminal_in_directory(dir_path): settings = load_json('Core Settings.json', default={}) app = settings.get('terminal', {}) if app: _run_app_from_setting(app, dir_path) else: alternatives = [ 'x-terminal-emulator', # Debian-based 'konsole' # KDE ] for alternative in alternatives: binary = which(alternative) if binary: app = {'args': [binary], 'cwd': '{curr_dir}'} _run_app_from_setting(app, dir_path) break else: show_alert( 'Could not determine the Popen(...) arguments for opening the ' 'terminal. Please configure the "terminal" dictionary in ' '"Core Settings.json" as explained ' '<a href="https://fman.io/docs/terminal?s=f">here</a>.' )
from fman import DirectoryPaneCommand, show_alert, show_prompt, load_json, save_json, YES, NO from fman.fs import is_dir, exists from fman.url import splitscheme, as_url, as_human_readable from subprocess import DEVNULL, Popen import os import shlex _TORTOISEPROCPATHDEFAULT = 'C:/Program Files/TortoiseSVN/bin/TortoiseProc.exe' _TORTOISEPROCCONFIGFILE = 'TortoiseSVNHelper Config.json' _TORTOISEPROCPATH = '' settings = load_json(_TORTOISEPROCCONFIGFILE, default={'path': _TORTOISEPROCPATHDEFAULT}) if settings['path'] and exists(as_url(settings['path'])): _TORTOISEPROCPATH = settings['path'] else: _TORTOISEPROCPATH = _TORTOISEPROCPATHDEFAULT class SVNSwtich(DirectoryPaneCommand): aliases = ('Svn: Switch', 'SVN: SWITCH') def __call__(self): url = self.pane.get_path() scheme, path = splitscheme(url) paths = [] paths.append(as_url(path))
def loadConfig(cls): """Check StatusBarExtended.json for consistency/completeness, restore defaults on fail""" msg_t = cls.msgTimeout if hasattr(cls, 'locked_update'): show_status_message( "StatusBarExtended: waiting for the config files to be updated, try again later..." ) return None, 'UpdateInProgress' cls.locked_update = True # ensure globally unique 'loadConfig' run so that e.g. we don't ask a user multiple times to delete corrupted configs cfgCurrent = load_json( 'StatusBarExtended.json' ) # within one fman session, it is guaranteed that multiple calls to load_json(...) with the same JSON name always return the same object, so save {} when deleting the files to force reload if type(cfgCurrent) not in (type(dict()), type(None)): # delete config files, fman's save_json can't replace types config_files = ['StatusBarExtended.json'] config_files.append('StatusBarExtended (' + PLATFORM + ').json') user_settings_url = join(as_url(DATA_DIRECTORY), 'Plugins', 'User', 'Settings') user_input_allow = '' prompt_msg_full = '' corrupt_config = [] for f in config_files: f_url = join(user_settings_url, f) f_path = as_path(f_url) if not exists(f_url): continue excerpt = str(load_json(f_path))[:100] prompt_msg = f_path \ + "\n that begins with:"\ + "\n " + excerpt corrupt_config.append({}) corrupt_config[-1]['url'] = f_url corrupt_config[-1]['path'] = f_path corrupt_config[-1]['prompt_msg'] = prompt_msg corrupt_count = len(corrupt_config) if corrupt_count: # delete corrupt config files with the user's permission prompt_msg_full += "Please enter 'y' or 'yes' or '1' (without the quotes) to delete " + str(corrupt_count) + " corrupt plugin config file" \ + ("\n" if corrupt_count==1 else "s\n") \ + "with incompatible data type " + str(type(cfgCurrent)) + '\n'\ + "(all settings will be reset to their defaults)\n" for corrupt_file_dict in corrupt_config: prompt_msg_full += '\n' + corrupt_file_dict[ 'prompt_msg'] + '\n' user_input_allow, ok = show_prompt(prompt_msg_full, default=user_input_allow) if ok and user_input_allow in ('y', 'yes', '1'): _reset = False for corrupt_file_dict in corrupt_config: f_url = corrupt_file_dict['url'] f_path = corrupt_file_dict['path'] try: move_to_trash(f_url) except Exception as e: show_status_message( "StatusBarExtended: failed to move to trash — " + f_path + " — with exception " + repr(e), msg_t) pass if not exists(f_url): show_status_message( "StatusBarExtended: moved to trash — " + f_path, msg_t) _reset = True else: show_status_message( "StatusBarExtended: failed to move to trash, deleting — " + f_path, msg_t) try: delete(f_url) except Exception as e: show_status_message( "StatusBarExtended: failed to delete — " + f_path + " — with exception " + repr(e), msg_t) pass if not exists(f_url): show_status_message( "StatusBarExtended: deleted — " + f_path, msg_t) _reset = True else: show_alert( "StatusBarExtended: failed to move to trash or delete — " + f_path + "\nPlease, delete it manually") del cls.locked_update return None, 'ConfigDeleteFail' if _reset == True: # can save_json only when both files are deleted, otherwise there is a format mismatch ValueError cls.saveConfig({}) cfgCurrent = load_json('StatusBarExtended.json') else: # user canceled or didn't enter y/1 show_status_message( "StatusBarExtended: you canceled the deletion of the corrupted config files", msg_t) del cls.locked_update return None, 'Canceled' else: # can't find the config files show_alert("StatusBarExtended: can't find the corrupt config files:\n" \ + str(config_files) + "\n @ " + as_path(user_settings_url) \ + "\nMaybe their default location changed, please, delete them manually") del cls.locked_update return None, 'CorruptConfigNotFound' reload = False if (cfgCurrent is None) or ( cfgCurrent == {} ): # empty file or empty dictionary (corrupt configs deleted and replaced with {}), save defaults to the config file cfgCurrent = dict() for key in cls.Default: cfgCurrent[key] = cls.Default[key] reload = True if type(cfgCurrent) is dict: for key in cls.Default: # Fill in missing default values (e.g. in older installs) if key not in cfgCurrent: cfgCurrent[key] = cls.Default[key] reload = True if reload: cls.saveConfig(cfgCurrent) cfgCurrent = load_json('StatusBarExtended.json') if type(cfgCurrent) is dict: # check for still missing keys missing_keys = [] for key in cls.Default: if key in cfgCurrent: continue missing_keys.append(key) if len(missing_keys): show_status_message( "StatusBarExtended: config files are missing some required keys:" + str(missing_keys) + " Maybe try to reload?", msg_t) del cls.locked_update return None, 'MissingKeys' else: del cls.locked_update return cfgCurrent, 'Success' else: show_status_message( "StatusBarExtended: couldn't fix config files, maybe try to reload?", msg_t) del cls.locked_update return None, 'UnknownError'
from fman import load_json from fman.fs import exists, is_dir from fman.url import as_url _USER_7ZIP = None _SUPPORTED_EXTENSIONS = ['.7z', '.zip'] _CHECK_EXTENSION = True _COMPRESS_ARGS = ['a'] _HASH = 'sha256' settings = load_json('SevenZipTools.json', default={}) result = settings.get('7zip', {}) with open('R:/out.txt', 'w') as myfile: myfile.write(str(settings) + '\n') if result: try: exePath = result['path'] except (KeyError, TypeError): pass else: exePathUrl = as_url(exePath) if exists(exePathUrl) and not is_dir(exePathUrl): _USER_7ZIP = exePath _SUPPORTED_EXTENSIONS += ['.rar'] result = settings.get('additional extensions', []) if result and isinstance(result, list): _SUPPORTED_EXTENSIONS += result result = settings.get('ignore extension', None) if result:
def _load_comparison_tool(self) -> str: settings = load_json(_SETTINGS_FILE, default={}) return settings.get(_COMPAISON_TOOL_KEY, None)
from subprocess import Popen import platform from fman import DirectoryPaneCommand, show_alert, load_json PLUGIN_SETTINGS = load_json("OpenInGithub Settings.json")[0] GITHUB_BINARY = PLUGIN_SETTINGS["github_binary"] class OpenInGithub(DirectoryPaneCommand): def __call__(self): file_under_cursor = self.pane.get_file_under_cursor() if file_under_cursor: if platform.system() == "Windows": Popen('"%s" %s' % (GITHUB_BINARY, file_under_cursor), shell=True) else: Popen('%s "%s"' % (GITHUB_BINARY, file_under_cursor), shell=True) else: show_alert("No file selected.")
def load_config() -> dict: config = load_json(CONFIG_FILE) if config is None: config = {"bin": find_code(), "additionalArgs": []} save_json(CONFIG_FILE, config) return config
from fman import DirectoryPaneCommand, show_alert, show_prompt, load_json, save_json, YES, NO from fman.fs import is_dir, exists from fman.url import splitscheme, as_url from subprocess import DEVNULL, Popen import os # TODO, Add this path to Settings file _SUBLIMETEXTPATHDEFAULT = 'C:/Program Files/Sublime Text 3/subl.exe' _SUBLIMETEXTCONFIGFILE = 'Sublime Text Config.json' _SUBLIMETEXTPATH = '' settings = load_json(_SUBLIMETEXTCONFIGFILE, default={'path': _SUBLIMETEXTPATHDEFAULT}) if settings['path'] and exists(as_url(settings['path'])): _SUBLIMETEXTPATH = settings['path'] else: _SUBLIMETEXTPATH = _SUBLIMETEXTPATHDEFAULT class SublimeOpenSelected(DirectoryPaneCommand): def __call__(self): url = self.pane.get_path() scheme, path = splitscheme(url) if scheme != 'file://': show_alert('{} is not supported'.format(url)) return
def _load_suffixes_from_json(self): settings = load_json('Core Settings.json', default={}) archive_handlers = settings.get('archive_handlers', {}) return set(suffix for suffix, scheme in archive_handlers.items() if scheme == self.scheme)