Skip to content

Instantly share code, notes, and snippets.

@gavinwahl
Created June 3, 2013 20:36
Show Gist options
  • Save gavinwahl/5701185 to your computer and use it in GitHub Desktop.
Save gavinwahl/5701185 to your computer and use it in GitHub Desktop.
Splits up a string into pages of a maximum length. Includes pages numbers. Tries not to split in the middle of a word. Good for SMS.
from math import ceil
def split_up(s, length=160):
"""
Splits the string s into pages of no longer than length. Includes
pages numbers. Tries not to split in the middle of a word.
>>> split_up("abc", 5)
['abc']
>>> split_up("abcdef", 5)
['a 1/6', 'b 2/6', 'c 3/6', 'd 4/6', 'e 5/6', 'f 6/6']
>>> split_up("%s %s" % ("a" * 150, "b" * 150), 160) # doctest: +ELLIPSIS
['aaa...aaa 1/2', 'bbb...bbb 2/2']
>>> split_up("a" * 160) == ["a" * 160]
True
>>> split_up("a" * 161) # doctest: +ELLIPSIS
['aaa...aaa 1/2', 'aaaaa 2/2']
"""
if len(s) <= length:
return [s]
length -= 4 # correct for the length of the page number, len(' 1/3') == 4
total_pages = int(ceil(len(s)/float(length)))
assert total_pages < 10, 'only a single digit will work'
words = s.split()
words.reverse()
pages = []
for i in range(total_pages):
page = []
needed = length
while needed and words:
word = words.pop()
if len(word) > needed:
if page:
# Put the word back, it'll go on the next page.
words.append(word)
break
else:
# There is no choice but to split a word. go ahead
# and split the word. Put the extra characters we
# couldn't use back into consideration for the next
# page.
extra = word[needed:]
word = word[:needed]
words.append(extra)
page.append(word)
needed -= len(word)
page_num = i + 1 # one-based page numbers
pages.append('%s %s/%s' % (' '.join(page), page_num, total_pages))
return pages
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment