breily / cheat

easily create and view help/reminder files

This URL has Read+Write access

cheat / cheat.py
100755 176 lines (160 sloc) 6.281 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
#!/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()