Skip to content

Instantly share code, notes, and snippets.

@kkew3
Last active February 5, 2022 10:44
Show Gist options
  • Save kkew3/3dde88ec52df12d7cc855ffeb2091a7c to your computer and use it in GitHub Desktop.
Save kkew3/3dde88ec52df12d7cc855ffeb2091a7c to your computer and use it in GitHub Desktop.
Pretty print list of strings like BSD `ls`
import math
import itertools
import shutil
# https://gist.github.com/kkew3/8bb9aa225a6c82ae5e1a0fa609c9a65a
import cjkjust
def calc_layout(n_strings, total_width, column_width, width_between_cols):
# expected_ncols * column_width +
# (expected_ncols - 1) * width_between_cols <= total_width
#
# -> expected_ncols <= (total_width + width_between_cols) /
# (column_width + width_between_cols)
#
# Therefore, expected_ncols is at most the floor of the RHS
expected_ncols = math.floor((total_width + width_between_cols) /
(column_width + width_between_cols))
expected_ncols = max(expected_ncols, 1)
actual_nrows = math.ceil(n_strings / expected_ncols)
actual_ncols = (n_strings - 1) // actual_nrows + 1
return actual_nrows, actual_ncols
def pprint(strings, total_width=None, width_between_cols=1, file=None) -> None:
"""
Pretty print list of strings like ``ls``.
:param strings: list of strings
:param total_width: the disposable total width, default to terminal width
:param width_between_cols: width between columns, default to 1
:param file: file handle to which to print, default to stdout
"""
total_width = total_width or shutil.get_terminal_size().columns
assert total_width >= 1, total_width
assert width_between_cols >= 1, width_between_cols
if not strings:
return
column_width = max(map(cjkjust.cjklen, strings))
nrows, ncols = calc_layout(
len(strings), total_width, column_width, width_between_cols)
columns = [[] for _ in range(ncols)]
for i, s in enumerate(strings):
columns[i // nrows].append(s)
for row in itertools.zip_longest(*columns):
padded_row = (cjkjust.cjkljust(s or '', column_width) for s in row)
print((' ' * width_between_cols).join(padded_row), file=file)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment