#! /usr/bin/python

"""progressbars.py - Print progress bars on stdout

Tests progress bars implemented in different ways, using backspace and
carriage return characters to see how the terminal behaves and then
use to test GParted reading of program output.
"""

import sys
import time

SLEEP=0.1
BARLEN = 50

def bar_backspace_1(full):
    """Print progress bar using backspaces on stdout method 1

    Keeps the cursor position exactly where the next "X" needs to
    be written.  Like this:
        bar []: XXXXXXXXXXXX----------------------------
                            ^
                            Cursor position

    This is how "resize2fs -p" draws it's progress bars.
"""
    sys.stdout.write("bar [backspace 1]: " + "-"*BARLEN + "\b"*BARLEN)
    sys.stdout.flush()
    time.sleep(1)
    if full:
        limit = BARLEN
    else:
        limit = BARLEN / 2
    i = 1
    while i <= limit:
        sys.stdout.write("X")
        sys.stdout.flush()
        i += 1
        time.sleep(SLEEP)
    time.sleep(1)
    sys.stdout.write("\n")
    sys.stdout.flush()

def bar_backspace_2(full):
    """Print progress bar using backspaces on stdout method 2

    Keeps the cursor position at the start of the line by printing the
    whole line immedately followed by too many backspace characters.
    Each time the progress bar is updated the whole line is written.
    Like this:
        bar []: XXXXXXXXXXXX----------------------------
        ^
        Cursor position always at the start"""
    s = "bar [backspace 2]: "
    bss = "\b"*(BARLEN+50)
    sys.stdout.write(s + "-"*BARLEN + bss)
    sys.stdout.flush()
    time.sleep(1)
    if full:
        limit = BARLEN
    else:
        limit = BARLEN / 2
    i = 1
    while i <= limit:
        sys.stdout.write(s + "X"*i + "-"*(BARLEN-i) + bss)
        sys.stdout.flush()
        i += 1
        time.sleep(SLEEP)
    time.sleep(1)
    sys.stdout.write("\n")
    sys.stdout.flush()

def bar_backspace_3(full):
    """Print progress bar using backspaces on stdout method 3

    Keeps the cursor position at the end of the line by printing too
    many backspace characters immediately followed by the progress bar.
    Each time the progress bar is updated the whole line is written.
    Like this:
        bar []: XXXXXXXXXXXX----------------------------
                                                        ^
                        Cursor position always at the end"""
    s = "bar [backspace 3]: "
    bss = "\b"*(BARLEN+50)
    sys.stdout.write(s + "-"*BARLEN)
    sys.stdout.flush()
    time.sleep(1)
    if full:
        limit = BARLEN
    else:
        limit = BARLEN / 2
    i = 1
    while i <= limit:
        sys.stdout.write(bss + s + "X"*i + "-"*(BARLEN-i))
        sys.stdout.flush()
        i += 1
        time.sleep(SLEEP)
    time.sleep(1)
    sys.stdout.write("\n")
    sys.stdout.flush()

def bar_carriage_return_1(full):
    """Print progress bar using carriage return on stdout method 1

    Keeps the cursor position at the start of the line by printing the
    progress bar immediately followed by a carriage return.  Each time
    the progress bar is updated the whole line is written.  Like this:
        bar []: XXXXXXXXXXXX----------------------------
        ^
        Cursor position always at the start"""
    s = "bar [carriage return 1]: "
    sys.stdout.write(s + "-"*BARLEN + "\r")
    sys.stdout.flush()
    time.sleep(1)
    if full:
        limit = BARLEN
    else:
        limit = BARLEN / 2
    i = 1
    while i <= limit:
        sys.stdout.write(s + "X"*i + "-"*(BARLEN-i) + "\r")
        sys.stdout.flush()
        i += 1
        time.sleep(SLEEP)
    time.sleep(1)
    sys.stdout.write("\n")
    sys.stdout.flush()

def bar_carriage_return_2(full):
    """Print progress bar using carriage return on stdout method 2

    Keeps the cursor position at the end of the line by printing the
    carriage return immediately followed by the progress bar.  Each time
    the progress bar is updated the whole line is written.  Like this:
        bar []: XXXXXXXXXXXX----------------------------
                                                        ^
                        Cursor position always at the end"""
    s = "bar [carriage return 2]: "
    sys.stdout.write(s + "-"*BARLEN)
    sys.stdout.flush()
    time.sleep(1)
    if full:
        limit = BARLEN
    else:
        limit = BARLEN / 2
    i = 1
    while i <= limit:
        sys.stdout.write("\r" + s + "X"*i + "-"*(BARLEN-i))
        sys.stdout.flush()
        i += 1
        time.sleep(SLEEP)
    time.sleep(1)
    sys.stdout.write("\n")
    sys.stdout.flush()

def main(args=None):
    """Print program name, parameters and initiate progress bars"""
    sys.stdout.write("Progressbars\n")
    sys.stdout.write("argv=%s\n" % (repr(sys.argv)))
    bar_backspace_1(True)
    bar_backspace_1(False)
    bar_backspace_2(True)
    bar_backspace_2(False)
    bar_backspace_3(True)
    bar_backspace_3(False)
    bar_carriage_return_1(True)
    bar_carriage_return_1(False)
    bar_carriage_return_2(True)
    bar_carriage_return_2(False)
    sys.stdout.write("OK\n")
    return 0

if __name__ == "__main__":
    sys.exit(main(sys.argv))
