#!/usr/bin/env python
import os, sys, getopt
# directories to look for cheat files
CHEAT_DIRS = ['~/.cheat/']
# the default editor to use when editing cheat sheets
EDITOR = 'vim'
# since cheat prints a line above and below data, this char gets
# printed. replace with ' ' to get a blank line
DIV_CHAR = '-'
# global verbosity level
VERBOSE = 0
def main():
global VERBOSE
try: opts, args = getopt.getopt(sys.argv[1:], 'vhle:',
['list', 'edit=', 'help', 'verbose'])
except: usage()
mode = 'view' # can be 'view', 'list', 'edit'
term = ' '.join(args) # search term is all irrelevant terms joined
for o, a in opts:
if o in ('-h', '--help'): usage()
if o in ('-v', '--verbose'): VERBOSE = 1
if o in ('-l', '--list'): mode = 'list'
if o in ('-e', '--edit'):
mode = 'edit'
# if a search term is given with edit, use that.
# otherwise use the term given elsewhere
if a != '': term = a
# List all available cheat files
if mode == 'list': list_sheets()
# default search term is 'cheat'; basically a help page
if term == '': term = 'cheat'
# Read in all possible search terms
files = build_term_list()
# Find all matches
matches = []
for file in files:
if term in files[file]: matches.append(file)
# no matches found
if len(matches) == 0:
print 'No matches found for: %s' %term
# only one sheet is found
elif len(matches) == 1:
if mode == 'view': print_sheet(matches[0])
elif mode == 'edit': edit_sheet(matches[0])
# multiple sheets found
else:
# prints a selection menu
for i in range(len(matches)):
print '[%s] %s' %(i, matches[i])
print '[%s] Show All' %(i + 1)
print '[%s] Cancel and Quit' %(i + 2)
choice = raw_input('Selection: ')
# default choice is i + 1, which is 'Show All'
try: choice = int(choice)
except: choice = i + 1
# i + 2 cancels and quits
if choice == i + 2: sys.exit()
# print/edit just one sheet
if choice in range(len(matches)):
if mode == 'view':
print '\n\tShowing: %s' %matches[choice]
print_sheet(matches[choice])
elif mode == 'edit': edit_sheet(matches[choice])
sys.exit()
# print/edit all results
elif choice == i + 1:
for match in matches:
if mode == 'view':
print '\tShowing: %s' %match
print_sheet(match)
elif mode == 'edit': edit_sheet(match)
# Returns a mapping of filenames to terms
def build_term_list():
files = {}
for dir in CHEAT_DIRS:
# Expand '~' in path names
dir = os.path.expanduser(dir)
# append a trailing slash if not present
if dir[-1] != '/': dir = dir + '/'
# list all sheets in directory
file_ls = os.popen('ls %s' %dir).readlines()
for file in file_ls:
# ls returns lines with a '\n' on the end
file = file.strip('\n')
term_list = []
lines = open(dir + file, 'r').readlines()
# find lines listing search terms
term_lines = [l for l in lines if l.strip()[0:5] == 'terms']
if len(term_lines) == 0: continue
# for each one add those terms to term_list
for line in term_lines:
# term line syntax is 'terms :: <term> | etc.'
line = line.split('::')[1].strip('\n')
for term in line.split('|'):
# add term if its not ''
if term: term_list.append(term.strip())
files[file] = term_list
return files
# Prints a files information lines - marked by ], >, }, ), |
def print_sheet(file):
# find out where the file is
for dir in CHEAT_DIRS:
# Expand '~' in path names
dir = os.path.expanduser(dir)
if file + '\n' in os.popen('ls %s' %dir).readlines(): break
text = open(dir + file, 'r').readlines()
# only keep the content lines
info = [line for line in text if line[0] in (']>})|')]
# figure out the longest line to make borders that match
long = max([len(line) for line in info])
# if we can get terminal width, limit delimiter length to that
cols = os.getenv('COLUMNS')
if cols and long > cols: long = int(cols)
# print the top border
print DIV_CHAR * (long / len(DIV_CHAR))
for line in info:
print line.strip(' \n')
# print the bottom border
print DIV_CHAR * (long / len(DIV_CHAR))
# Lists the available cheat files and exits
def list_sheets():
files = []
# find all cheatsheets
for dir in CHEAT_DIRS:
# Expand '~' in path names
dir = os.path.expanduser(dir)
file_ls = os.popen('ls %s' %dir).readlines()
for file in file_ls:
# keep track of its directory
files.append( (file.strip('\n'), dir) )
# ls sorts, but in case there are multiple directories
files.sort()
# used for verbose pretty printing
long = max([len(file[0]) for file in files])
# print one on each line for easy grepability
for file in files:
# VERBOSE prints file location as well as filename
if VERBOSE:
print '%s' %file[0], ' ' * (long - len(file[0])), '\t-> %s' %(file[1] + file[0])
# just print the file name
else: print file[0]
sys.exit()
def edit_sheet(sheet):
# find out where the file is
for dir in CHEAT_DIRS:
# Expand '~' in path names
dir = os.path.expanduser(dir)
if sheet + '\n' in os.popen('ls %s' %dir).readlines(): break
os.system(EDITOR + ' ' + dir + sheet)
def die(msg):
print msg
sys.exit()
def usage():
print 'usage: %s [options]' %sys.argv[0]
print ' ' * len(sys.argv[0]) + " [ 'term' ]"
print ' ' * len(sys.argv[0]) + ' [ -h | --help ]'
print ' ' * len(sys.argv[0]) + ' [ -l | --list ] [ -v | --verbose ]'
print ' ' * len(sys.argv[0]) + " [ -e | --edit 'term' ]"
sys.exit()
if __name__ == '__main__': main()