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
|
import vim
import re
from vim_bridge import bridged
def get_table_bounds():
row, col = vim.current.window.cursor
upper = lower = row
try:
while vim.current.buffer[upper - 1].strip():
upper -= 1
except IndexError:
pass
else:
upper += 1
try:
while vim.current.buffer[lower - 1].strip():
lower += 1
except IndexError:
pass
else:
lower -= 1
return (upper, lower)
def unify_table(table):
max_fields = max(map(lambda row: len(row), table))
output = []
for row in table:
curr_len = len(row)
if curr_len < max_fields:
row += [''] * (max_fields - curr_len)
output.append(row)
return output
def parse_table(raw_lines):
mkfields = lambda line: re.split('\s\s+', line.rstrip())
output = map(mkfields, raw_lines)
output = unify_table(output)
return output
def table_line(widths, header=False):
if header:
linechar = '='
else:
linechar = '-'
sep = '+'
parts = []
for width in widths:
parts.append(linechar * width)
if parts:
parts = [''] + parts + ['']
return sep.join(parts)
def get_column_widths(table):
widths = []
for row in table:
num_fields = len(row)
# dynamically grow
if num_fields >= len(widths):
widths.extend([0] * (num_fields - len(widths)))
for i in range(num_fields):
field_text = row[i]
field_width = len(field_text)
widths[i] = max(widths[i], field_width)
return widths
def pad_fields(table, widths=None):
"""Pads fields of the table, so each row lines up nicely with the others.
If the widths param is None, the widths are calculated automatically.
"""
if widths is None:
widths = get_column_widths(table)
widths = map(lambda w: ' %-' + str(w) + 's ', widths)
# Pad all fields using the calculated widths
output = []
for row in table:
new_row = []
for i in range(len(row)):
col = row[i]
col = widths[i] % col.strip()
new_row.append(col)
output.append(new_row)
return output
def draw_table(table):
if table == []:
return []
col_widths = get_column_widths(table)
table = pad_fields(table, col_widths)
# Reserve room for the spaces
col_widths = map(lambda x: x + 2, col_widths)
header_line = table_line(col_widths, header=True)
normal_line = table_line(col_widths, header=False)
output = [header_line]
first = True
for row in table:
output.append("|".join([''] + row + ['']))
if first:
output.append(header_line)
first = False
else:
output.append(normal_line)
return output
@bridged
def create_table():
upper, lower = get_table_bounds()
slice = vim.current.buffer[upper - 1:lower]
table = parse_table(slice)
slice = draw_table(table)
vim.current.buffer[upper - 1:lower] = slice
|