Python 3 can easily handle printing a lot of text:
text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent vitae odio quis felis consectetur blandit. Etiam mattis vehicula ex id sodales. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris fermentum semper nisi vel aliquam. Ut nec facilisis lectus. Maecenas auctor blandit condimentum. Donec finibus orci ac imperdiet congue. Pellentesque sem leo, commodo non metus ac, posuere maximus lorem. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. "
print(text)
The problem is that this text is printed like this:
This is of course not very good for readability of the text. Going through all of the text by hand to insert white lines makes for quite a hassle. I have seen this question, but I'm wondering if there's an option to do this automatically.
As mentioned in the comments, pprint
and textwrap
can be used to align output to a given width. Given that, the only trick is determining the width to use. You could just use 78 or 80 and assume the window is that large, but that means bad wrapping if the terminal is smaller, and wasted space if it's larger.
To check the actual width for use with pprint
/textwrap
, if you're on Python 3.3 or higher, you can use shutil.get_terminal_size
:
import shutil
def get_terminal_columns():
return shutil.get_terminal_size().columns
If you can't use 3.3+, you can use the curses
module to determine the size in a somewhat more complicated way:
import curses
def get_terminal_columns():
try:
# Initialize curses for terminal and check dimensions
rows, cols = curses.initscr().getmaxyx()
finally:
# Unload curses to release control of terminal so it behaves normally
curses.endwin()
return cols
Using one of these functions, you can then define:
from __future__ import print_function # Only needed on Py2
import textwrap
def print_autobreak(*args, sep=' '):
width = get_terminal_columns() # Check size once to avoid rechecks per "paragraph"
# Convert all args to strings, join with separator, then split on any newlines,
# preserving line endings, so each "paragraph" wrapped separately
for line in sep.join(map(str, args)).splitlines(True):
# Py3's print function makes it easy to print textwrap.wrap's result as one-liner
print(*textwrap.wrap(line, width), sep="\n")
This automatically performs line breaking between words based on the terminal size, preserves existing "hard" newlines and spaces, and (partially) matches the behavior of print
by allowing multiple arguments with an optional separator. It needs to completely realize the output string before printing (the original print
can print one-by-one, reducing memory usage a bit for huge outputs), but that's a side-effect of performing appropriate global wrapping.
If you need more complete line breaking handling (so two prints can occur without newlines, yet the second one accounts for the length of the first), you'll need a more stateful printer (to remember used characters on a line) or invent something a tad more complex with full curses
functionality. I'll leave that as an exercise.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With