Skip to content

Instantly share code, notes, and snippets.

@kallookoo
Created March 7, 2025 16:38
Show Gist options
  • Save kallookoo/47fa5c7755e26e652712e6b5be3093a6 to your computer and use it in GitHub Desktop.
Save kallookoo/47fa5c7755e26e652712e6b5be3093a6 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
import re
import argparse
import shutil
from pathlib import Path
def split_escaped(s, delimiter):
"""Split a string by a delimiter, ignoring escaped delimiters."""
parts = []
current = []
escape = False
for char in s:
if char == '\\' and not escape:
escape = True
elif char == delimiter and not escape:
parts.append(''.join(current).strip())
current = []
else:
current.append(char)
escape = False
parts.append(''.join(current).strip())
return parts
def format_table(table):
lines = table.strip().split('\n')
headers = split_escaped(lines[0], '|')[1:-1]
separators = split_escaped(lines[1], '|')[1:-1]
rows = [split_escaped(line, '|')[1:-1] for line in lines[2:]]
# Calculate the maximum width for each column
col_widths = [max(len(cell) for cell in col) for col in zip(headers, *rows)]
# Create a format string for each row
row_format = '| ' + ' | '.join(f'{{:<{width}}}' for width in col_widths) + ' |'
# Format the headers, separators, and rows
formatted_table = [
row_format.format(*headers),
row_format.format(*['-' * width for width in col_widths])
]
for row in rows:
formatted_table.append(row_format.format(*row))
return '\n'.join(formatted_table) + '\n'
def format_markdown_tables(markdown_file, backup):
markdown_file = Path(markdown_file)
if not markdown_file.is_file():
raise FileNotFoundError(f"The file '{markdown_file}' does not exist.")
if backup:
backup_file = markdown_file.with_suffix('.bak')
shutil.copy(markdown_file, backup_file) # Create a backup
if not backup_file.is_file():
raise IOError(f"Failed to create backup at '{backup_file}'.")
with markdown_file.open('r') as file:
content = file.read()
# Find all tables in the markdown file
tables = re.findall(r'(\|.*?\|\n\|.*?\|\n(?:\|.*?\|\n)+)', content, re.DOTALL)
# Format each table
formatted_tables = [format_table(table) for table in tables]
# Replace the old tables with the formatted tables
for old_table, new_table in zip(tables, formatted_tables):
content = content.replace(old_table, new_table)
with markdown_file.open('w') as file:
file.write(content)
def main():
parser = argparse.ArgumentParser(description='Format markdown tables in a file.')
parser.add_argument('markdown_file', type=str, help='Path to the markdown file')
parser.add_argument('--backup', action='store_true', help='Create a backup of the file before formatting')
args = parser.parse_args()
try:
format_markdown_tables(args.markdown_file, args.backup)
print(f'Tables in {args.markdown_file} have been formatted.')
if args.backup:
print(f'Backup created at {args.markdown_file}.bak')
except Exception as e:
print(f"An error occurred: {e}")
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment