def read(self, sheet): """ Returns the contents of the cheatsheet as a String """ if not self._exists(sheet): Utils.die('No cheatsheet found for ' + sheet) with io.open(self._path(sheet), encoding='utf-8') as cheatfile: return cheatfile.read()
def open(self, filepath): """ Open `filepath` using the EDITOR specified by the env variables """ editor_cmd = self.editor().split() try: subprocess.call(editor_cmd + [filepath]) except OSError: Utils.die('Could not launch ' + self.editor())
def __init__(self, config): self._config = config self._colorize = Colorize(config) # Assembles a dictionary of cheatsheets as name => file-path self._sheets = {} sheet_paths = [config.cheat_user_dir] # merge the CHEAT_PATH paths into the sheet_paths if config.cheat_path: for path in config.cheat_path.split(os.pathsep): if os.path.isdir(path): sheet_paths.append(path) if not sheet_paths: Utils.die('The CHEAT_USER_DIR dir does not exist ' + 'or the CHEAT_PATH is not set.') # otherwise, scan the filesystem for cheat_dir in reversed(sheet_paths): self._sheets.update( dict([ (cheat, os.path.join(cheat_dir, cheat)) for cheat in os.listdir(cheat_dir) if not cheat.startswith('.') and not cheat.startswith('__') ]))
def open(self, filepath): """ Open `filepath` using the EDITOR specified by the env variables """ editor_cmd = self.editor().split() try: subprocess.call(editor_cmd + [filepath]) except OSError: Utils.die('Could not launch ' + self.editor())
def edit(self, sheet): """ Creates or edits a cheatsheet """ # if the cheatsheet does not exist if not self._exists(sheet): new_path = os.path.join(self._config.cheat_user_dir, sheet) self._editor.open(new_path) # if the cheatsheet exists but not in the default_path, copy it to the # default path before editing elif self._exists(sheet) and not self._exists_in_default_path(sheet): try: shutil.copy(self._path(sheet), os.path.join(self._config.cheat_user_dir, sheet)) # fail gracefully if the cheatsheet cannot be copied. This can # happen if CHEAT_USER_DIR does not exist except IOError: Utils.die('Could not copy cheatsheet for editing.') self._editor.open(self._path(sheet)) # if it exists and is in the default path, then just open it else: self._editor.open(self._path(sheet))
def read(self, sheet): """ Returns the contents of the cheatsheet as a String """ if not self._exists(sheet): Utils.die('No cheatsheet found for ' + sheet) with io.open(self._path(sheet), encoding='utf-8') as cheatfile: return cheatfile.read()
def edit(self, sheet): """ Creates or edits a cheatsheet """ # if the cheatsheet does not exist if not self._exists(sheet): new_path = os.path.join(self._config.cheat_user_dir, sheet) self._editor.open(new_path) # if the cheatsheet exists but not in the default_path, copy it to the # default path before editing elif self._exists(sheet) and not self._exists_in_default_path(sheet): try: shutil.copy( self._path(sheet), os.path.join(self._config.cheat_user_dir, sheet) ) # fail gracefully if the cheatsheet cannot be copied. This can # happen if CHEAT_USER_DIR does not exist except IOError: Utils.die('Could not copy cheatsheet for editing.') self._editor.open(self._path(sheet)) # if it exists and is in the default path, then just open it else: self._editor.open(self._path(sheet))
def read(self, sheet): """ Returns the contents of the cheatsheet as a String """ if not self.exists(sheet): Utils.die('No cheatsheet found for ' + sheet) with open(self.path(sheet)) as cheatfile: return cheatfile.read()
def __init__(self, config): self._config = config self._colorize = Colorize(config) # Assembles a dictionary of cheatsheets as name => file-path self._sheets = {} sheet_paths = [ config.cheat_user_dir ] # merge the CHEAT_PATH paths into the sheet_paths if config.cheat_path: for path in config.cheat_path.split(os.pathsep): if os.path.isdir(path): sheet_paths.append(path) if not sheet_paths: Utils.die('The CHEAT_USER_DIR dir does not exist ' + 'or the CHEAT_PATH is not set.') # otherwise, scan the filesystem for cheat_dir in reversed(sheet_paths): self._sheets.update( dict([ (cheat, os.path.join(cheat_dir, cheat)) for cheat in os.listdir(cheat_dir) if not cheat.startswith('.') and not cheat.startswith('__') ]) )
def editor(self): """ Determines the user's preferred editor """ # assert that the editor is set if not self._config.cheat_editor: Utils.die( 'You must set a CHEAT_EDITOR, VISUAL, or EDITOR environment ' 'variable or setting in order to create/edit a cheatsheet.') return self._config.cheat_editor
def copy(self, current_sheet_path, new_sheet_path): """ Copies a sheet to a new path """ # attempt to copy the sheet to DEFAULT_CHEAT_DIR try: shutil.copy(current_sheet_path, new_sheet_path) # fail gracefully if the cheatsheet cannot be copied. This can happen # if DEFAULT_CHEAT_DIR does not exist except IOError: Utils.die('Could not copy cheatsheet for editing.')
def _check_configuration(self, config): """ Check values in config and warn user or die """ # validate CHEAT_HIGHLIGHT values if set colors = [ 'grey', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white' ] if (config.get('CHEAT_HIGHLIGHT') and config.get('CHEAT_HIGHLIGHT') not in colors): Utils.die("%s %s" % ('CHEAT_HIGHLIGHT must be one of:', colors))
def editor(self): """ Determines the user's preferred editor """ # assert that the editor is set if not self._config.cheat_editor: Utils.die( 'You must set a CHEAT_EDITOR, VISUAL, or EDITOR environment ' 'variable or setting in order to create/edit a cheatsheet.' ) return self._config.cheat_editor
def paths(self): """ Assembles a list of directories containing cheatsheets """ sheet_paths = [ self.default_path(), ] # merge the CHEATPATH paths into the sheet_paths if self._cheatpath: for path in self._cheatpath.split(os.pathsep): if os.path.isdir(path): sheet_paths.append(path) if not sheet_paths: Utils.die('The DEFAULT_CHEAT_DIR dir does not exist ' + 'or the CHEATPATH is not set.') return sheet_paths
def validate(self): """ Validates configuration parameters """ # assert that cheat_highlight contains a valid value highlights = [ 'grey', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white', False ] if self.cheat_highlight not in highlights: Utils.die("%s %s" % ('CHEAT_HIGHLIGHT must be one of:', highlights)) # assert that the color scheme is valid colorschemes = ['light', 'dark'] if self.cheat_colorscheme not in colorschemes: Utils.die("%s %s" % ('CHEAT_COLORSCHEME must be one of:', colorschemes)) return True
def validate(self): """ Validates configuration parameters """ # assert that cheat_highlight contains a valid value highlights = [ 'grey', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white', False ] if self.cheat_highlight not in highlights: Utils.die("%s %s" % ('CHEAT_HIGHLIGHT must be one of:', highlights)) # assert that the color scheme is valid colorschemes = ['light', 'dark'] if self.cheat_colorscheme not in colorschemes: Utils.die("%s %s" % ('CHEAT_COLORSCHEME must be one of:', colorschemes)) return True
def default_path(self): """ Returns the default cheatsheet path """ # determine the default cheatsheet dir default_sheets_dir = (self._default_cheat_dir or os.path.join('~', '.cheat')) default_sheets_dir = os.path.expanduser( os.path.expandvars(default_sheets_dir)) # create the DEFAULT_CHEAT_DIR if it does not exist if not os.path.isdir(default_sheets_dir): try: # @kludge: unclear on why this is necessary os.umask(0000) os.mkdir(default_sheets_dir) except OSError: Utils.die('Could not create DEFAULT_CHEAT_DIR') # assert that the DEFAULT_CHEAT_DIR is readable and writable if not os.access(default_sheets_dir, os.R_OK): Utils.die('The DEFAULT_CHEAT_DIR (' + default_sheets_dir + ') is not readable.') if not os.access(default_sheets_dir, os.W_OK): Utils.die('The DEFAULT_CHEAT_DIR (' + default_sheets_dir + ') is not writable.') # return the default dir return default_sheets_dir
def _get_configuration(self): # get options from config files and environment vairables merged_config = {} try: merged_config.update( self._read_configuration_file(self.glob_config_path)) except Exception as e: Utils.warn('error while parsing global configuration Reason: ' + e.message) try: merged_config.update( self._read_configuration_file(self.local_config_path)) except Exception as e: Utils.warn('error while parsing user configuration Reason: ' + e.message) merged_config.update(self._read_env_vars_config()) self._check_configuration(merged_config) return merged_config
class Sheets: def __init__(self, config): self._default_cheat_dir = config.get_default_cheat_dir() self._cheatpath = config.get_cheatpath() self._utils = Utils(config) def default_path(self): """ Returns the default cheatsheet path """ # determine the default cheatsheet dir default_sheets_dir = (self._default_cheat_dir or os.path.join('~', '.cheat')) default_sheets_dir = os.path.expanduser( os.path.expandvars(default_sheets_dir)) # create the DEFAULT_CHEAT_DIR if it does not exist if not os.path.isdir(default_sheets_dir): try: # @kludge: unclear on why this is necessary os.umask(0000) os.mkdir(default_sheets_dir) except OSError: Utils.die('Could not create DEFAULT_CHEAT_DIR') # assert that the DEFAULT_CHEAT_DIR is readable and writable if not os.access(default_sheets_dir, os.R_OK): Utils.die('The DEFAULT_CHEAT_DIR (' + default_sheets_dir + ') is not readable.') if not os.access(default_sheets_dir, os.W_OK): Utils.die('The DEFAULT_CHEAT_DIR (' + default_sheets_dir + ') is not writable.') # return the default dir return default_sheets_dir def get(self): """ Assembles a dictionary of cheatsheets as name => file-path """ cheats = {} # otherwise, scan the filesystem for cheat_dir in reversed(self.paths()): cheats.update( dict([ (cheat, os.path.join(cheat_dir, cheat)) for cheat in os.listdir(cheat_dir) if not cheat.startswith('.') and not cheat.startswith('__') ])) return cheats def paths(self): """ Assembles a list of directories containing cheatsheets """ sheet_paths = [ self.default_path(), ] # merge the CHEATPATH paths into the sheet_paths if self._cheatpath: for path in self._cheatpath.split(os.pathsep): if os.path.isdir(path): sheet_paths.append(path) if not sheet_paths: Utils.die('The DEFAULT_CHEAT_DIR dir does not exist ' + 'or the CHEATPATH is not set.') return sheet_paths def list(self): """ Lists the available cheatsheets """ sheet_list = '' pad_length = max([len(x) for x in self.get().keys()]) + 4 for sheet in sorted(self.get().items()): sheet_list += sheet[0].ljust(pad_length) + sheet[1] + "\n" return sheet_list def search(self, term): """ Searches all cheatsheets for the specified term """ result = '' for cheatsheet in sorted(self.get().items()): match = '' for line in io.open(cheatsheet[1], encoding='utf-8'): if term in line: match += ' ' + self._utils.highlight(term, line) if match != '': result += cheatsheet[0] + ":\n" + match + "\n" return result
def __init__(self): # compute the location of the config files config_file_path_global = self._select([ os.environ.get('CHEAT_GLOBAL_CONF_PATH'), '/etc/cheat', ]) config_file_path_local = self._select([ os.environ.get('CHEAT_LOCAL_CONF_PATH'), os.path.expanduser('~/.config/cheat/cheat'), ]) # attempt to read the global config file config = {} try: config.update(self._read_config_file(config_file_path_global)) except Exception as e: Utils.warn('Error while parsing global configuration: ' + e.message) # attempt to read the local config file try: config.update(self._read_config_file(config_file_path_local)) except Exception as e: Utils.warn('Error while parsing local configuration: ' + e.message) # With config files read, now begin to apply envvar overrides and # default values # self.cheat_colors self.cheat_colors = self._select([ Utils.boolify(os.environ.get('CHEAT_COLORS')), Utils.boolify(os.environ.get('CHEATCOLORS')), Utils.boolify(config.get('CHEAT_COLORS')), True, ]) # self.cheat_colorscheme self.cheat_colorscheme = self._select([ os.environ.get('CHEAT_COLORSCHEME'), config.get('CHEAT_COLORSCHEME'), 'friendly', ]).strip().lower() # self.cheat_user_dir self.cheat_user_dir = self._select( map(os.path.expanduser, filter(None, [os.environ.get('CHEAT_USER_DIR'), os.environ.get('CHEAT_DEFAULT_DIR'), os.environ.get('DEFAULT_CHEAT_DIR'), # TODO: XDG home? os.path.join('~', '.cheat')]))) # self.cheat_editor self.cheat_editor = self._select([ os.environ.get('CHEAT_EDITOR'), os.environ.get('EDITOR'), os.environ.get('VISUAL'), config.get('CHEAT_EDITOR'), 'vi', ]) # self.cheat_highlight self.cheat_highlight = self._select([ os.environ.get('CHEAT_HIGHLIGHT'), config.get('CHEAT_HIGHLIGHT'), False, ]) if isinstance(self.cheat_highlight, str): Utils.boolify(self.cheat_highlight) # self.cheat_path self.cheat_path = self._select([ os.environ.get('CHEAT_PATH'), os.environ.get('CHEATPATH'), config.get('CHEAT_PATH'), '/usr/share/cheat', ])
def __init__(self): # compute the location of the config files config_file_path_global = self._select([ os.environ.get('CHEAT_GLOBAL_CONF_PATH'), '/etc/cheat', ]) config_file_path_local = self._select([ os.environ.get('CHEAT_LOCAL_CONF_PATH'), os.path.expanduser('~/.config/cheat/cheat'), ]) # attempt to read the global config file config = {} try: config.update(self._read_config_file(config_file_path_global)) except Exception as e: Utils.warn('Error while parsing global configuration: ' + e.message) # attempt to read the local config file try: config.update(self._read_config_file(config_file_path_local)) except Exception as e: Utils.warn('Error while parsing local configuration: ' + e.message) # With config files read, now begin to apply envvar overrides and # default values # self.cheat_colors self.cheat_colors = self._select([ Utils.boolify(os.environ.get('CHEAT_COLORS')), Utils.boolify(os.environ.get('CHEATCOLORS')), Utils.boolify(config.get('CHEAT_COLORS')), True, ]) # self.cheat_colorscheme self.cheat_colorscheme = self._select([ os.environ.get('CHEAT_COLORSCHEME'), config.get('CHEAT_COLORSCHEME'), 'light', ]).strip().lower() # self.cheat_user_dir self.cheat_user_dir = self._select( map(os.path.expanduser, filter(None, [os.environ.get('CHEAT_USER_DIR'), os.environ.get('CHEAT_DEFAULT_DIR'), os.environ.get('DEFAULT_CHEAT_DIR'), # TODO: XDG home? os.path.join('~', '.cheat')]))) # self.cheat_editor self.cheat_editor = self._select([ os.environ.get('CHEAT_EDITOR'), os.environ.get('EDITOR'), os.environ.get('VISUAL'), config.get('CHEAT_EDITOR'), 'vi', ]) # self.cheat_highlight self.cheat_highlight = self._select([ os.environ.get('CHEAT_HIGHLIGHT'), config.get('CHEAT_HIGHLIGHT'), False, ]) if isinstance(self.cheat_highlight, str): Utils.boolify(self.cheat_highlight) # self.cheat_path self.cheat_path = self._select([ os.environ.get('CHEAT_PATH'), os.environ.get('CHEATPATH'), config.get('CHEAT_PATH'), '/usr/share/cheat', ])
def __init__(self, config): self._default_cheat_dir = config.get_default_cheat_dir() self._cheatpath = config.get_cheatpath() self._utils = Utils(config)