#!/usr/bin/env python
"""
Fixed Width
===========
Pagination navigation that does not grow or shrink depending on what position
the current page.
Example
::
< *0* 1 2 3 4 ... 8 >
< 0 *1* 2 3 4 ... 8 >
< 0 1 *2* 3 4 ... 8 >
< 0 1 2 *3* 4 ... 8 >
< 0 ... 3 *4* 5 ... 8 >
< 0 ... 4 *5* 6 7 8 >
< 0 ... 4 5 *6* 7 8 >
< 0 ... 4 5 6 *7* 8 >
< 0 ... 4 5 6 7 *8* >
"""
# TODO(nick): Allow both 0 and 1 based indexing.
# TODO(nick): Allow an offset? e.g., pages 30-90.
[docs]def pagify(page, pages, left_pages=1, right_pages=1, begin_pages=1,
end_pages=1, include_ellipses=True):
"""Return a list of page segments useful for displaying paginated navigation.
Args
----
page : int
The current page.
pages : int
The total number of pages. (Must be >= page.)
left_pages : int
The number of pages to show to the left of the current page.
This is the exact number of pages shown if there are ellipses on both
sides. However, there may be more pages shown to the left if the current
page is near the end of the range, and less if the current page is near
the beginning of the range.
right_pages : int
The number of pages to show to the right of the current page.
This is the exact number of pages shown if there are ellipses on both
sides. However, there may be more pages shown to the right if the
current page is near the beginning of the range, and less if the current
page is near the end of the range.
begin_pages : int
The number of pages to include at the beginning of the pagination list
(before the ellipses, if they are present).
end_pages : int
The number of pages to include at the end of the pagination list (after
the ellipses, if they are present).
Example
-------
.. testcode::
from pagination.fixed import pagify, ascii_format
for i in range(0, 9):
print pagify(i, 9)
.. testoutput::
[[], [], 0, [1, 2, 3, 4], ['...', 8]]
[[], [0], 1, [2, 3, 4], ['...', 8]]
[[], [0, 1], 2, [3, 4], ['...', 8]]
[[], [0, 1, 2], 3, [4], ['...', 8]]
[[0, '...'], [3], 4, [5], ['...', 8]]
[[0, '...'], [4], 5, [6, 7, 8], []]
[[0, '...'], [4, 5], 6, [7, 8], []]
[[0, '...'], [4, 5, 6], 7, [8], []]
[[0, '...'], [4, 5, 6, 7], 8, [], []]
Returns
-------
list
[[start], [left], page, [right], [end]]
"""
assert page <= pages, ("`page` (%s) cannot be greater than `pages` (%s)." %
(page, pages))
# The minimum number of pages before we need to use ellipses.
min_pages = (
(begin_pages + 1) + # The +1s are here to include the ellipses.
(end_pages + 1) +
(left_pages + right_pages + 1) # The +1 here includes the current page.
)
if pages <= min_pages:
return [[], range(0, page), page, range(page + 1, pages), []]
no_left_ellipses = page <= ((begin_pages + 1) + left_pages)
no_right_ellipses = page >= (pages - ((end_pages + 1) + right_pages + 1))
if no_left_ellipses:
# Example: < 0 1 2 *3* 4 ... 8 >
start = []
toleft = range(0, page)
maxright = (begin_pages + 1) + (left_pages + right_pages) + 1
toright = range(page + 1, maxright)
end = ['...'] + range(pages - end_pages, pages)
else:
start = range(0, begin_pages) + ['...']
if no_right_ellipses:
# Example: < 0 ... 4 *5* 6 7 8 >
toleft = range(pages - (left_pages + right_pages + end_pages) - 2, page)
toright = range(page + 1, pages)
end = []
else:
# We're in the center! Example: < 0 ... 3 *4* 5 ... 8 >
toleft = range(page - left_pages, page)
toright = range(page + 1, page + right_pages + 1)
end = ['...'] + range(pages - end_pages, pages)
return [start, toleft, page, toright, end]
def _fmt(i):
return str(i).rjust(2, ' ').ljust(3, ' ')
def _page_range_to_string(page_range):
if isinstance(page_range, int):
return "*%s*" % _fmt(page_range)
s = ""
for p in page_range:
if p == '...':
s += ' ... '
else:
s += " %s " % _fmt(p)
return s
if __name__ == '__main__':
# TODO(nick): The below is primarily for doing a quick visual/manual "test"
# of this algorithm. This would obviously be better if automated.
print '\n'
pages = 9
left = 1
right = 1
start = 1
end = 1
include_ellipses = True
# pretty_print = False
pretty_print = True
for i in range(0, pages):
pagified = pagify(page=i,
pages=pages,
left_pages=left,
right_pages=right,
begin_pages=start,
end_pages=end,
include_ellipses=include_ellipses)
if pretty_print:
print 'pagify(%s, %s): ' % (_fmt(i), pages), ascii_format(pagified)
else:
print 'pagify(%s, %s): ' % (_fmt(i), pages), pagified
print '\n'