Skip to content

Instantly share code, notes, and snippets.

@tgray
Created April 29, 2022 15:48
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tgray/c1392d6e68c24708bba2926c1aacd76f to your computer and use it in GitHub Desktop.
Save tgray/c1392d6e68c24708bba2926c1aacd76f to your computer and use it in GitHub Desktop.
Markdown table scripts
#!/usr/bin/env python
import sys
def just(string, type, n):
"Justify a string to length n according to type."
if type == '::':
return string.center(n)
elif type == '-:':
return string.rjust(n)
elif type == ':-':
return string.ljust(n)
else:
return string
def normtable(text):
"Aligns the vertical bars in a text table."
# Start by turning the text into a list of lines.
lines = text.splitlines()
rows = len(lines)
# Figure out the cell formatting.
# First, find the separator line.
for i in range(rows):
if set(lines[i]).issubset('|:.-'):
formatline = lines[i]
formatrow = i
break
# Delete the separator line from the content.
del lines[formatrow]
# Determine how each column is to be justified.
formatline = formatline.strip(' ')
if formatline[0] == '|': formatline = formatline[1:]
if formatline[-1] == '|': formatline = formatline[:-1]
fstrings = formatline.split('|')
justify = []
for i, cell in enumerate(fstrings):
ends = cell[0] + cell[-1]
if ends == '::':
justify.append('::')
elif ends == '-:':
justify.append('-:')
elif ends == ':-':
justify.append(':-')
else:
# left justify first column, center the rest
if i == 0:
justify.append(':-')
else:
justify.append('::')
# Assume the number of columns in the separator line is the number
# for the entire table.
columns = len(justify)
# Extract the content into a matrix.
content = []
for line in lines:
line = line.strip(' ')
if line[0] == '|': line = line[1:]
if line[-1] == '|': line = line[:-1]
cells = line.split('|')
# Put exactly one space at each end as "bumpers."
linecontent = [ ' ' + x.strip() + ' ' for x in cells ]
content.append(linecontent)
# Append cells to rows that don't have enough.
rows = len(content)
for i in range(rows):
while len(content[i]) < columns:
content[i].append('')
# Get the width of the content in each column. The minimum width will
# be 2, because that's the shortest length of a formatting string and
# because that matches an empty column with "bumper" spaces.
widths = [2] * columns
for row in content:
for i in range(columns):
widths[i] = max(len(row[i]), widths[i])
# Add whitespace to make all the columns the same width and
formatted = []
for row in content:
formatted.append('|' + '|'.join([ just(s, t, n) for (s, t, n) in zip(row, justify, widths) ]) + '|')
# Recreate the format line with the appropriate column widths.
formatline = '|' + '|'.join([ s[0] + '-'*(n-2) + s[-1] for (s, n) in zip(justify, widths) ]) + '|'
# Insert the formatline back into the table.
formatted.insert(formatrow, formatline)
# Return the formatted table.
return '\n'.join(formatted)
# Read the input, process, and print.
unformatted = sys.stdin.read()
print(normtable(unformatted))
#!/usr/bin/perl -p
# For each line...
$n = s/[ \t]{2,}/\t/g; # tabs to pipes, saving the count
# s/^/\|/; # pipe at beginning
# s/$/\|/; # pipe at end
#
# # Add the formatting line above the second line.
# printf "|" . "--|"x($n+1) . "\n" if $. == 2
#!/usr/bin/perl -n
# For each line...
next if $. == 2; # skip the header separator
s/\|/\t/g; # pipes to tabs
s/[:-]+/ /g; # remove dashes
s/ +/ /g; # runs of spaces to one space
s/ *\t */\t/g; # spaces-tab-spaces to tab
s/^\t//; # remove tab at beginning
s/\t$//; # remove tab at end
print $_; # print the line
# Add the formatting line above the second line.
# printf "" if $. == 2
#!/usr/bin/perl -p
# For each line...
$n = s/\t/\|/g; # tabs to pipes, saving the count
s/^/\|/; # pipe at beginning
s/$/\|/; # pipe at end
# Add the formatting line above the second line.
printf "|" . "--|"x($n+1) . "\n" if $. == 2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment