« Back to blog

Fancy Printing with Python

Box Printing and More!

From time to time, I need to print something nice and fancy, like say a box in a terminal:

=================
= Hello, world! =
=================

But, the task of printing these things becomes tedious, especially if you want to say, center the text:

==============================
=       Hello, world!        =
==============================

But what if you wanted to change all of that: not have it in a box, specify arbitrary widths, specify filler characters, specify line characters, margins, padding, etc?

Here's the output of: fancyPrinter('Hello, world!', centered = True, width = 50, char = '*', mode = 'box', filler = 'X', margin = 1, padding = 1):

 
**************************************************
*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX*
*XXXXXXXXXXXXXXXX Hello, world! XXXXXXXXXXXXXXXXX*
*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX*
**************************************************
 

Or what about multiple lines? That are longer than your width?

Try this out: fancyPrinter('Wow, this sure is a lot of text.\nQuite a bit of text, actually.\nWhy would anyone have this much text to output?', centered = True, width = 20)

====================
=  Wow, this sure  =
=   is a lot of    =
=      text.       =
=  Quite a bit of  =
=      text,       =
=    actually.     =
=    Why would     =
=   anyone have    =
=  this much text  =
=    to output?    =
====================

And here's the same thing, not centered, with no width specified:

===================================================
= Wow, this sure is a lot of text.                =
= Quite a bit of text, actually.                  =
= Why would anyone have this much text to output? =
===================================================

Then you would need my fancyPrinter() method:

def fancyPrinter(text, filler = ' ', char = None, centered = False, width = None, margin = None, padding = None, mode = 'box', output = sys.stdout):
 
 '''
 Copyright 2011 Sebastian Weigand, released under the GPLv3
 Print text in a fancier fashion.
 print >> output,  text in a fancier fashion.
 
 Accepts multiple lines, and will fit a box (if that is the mode) around it, and truncate
 each line which is over the specified width (maximum of terminal, or specified; minimum
 of the longest word in the text).
 '''
 
 textLength = max(map(len, text.splitlines()))
 textArray = text.split()
 maxWordLength = max(map(len, textArray))
 rows, columns = os.popen('stty size', 'r').read().split()
 termWidth = int(columns)
 modes = ['box', 'overline', 'underline', 'simple']

 if mode not in modes:
  raise TypeError('\'' + mode + '\' is an invalid mode for boxprint >> output, er().')

 if 'line' in mode:
  if not char:
   char = '-'
 elif mode == 'center':
  if not char:
   char = ' '
  centered = True
  if not width:
   width = termWidth
 else:
  if not char:
   char = '='

 if centered and not width:
  width = termWidth

 if width:
  if width < maxWordLength + 4:
   width = maxWordLength + 4
 else:
  width = textLength + 4
 
 # Set maximum width to that of terminal:
 if textLength >= termWidth + 4 or width >= termWidth + 4:
  width = termWidth
 
 lines = []

 # Chop up lines to fit within confines of width, or max width (terminal):
 if width < textLength + 4:
  
  for line in text.splitlines():
   sentence = ''

   for word in line.split():

    word = word + ' '

    newSentence = sentence + word
    
    if len(newSentence) < width - 4:
     sentence = newSentence
    else:
     if len(sentence) > 0:
      lines.append(sentence)
     sentence = word

   lines.append(sentence)
 else:
  lines = (text + ' ').splitlines()

 if margin:
  print >> output,  '\n' * (margin - 1)

 if centered:
  if mode == 'box' or mode == 'overline':
   print >> output,  char * width
  
  if padding:
   for i in xrange(0, padding):
    if 'box' in mode:
     print >> output,  char + filler * (width - 2) + char
    else:
     print >> output,  filler * width
  
  for line in lines:
   # "line" is text + :
   spacing = (width - len(line) - 2)
   
   # Prefer extra right spaces when width is not even:
   leftSpacing = (spacing / 2) + (spacing % 2) - 1
   rightSpacing = (spacing / 2)
   
   if mode == 'box':
    print >> output,  char + (filler * leftSpacing) + ' ' + line + (filler * rightSpacing) + char
   else:
    # Extra padding, as there's no preceeding char:
    print >> output,  (filler * (leftSpacing + 1)) + ' ' + line + (filler * (rightSpacing + 1))
  
  if padding:
   for i in xrange(0, padding):
    if 'box' in mode:
     print >> output,  char + filler * (width - 2) + char
    else:
     print >> output,  filler * width
  
  if mode == 'box' or mode == 'underline':
   print >> output,  char * width
  
 else:
  if mode == 'box' or mode == 'overline':
   print >> output,  char * width
  
  if padding:
   for i in xrange(0, padding):
    if 'box' in mode:
     print >> output,  char + filler * (width - 2) + char
    else:
     print >> output,  filler * width
  
  for line in lines:
   if mode == 'box':
    print >> output,  char + ' ' + line + filler * (width - len(line) - 3) + char
   else:
    print >> output,  ' ' + line
  
  if padding:
   for i in xrange(0, padding):
    if 'box' in mode:
     print >> output,  char + filler * (width - 2) + char
    else:
     print >> output,  filler * width
  
  if mode == 'box' or mode == 'underline':
   # This will produce a line which is slighlty longer on the right,
   #  but it looks nice in underline.
   print >> output,  char * width  

 if margin:
  print >> output,  '\n' * (margin - 1)

I hope you enjoy :)

| Viewed
times | Favorited 0 times

0 Comments

Leave a comment...