beemovie.py 4.92 KB
Newer Older
Henke's avatar
Henke committed
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
import argparse
import sys
from collections import namedtuple

TextPointer = namedtuple('TextPointer', 'index')

NO_EXCEPT = True
BEE_FILE = 'beemovie.txt'

def read_file(cache=[]):
    if cache:
        return cache
    with open(BEE_FILE, 'r') as f:
        lines = [x.strip() for x in f]
    non_empty_lines = [x for x in lines if x]
    for line in non_empty_lines:
        cache.extend(line.split())
    return cache

def beetext():
    return read_file()

def beeify(line, text_ptr, max_len, comment, inline_l, inline_r):
    '''Returns an updated line and a new text pointer.'''
    if len(line) > max_len and not NO_EXCEPT:
        raise Exception("You have one line that is too long: {}".format(line))
    if text_ptr.index >= len(beetext()):
        return line, text_ptr
    text = beetext()

    # Fix inline comments
    if inline_l:
        space_len = 0
        while space_len < len(line) and line[space_len] == ' ':
            space_len += 1
        space_len -= 1
        current = inline_l
        while len(current) + 1 + len(inline_r) + len(text[text_ptr.index]) <= space_len:
            current += ' {}'.format(text[text_ptr.index])
            text_ptr = TextPointer(text_ptr.index + 1)
            if text_ptr.index >= len(text):
                break

        if current != inline_l:
            while len(current) + 1 + len(inline_r) < space_len:
                current += ' '
            current += ' {}'.format(inline_r)
            line = current + line[len(current):]

        if line.strip().endswith('\\'):
            # Use inline comments at end of line
            current = ' {}'.format(inline_l)
            while len(line) + len(current) + 1 + len(inline_r) + len(text[text_ptr.index]) <= max_len:
                current += ' {}'.format(text[text_ptr.index])
                text_ptr = TextPointer(text_ptr.index + 1)
                if text_ptr.index >= len(text):
                    break
            if current != inline_l:
                while len(line) + len(current) + 1 + len(inline_r) < max_len:
                    current += ' '
                current += ' {}'.format(inline_r)
                return '{}{}'.format(line, current), text_ptr

    # Fix end of line comments
    current = ''
    comment_len = len(' {}'.format(comment))
    while text_ptr.index < len(text) and \
          len(line) + comment_len + len(current) + len(text[text_ptr.index]) + 1 <= max_len:
        current += ' {}'.format(beetext()[text_ptr.index])
        text_ptr = TextPointer(text_ptr.index + 1)
        if text_ptr.index >= len(beetext()):
            break

    if not current:
        return line, text_ptr

    # Left pad until right aligned
    while len('{} {}{}'.format(line, comment, current)) < max_len:
        line += ' '
    return '{} {}{}'.format(line, comment, current), text_ptr

def beeify_file(fname, max_len, comment, text_ptr, L, R):
    with open(fname, 'r') as f:
        lines = [x.rstrip() for x in f.readlines()]
    bee_lines = []
    for line in lines:
        bee, text_ptr = beeify(line, text_ptr, max_len, comment, L, R)
        bee_lines.append(bee)
    return bee_lines, text_ptr

def beeify_filename(fname):
    return '{}.bee'.format(fname)

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Create bee-ified source code')
    parser.add_argument('filename', nargs='+', help='Input files to apply the bee-ifier on')
    parser.add_argument('--print', dest='should_print', action='store_const',
                        const=True, default=False, help='Prints the resulting file')
    parser.add_argument('--width', type=int, default=80, help='width of each file line')
    parser.add_argument('--comment', type=str, default='//', help='comment string')
    parser.add_argument('--beesource', help='Specify source for bee movie script')
    parser.add_argument('--exceptions', action='store_const',
                        const=True, default=False, help='Raise exceptions for long lines')
    parser.add_argument('--comment-l', type=str, default='', dest='L',
                        help='Use this as left side of inline comment.')
    parser.add_argument('--comment-r', type=str, default='', dest='R',
                        help='Use this as right side of inline comment. (Both left and right needs to be set to work)')

    args = parser.parse_args()
    BEE_FILE = BEE_FILE or args.beesource
    NO_EXCEPT = not args.exceptions
    L, R = args.L, args.R
    text_ptr = TextPointer(0)
    if args.should_print:
        bee = []
        for fname in args.filename:
            line, text_ptr = beeify_file(fname, args.width, args.comment, text_ptr, L, R)
            bee.extend(line)
        for line in bee:
            print(line)
    else:
        for fname in args.filename:
            beefname = beeify_filename(fname)
            lines, text_ptr = beeify_file(fname, args.width, args.comment, text_ptr, L, R)
            with open(beefname, 'w') as f:
                for line in lines:
                    print(line, file=f)