def __init__(self, debug=(), log_setting=None): self.__version__ = __version__ # Intercept IO enable_io_wrapper() self.config = self._load_config() self.logger = self._config_logging(log_setting) # Tab handler for running scripts self.external_tab_handler = None # Wire the components self.main_screen = ShSequentialScreen(self, nlines_max=self.config.getint( 'display', 'BUFFER_MAX'), debug=_DEBUG_MAIN_SCREEN in debug) self.mini_buffer = ShMiniBuffer(self, self.main_screen, debug=_DEBUG_MINI_BUFFER in debug) self.stream = ShStream(self, self.main_screen, debug=_DEBUG_STREAM in debug) self.io = ShIO(self, debug=_DEBUG_IO in debug) self.terminal = None # will be set during UI initialisation self.ui = ShUI(self, debug=_DEBUG_UI in debug) self.renderer = ShSequentialRenderer(self.main_screen, self.terminal, debug=_DEBUG_RENDERER in debug) parser = ShParser(debug=_DEBUG_PARSER in debug) expander = ShExpander(self, debug=_DEBUG_EXPANDER in debug) self.runtime = ShRuntime(self, parser, expander, debug=_DEBUG_RUNTIME in debug) self.completer = ShCompleter(self, debug=_DEBUG_COMPLETER in debug) # Navigate to the startup folder if IN_PYTHONISTA: os.chdir(self.runtime.state.environ_get('HOME2')) self.runtime.load_rcfile() self.io.write( self.text_style('StaSh v%s\n' % self.__version__, { 'color': 'blue', 'traits': ['bold'] })) self.runtime.script_will_end() # configure the read callback # Load shared libraries self._load_lib()
def __init__(self, debug=(), log_setting=None, no_cfgfile=False, no_rcfile=False, no_historyfile=False): self.__version__ = __version__ # Intercept IO enable_io_wrapper() self.config = self._load_config(no_cfgfile=no_cfgfile) self.logger = self._config_logging(log_setting) self.user_action_proxy = ShUserActionProxy(self) # Tab handler for running scripts self.external_tab_handler = None # Wire the components self.main_screen = ShSequentialScreen(self, nlines_max=self.config.getint('display', 'BUFFER_MAX'), debug=_DEBUG_MAIN_SCREEN in debug) self.mini_buffer = ShMiniBuffer(self, self.main_screen, debug=_DEBUG_MINI_BUFFER in debug) self.stream = ShStream(self, self.main_screen, debug=_DEBUG_STREAM in debug) self.io = ShIO(self, debug=_DEBUG_IO in debug) self.terminal = None # will be set during UI initialisation self.ui = ShUI(self, debug=_DEBUG_UI in debug) self.renderer = ShSequentialRenderer(self.main_screen, self.terminal, debug=_DEBUG_RENDERER in debug) parser = ShParser(debug=_DEBUG_PARSER in debug) expander = ShExpander(self, debug=_DEBUG_EXPANDER in debug) self.runtime = ShRuntime(self, parser, expander, no_historyfile=no_historyfile, debug=_DEBUG_RUNTIME in debug) self.completer = ShCompleter(self, debug=_DEBUG_COMPLETER in debug) # Navigate to the startup folder if IN_PYTHONISTA: os.chdir(self.runtime.state.environ_get('HOME2')) self.runtime.load_rcfile(no_rcfile=no_rcfile) self.io.write(self.text_style('StaSh v%s\n' % self.__version__, {'color': 'blue', 'traits': ['bold']}, always=True)) # Load shared libraries self._load_lib() # Show tip of the day (this calls script_will_end) self('$STASH_ROOT/bin/totd.py', add_to_history=False, persistent_level=0)
def __init__(self, debug=(), log_setting=None): self.__version__ = __version__ # Intercept IO enable_io_wrapper() self.config = self._load_config() self.logger = self._config_logging(log_setting) # Tab handler for running scripts self.external_tab_handler = None # Wire the components self.main_screen = ShSequentialScreen(self, nlines_max=self.config.getint('display', 'BUFFER_MAX'), debug=_DEBUG_MAIN_SCREEN in debug) self.mini_buffer = ShMiniBuffer(self, self.main_screen, debug=_DEBUG_MINI_BUFFER in debug) self.stream = ShStream(self, self.main_screen, debug=_DEBUG_STREAM in debug) self.io = ShIO(self, debug=_DEBUG_IO in debug) self.terminal = None # will be set during UI initialisation self.ui = ShUI(self, debug=_DEBUG_UI in debug) self.renderer = ShSequentialRenderer(self.main_screen, self.terminal, debug=_DEBUG_RENDERER in debug) parser = ShParser(debug=_DEBUG_PARSER in debug) expander = ShExpander(self, debug=_DEBUG_EXPANDER in debug) self.runtime = ShRuntime(self, parser, expander, debug=_DEBUG_RUNTIME in debug) self.completer = ShCompleter(self, debug=_DEBUG_COMPLETER in debug) # Navigate to the startup folder if IN_PYTHONISTA: os.chdir(self.runtime.state.environ_get('HOME2')) self.runtime.load_rcfile() self.io.write(self.text_style('StaSh v%s\n' % self.__version__, {'color': 'blue', 'traits': ['bold']})) self.runtime.script_will_end() # configure the read callback # Load shared libraries self._load_lib()
class StaSh(object): """ Main application class. It initialize and wires the components and provide utility interfaces to running scripts. """ def __init__(self, debug=(), log_setting=None, no_cfgfile=False, no_rcfile=False, no_historyfile=False): self.__version__ = __version__ # Intercept IO enable_io_wrapper() self.config = self._load_config(no_cfgfile=no_cfgfile) self.logger = self._config_logging(log_setting) self.user_action_proxy = ShUserActionProxy(self) # Tab handler for running scripts self.external_tab_handler = None # Wire the components self.main_screen = ShSequentialScreen(self, nlines_max=self.config.getint('display', 'BUFFER_MAX'), debug=_DEBUG_MAIN_SCREEN in debug) self.mini_buffer = ShMiniBuffer(self, self.main_screen, debug=_DEBUG_MINI_BUFFER in debug) self.stream = ShStream(self, self.main_screen, debug=_DEBUG_STREAM in debug) self.io = ShIO(self, debug=_DEBUG_IO in debug) self.terminal = None # will be set during UI initialisation self.ui = ShUI(self, debug=_DEBUG_UI in debug) self.renderer = ShSequentialRenderer(self.main_screen, self.terminal, debug=_DEBUG_RENDERER in debug) parser = ShParser(debug=_DEBUG_PARSER in debug) expander = ShExpander(self, debug=_DEBUG_EXPANDER in debug) self.runtime = ShRuntime(self, parser, expander, no_historyfile=no_historyfile, debug=_DEBUG_RUNTIME in debug) self.completer = ShCompleter(self, debug=_DEBUG_COMPLETER in debug) # Navigate to the startup folder if IN_PYTHONISTA: os.chdir(self.runtime.state.environ_get('HOME2')) self.runtime.load_rcfile(no_rcfile=no_rcfile) self.io.write(self.text_style('StaSh v%s\n' % self.__version__, {'color': 'blue', 'traits': ['bold']}, always=True)) # Load shared libraries self._load_lib() # Show tip of the day (this calls script_will_end) self('$STASH_ROOT/bin/totd.py', add_to_history=False, persistent_level=0) def __call__(self, input_, persistent_level=2, *args, **kwargs): """ This function is to be called by external script for executing shell commands """ worker = self.runtime.run( input_, persistent_level=persistent_level, *args, **kwargs) worker.join() return worker @staticmethod def _load_config(no_cfgfile=False): config = ConfigParser() config.optionxform = str # make it preserve case # defaults config.readfp(StringIO(_DEFAULT_CONFIG)) # update from config file if not no_cfgfile: config.read(os.path.join(_STASH_ROOT, f) for f in _STASH_CONFIG_FILES) return config @staticmethod def _config_logging(log_setting): logger = logging.getLogger('StaSh') _log_setting = { 'level': 'DEBUG', 'stdout': True, } _log_setting.update(log_setting or {}) level = { 'CRITICAL': logging.CRITICAL, 'ERROR': logging.ERROR, 'WARNING': logging.WARNING, 'INFO': logging.INFO, 'DEBUG': logging.DEBUG, 'NOTEST': logging.NOTSET, }.get(_log_setting['level'], logging.DEBUG) logger.setLevel(level) if not logger.handlers: if _log_setting['stdout']: _log_handler = logging.StreamHandler(_SYS_STDOUT) else: _log_handler = logging.handlers.RotatingFileHandler('stash.log', mode='w') _log_handler.setLevel(level) _log_handler.setFormatter(logging.Formatter( '[%(asctime)s] [%(levelname)s] [%(threadName)s] [%(name)s] [%(funcName)s] [%(lineno)d] - %(message)s' )) logger.addHandler(_log_handler) return logger def _load_lib(self): """ Load library files as modules and save each of them as attributes """ lib_path = os.path.join(_STASH_ROOT, 'lib') os.environ['STASH_ROOT'] = _STASH_ROOT # libcompleter needs this value try: for f in os.listdir(lib_path): if f.startswith('lib') and f.endswith('.py') \ and os.path.isfile(os.path.join(lib_path, f)): name, _ = os.path.splitext(f) try: self.__dict__[name] = pyimp.load_source(name, os.path.join(lib_path, f)) except Exception as e: self.write_message('%s: failed to load library file (%s)' % (f, repr(e))) finally: # do not modify environ permanently os.environ.pop('STASH_ROOT') def write_message(self, s): self.io.write('stash: %s\n' % s) def launch(self, style='panel'): self.ui.present(style) self.terminal.begin_editing() def cleanup(self): disable_io_wrapper() def get_workers(self): return [worker for worker in self.runtime.worker_registry] # noinspection PyProtectedMember @staticmethod def text_style(s, style, always=False): """ Style the given string with ASCII escapes. :param str s: String to decorate :param dict style: A dictionary of styles :param bool always: If true, style will be applied even for pipes. :return: """ # No color for pipes, files and Pythonista console if not always and (isinstance(sys.stdout, StringIO) or isinstance(sys.stdout, file) or sys.stdout.write.im_self is _SYS_STDOUT): return s fmt_string = u'%s%%d%s%%s%s%%d%s' % (ctrl.CSI, esc.SGR, ctrl.CSI, esc.SGR) for style_name, style_value in style.items(): if style_name == 'color': color_id = graphics._SGR.get(style_value.lower()) if color_id is not None: s = fmt_string % (color_id, s, graphics._SGR['default']) elif style_name == 'bgcolor': color_id = graphics._SGR.get('bg-' + style_value.lower()) if color_id is not None: s = fmt_string % (color_id, s, graphics._SGR['default']) elif style_name == 'traits': for val in style_value: val = val.lower() if val == 'bold': s = fmt_string % (graphics._SGR['+bold'], s, graphics._SGR['-bold']) elif val == 'italic': s = fmt_string % (graphics._SGR['+italics'], s, graphics._SGR['-italics']) elif val == 'underline': s = fmt_string % (graphics._SGR['+underscore'], s, graphics._SGR['-underscore']) elif val == 'strikethrough': s = fmt_string % (graphics._SGR['+strikethrough'], s, graphics._SGR['-strikethrough']) return s def text_color(self, s, color_name='default', **kwargs): return self.text_style(s, {'color': color_name}, **kwargs) def text_bgcolor(self, s, color_name='default', **kwargs): return self.text_style(s, {'bgcolor': color_name}, **kwargs) def text_bold(self, s, **kwargs): return self.text_style(s, {'traits': ['bold']}, **kwargs) def text_italic(self, s, **kwargs): return self.text_style(s, {'traits': ['italic']}, **kwargs) def text_bold_italic(self, s, **kwargs): return self.text_style(s, {'traits': ['bold', 'italic']}, **kwargs) def text_underline(self, s, **kwargs): return self.text_style(s, {'traits': ['underline']}, **kwargs) def text_strikethrough(self, s, **kwargs): return self.text_style(s, {'traits': ['strikethrough']}, **kwargs)
class StaSh(object): """ Main application class. It initialize and wires the components and provide utility interfaces to running scripts. """ def __init__(self, debug=(), log_setting=None): self.__version__ = __version__ # Intercept IO enable_io_wrapper() self.config = self._load_config() self.logger = self._config_logging(log_setting) # Tab handler for running scripts self.external_tab_handler = None # Wire the components self.main_screen = ShSequentialScreen(self, nlines_max=self.config.getint( 'display', 'BUFFER_MAX'), debug=_DEBUG_MAIN_SCREEN in debug) self.mini_buffer = ShMiniBuffer(self, self.main_screen, debug=_DEBUG_MINI_BUFFER in debug) self.stream = ShStream(self, self.main_screen, debug=_DEBUG_STREAM in debug) self.io = ShIO(self, debug=_DEBUG_IO in debug) self.terminal = None # will be set during UI initialisation self.ui = ShUI(self, debug=_DEBUG_UI in debug) self.renderer = ShSequentialRenderer(self.main_screen, self.terminal, debug=_DEBUG_RENDERER in debug) parser = ShParser(debug=_DEBUG_PARSER in debug) expander = ShExpander(self, debug=_DEBUG_EXPANDER in debug) self.runtime = ShRuntime(self, parser, expander, debug=_DEBUG_RUNTIME in debug) self.completer = ShCompleter(self, debug=_DEBUG_COMPLETER in debug) # Navigate to the startup folder if IN_PYTHONISTA: os.chdir(self.runtime.state.environ_get('HOME2')) self.runtime.load_rcfile() self.io.write( self.text_style('StaSh v%s\n' % self.__version__, { 'color': 'blue', 'traits': ['bold'] })) self.runtime.script_will_end() # configure the read callback # Load shared libraries self._load_lib() def __call__(self, *args, **kwargs): """ This function is to be called by external script for executing shell commands """ worker = self.runtime.run(*args, **kwargs) worker.join() return worker @staticmethod def _load_config(): config = ConfigParser() config.optionxform = str # make it preserve case # defaults config.readfp(StringIO(_DEFAULT_CONFIG)) # update from config file config.read(os.path.join(_STASH_ROOT, f) for f in _STASH_CONFIG_FILES) return config @staticmethod def _config_logging(log_setting): logger = logging.getLogger('StaSh') _log_setting = { 'level': 'DEBUG', 'stdout': True, } _log_setting.update(log_setting or {}) level = { 'CRITICAL': logging.CRITICAL, 'ERROR': logging.ERROR, 'WARNING': logging.WARNING, 'INFO': logging.INFO, 'DEBUG': logging.DEBUG, 'NOTEST': logging.NOTSET, }.get(_log_setting['level'], logging.DEBUG) logger.setLevel(level) if not logger.handlers: if _log_setting['stdout']: _log_handler = logging.StreamHandler(_SYS_STDOUT) else: _log_handler = logging.handlers.RotatingFileHandler( 'stash.log', mode='w') _log_handler.setLevel(level) _log_handler.setFormatter( logging.Formatter( '[%(asctime)s] [%(levelname)s] [%(threadName)s] [%(name)s] [%(funcName)s] [%(lineno)d] - %(message)s' )) logger.addHandler(_log_handler) return logger def _load_lib(self): """ Load library files as modules and save each of them as attributes """ lib_path = os.path.join(_STASH_ROOT, 'lib') os.environ['STASH_ROOT'] = _STASH_ROOT # libcompleter needs this value try: for f in os.listdir(lib_path): if f.startswith('lib') and f.endswith('.py') \ and os.path.isfile(os.path.join(lib_path, f)): name, _ = os.path.splitext(f) try: self.__dict__[name] = pyimp.load_source( name, os.path.join(lib_path, f)) except Exception as e: self.write_message( '%s: failed to load library file (%s)' % (f, repr(e))) finally: # do not modify environ permanently os.environ.pop('STASH_ROOT') def write_message(self, s): self.io.write('stash: %s\n' % s) def launch(self, style='panel'): self.ui.present(style) self.terminal.begin_editing() def cleanup(self): disable_io_wrapper() def get_workers(self): return [worker for worker in self.runtime.worker_registry] # noinspection PyProtectedMember @staticmethod def text_style(s, style, always=False): """ Style the given string with ASCII escapes. :param str s: String to decorate :param dict style: A dictionary of styles :param bool always: If true, style will be applied even for pipes. :return: """ # No color for pipes if not always and (isinstance(sys.stdout, StringIO) or isinstance(sys.stdout, file)): return s fmt_string = u'%s%%d%s%%s%s%%d%s' % (ctrl.CSI, esc.SGR, ctrl.CSI, esc.SGR) for style_name, style_value in style.items(): if style_name == 'color': color_id = graphics._SGR.get(style_value.lower()) if color_id is not None: s = fmt_string % (color_id, s, graphics._SGR['default']) elif style_name == 'bgcolor': color_id = graphics._SGR.get('bg-' + style_value.lower()) if color_id is not None: s = fmt_string % (color_id, s, graphics._SGR['default']) elif style_name == 'traits': for val in style_value: val = val.lower() if val == 'bold': s = fmt_string % (graphics._SGR['+bold'], s, graphics._SGR['-bold']) elif val == 'italic': s = fmt_string % (graphics._SGR['+italics'], s, graphics._SGR['-italics']) elif val == 'underline': s = fmt_string % (graphics._SGR['+underscore'], s, graphics._SGR['-underscore']) elif val == 'strikethrough': s = fmt_string % (graphics._SGR['+strikethrough'], s, graphics._SGR['-strikethrough']) return s def text_color(self, s, color_name='default', **kwargs): return self.text_style(s, {'color': color_name}, **kwargs) def text_bgcolor(self, s, color_name='default', **kwargs): return self.text_style(s, {'bgcolor': color_name}, **kwargs) def text_bold(self, s, **kwargs): return self.text_style(s, {'traits': ['bold']}, **kwargs) def text_italic(self, s, **kwargs): return self.text_style(s, {'traits': ['italic']}, **kwargs) def text_bold_italic(self, s, **kwargs): return self.text_style(s, {'traits': ['bold', 'italic']}, **kwargs) def text_underline(self, s, **kwargs): return self.text_style(s, {'traits': ['underline']}, **kwargs) def text_strikethrough(self, s, **kwargs): return self.text_style(s, {'traits': ['strikethrough']}, **kwargs)
def __init__(self, debug=(), log_setting=None, no_cfgfile=False, no_rcfile=False, no_historyfile=False): self.__version__ = __version__ # Intercept IO enable_io_wrapper() self.config = self._load_config(no_cfgfile=no_cfgfile) self.logger = self._config_logging(log_setting) self.user_action_proxy = ShUserActionProxy(self) # Tab handler for running scripts self.external_tab_handler = None # Wire the components self.main_screen = ShSequentialScreen(self, nlines_max=self.config.getint( 'display', 'BUFFER_MAX'), debug=_DEBUG_MAIN_SCREEN in debug) self.mini_buffer = ShMiniBuffer(self, self.main_screen, debug=_DEBUG_MINI_BUFFER in debug) self.stream = ShStream(self, self.main_screen, debug=_DEBUG_STREAM in debug) self.io = ShIO(self, debug=_DEBUG_IO in debug) self.terminal = None # will be set during UI initialisation self.ui = ShUI(self, debug=_DEBUG_UI in debug) self.renderer = ShSequentialRenderer(self.main_screen, self.terminal, debug=_DEBUG_RENDERER in debug) parser = ShParser(debug=_DEBUG_PARSER in debug) expander = ShExpander(self, debug=_DEBUG_EXPANDER in debug) self.runtime = ShRuntime(self, parser, expander, no_historyfile=no_historyfile, debug=_DEBUG_RUNTIME in debug) self.completer = ShCompleter(self, debug=_DEBUG_COMPLETER in debug) # Navigate to the startup folder if IN_PYTHONISTA: os.chdir(self.runtime.state.environ_get('HOME2')) self.runtime.load_rcfile(no_rcfile=no_rcfile) self.io.write( self.text_style('StaSh v%s\n' % self.__version__, { 'color': 'blue', 'traits': ['bold'] }, always=True)) # Load shared libraries self._load_lib() # Show tip of the day (this calls script_will_end) self('$STASH_ROOT/bin/totd.py', add_to_history=False, persistent_level=0)