-
Notifications
You must be signed in to change notification settings - Fork 34
/
reformat-logs.py
130 lines (106 loc) · 3.83 KB
/
reformat-logs.py
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
#!/bin/python3
# coding=utf-8
#
# This script adjusts the `trace` output from racket to be more compatible
# with vscode's automatic code folding.
#
# Emits spaces and adds in a `>` and a `<` at the start of each line.
from pdb import line_prefix
import re
import sys
import fileinput
# When things get deeply nested, racket's tracing
# prints like `> > > >[10]`, where the `10` represents
# the total number of characteres of indent depth.
COUNT_RE = re.compile(r"^((c?[<> ]*)\[(\d+)\]) (.*)$")
# Otherwise it prints like `> > >Foo` when first
# entering Foo and `< < <Blah` when returning a result.
#
# Sometimes it also prints `> > > Bar` -- I *think* that
# is when `Bar` is a subtask of `Foo`.
INDENT_RE = re.compile(r"^(c?[<> ]*)(.*)$")
# Backtraces sometimes appear in the middle of text and should be reproduced just as is.
ERROR_RE = re.compile(
r"(?:^[a-zA-Z]|^ errortrace\.\.\.|^ /|^ context\.\.\.|^ \.\.\.)")
class Section:
def __init__(self, input_indent, input_ident_count, output_indent):
# number of lines of indent in the actual input text
self.input_indent_count = input_ident_count
# input header
if '>' in input_indent:
self.header = '>'
else:
self.header = '<'
# number of spaces we indented by in the output
self.output_indent_indent = output_indent
self.lines = 0
pass
def print_header(self, text):
print_line(self.output_indent_indent, self.header, text)
def print_body(self, input_indent_count, text):
output_indent = input_indent_count - \
self.input_indent_count + self.output_indent_indent
if self.lines == 0:
# putting this character lets you fold the contents of a new
# block without folding children
header = ' ⋮'
self.lines += 1
else:
header = ' '
print_line(output_indent, header, text)
def main():
current_section = None
for line in fileinput.input():
# Backtraces should just print exactly as is.
# mo = ERROR_RE.match(line)
# if mo:
# sys.stdout.write(line)
# continue
mo = COUNT_RE.match(line)
if mo:
input_indent_count = len(mo.group(1))
input_indent = mo.group(2)
output_indent_count = int(mo.group(3)) + 1
text = mo.group(4)
current_section = Section(
input_indent, input_indent_count, output_indent_count
)
current_section.print_header(text)
continue
mo = INDENT_RE.match(line)
if not mo:
raise "bad line: {}".format(line)
indent = mo.group(1)
text = mo.group(2)
if not indent or indent.isspace():
if current_section:
current_section.print_body(len(indent), text)
else:
print_line(len(indent), "", text)
else:
current_section = Section(
indent, len(indent), len(indent)
)
current_section.print_header(text)
def print_line(count, header, text):
print("{}{}{}".format(" " * count, header, text))
def adjust_count(new_header, old_count, count):
# when redex prints "> > >[18]", we adjust that to be 18 spaces,
# but the subsequent lines only have a smaller amount of whitespace,
# so we have to make it match.
if '>' not in new_header and '<' not in new_header:
if old_count > count:
return old_count
return count
def indent_header(old_header, indent):
if '>' in indent:
return '>'
elif '<' in indent:
return '<'
elif old_header == '>':
# putting this character lets you fold the contents of a new
# block without folding children
return ' ⋮'
else:
return ' '
main()