From a0cfee02d2603b412532b829559f06aa74398238 Mon Sep 17 00:00:00 2001 From: roemer_j Date: Mon, 16 Sep 2013 04:10:45 +0200 Subject: [PATCH 1/4] Revert Print back to main, would be easier to integrate other positional option like that --- cheat | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/cheat b/cheat index d3aafb8..fb8188e 100755 --- a/cheat +++ b/cheat @@ -158,26 +158,6 @@ def main(): edit_cheatsheet(values[0], cheatsheets) parser.exit() - # print the cheatsheet if it exists - class PrintSheet(argparse.Action): - def __call__(self, parser, namespace, value, option_string=None): - if not value or value in ['help', 'cheat']: - parser.print_help() - elif value in cheatsheets: - filename = os.path.join(cheatsheets[value], value) - if USE_PYGMENTS: - pretty_print(filename) - else: - with open(filename) as istream: - for l in istream: - sys.stdout.write(l) - - # if it does not, say so - else: - print >> sys.stderr, ('No cheatsheet found for %s.' % value) - parser.exit(1) - parser.exit() - desc = dedent(''' cheat allows you to create and view interactive cheatsheets on the command-line. It was designed to help remind *nix system @@ -205,7 +185,7 @@ def main(): formatter_class=argparse.RawDescriptionHelpFormatter) parser_group = parser.add_mutually_exclusive_group() parser_group.add_argument('sheet', metavar='cheatsheet', - action=PrintSheet, type=str, nargs='?', + action='store', type=str, nargs='?', help='Look at ') parser_group.add_argument('-c', '--create', metavar='cheatsheet', action=EditSheet, type=str, nargs=1, @@ -220,6 +200,25 @@ def main(): action=ListDirectories, nargs=0, help='List all current cheat dirs') args = parser.parse_args() + sheet = args.sheet + + # Print the cheatsheet if it exists + if not sheet or sheet in ['help', 'cheat']: + parser.print_help() + elif sheet in cheatsheets: + filename = os.path.join(cheatsheets[sheet], sheet) + if USE_PYGMENTS: + pretty_print(filename) + else: + with open(filename) as istream: + for l in istream: + sys.stdout.write(l) + + # if it does not, say so + else: + print >> sys.stderr, ('No cheatsheet found for %s.' % sheet) + exit(1) + exit() if __name__ == '__main__': main() From e02e5011fca4caf8775173b545d8f4722ecec703 Mon Sep 17 00:00:00 2001 From: 0rax Date: Fri, 20 Sep 2013 02:03:30 +0200 Subject: [PATCH 2/4] prepare to merge --- cheat | 224 ---------------------------------------------------------- 1 file changed, 224 deletions(-) delete mode 100755 cheat diff --git a/cheat b/cheat deleted file mode 100755 index fb8188e..0000000 --- a/cheat +++ /dev/null @@ -1,224 +0,0 @@ -#!/usr/bin/env python -""" -cheat.py -- cheat allows you to create and view interactive cheatsheets on the - command-line. It was designed to help remind *nix system - administrators of options for commands that they use frequently, - but not frequently enough to remember. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -""" - -import os -import sys -import argparse -import subprocess -from textwrap import dedent - -DEFAULT_CHEAT_DIR = os.environ.get('DEFAULT_CHEAT_DIR') or \ - os.path.join(os.path.expanduser('~'), '.cheat') -USE_PYGMENTS = False - -# NOTE remove this check if it is confirmed to work on windows -if os.name == 'posix' and 'CHEATCOLORS' in os.environ: - try: - from pygments import highlight - from pygments.util import ClassNotFound - from pygments.lexers import get_lexer_for_filename, TextLexer - from pygments.formatters import TerminalFormatter - USE_PYGMENTS = True - except ImportError: - pass - -def cheat_directories(): - "Assembles a list of directories containing cheatsheets." - default_directories = [DEFAULT_CHEAT_DIR] - try: - import cheatsheets - default_directories.append(cheatsheets.cheat_dir) - except ImportError: - pass - - default = [default_dir for default_dir in default_directories - if os.path.isdir(default_dir)] - - if 'CHEATPATH' in os.environ and os.environ['CHEATPATH']: - return [path for path in os.environ['CHEATPATH'].split(os.pathsep) - if os.path.isdir(path)] + default - else: - return default - - -def cheat_files(cheat_directories): - "Assembles a dictionary of cheatsheets found in the above directories." - cheats = {} - for cheat_dir in reversed(cheat_directories): - cheats.update(dict([(cheat, cheat_dir) - for cheat in os.listdir(cheat_dir) - if not cheat.startswith('.') - and not cheat.startswith('__')])) - return cheats - - -def edit_cheatsheet(cheat, cheatsheets): - "Creates or edits a cheatsheet" - - # Assert that the EDITOR environment variable is set and that at least 3 - # arguments have been given - if 'EDITOR' not in os.environ: - print('In order to use "create" or "edit" you must set your ' - 'EDITOR environment variable to your favorite editor\'s path') - exit() - - elif len(sys.argv) < 3: - print('Must provide a cheatsheet to edit/create') - exit() - - # if the cheatsheet already exists, open it for editing - if cheat in cheatsheets: - subprocess.call([os.environ['EDITOR'], - os.path.join(cheatsheets[cheat], cheat)]) - - # otherwise, create it - else: - import cheatsheets as cs - # Attempt to write the new cheatsheet to the user's ~/.cheat dir if it - # exists. If it does not exist, attempt to create it. - if os.access(DEFAULT_CHEAT_DIR, os.W_OK) or os.makedirs(DEFAULT_CHEAT_DIR): - subprocess.call([os.environ['EDITOR'], - os.path.join(DEFAULT_CHEAT_DIR, cheat)]) - - # If the directory cannot be created, write to the python package - # directory, though that will likely require the use of sudo - else: - subprocess.call([os.environ['EDITOR'], - os.path.join(cs.cheat_dir, cheat)]) - -def list_cheatsheets(cheatsheets): - "Lists the cheatsheets that are currently available" - max_command = max([len(x) for x in cheatsheets.keys()]) + 3 - return ('\n'.join(sorted(['%s [%s]' % (key.ljust(max_command), value) - for key, value in cheatsheets.items()]))) - -def pretty_print(filename): - "Applies syntax highlighting to a cheatsheet and writes it to stdout" - try: - if os.path.splitext(filename)[1]: - lexer = get_lexer_for_filename(filename) - else: - # shell is a sensible default when there is no extension - lexer = get_lexer_for_filename(filename + '.sh') - - except ClassNotFound: - lexer = TextLexer() - - with open(filename) as istream: - code = istream.read() - - fmt = TerminalFormatter() - highlight(code, lexer, fmt, sys.stdout) - -def main(): - cheat_dirs = cheat_directories() - - # verify that we have at least one cheat directory - if not cheat_dirs: - error_msg = 'The {default} dir does not exist or the CHEATPATH var is not set.' - print >> sys.stderr, error_msg.format(default=DEFAULT_CHEAT_DIR) - exit() - - # list the files in the ~/.cheat directory - cheatsheets = cheat_files(cheat_dirs) - - # list cheat directories and exit - class ListDirectories(argparse.Action): - def __call__(self, parser, namespace, values, option_string=None): - print cheat_directories() - parser.exit() - - # list cheatsheets and exit - class ListCheatsheets(argparse.Action): - def __call__(self, parser, namespace, values, option_string=None): - print list_cheatsheets(cheatsheets) - parser.exit() - - # if the user wants to edit a cheatsheet - class EditSheet(argparse.Action): - def __call__(self, parser, namespace, values, option_string=None): - edit_cheatsheet(values[0], cheatsheets) - parser.exit() - - desc = dedent(''' - cheat allows you to create and view interactive cheatsheets on the - command-line. It was designed to help remind *nix system - administrators of options for commands that they use frequently, - but not frequently enough to remember.''').strip() - - epi = dedent(''' - Examples: - - To look up 'tar': - cheat tar - - To create or edit the cheatsheet for 'foo': - cheat -e foo - - To list the directories on the CHEATPATH - cheat -d - - To list the available cheatsheets: - cheat -l - ''').strip() - - parser = argparse.ArgumentParser(prog='cheat', - description=desc, epilog=epi, - formatter_class=argparse.RawDescriptionHelpFormatter) - parser_group = parser.add_mutually_exclusive_group() - parser_group.add_argument('sheet', metavar='cheatsheet', - action='store', type=str, nargs='?', - help='Look at ') - parser_group.add_argument('-c', '--create', metavar='cheatsheet', - action=EditSheet, type=str, nargs=1, - help='Create ') - parser_group.add_argument('-e', '--edit', metavar='cheatsheet', - action=EditSheet, type=str, nargs=1, - help='Edit ') - parser_group.add_argument('-l', '--list', - action=ListCheatsheets, nargs=0, - help='List all available cheatsheets') - parser_group.add_argument('-d', '--cheat-directories', - action=ListDirectories, nargs=0, - help='List all current cheat dirs') - args = parser.parse_args() - sheet = args.sheet - - # Print the cheatsheet if it exists - if not sheet or sheet in ['help', 'cheat']: - parser.print_help() - elif sheet in cheatsheets: - filename = os.path.join(cheatsheets[sheet], sheet) - if USE_PYGMENTS: - pretty_print(filename) - else: - with open(filename) as istream: - for l in istream: - sys.stdout.write(l) - - # if it does not, say so - else: - print >> sys.stderr, ('No cheatsheet found for %s.' % sheet) - exit(1) - exit() - -if __name__ == '__main__': - main() From 72b7af171d2bcf9ae2be889eb011fdb621972a85 Mon Sep 17 00:00:00 2001 From: 0rax Date: Fri, 20 Sep 2013 02:12:48 +0200 Subject: [PATCH 3/4] Split EDITOR variable to prevent error on popen while using EDITOR var with spaces --- cheat | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/cheat b/cheat index de2d63b..e8de382 100755 --- a/cheat +++ b/cheat @@ -109,11 +109,11 @@ class CheatSheets(object): print('In order to use "create" or "edit" you must set your ' 'EDITOR environment variable to your favorite editor\'s path') exit() - + else: + editor = os.environ['EDITOR'].split() # if the cheatsheet already exists, open it for editing if cheat in sheets.sheets: - subprocess.call([os.environ['EDITOR'], - os.path.join(self.sheets[cheat], cheat)]) + subprocess.call(editor + [os.path.join(self.sheets[cheat], cheat)]) # otherwise, create it else: @@ -121,14 +121,12 @@ class CheatSheets(object): # Attempt to write the new cheatsheet to the user's ~/.cheat dir if it # exists. If it does not exist, attempt to create it. if os.access(DEFAULT_CHEAT_DIR, os.W_OK) or os.makedirs(DEFAULT_CHEAT_DIR): - subprocess.call([os.environ['EDITOR'], - os.path.join(DEFAULT_CHEAT_DIR, cheat)]) + subprocess.call(editor + [os.path.join(DEFAULT_CHEAT_DIR, cheat)]) # If the directory cannot be created, write to the python package # directory, though that will likely require the use of sudo else: - subprocess.call([os.environ['EDITOR'], - os.path.join(cs.cheat_dir, cheat)]) + subprocess.call(editor + [os.path.join(cs.cheat_dir, cheat)]) def list(self): """Lists the cheatsheets that are currently available""" From 50b04c52e1eedf6e892080ca867b195c7b015036 Mon Sep 17 00:00:00 2001 From: 0rax Date: Fri, 20 Sep 2013 02:27:06 +0200 Subject: [PATCH 4/4] Added 1 check for EDITOR var, if EDITOR is set to "" + added try catch to catch subprocess error like EDITOR variable pointing to a non installed editor --- cheat | 45 ++++++++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/cheat b/cheat index e8de382..6b296fb 100755 --- a/cheat +++ b/cheat @@ -69,7 +69,7 @@ class CheatSheets(object): if not self.dirs: error_msg = 'The {default} dir does not exist or the CHEATPATH var is not set.' print >> sys.stderr, error_msg.format(default=DEFAULT_CHEAT_DIR) - exit() + exit(1) self.sheets = self.__cheat_files() def __cheat_directories(self): @@ -106,27 +106,38 @@ class CheatSheets(object): # Assert that the EDITOR environment variable is set and that at least 3 # arguments have been given if 'EDITOR' not in os.environ: - print('In order to use "create" or "edit" you must set your ' - 'EDITOR environment variable to your favorite editor\'s path') - exit() + print >> sys.stderr, ('In order to create/edit a cheatsheet you ' + 'must set your EDITOR environment variable to your favorite ' + 'editor\'s path.') + exit(1) + elif os.environ['EDITOR'] == "": + print >> sys.stderr, ('Your EDITOR environment variable is set ' + 'to nothing, in order to create/edit a cheatsheet your must ' + 'set it to a valid editor\'s path.') + exit(1) else: editor = os.environ['EDITOR'].split() # if the cheatsheet already exists, open it for editing - if cheat in sheets.sheets: - subprocess.call(editor + [os.path.join(self.sheets[cheat], cheat)]) + try: + if cheat in sheets.sheets: + subprocess.call(editor + [os.path.join(self.sheets[cheat], cheat)]) - # otherwise, create it - else: - import cheatsheets as cs - # Attempt to write the new cheatsheet to the user's ~/.cheat dir if it - # exists. If it does not exist, attempt to create it. - if os.access(DEFAULT_CHEAT_DIR, os.W_OK) or os.makedirs(DEFAULT_CHEAT_DIR): - subprocess.call(editor + [os.path.join(DEFAULT_CHEAT_DIR, cheat)]) - - # If the directory cannot be created, write to the python package - # directory, though that will likely require the use of sudo + # otherwise, create it else: - subprocess.call(editor + [os.path.join(cs.cheat_dir, cheat)]) + import cheatsheets as cs + # Attempt to write the new cheatsheet to the user's ~/.cheat dir if it + # exists. If it does not exist, attempt to create it. + if os.access(DEFAULT_CHEAT_DIR, os.W_OK) or os.makedirs(DEFAULT_CHEAT_DIR): + subprocess.call(editor + [os.path.join(DEFAULT_CHEAT_DIR, cheat)]) + + # If the directory cannot be created, write to the python package + # directory, though that will likely require the use of sudo + else: + subprocess.call(editor + [os.path.join(cs.cheat_dir, cheat)]) + except OSError, e: + print >> sys.stderr, ("Could not launch `%s` as your editor : %s" + % (editor[0], e.strerror)) + exit(1) def list(self): """Lists the cheatsheets that are currently available"""