Skip to content

Instantly share code, notes, and snippets.

@marcusmueller
Last active March 13, 2024 00:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save marcusmueller/d65a08b88cd465d1b42439ad1986a920 to your computer and use it in GitHub Desktop.
Save marcusmueller/d65a08b88cd465d1b42439ad1986a920 to your computer and use it in GitHub Desktop.
Justify a text using Python
#! /usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0
#
# Title: Justify text
# Author: Marcus Müller
# Copyright: 2024
#
# Usage: justify.py [width [file1] [file2] [file…]]
#
# if no files are specified, read from standard input
# if no width is specified, default to 90
import textwrap
import sys
import random
from typing import TextIO
def reflow_file(file_in: [str, TextIO], wrapper: textwrap.TextWrapper):
random.seed(42)
if type(file_in) is str:
file_in = open(file_in, "r", encoding="utf-8")
lines = wrapper.wrap(file_in.read())
lines_out = []
for lineno, line in enumerate(lines):
if len(line) < wrapper.width and lineno != len(lines) - 1:
words = line.split()
spaces = len(words) - 1
if spaces > 0:
deficit = wrapper.width - len(line)
if deficit >= spaces:
# we have more deficit than spaces
# so add to each word
n_add = deficit // spaces
words = [word + " " * n_add for word in words]
deficit = deficit - n_add * spaces
choices = set(random.sample(range(spaces), k=deficit))
words_out = []
for idx, word in enumerate(words):
words_out.append(word)
if idx in choices:
words_out.append("")
line = " ".join(words_out)
lines_out.append(line)
return "\n".join(lines_out)
if len(sys.argv) < 2:
width = 90
files = [sys.stdin]
elif len(sys.argv) < 3:
width = int(sys.argv[1])
files = [sys.stdin]
else:
width = int(sys.argv[1])
files = sys.argv[2:]
# set up the Text Wrapper. Add break_on_hyphens=False to the following
# arguments should you not want to allow breaking at every "-".
wrapper = textwrap.TextWrapper(width=width, tabsize=4)
lines = (reflow_file(f, wrapper) for f in files)
print("\n".join(lines))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment