def plugin_loaded(): global called_plugin_loaded if called_plugin_loaded: return called_plugin_loaded = True print('Floobits: Called plugin_loaded.') if not os.path.exists(G.FLOORC_JSON_PATH): migrations.migrate_floorc() utils.reload_settings() # TODO: one day this can be removed (once all our users have updated) old_colab_dir = os.path.realpath(os.path.expanduser(os.path.join('~', '.floobits'))) if os.path.isdir(old_colab_dir) and not os.path.exists(G.BASE_DIR): print('Renaming %s to %s' % (old_colab_dir, G.BASE_DIR)) os.rename(old_colab_dir, G.BASE_DIR) os.symlink(G.BASE_DIR, old_colab_dir) try: utils.normalize_persistent_data() except Exception as e: print('Floobits: Error normalizing persistent data:', str_e(e)) # Keep on truckin' I guess d = utils.get_persistent_data() G.AUTO_GENERATED_ACCOUNT = d.get('auto_generated_account', False) # Sublime plugin API stuff can't be called right off the bat if not utils.can_auth(): utils.set_timeout(create_or_link_account, 1) utils.set_timeout(global_tick, 1)
def join_workspace(self, context, host, name, owner, possible_dirs=None): utils.reload_settings() # legacy urls in emacs... if owner and owner[:2] == "r/": owner = owner[2:] if not utils.can_auth(): success = yield self.create_or_link_account, context, host, False if not success: return utils.reload_settings() possible_dirs = possible_dirs or [] for d in possible_dirs: info = utils.read_floo_file(d) if not info: continue try: parsed_url = utils.parse_url(info["url"]) except Exception: parsed_url = None if ( parsed_url and parsed_url["host"] == host and parsed_url["workspace"] == name and parsed_url["owner"] == owner ): self.remote_connect(context, host, owner, name, d) return try: d = utils.get_persistent_data()["workspaces"][owner][name]["path"] except Exception: d = "" if d and os.path.isdir(d): self.remote_connect(context, host, owner, name, d) return d = d or os.path.join(G.SHARE_DIR or G.BASE_DIR, owner, name) join_action = utils.JOIN_ACTION.PROMPT while True: d = yield self.user_dir, context, "Save workspace files to: ", d if not d: return d = os.path.realpath(os.path.expanduser(d)) if not os.path.isdir(d): y_or_n = yield self.user_y_or_n, context, "%s is not a directory. Create it? " % d, "Create Directory" if not y_or_n: return utils.mkdir(d) if not os.path.isdir(d): msg.error("Couldn't create directory", d) continue join_action = utils.JOIN_ACTION.DOWNLOAD if os.path.isdir(d): self.remote_connect(context, host, owner, name, d, join_action) return
def plugin_loaded(): global called_plugin_loaded if called_plugin_loaded: return called_plugin_loaded = True print('Floobits: Called plugin_loaded.') if not os.path.exists(G.FLOORC_JSON_PATH): migrations.migrate_floorc() utils.reload_settings() # TODO: one day this can be removed (once all our users have updated) old_colab_dir = os.path.realpath( os.path.expanduser(os.path.join('~', '.floobits'))) if os.path.isdir(old_colab_dir) and not os.path.exists(G.BASE_DIR): print('Renaming %s to %s' % (old_colab_dir, G.BASE_DIR)) os.rename(old_colab_dir, G.BASE_DIR) os.symlink(G.BASE_DIR, old_colab_dir) try: utils.normalize_persistent_data() except Exception as e: print('Floobits: Error normalizing persistent data:', str_e(e)) # Keep on truckin' I guess d = utils.get_persistent_data() G.AUTO_GENERATED_ACCOUNT = d.get('auto_generated_account', False) # Sublime plugin API stuff can't be called right off the bat if not utils.can_auth(): utils.set_timeout(create_or_link_account, 1) utils.set_timeout(global_tick, 1)
def plugin_loaded(): global called_plugin_loaded if called_plugin_loaded: return called_plugin_loaded = True print('Floobits: Called plugin_loaded.') utils.reload_settings() G.SOCK_SINGLE_READ = SOCK_SINGLE_READ # TODO: one day this can be removed (once all our users have updated) old_colab_dir = os.path.realpath(os.path.expanduser(os.path.join('~', '.floobits'))) if os.path.isdir(old_colab_dir) and not os.path.exists(G.BASE_DIR): print('Renaming %s to %s' % (old_colab_dir, G.BASE_DIR)) os.rename(old_colab_dir, G.BASE_DIR) os.symlink(G.BASE_DIR, old_colab_dir) try: utils.normalize_persistent_data() except Exception as e: print('Floobits: Error normalizing persistent data:', str_e(e)) # Keep on truckin' I guess d = utils.get_persistent_data() G.AUTO_GENERATED_ACCOUNT = d.get('auto_generated_account', False) setup()
def main(): G.__VERSION__ = '0.11' G.__PLUGIN_VERSION__ = None parser = optparse.OptionParser(usage='%prog [options]') parser.add_option("-p", "--port", dest="port", default=0, help="The port to listen on. Useful for debugging.") parser.add_option("--set-version", dest="version") options, args = parser.parse_args() port = int(options.port) G.__PLUGIN_VERSION__ = options.version if not G.__PLUGIN_VERSION__: print('--set-version is a required argument') print('args: %s' % ' '.join(args)) sys.exit(1) utils.reload_settings() try: utils.normalize_persistent_data() except Exception: pass emacs = emacs_handler.EmacsHandler() G.emacs = emacs _, port = reactor.reactor.listen(emacs, port=port) utils.set_timeout(cb, 100, port) reactor.reactor.block()
def plugin_loaded(): global called_plugin_loaded if called_plugin_loaded: return called_plugin_loaded = True print('Floobits: Called plugin_loaded.') utils.reload_settings() G.SOCK_SINGLE_READ = SOCK_SINGLE_READ # TODO: one day this can be removed (once all our users have updated) old_colab_dir = os.path.realpath( os.path.expanduser(os.path.join('~', '.floobits'))) if os.path.isdir(old_colab_dir) and not os.path.exists(G.BASE_DIR): print('Renaming %s to %s' % (old_colab_dir, G.BASE_DIR)) os.rename(old_colab_dir, G.BASE_DIR) os.symlink(G.BASE_DIR, old_colab_dir) try: utils.normalize_persistent_data() except Exception as e: print('Floobits: Error normalizing persistent data:', str_e(e)) # Keep on truckin' I guess d = utils.get_persistent_data() G.AUTO_GENERATED_ACCOUNT = d.get('auto_generated_account', False) setup()
def plugin_loaded(): global called_plugin_loaded if called_plugin_loaded: return called_plugin_loaded = True print('Floobits: Called plugin_loaded.') utils.reload_settings() # TODO: one day this can be removed (once all our users have updated) old_colab_dir = os.path.realpath(os.path.expanduser(os.path.join('~', '.floobits'))) if os.path.isdir(old_colab_dir) and not os.path.exists(G.BASE_DIR): print('renaming %s to %s' % (old_colab_dir, G.BASE_DIR)) os.rename(old_colab_dir, G.BASE_DIR) os.symlink(G.BASE_DIR, old_colab_dir) d = utils.get_persistent_data() G.AUTO_GENERATED_ACCOUNT = d.get('auto_generated_account', False) can_auth = (G.USERNAME or G.API_KEY) and G.SECRET # Sublime plugin API stuff can't be called right off the bat if not can_auth: utils.set_timeout(create_or_link_account, 1) utils.set_timeout(global_tick, 1)
def main(): G.__VERSION__ = "0.11" G.__PLUGIN_VERSION__ = None parser = optparse.OptionParser(usage="%prog [options]") parser.add_option("-p", "--port", dest="port", default=0, help="The port to listen on. Useful for debugging.") parser.add_option("--set-version", dest="version") options, args = parser.parse_args() port = int(options.port) G.__PLUGIN_VERSION__ = options.version if not G.__PLUGIN_VERSION__: print("--set-version is a required argument") print("args: %s" % " ".join(args)) sys.exit(1) utils.reload_settings() try: utils.normalize_persistent_data() except Exception: pass emacs = emacs_handler.EmacsHandler() G.emacs = emacs _, port = reactor.reactor.listen(emacs, port=port) utils.set_timeout(cb, 100, port) reactor.reactor.block()
def join_workspace(self, context, host, name, owner, possible_dirs=None): utils.reload_settings() # legacy urls in emacs... if owner and owner[:2] == "r/": owner = owner[2:] if not utils.can_auth(): success = yield self.create_or_link_account, context, host, False if not success: return utils.reload_settings() possible_dirs = possible_dirs or [] for d in possible_dirs: info = utils.read_floo_file(d) if not info: continue try: parsed_url = utils.parse_url(info['url']) except Exception: parsed_url = None if parsed_url and parsed_url['host'] == host and parsed_url[ 'workspace'] == name and parsed_url['owner'] == owner: self.remote_connect(context, host, owner, name, d) return try: d = utils.get_persistent_data()['workspaces'][owner][name]['path'] except Exception: d = '' if d and os.path.isdir(d): self.remote_connect(context, host, owner, name, d) return # TODO: make per-host settings fully general host_share_dir = G.AUTH.get(host, {}).get('share_dir') d = d or os.path.join(host_share_dir or G.SHARE_DIR or G.BASE_DIR, owner, name) join_action = utils.JOIN_ACTION.PROMPT while True: d = yield self.user_dir, context, 'Save workspace files to: ', d if not d: return d = os.path.realpath(os.path.expanduser(d)) if not os.path.isdir(d): y_or_n = yield self.user_y_or_n, context, '%s is not a directory. Create it? ' % d, "Create Directory" if not y_or_n: return utils.mkdir(d) if not os.path.isdir(d): msg.error("Couldn't create directory", d) continue join_action = utils.JOIN_ACTION.DOWNLOAD if os.path.isdir(d): self.remote_connect(context, host, owner, name, d, join_action) return
def join_workspace(self, context, host, name, owner, possible_dirs=None): utils.reload_settings() # legacy urls in emacs... if owner and owner[:2] == "r/": owner = owner[2:] if not utils.can_auth(): success = yield self.create_or_link_account, context, host, False if not success: return utils.reload_settings() possible_dirs = possible_dirs or [] for d in possible_dirs: info = utils.read_floo_file(d) if not info: continue try: parsed_url = utils.parse_url(info['url']) except Exception: parsed_url = None if parsed_url and parsed_url['host'] == host and parsed_url['workspace'] == name and parsed_url['owner'] == owner: self.remote_connect(context, host, owner, name, d) return try: d = utils.get_persistent_data()['workspaces'][owner][name]['path'] except Exception: d = '' if d and os.path.isdir(d): self.remote_connect(context, host, owner, name, d) return # TODO: make per-host settings fully general host_share_dir = G.AUTH.get(host, {}).get('share_dir') d = d or os.path.join(host_share_dir or G.SHARE_DIR or G.BASE_DIR, owner, name) join_action = utils.JOIN_ACTION.PROMPT while True: d = yield self.user_dir, context, 'Save workspace files to: ', d if not d: return d = os.path.realpath(os.path.expanduser(d)) if not os.path.isdir(d): y_or_n = yield self.user_y_or_n, context, '%s is not a directory. Create it? ' % d, "Create Directory" if not y_or_n: return utils.mkdir(d) if not os.path.isdir(d): msg.error("Couldn't create directory", d) continue join_action = utils.JOIN_ACTION.DOWNLOAD if os.path.isdir(d): self.remote_connect(context, host, owner, name, d, join_action) return
def main(): G.__VERSION__ = '0.11' G.__PLUGIN_VERSION__ = '1.2.0' utils.reload_settings() migrations.rename_floobits_dir() migrations.migrate_symlinks() utils.normalize_persistent_data() emacs = emacs_handler.EmacsHandler() G.emacs = emacs _, port = reactor.reactor.listen(emacs) utils.set_timeout(cb, 100, port) reactor.reactor.block()
def run(self, dir_to_share=None, paths=None, current_file=False, api_args=None): global on_room_info_waterfall self.api_args = api_args utils.reload_settings() if not (G.USERNAME and G.SECRET): return create_or_link_account() if paths: if len(paths) != 1: return sublime.error_message('Only one folder at a time, please. :(') return self.on_input(paths[0]) if dir_to_share is None: dir_to_share = os.path.expanduser(os.path.join('~', 'share_me')) on_room_info_waterfall = utils.Waterfall() self.window.show_input_panel('Directory to share:', dir_to_share, self.on_input, None, None)
def handle(self, req): self.net_buf += req while True: before, sep, after = self.net_buf.partition('\n') if not sep: break self.net_buf = after try: data = json.loads(before) except Exception as e: msg.error('Unable to parse json:', e) msg.error('Data:', before) raise e if data['name'] == 'share_dir': utils.reload_settings() G.USERNAME = data['username'] G.SECRET = data['secret'] self.share_dir(data['dir_to_share'], data.get('perms')) elif data['name'] == 'join_workspace': utils.reload_settings() workspace = data['workspace'] owner = data['workspace_owner'] G.USERNAME = data['username'] G.SECRET = data['secret'] try: G.PROJECT_PATH = utils.get_persistent_data()['workspaces'][owner][workspace]['path'] except Exception: G.PROJECT_PATH = '' if G.PROJECT_PATH and os.path.isdir(G.PROJECT_PATH): workspace_url = utils.to_workspace_url({'secure': True, 'owner': owner, 'workspace': workspace}) self.remote_connect(workspace_url) continue G.PROJECT_PATH = '~/floobits/share/%s/%s' % (owner, workspace) self.get_input('Give me a directory to sync data to: ', G.PROJECT_PATH, self.join_workspace, owner, workspace) elif data['name'] == 'user_input': cb_id = int(data['id']) cb = self.user_inputs.get(cb_id) if cb is None: msg.error('cb for input %s is none' % cb_id) continue cb(data) del self.user_inputs[cb_id] else: self.agent.protocol.emacs_handle(data)
def run(self, dir_to_share=None, paths=None, current_file=False, api_args=None): self.api_args = api_args utils.reload_settings() if not utils.can_auth(): return create_or_link_account() if paths: if len(paths) != 1: return sublime.error_message('Only one folder at a time, please. :(') return self.on_input(paths[0]) if dir_to_share is None: folders = self.window.folders() if folders: dir_to_share = folders[0] else: dir_to_share = os.path.expanduser(os.path.join('~', 'share_me')) self.window.show_input_panel('Directory to share:', dir_to_share, self.on_input, None, None)
def on_connect(self): utils.reload_settings() req = { 'username': self.username, 'secret': self.secret, 'room': self.workspace, 'room_owner': self.owner, 'client': self.client, 'platform': sys.platform, 'supported_encodings': ['utf8', 'base64'], 'version': G.__VERSION__ } if self.api_key: req['api_key'] = self.api_key self.send(req)
def main(): G.__VERSION__ = '0.03' G.__PLUGIN_VERSION__ = '1.0' utils.reload_settings() floo_log_level = 'msg' if G.DEBUG: floo_log_level = 'debug' msg.LOG_LEVEL = msg.LOG_LEVELS.get(floo_log_level.upper(), msg.LOG_LEVELS['MSG']) migrations.rename_floobits_dir() migrations.migrate_symlinks() emacs = emacs_handler.EmacsHandler() G.emacs = emacs _, port = reactor.reactor.listen(emacs) utils.set_timeout(cb, 100, port) reactor.reactor.block()
def main(): G.__VERSION__ = '0.11' G.__PLUGIN_VERSION__ = '1.1.1' utils.reload_settings() floo_log_level = 'msg' if G.DEBUG: floo_log_level = 'debug' msg.LOG_LEVEL = msg.LOG_LEVELS.get(floo_log_level.upper(), msg.LOG_LEVELS['MSG']) migrations.rename_floobits_dir() migrations.migrate_symlinks() utils.normalize_persistent_data() emacs = emacs_handler.EmacsHandler() G.emacs = emacs _, port = reactor.reactor.listen(emacs) utils.set_timeout(cb, 100, port) reactor.reactor.block()
def run(self, dir_to_share=None, paths=None, current_file=False, api_args=None): global on_room_info_waterfall self.api_args = api_args utils.reload_settings() if not (G.USERNAME and G.SECRET): return create_or_link_account() if paths: if len(paths) != 1: return sublime.error_message( 'Only one folder at a time, please. :(') return self.on_input(paths[0]) if dir_to_share is None: dir_to_share = os.path.expanduser(os.path.join('~', 'share_me')) on_room_info_waterfall = utils.Waterfall() self.window.show_input_panel('Directory to share:', dir_to_share, self.on_input, None, None)
def main(): G.__VERSION__ = '0.11' G.__PLUGIN_VERSION__ = None parser = optparse.OptionParser(usage='%prog [options]') parser.add_option("-p", "--port", dest="port", default=0, help="The port to listen on. Useful for debugging.") parser.add_option("--set-version", dest="version") options, args = parser.parse_args() port = int(options.port) G.__PLUGIN_VERSION__ = options.version if not G.__PLUGIN_VERSION__: print('--set-version is a required argument') print('args: %s' % ' '.join(args)) sys.exit(1) utils.reload_settings() if not os.path.exists(G.FLOORC_JSON_PATH): migrations.migrate_floorc() utils.reload_settings() migrations.rename_floobits_dir() migrations.migrate_symlinks() try: utils.normalize_persistent_data() except Exception: pass emacs = emacs_handler.EmacsHandler() G.emacs = emacs _, port = reactor.reactor.listen(emacs, port=port) utils.set_timeout(cb, 100, port) reactor.reactor.block()
def main(): G.__VERSION__ = '0.11' G.__PLUGIN_VERSION__ = '1.5.10' utils.reload_settings() if not os.path.exists(G.FLOORC_JSON_PATH): migrations.migrate_floorc() utils.reload_settings() migrations.rename_floobits_dir() migrations.migrate_symlinks() try: utils.normalize_persistent_data() except Exception: pass emacs = emacs_handler.EmacsHandler() G.emacs = emacs _, port = reactor.reactor.listen(emacs) utils.set_timeout(cb, 100, port) reactor.reactor.block()
def main(): G.__VERSION__ = '0.11' G.__PLUGIN_VERSION__ = '1.5.6' utils.reload_settings() if not os.path.exists(G.FLOORC_JSON_PATH): migrations.migrate_floorc() utils.reload_settings() migrations.rename_floobits_dir() migrations.migrate_symlinks() try: utils.normalize_persistent_data() except Exception: pass emacs = emacs_handler.EmacsHandler() G.emacs = emacs _, port = reactor.reactor.listen(emacs) utils.set_timeout(cb, 100, port) reactor.reactor.block()
def run(self, dir_to_share=None, paths=None, current_file=False, api_args=None): self.api_args = api_args utils.reload_settings() if not utils.can_auth(): return create_or_link_account() if paths: if len(paths) != 1: return sublime.error_message( 'Only one folder at a time, please. :(') return self.on_input(paths[0]) if dir_to_share is None: folders = self.window.folders() if folders: dir_to_share = folders[0] else: dir_to_share = os.path.expanduser(os.path.join( '~', 'share_me')) self.window.show_input_panel('Directory to share:', dir_to_share, self.on_input, None, None)
def share_dir(self, context, dir_to_share, api_args): utils.reload_settings() if not utils.can_auth(): success = yield self.create_or_link_account, context, G.DEFAULT_HOST, False if not success: return utils.reload_settings() dir_to_share = os.path.expanduser(dir_to_share) dir_to_share = os.path.realpath(dir_to_share) dir_to_share = utils.unfuck_path(dir_to_share) if os.path.isfile(dir_to_share): dir_to_share = os.path.dirname(dir_to_share) workspace_name = os.path.basename(dir_to_share) msg.debug('', workspace_name, dir_to_share) if os.path.isfile(dir_to_share): dir_to_share = os.path.dirname(dir_to_share) try: utils.mkdir(dir_to_share) except Exception: msg.error("The directory", dir_to_share, "doesn't exist and I can't create it.") return info = utils.read_floo_file(dir_to_share) def prejoin(workspace_url): try: return self.prejoin_workspace(workspace_url, dir_to_share, api_args) except ValueError: pass workspace_url = info.get('url') if workspace_url: parsed_url = prejoin(workspace_url) if parsed_url: self.remote_connect(context, parsed_url['host'], parsed_url['owner'], parsed_url['workspace'], dir_to_share) return parsed_url = utils.get_workspace_by_path(dir_to_share, prejoin) if parsed_url: self.remote_connect(context, parsed_url['host'], parsed_url['owner'], parsed_url['workspace'], dir_to_share) return host = yield self._get_host, context if not host: return try: r = api.get_orgs_can_admin(host) except IOError as e: editor.error_message('Error getting org list: %s' % str_e(e)) return choices = [G.AUTH[host]['username']] if r.code >= 400: editor.error_message('Error getting org list: %s' % r.body) elif r.body: choices += [org['name'] for org in r.body] if len(choices) == 1: owner = choices[0] else: little = ['Create workspace owned by %s' % s for s in choices] (owner, index) = yield self.user_select, context, 'Create workspace owned by', choices, little if not owner: return self.create_workspace(context, host, owner, workspace_name, api_args, dir_to_share)
def run(self, workspace_url, agent_conn_kwargs=None): agent_conn_kwargs = agent_conn_kwargs or {} def get_workspace_window(): workspace_window = None for w in sublime.windows(): for f in w.folders(): if f == G.PROJECT_PATH: workspace_window = w break return workspace_window def set_workspace_window(cb): workspace_window = get_workspace_window() if workspace_window is None: return utils.set_timeout(set_workspace_window, 50, cb) G.WORKSPACE_WINDOW = workspace_window cb() def truncate_chat_view(chat_view, cb): if chat_view: chat_view.set_read_only(False) chat_view.run_command('floo_view_replace_region', {'r': [0, chat_view.size()], 'data': ''}) chat_view.set_read_only(True) cb() def create_chat_view(cb): with open(os.path.join(G.BASE_DIR, 'msgs.floobits.log'), 'a') as msgs_fd: msgs_fd.write('') get_or_create_chat(lambda chat_view: truncate_chat_view(chat_view, cb)) def open_workspace_window2(cb): if sublime.platform() == 'linux': subl = open('/proc/self/cmdline').read().split(chr(0))[0] elif sublime.platform() == 'osx': # TODO: totally explodes if you install ST2 somewhere else settings = sublime.load_settings('Floobits.sublime-settings') subl = settings.get('sublime_executable', '/Applications/Sublime Text 2.app/Contents/SharedSupport/bin/subl') if not os.path.exists(subl): return sublime.error_message('Can\'t find your Sublime Text executable at %s. Please add "sublime_executable /path/to/subl" to your ~/.floorc and restart Sublime Text' % subl) elif sublime.platform() == 'windows': subl = sys.executable else: raise Exception('WHAT PLATFORM ARE WE ON?!?!?') command = [subl] if get_workspace_window() is None: command.append('--new-window') command.append('--add') command.append(G.PROJECT_PATH) # Maybe no msg view yet :( print('command:', command) p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) poll_result = p.poll() print('poll:', poll_result) set_workspace_window(lambda: create_chat_view(cb)) def open_workspace_window3(cb): G.WORKSPACE_WINDOW = get_workspace_window() if not G.WORKSPACE_WINDOW: G.WORKSPACE_WINDOW = sublime.active_window() msg.debug('Setting project data. Path: %s' % G.PROJECT_PATH) G.WORKSPACE_WINDOW.set_project_data({'folders': [{'path': G.PROJECT_PATH}]}) create_chat_view(cb) def open_workspace_window(cb): if PY2: open_workspace_window2(cb) else: open_workspace_window3(cb) def run_agent(owner, workspace, host, port, secure): global on_room_info_waterfall if G.AGENT: msg.debug('Stopping agent.') G.AGENT.stop() G.AGENT = None on_room_info_waterfall.add(update_recent_workspaces, {'url': workspace_url}) try: msg.debug("agent_conn_kwargs: %s" % str(agent_conn_kwargs)) G.AGENT = AgentConnection(owner=owner, workspace=workspace, host=host, port=port, secure=secure, on_room_info=on_room_info_waterfall.call, **agent_conn_kwargs) on_room_info_waterfall = utils.Waterfall() Listener.reset() G.AGENT.connect() except Exception as e: print(e) tb = traceback.format_exc() print(tb) def make_dir(d): d = os.path.realpath(os.path.expanduser(d)) if not os.path.isdir(d): make_dir = sublime.ok_cancel_dialog('%s is not a directory. Create it?' % d) if not make_dir: return self.window.show_input_panel('%s is not a directory. Enter an existing path:' % d, d, None, None, None) try: utils.mkdir(d) except Exception as e: return sublime.error_message('Could not create directory %s: %s' % (d, str(e))) G.PROJECT_PATH = d add_workspace_to_persistent_json(result['owner'], result['workspace'], workspace_url, d) open_workspace_window(lambda: run_agent(**result)) try: result = utils.parse_url(workspace_url) except Exception as e: return sublime.error_message(str(e)) utils.reload_settings() if not (G.USERNAME and G.SECRET): return create_or_link_account() d = utils.get_persistent_data() try: G.PROJECT_PATH = d['workspaces'][result['owner']][result['workspace']]['path'] except Exception as e: G.PROJECT_PATH = '' print('Project path is %s' % G.PROJECT_PATH) if not os.path.isdir(G.PROJECT_PATH): default_dir = os.path.realpath(os.path.join(G.COLAB_DIR, result['owner'], result['workspace'])) return self.window.show_input_panel('Save workspace in directory:', default_dir, make_dir, None, None) open_workspace_window(lambda: run_agent(**result))
try: from .floo import AgentConnection, CreateAccountConnection, RequestCredentialsConnection, listener, version from .floo.common import api, ignore, msg, shared as G, utils from .floo.listener import Listener assert HTTPError and api and AgentConnection and CreateAccountConnection and RequestCredentialsConnection and G and Listener and ignore and listener and msg and utils and version except (ImportError, ValueError): from floo import AgentConnection, CreateAccountConnection, RequestCredentialsConnection, listener, version from floo.common import api, ignore, msg, shared as G, utils from floo.listener import Listener assert version sublime.log = lambda d: G.CHAT_VIEW and G.CHAT_VIEW .run_command('floo_view_set_msg', {'data': d}) utils.reload_settings() # TODO: one day this can be removed (once all our users have updated) old_colab_dir = os.path.realpath(os.path.expanduser(os.path.join('~', '.floobits'))) if os.path.isdir(old_colab_dir) and not os.path.exists(G.BASE_DIR): print('renaming %s to %s' % (old_colab_dir, G.BASE_DIR)) os.rename(old_colab_dir, G.BASE_DIR) os.symlink(G.BASE_DIR, old_colab_dir) on_room_info_waterfall = utils.Waterfall() def update_recent_workspaces(workspace): d = utils.get_persistent_data() recent_workspaces = d.get('recent_workspaces', [])
def floobits_share_dir(dir_to_share, perms): utils.reload_settings() workspace_name = os.path.basename(dir_to_share) G.PROJECT_PATH = os.path.realpath(dir_to_share) msg.debug('%s %s %s' % (G.USERNAME, workspace_name, G.PROJECT_PATH)) file_to_share = None dir_to_share = os.path.expanduser(dir_to_share) dir_to_share = utils.unfuck_path(dir_to_share) dir_to_share = os.path.abspath(dir_to_share) dir_to_share = os.path.realpath(dir_to_share) workspace_name = os.path.basename(dir_to_share) if os.path.isfile(dir_to_share): file_to_share = dir_to_share dir_to_share = os.path.dirname(dir_to_share) try: utils.mkdir(dir_to_share) except Exception: return msg.error("The directory %s doesn't exist and I can't create it." % dir_to_share) if not os.path.isdir(dir_to_share): return msg.error('The directory %s doesn\'t appear to exist' % dir_to_share) floo_file = os.path.join(dir_to_share, '.floo') # look for the .floo file for hints about previous behavior info = {} try: floo_info = open(floo_file, 'rb').read().decode('utf-8') info = json.loads(floo_info) except (IOError, OSError): pass except Exception: msg.warn('couldn\'t read the floo_info file: %s' % floo_file) workspace_url = info.get('url') if workspace_url: parsed_url = api.prejoin_workspace(workspace_url, dir_to_share, {'perms': perms}) if parsed_url: return floobits_join_workspace(workspace_url, dir_to_share, upload_path=file_to_share or dir_to_share) filter_func = lambda workspace_url: api.prejoin_workspace(workspace_url, dir_to_share, {'perms': perms}) parsed_url = utils.get_workspace_by_path(dir_to_share, filter_func) if parsed_url: return floobits_join_workspace(workspace_url, dir_to_share, upload_path=file_to_share or dir_to_share) try: r = api.get_orgs_can_admin() except IOError as e: return editor.error_message('Error getting org list: %s' % str(e)) if r.code >= 400 or len(r.body) == 0: workspace_name = vim_input('Workspace name:', workspace_name, "file") return create_workspace(workspace_name, dir_to_share, G.USERNAME, perms, upload_path=file_to_share or dir_to_share) orgs = r.body if len(orgs) == 0: return create_workspace(workspace_name, dir_to_share, G.USERNAME, perms, upload_path=file_to_share or dir_to_share) choices = [] choices.append(G.USERNAME) for o in orgs: choices.append(o['name']) owner = vim_choice('Create workspace for:', G.USERNAME, choices) if owner: return create_workspace(workspace_name, dir_to_share, owner, perms, upload_path=file_to_share or dir_to_share)
def run(self, workspace_url, agent_conn_kwargs=None, upload=None): agent_conn_kwargs = agent_conn_kwargs or {} self.upload = upload def get_workspace_window(): workspace_window = None for w in sublime.windows(): for f in w.folders(): if utils.unfuck_path(f) == utils.unfuck_path( G.PROJECT_PATH): workspace_window = w break return workspace_window def set_workspace_window(cb): workspace_window = get_workspace_window() if workspace_window is None: return utils.set_timeout(set_workspace_window, 50, cb) G.WORKSPACE_WINDOW = workspace_window cb() def open_workspace_window(cb): if PY2: open_workspace_window2(cb) else: open_workspace_window3(cb) def open_workspace_window2(cb): if sublime.platform() == 'linux': subl = open('/proc/self/cmdline').read().split(chr(0))[0] elif sublime.platform() == 'osx': floorc = utils.load_floorc_json() subl = floorc.get('SUBLIME_EXECUTABLE') if not subl: settings = sublime.load_settings( 'Floobits.sublime-settings') subl = settings.get( 'sublime_executable', '/Applications/Sublime Text 2.app/Contents/SharedSupport/bin/subl' ) if not os.path.exists(subl): return sublime.error_message( '''Can't find your Sublime Text executable at %s. Please add "sublime_executable": "/path/to/subl" to your ~/.floorc.json and restart Sublime Text''' % subl) elif sublime.platform() == 'windows': subl = sys.executable else: raise Exception('WHAT PLATFORM ARE WE ON?!?!?') command = [subl] if get_workspace_window() is None: command.append('--new-window') command.append('--add') command.append(G.PROJECT_PATH) msg.debug('command:', command) p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) poll_result = p.poll() msg.debug('poll:', poll_result) set_workspace_window(cb) def open_workspace_window3(cb): def finish(w): G.WORKSPACE_WINDOW = w msg.debug('Setting project data. Path: %s' % G.PROJECT_PATH) G.WORKSPACE_WINDOW.set_project_data( {'folders': [{ 'path': G.PROJECT_PATH }]}) cb() def get_empty_window(): for w in sublime.windows(): project_data = w.project_data() try: folders = project_data.get('folders', []) if len(folders) == 0 or not folders[0].get('path'): # no project data. co-opt this window return w except Exception as e: print(str_e(e)) def wait_empty_window(i): if i > 10: print( 'Too many failures trying to find an empty window. Using active window.' ) return finish(sublime.active_window()) w = get_empty_window() if w: return finish(w) return utils.set_timeout(wait_empty_window, 50, i + 1) w = get_workspace_window() or get_empty_window() if w: return finish(w) sublime.run_command('new_window') wait_empty_window(0) def make_dir(d): d = os.path.realpath(os.path.expanduser(d)) if not os.path.isdir(d): make_dir = sublime.ok_cancel_dialog( '%s is not a directory. Create it?' % d) if not make_dir: return self.window.show_input_panel( '%s is not a directory. Enter an existing path:' % d, d, None, None, None) try: utils.mkdir(d) except Exception as e: return sublime.error_message( 'Could not create directory %s: %s' % (d, str_e(e))) G.PROJECT_PATH = d if self.upload: result['upload'] = d else: result['upload'] = "" utils.add_workspace_to_persistent_json(result['owner'], result['workspace'], workspace_url, d) open_workspace_window(lambda: run_agent(**result)) @utils.inlined_callbacks def run_agent(owner, workspace, host, port, secure, upload): if G.AGENT: msg.debug('Stopping agent.') reactor.stop() G.AGENT = None try: auth = G.AUTH.get(host) if not auth: success = yield link_account, host if not success: return auth = G.AUTH.get(host) conn = SublimeConnection(owner, workspace, auth, upload) reactor.connect(conn, host, port, secure) except Exception as e: msg.error(str_e(e)) try: result = utils.parse_url(workspace_url) except Exception as e: return sublime.error_message(str_e(e)) utils.reload_settings() if not utils.can_auth(): return create_or_link_account() d = utils.get_persistent_data() try: G.PROJECT_PATH = d['workspaces'][result['owner']][ result['workspace']]['path'] except Exception: msg.log('%s/%s not in persistent.json' % (result['owner'], result['workspace'])) G.PROJECT_PATH = '' msg.log('Project path is %s' % G.PROJECT_PATH) if not os.path.isdir(G.PROJECT_PATH): default_dir = None for w in sublime.windows(): if default_dir: break for d in self.window.folders(): floo_file = os.path.join(d, '.floo') try: floo_info = open(floo_file, 'r').read() wurl = json.loads(floo_info).get('url') if wurl == workspace_url: # TODO: check if workspace actually exists default_dir = d break except Exception: pass default_dir = default_dir or os.path.realpath( os.path.join(G.COLAB_DIR, result['owner'], result['workspace'])) return self.window.show_input_panel('Save workspace in directory:', default_dir, make_dir, None, None) open_workspace_window(lambda: run_agent(upload=upload, **result))
def run(self, workspace_url, agent_conn_kwargs=None): agent_conn_kwargs = agent_conn_kwargs or {} def get_workspace_window(): workspace_window = None for w in sublime.windows(): for f in w.folders(): if utils.unfuck_path(f) == utils.unfuck_path(G.PROJECT_PATH): workspace_window = w break return workspace_window def set_workspace_window(cb): workspace_window = get_workspace_window() if workspace_window is None: return utils.set_timeout(set_workspace_window, 50, cb) G.WORKSPACE_WINDOW = workspace_window cb() def open_workspace_window(cb): if PY2: open_workspace_window2(cb) else: open_workspace_window3(cb) def open_workspace_window2(cb): if sublime.platform() == 'linux': subl = open('/proc/self/cmdline').read().split(chr(0))[0] elif sublime.platform() == 'osx': # TODO: totally explodes if you install ST2 somewhere else settings = sublime.load_settings('Floobits.sublime-settings') subl = settings.get('sublime_executable', '/Applications/Sublime Text 2.app/Contents/SharedSupport/bin/subl') if not os.path.exists(subl): return sublime.error_message('''Can't find your Sublime Text executable at %s. Please add "sublime_executable /path/to/subl" to your ~/.floorc and restart Sublime Text''' % subl) elif sublime.platform() == 'windows': subl = sys.executable else: raise Exception('WHAT PLATFORM ARE WE ON?!?!?') command = [subl] if get_workspace_window() is None: command.append('--new-window') command.append('--add') command.append(G.PROJECT_PATH) msg.debug('command:', command) p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) poll_result = p.poll() msg.debug('poll:', poll_result) set_workspace_window(cb) def open_workspace_window3(cb): def finish(w): G.WORKSPACE_WINDOW = w msg.debug('Setting project data. Path: %s' % G.PROJECT_PATH) G.WORKSPACE_WINDOW.set_project_data({'folders': [{'path': G.PROJECT_PATH}]}) cb() def get_empty_window(): for w in sublime.windows(): project_data = w.project_data() try: folders = project_data.get('folders', []) if len(folders) == 0 or not folders[0].get('path'): # no project data. co-opt this window return w except Exception as e: print(e) def wait_empty_window(i): if i > 10: print('Too many failures trying to find an empty window. Using active window.') return finish(sublime.active_window()) w = get_empty_window() if w: return finish(w) return utils.set_timeout(wait_empty_window, 50, i + 1) w = get_workspace_window() or get_empty_window() if w: return finish(w) sublime.run_command('new_window') wait_empty_window(0) def make_dir(d): d = os.path.realpath(os.path.expanduser(d)) if not os.path.isdir(d): make_dir = sublime.ok_cancel_dialog('%s is not a directory. Create it?' % d) if not make_dir: return self.window.show_input_panel('%s is not a directory. Enter an existing path:' % d, d, None, None, None) try: utils.mkdir(d) except Exception as e: return sublime.error_message('Could not create directory %s: %s' % (d, str(e))) G.PROJECT_PATH = d utils.add_workspace_to_persistent_json(result['owner'], result['workspace'], workspace_url, d) open_workspace_window(lambda: run_agent(**result)) def run_agent(owner, workspace, host, port, secure): global on_room_info_waterfall if G.AGENT: msg.debug('Stopping agent.') reactor.stop() G.AGENT = None on_room_info_waterfall.add(update_recent_workspaces, {'url': workspace_url}) try: conn = SublimeConnection(owner, workspace, agent_conn_kwargs.get('get_bufs', True)) reactor.connect(conn, host, port, secure) conn.once('room_info', on_room_info_waterfall.call) on_room_info_waterfall = utils.Waterfall() except Exception as e: print(e) tb = traceback.format_exc() print(tb) try: result = utils.parse_url(workspace_url) except Exception as e: return sublime.error_message(str(e)) utils.reload_settings() if not (G.USERNAME and G.SECRET): return create_or_link_account() d = utils.get_persistent_data() try: G.PROJECT_PATH = d['workspaces'][result['owner']][result['workspace']]['path'] except Exception as e: G.PROJECT_PATH = '' print('Project path is %s' % G.PROJECT_PATH) if not os.path.isdir(G.PROJECT_PATH): default_dir = os.path.realpath(os.path.join(G.COLAB_DIR, result['owner'], result['workspace'])) return self.window.show_input_panel('Save workspace in directory:', default_dir, make_dir, None, None) open_workspace_window(lambda: run_agent(**result))
def run(self, workspace_url, agent_conn_kwargs=None, upload=None): agent_conn_kwargs = agent_conn_kwargs or {} self.upload = upload def get_workspace_window(): workspace_window = None for w in sublime.windows(): for f in w.folders(): if utils.unfuck_path(f) == utils.unfuck_path(G.PROJECT_PATH): workspace_window = w break return workspace_window def set_workspace_window(cb): workspace_window = get_workspace_window() if workspace_window is None: return utils.set_timeout(set_workspace_window, 50, cb) G.WORKSPACE_WINDOW = workspace_window cb() def open_workspace_window(cb): if PY2: open_workspace_window2(cb) else: open_workspace_window3(cb) def open_workspace_window2(cb): if sublime.platform() == 'linux': subl = open('/proc/self/cmdline').read().split(chr(0))[0] elif sublime.platform() == 'osx': floorc = utils.load_floorc_json() subl = floorc.get('SUBLIME_EXECUTABLE') if not subl: settings = sublime.load_settings('Floobits.sublime-settings') subl = settings.get('sublime_executable', '/Applications/Sublime Text 2.app/Contents/SharedSupport/bin/subl') if not os.path.exists(subl): return sublime.error_message('''Can't find your Sublime Text executable at %s. Please add "sublime_executable": "/path/to/subl" to your ~/.floorc.json and restart Sublime Text''' % subl) elif sublime.platform() == 'windows': subl = sys.executable else: raise Exception('WHAT PLATFORM ARE WE ON?!?!?') command = [subl] if get_workspace_window() is None: command.append('--new-window') command.append('--add') command.append(G.PROJECT_PATH) msg.debug('command:', command) p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) poll_result = p.poll() msg.debug('poll:', poll_result) set_workspace_window(cb) def open_workspace_window3(cb): def finish(w): G.WORKSPACE_WINDOW = w msg.debug('Setting project data. Path: %s' % G.PROJECT_PATH) G.WORKSPACE_WINDOW.set_project_data({'folders': [{'path': G.PROJECT_PATH}]}) cb() def get_empty_window(): for w in sublime.windows(): project_data = w.project_data() try: folders = project_data.get('folders', []) if len(folders) == 0 or not folders[0].get('path'): # no project data. co-opt this window return w except Exception as e: print(str_e(e)) def wait_empty_window(i): if i > 10: print('Too many failures trying to find an empty window. Using active window.') return finish(sublime.active_window()) w = get_empty_window() if w: return finish(w) return utils.set_timeout(wait_empty_window, 50, i + 1) w = get_workspace_window() or get_empty_window() if w: return finish(w) sublime.run_command('new_window') wait_empty_window(0) def make_dir(d): d = os.path.realpath(os.path.expanduser(d)) if not os.path.isdir(d): make_dir = sublime.ok_cancel_dialog('%s is not a directory. Create it?' % d) if not make_dir: return self.window.show_input_panel('%s is not a directory. Enter an existing path:' % d, d, None, None, None) try: utils.mkdir(d) except Exception as e: return sublime.error_message('Could not create directory %s: %s' % (d, str_e(e))) G.PROJECT_PATH = d if self.upload: result['upload'] = d else: result['upload'] = "" utils.add_workspace_to_persistent_json(result['owner'], result['workspace'], workspace_url, d) open_workspace_window(lambda: run_agent(**result)) @utils.inlined_callbacks def run_agent(owner, workspace, host, port, secure, upload): if G.AGENT: msg.debug('Stopping agent.') reactor.stop() G.AGENT = None try: auth = G.AUTH.get(host) if not auth: success = yield link_account, host if not success: return auth = G.AUTH.get(host) conn = SublimeConnection(owner, workspace, auth, upload) reactor.connect(conn, host, port, secure) except Exception as e: msg.error(str_e(e)) try: result = utils.parse_url(workspace_url) except Exception as e: return sublime.error_message(str_e(e)) utils.reload_settings() if not utils.can_auth(): return create_or_link_account() d = utils.get_persistent_data() try: G.PROJECT_PATH = d['workspaces'][result['owner']][result['workspace']]['path'] except Exception: msg.log('%s/%s not in persistent.json' % (result['owner'], result['workspace'])) G.PROJECT_PATH = '' msg.log('Project path is %s' % G.PROJECT_PATH) if not os.path.isdir(G.PROJECT_PATH): default_dir = None for w in sublime.windows(): if default_dir: break for d in self.window.folders(): floo_file = os.path.join(d, '.floo') try: floo_info = open(floo_file, 'r').read() wurl = json.loads(floo_info).get('url') if wurl == workspace_url: # TODO: check if workspace actually exists default_dir = d break except Exception: pass default_dir = default_dir or os.path.realpath(os.path.join(G.COLAB_DIR, result['owner'], result['workspace'])) return self.window.show_input_panel('Save workspace in directory:', default_dir, make_dir, None, None) open_workspace_window(lambda: run_agent(upload=upload, **result))
def main(): if not os.path.exists(G.FLOORC_JSON_PATH): migrations.migrate_floorc() utils.reload_settings() default_auth = G.AUTH.get(G.DEFAULT_HOST, {}) parser = optparse.OptionParser(usage=usage) parser.add_option("-u", "--username", dest="username", default=default_auth.get('username'), help="Your Floobits username") parser.add_option("-s", "--secret", dest="secret", default=default_auth.get('secret'), help="Your Floobits secret (api key)") parser.add_option("-c", "--create", dest="create", default=False, action="store_true", help="The terminal name to create") parser.add_option("--host", dest="host", default=G.DEFAULT_HOST, help="The host to connect to. Deprecated. Use --url instead.") parser.add_option("-p", "--port", dest="port", default=G.DEFAULT_PORT, help="The port to connect to. Deprecated. Use --url instead.") parser.add_option("-w", "--workspace", dest="workspace", help="The workspace name. --owner is required with this option. Deprecated. Use --url instead.") parser.add_option("-o", "--owner", dest="owner", help="The workspace owner. --workspace is required with this option. Deprecated. Use --url instead.") parser.add_option("-l", "--list", dest="list", default=False, action="store_true", help="List all terminals in the workspace") parser.add_option("--unsafe", dest="safe", default=True, action="store_false", help="Less safe terminal. This allows other users to send enter in your terminal.") parser.add_option("--no-ssl", dest="use_ssl", default=True, action="store_false", help="Do not use this option unless you know what you are doing!") parser.add_option("--url", dest="workspace_url", default=None, help="The URL of the workspace to connect to.") parser.add_option("--resize", dest="resize", default=False, action="store_true", help="Resize your terminal to the host terminal size.") parser.add_option("-P", "--preserve-ps1", dest="set_prompt", default=True, action="store_false", help="Don't change $PS1 (bash/zsh prompt)") parser.add_option("-v", "--version", dest="version", default=False, action="store_true", help="Print version") options, args = parser.parse_args() if options.version: print('flootty %s' % version.FLOOTTY_VERSION) return default_term_name = "" if options.create: default_term_name = "ftty" term_name = args and args[0] or default_term_name if options.workspace and options.owner and options.workspace_url: # TODO: confusing parser.error("You can either specify --workspace and --owner, or --url, but not both.") if bool(options.workspace) != bool(options.owner): parser.error("You must specify a workspace and owner or neither.") for opt in ['owner', 'workspace']: if getattr(options, opt): print('%s is deprecated. Please use --url instead.' % opt) if not options.workspace or not options.owner: floo = {} if options.workspace_url: floo = utils.parse_url(options.workspace_url) else: for floo_path in walk_up(os.path.realpath('.')): try: floo = json.loads(open(os.path.join(floo_path, '.floo'), 'rb').read().decode('utf-8')) floo = utils.parse_url(floo['url']) except Exception: pass else: break options.host = floo.get('host') options.workspace = floo.get('workspace') options.owner = floo.get('owner') options.use_ssl = floo.get('secure') if not options.port: options.port = floo.get('port') if not options.host: options.host = floo.get('host') if options.host is None: options.host = G.DEFAULT_HOST if options.host != G.DEFAULT_HOST and options.secret == default_auth.get('secret'): auth = G.AUTH.get(options.host) if not auth: return die("Please add credentials for %s in ~/.floorc.json" % options.host) options.username = auth.get('username') options.secret = auth.get('secret') if not options.workspace or not options.owner: try: now_editing = get_now_editing_workspaces() except Exception as e: print(str_e(e)) else: if len(now_editing.body) == 1: options.workspace = now_editing.body[0]['name'] options.owner = now_editing.body[0]['owner'] # TODO: list possible workspaces to join if > 1 is active if options.list: if len(term_name) != 0: die("I don't understand why you gave me a positional argument.") for opt in ['workspace', 'owner', 'username', 'secret']: if not getattr(options, opt): parser.error('%s not given' % opt) color_reset = '\033[0m' if options.safe: green = '\033[92m' print('%sTerminal is safe. Other users will not be able to send [enter]%s' % (green, color_reset)) else: yellorange = '\033[93m' print('%sTerminal is unsafe. Other users will be able to send [enter]. Be wary!%s' % (yellorange, color_reset)) f = Flootty(options, term_name) G.AGENT = f atexit.register(f.cleanup) f.connect_to_internet() f.select()
URLError = urllib2.URLError import vim from floo.common import api, migrations, msg, reactor, utils, shared as G from floo import editor, vui VUI = vui.VUI() reactor = reactor.reactor # Protocol version G.__VERSION__ = '0.11' G.__PLUGIN_VERSION__ = '3.0.7' utils.reload_settings() migrations.rename_floobits_dir() migrations.migrate_symlinks() G.DELETE_LOCAL_FILES = bool(int(vim.eval('floo_delete_local_files'))) G.SHOW_HIGHLIGHTS = bool(int(vim.eval('floo_show_highlights'))) G.SPARSE_MODE = bool(int(vim.eval('floo_sparse_mode'))) G.TIMERS = bool(int(vim.eval('has("timers")'))) def _get_line_endings(): formats = vim.eval('&fileformats') if not formats: return '\n' name = formats.split(',')[0]
def main(): utils.reload_settings() default_auth = G.AUTH.get(G.DEFAULT_HOST, {}) parser = optparse.OptionParser(usage=usage) parser.add_option("-u", "--username", dest="username", default=default_auth.get('username'), help="Your Floobits username") parser.add_option("-s", "--secret", dest="secret", default=default_auth.get('secret'), help="Your Floobits secret (api key)") parser.add_option("-c", "--create", dest="create", default=False, action="store_true", help="The terminal name to create") parser.add_option( "--host", dest="host", default=G.DEFAULT_HOST, help="The host to connect to. Deprecated. Use --url instead.") parser.add_option( "-p", "--port", dest="port", default=G.DEFAULT_PORT, help="The port to connect to. Deprecated. Use --url instead.") parser.add_option( "-w", "--workspace", dest="workspace", help= "The workspace name. --owner is required with this option. Deprecated. Use --url instead." ) parser.add_option( "-o", "--owner", dest="owner", help= "The workspace owner. --workspace is required with this option. Deprecated. Use --url instead." ) parser.add_option("-l", "--list", dest="list", default=False, action="store_true", help="List all terminals in the workspace") parser.add_option( "--unsafe", dest="safe", default=True, action="store_false", help= "Less safe terminal. This allows other users to send enter in your terminal." ) parser.add_option( "--no-ssl", dest="use_ssl", default=True, action="store_false", help="Do not use this option unless you know what you are doing!") parser.add_option("--url", dest="workspace_url", default=None, help="The URL of the workspace to connect to.") parser.add_option("--resize", dest="resize", default=False, action="store_true", help="Resize your terminal to the host terminal size.") parser.add_option( "--shell", dest="shell", default=os.environ.get("SHELL", None), help="The shell you would like to use with flootty. Defaults to $SHELL." ) parser.add_option("-P", "--preserve-ps1", dest="set_prompt", default=True, action="store_false", help="Don't change $PS1 (bash/zsh prompt)") parser.add_option("-v", "--version", dest="version", default=False, action="store_true", help="Print version") options, args = parser.parse_args() if options.version: print('flootty %s' % version.FLOOTTY_VERSION) return default_term_name = "" if options.create: default_term_name = "ftty" term_name = args and args[0] or default_term_name if options.workspace and options.owner and options.workspace_url: # TODO: confusing parser.error( "You can either specify --workspace and --owner, or --url, but not both." ) if bool(options.workspace) != bool(options.owner): parser.error("You must specify a workspace and owner or neither.") for opt in ['owner', 'workspace']: if getattr(options, opt): print('%s is deprecated. Please use --url instead.' % opt) if not options.workspace or not options.owner: floo = {} if options.workspace_url: floo = utils.parse_url(options.workspace_url) else: for floo_path in walk_up(os.path.realpath('.')): try: floo = json.loads( open(os.path.join(floo_path, '.floo'), 'rb').read().decode('utf-8')) floo = utils.parse_url(floo['url']) except Exception: pass else: break options.host = floo.get('host') options.workspace = floo.get('workspace') options.owner = floo.get('owner') options.use_ssl = floo.get('secure') if not options.port: options.port = floo.get('port') if not options.host: options.host = floo.get('host') if options.host is None: options.host = G.DEFAULT_HOST if options.host != G.DEFAULT_HOST and options.secret == default_auth.get( 'secret'): auth = G.AUTH.get(options.host) if not auth: return die("Please add credentials for %s in ~/.floorc.json" % options.host) options.username = auth.get('username') options.secret = auth.get('secret') if not options.workspace or not options.owner: try: now_editing = get_now_editing_workspaces() except Exception as e: print(str_e(e)) else: if len(now_editing.body) == 1: options.workspace = now_editing.body[0]['name'] options.owner = now_editing.body[0]['owner'] # TODO: list possible workspaces to join if > 1 is active if options.list: if len(term_name) != 0: die("I don't understand why you gave me a positional argument.") for opt in ['username', 'secret']: if not getattr(options, opt): parser.error( '%s not given. Please use --%s or add credentials to ~/.floorc.json' % (opt, opt)) for opt in ['workspace', 'owner']: if not getattr(options, opt): parser.error('%s not given' % opt) color_reset = '\033[0m' if not G.FLOOTTY_SAFE: options.safe = G.FLOOTTY_SAFE if options.safe: green = '\033[92m' print( '%sTerminal is safe. Other users will not be able to send [enter]%s' % (green, color_reset)) else: yellorange = '\033[93m' print( '%sTerminal is unsafe. Other users will be able to send [enter]. Be wary!%s' % (yellorange, color_reset)) f = Flootty(options, term_name) G.AGENT = f atexit.register(f.cleanup) f.connect_to_internet() f.select()
def run(self, workspace_url, agent_conn_kwargs=None): agent_conn_kwargs = agent_conn_kwargs or {} def get_workspace_window(): workspace_window = None for w in sublime.windows(): for f in w.folders(): if f == G.PROJECT_PATH: workspace_window = w break return workspace_window def set_workspace_window(cb): workspace_window = get_workspace_window() if workspace_window is None: return utils.set_timeout(set_workspace_window, 50, cb) G.WORKSPACE_WINDOW = workspace_window cb() def truncate_chat_view(chat_view, cb): if chat_view: chat_view.set_read_only(False) chat_view.run_command('floo_view_replace_region', { 'r': [0, chat_view.size()], 'data': '' }) chat_view.set_read_only(True) cb() def create_chat_view(cb): with open(os.path.join(G.BASE_DIR, 'msgs.floobits.log'), 'a') as msgs_fd: msgs_fd.write('') get_or_create_chat( lambda chat_view: truncate_chat_view(chat_view, cb)) def open_workspace_window2(cb): if sublime.platform() == 'linux': subl = open('/proc/self/cmdline').read().split(chr(0))[0] elif sublime.platform() == 'osx': # TODO: totally explodes if you install ST2 somewhere else settings = sublime.load_settings('Floobits.sublime-settings') subl = settings.get( 'sublime_executable', '/Applications/Sublime Text 2.app/Contents/SharedSupport/bin/subl' ) if not os.path.exists(subl): return sublime.error_message( 'Can\'t find your Sublime Text executable at %s. Please add "sublime_executable /path/to/subl" to your ~/.floorc and restart Sublime Text' % subl) elif sublime.platform() == 'windows': subl = sys.executable else: raise Exception('WHAT PLATFORM ARE WE ON?!?!?') command = [subl] if get_workspace_window() is None: command.append('--new-window') command.append('--add') command.append(G.PROJECT_PATH) # Maybe no msg view yet :( print('command:', command) p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) poll_result = p.poll() print('poll:', poll_result) set_workspace_window(lambda: create_chat_view(cb)) def open_workspace_window3(cb): G.WORKSPACE_WINDOW = get_workspace_window() if not G.WORKSPACE_WINDOW: G.WORKSPACE_WINDOW = sublime.active_window() msg.debug('Setting project data. Path: %s' % G.PROJECT_PATH) G.WORKSPACE_WINDOW.set_project_data( {'folders': [{ 'path': G.PROJECT_PATH }]}) create_chat_view(cb) def open_workspace_window(cb): if PY2: open_workspace_window2(cb) else: open_workspace_window3(cb) def run_agent(owner, workspace, host, port, secure): global on_room_info_waterfall if G.AGENT: msg.debug('Stopping agent.') G.AGENT.stop() G.AGENT = None on_room_info_waterfall.add(update_recent_workspaces, {'url': workspace_url}) try: msg.debug("agent_conn_kwargs: %s" % str(agent_conn_kwargs)) G.AGENT = AgentConnection( owner=owner, workspace=workspace, host=host, port=port, secure=secure, on_room_info=on_room_info_waterfall.call, **agent_conn_kwargs) on_room_info_waterfall = utils.Waterfall() Listener.reset() G.AGENT.connect() except Exception as e: print(e) tb = traceback.format_exc() print(tb) def make_dir(d): d = os.path.realpath(os.path.expanduser(d)) if not os.path.isdir(d): make_dir = sublime.ok_cancel_dialog( '%s is not a directory. Create it?' % d) if not make_dir: return self.window.show_input_panel( '%s is not a directory. Enter an existing path:' % d, d, None, None, None) try: utils.mkdir(d) except Exception as e: return sublime.error_message( 'Could not create directory %s: %s' % (d, str(e))) G.PROJECT_PATH = d add_workspace_to_persistent_json(result['owner'], result['workspace'], workspace_url, d) open_workspace_window(lambda: run_agent(**result)) try: result = utils.parse_url(workspace_url) except Exception as e: return sublime.error_message(str(e)) utils.reload_settings() if not (G.USERNAME and G.SECRET): return create_or_link_account() d = utils.get_persistent_data() try: G.PROJECT_PATH = d['workspaces'][result['owner']][ result['workspace']]['path'] except Exception as e: G.PROJECT_PATH = '' print('Project path is %s' % G.PROJECT_PATH) if not os.path.isdir(G.PROJECT_PATH): default_dir = os.path.realpath( os.path.join(G.COLAB_DIR, result['owner'], result['workspace'])) return self.window.show_input_panel('Save workspace in directory:', default_dir, make_dir, None, None) open_workspace_window(lambda: run_agent(**result))
def share_dir(self, context, dir_to_share, api_args): utils.reload_settings() if not utils.can_auth(): success = yield self.create_or_link_account, context, G.DEFAULT_HOST, False if not success: return utils.reload_settings() dir_to_share = os.path.expanduser(dir_to_share) dir_to_share = os.path.realpath(dir_to_share) dir_to_share = utils.unfuck_path(dir_to_share) if os.path.isfile(dir_to_share): dir_to_share = os.path.dirname(dir_to_share) workspace_name = os.path.basename(dir_to_share) msg.debug('', workspace_name, dir_to_share) if os.path.isfile(dir_to_share): dir_to_share = os.path.dirname(dir_to_share) try: utils.mkdir(dir_to_share) except Exception: msg.error("The directory", dir_to_share, "doesn't exist and I can't create it.") return info = utils.read_floo_file(dir_to_share) def prejoin(workspace_url): try: return self.prejoin_workspace(workspace_url, dir_to_share, api_args) except ValueError: pass workspace_url = info.get('url') if workspace_url: parsed_url = prejoin(workspace_url) if parsed_url: self.remote_connect(context, parsed_url['host'], parsed_url['owner'], parsed_url['workspace'], dir_to_share) return parsed_url = utils.get_workspace_by_path(dir_to_share, prejoin) if parsed_url: self.remote_connect(context, parsed_url['host'], parsed_url['owner'], parsed_url['workspace'], dir_to_share) return host = yield self._get_host, context if not host: return try: r = api.get_orgs_can_admin(host) except IOError as e: editor.error_message('Error getting org list: %s' % str_e(e)) return choices = [G.AUTH[host]['username']] if r.code >= 400: editor.error_message('Error getting org list: %s' % r.body) elif r.body: choices += [org['name'] for org in r.body] if len(choices) == 1: owner = choices[0] else: little = ['Create workspace owned by %s' % s for s in choices] ( owner, index ) = yield self.user_select, context, 'Create workspace owned by', choices, little if not owner: return self.create_workspace(context, host, owner, workspace_name, api_args, dir_to_share)
def floobits_share_dir(dir_to_share, perms): utils.reload_settings() workspace_name = os.path.basename(dir_to_share) G.PROJECT_PATH = os.path.realpath(dir_to_share) msg.debug('%s %s %s' % (G.USERNAME, workspace_name, G.PROJECT_PATH)) file_to_share = None dir_to_share = os.path.expanduser(dir_to_share) dir_to_share = utils.unfuck_path(dir_to_share) dir_to_share = os.path.abspath(dir_to_share) dir_to_share = os.path.realpath(dir_to_share) workspace_name = os.path.basename(dir_to_share) if os.path.isfile(dir_to_share): file_to_share = dir_to_share dir_to_share = os.path.dirname(dir_to_share) try: utils.mkdir(dir_to_share) except Exception: return msg.error( "The directory %s doesn't exist and I can't create it." % dir_to_share) if not os.path.isdir(dir_to_share): return msg.error('The directory %s doesn\'t appear to exist' % dir_to_share) floo_file = os.path.join(dir_to_share, '.floo') # look for the .floo file for hints about previous behavior info = {} try: floo_info = open(floo_file, 'rb').read().decode('utf-8') info = json.loads(floo_info) except (IOError, OSError): pass except Exception: msg.warn('couldn\'t read the floo_info file: %s' % floo_file) workspace_url = info.get('url') if workspace_url: parsed_url = api.prejoin_workspace(workspace_url, dir_to_share, {'perms': perms}) if parsed_url: return floobits_join_workspace(workspace_url, dir_to_share, upload_path=file_to_share or dir_to_share) filter_func = lambda workspace_url: api.prejoin_workspace( workspace_url, dir_to_share, {'perms': perms}) parsed_url = utils.get_workspace_by_path(dir_to_share, filter_func) if parsed_url: return floobits_join_workspace(workspace_url, dir_to_share, upload_path=file_to_share or dir_to_share) try: r = api.get_orgs_can_admin() except IOError as e: return editor.error_message('Error getting org list: %s' % str(e)) if r.code >= 400 or len(r.body) == 0: workspace_name = vim_input('Workspace name:', workspace_name, "file") return create_workspace(workspace_name, dir_to_share, G.USERNAME, perms, upload_path=file_to_share or dir_to_share) orgs = r.body if len(orgs) == 0: return create_workspace(workspace_name, dir_to_share, G.USERNAME, perms, upload_path=file_to_share or dir_to_share) choices = [] choices.append(G.USERNAME) for o in orgs: choices.append(o['name']) owner = vim_choice('Create workspace for:', G.USERNAME, choices) if owner: return create_workspace(workspace_name, dir_to_share, owner, perms, upload_path=file_to_share or dir_to_share)