5

I have this code which is meant to display some text on a 20x2 LCD display:

#!/usr/bin/python

LCDCHARS = 20
LCDLINES = 2

def WriteLCD(text_per_LCD):
    chunked = (text_per_LCD[i:LCDCHARS+i] for i in range (0, len(text_per_LCD), LCDCHARS))
    count_l = 0
    for text_per_line in chunked:
        # print will be replaced by actual LCD call
        print (text_per_line)
        count_l += 1
        if count_l >= LCDLINES:
            # agree to lose any extra lines
            break

WriteLCD("This text will display on %s LCD lines" % (LCDLINES))

The example string will output

This text will displ
ay on 2 LCD lines

What should I do to split the string without breaking the words? This even if the second line becomes longer and goes out of display.

I read a similar question on javascript section and another one in ruby section, but I was not able to translate the given answers into my Python case.

3 Answers 3

17

Use the textwrap module:

>>> textwrap.wrap("This text will display on 3 LCD lines", 20)
['This text will', 'display on 3 LCD', 'lines']
Sign up to request clarification or add additional context in comments.

1 Comment

While I actually used this solution, I still have a dilemma as expressed in my other comment related to the darkryder solution.
2
YOUR_STRING = "This text will display on 10 LCD lines"
CHAR_LIMIT = 25 # anything

First off, let's start with finding out the breakpoints(spaces in your case).

Let's use the function from https://stackoverflow.com/a/11122355/2851353

def find(s, ch):
    return [i for i, ltr in enumerate(s) if ltr == ch]

breakpoints = find(YOUR_STRING, " ")
# [4, 9, 14, 22, 25, 28, 32]

Now, we find what's the index of the word till where we can safely split the sentence.

Let's find another function from: https://stackoverflow.com/a/2236956/2851353

def element_index_partition(points, breakpoint):
    return [ n for n,i in enumerate(points) if i>breakpoint ][0]

best = element_index_partition(breakpoints, CHAR_LIMIT)

Now, we just need to split and rejoin the string.

# We won't go till `best` (inclusive) because the function returns the next index of the partition
first_str = " ".join(YOUR_STRING.split(" ")[:best])
last_str =  " ".join(YOUR_STRING.split(" ")[best:])

EDIT After seeing the answer given by Dan D., use that answer. Always use libraries instead of making feeble attempts to reinvent the wheel. Always.

2 Comments

Regarding "Always use libraries instead of making feeble attempts to reinvent the wheel", I am a bit in doubt here: in terms of overall efficiency when running the program, given a particular case where a function is only required once in a relatively long (>1000 lines) overall program code, is it ok to just import one (more) library in order to simplify few lines of my code (like textwrap in Dan D. answer), or is it better to complicate a bit my local code in order to avoid importing a library? So just then, not if the function call is required more than once (assuming this is foreseeable).
When the standard library solves exactly your need in a single stroke, go for it. It will be well tested, used by other people in the world, will handle obscure corner cases. But the best thing is that the meaning will be so much clearer, for a future maintainer and for yourself.
0

Using generator:

LCDCHARS = 20
LINE = "This text will display on 2 LCD lines No more!"
LCDLINES = 2

def split_line(line):
    words = line.split()                                                                                                                               
    l = ""
    # Number of lines printed
    i = 0
    for word in words:
        if i < LCDLINES - 1 and len(word)+ len(l) > LCDCHARS:
            yield l.strip()
            l = word
            i += 1
        else:
            l+= " " + word
    yield l.strip()

for line in split_line(LINE):
    print line

Output:

This text will
display on 2 LCD lines No more!

1 Comment

OP wants only two lines, even if it runs off the side.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.