viernes, 10 de diciembre de 2010

Temporizador con python+curses.

Se trata de la traducción y modificación del programa "teatime" para un uso más general:

#!/usr/bin/python
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
# Author: scorch
# Email: scorch@eldslott.org
# Date: 2009-08-15
# Version: 0.2
#
# Modificado y traducido por: Ket-SIF
# Date: 2010-12-10
# Version: 0.3

import os, time, sys, atexit, curses, traceback, select
from signal import signal, SIGTERM
from sys import exit

# ncurses screen
stdscr = None

############### CONFIGURATION ###############
#
# how the progress bar should look like
#
# 1: [===========------------]
# 2: |---------->            |
# 3: [###########------------]
#
BAR = ['[', '=', '=', '-', ']']
#BAR = ['|', '-', '>', ':', '|']
#BAR = ['[', '#', '#', '-', ']']
#
# the initial string for the top line
# "HEADER XX minutes and XX seconds."
HEADER = "El tiempo se acaba en"
#
# how long to sleep between updates
SLEEP = 0.05
#
# time in seconds used if no time specified on command line
TIME = 220
#
# CAUTION: WILL FLASH LIKE NOTHING YOU'VE SEEN BEFORE! Turn off
# by setting it to False
#
# (if you get an epileptic seisure, don't blame me, I tried to
# warn you!)
FLASH = True
#############################################

def main():
    time_passed = bar_length = 0
    time_last = time.time()
    time_length = TIME
    if len(sys.argv) > 1:
        time_length = int(sys.argv[1].split(':')[3])+60*int(sys.argv[1].split(':')[2])+60*60*int(sys.argv[1].split(':')[1])+24*60*60*int(sys.argv[1].split(':')[0])
        #time_length = int(sys.argv[1])

    done = False
    while True:
        # dynamic width of progress bar (-12 for percentage to fit)
        bar_max_length = int(os.popen('stty size', 'r').read().split()[1])-12

        # determine how OFTEN we should update the progress bar
        dbar = time_length/bar_max_length/SLEEP
        # determine how MUCH we should update the progress bar
        if time_length is 0:
            dbarl = bar_max_length - bar_length
        else:
            dbarl = bar_max_length/time_length*SLEEP
        # calculate minutes and seconds left
        secs = time_left = int(time_length - time_passed)
        mins = 0
        if time_left > 59:
            dias = time_left/86400
            horas = (time_left%86400)/3600
            mins = ((time_left%86400)%3600)/60
            secs = time_left % 60
        else:
            dias = 0
            horas = 0
            mins = 0
            ssecs = time_left
        # calculate remaining time and generate the top line
        output = HEADER + ' '
        if dias == 1:    output += str(dias)+" dia, "
        else:        output += str(dias)+" dias, "
        if horas == 1:    output += str(horas)+" hora, "
        else:        output += str(horas)+" horas, "
        if mins == 1:    output += str(mins)+" minuto y "
        else:        output += str(mins)+" minutos y "
        if secs == 1:   stdscr.addstr(0, 1, output + str(secs) + " segundo.\n")
        else:           stdscr.addstr(0, 1, output + str(secs) + " segundos.\n")
        # calculate percentage for the bottom line
        if time_length is not 0:
            percent = float(time_passed)/float(time_length)*100
        if percent > 100 or done:
            percent = 100
        # right align percentage
        output = '  '
        if   percent == 100: output = ''
        elif percent >=  10: output = ' '
        output += '%.2f%% ' % percent
        # always recount the length of the bar; user might have resized window
        bar_length = percent * (bar_max_length/100.0)
        if bar_length > bar_max_length:
            bar_length = bar_max_length
        # generate the progress bar and print it together with the percentage
        output += gen_progress_bar(bar_length, bar_max_length)
        stdscr.addstr(1, 1, output)
        # time_delta is how long since we were here the last time
        time_delta = time.time() - time_last
        time_passed += float('%.4f' % time_delta)
        time_last = time.time()
        # nothing is acutally shown until now
        stdscr.refresh()
        # if we're done
        if done:
            break
        # loop once more so we get 0 seconds left in the end
        if time_passed >= time_length:
            done = True
        else:
            time.sleep(SLEEP)
    return
# generate the progress bar that will later be printed
def gen_progress_bar(bar_length, bar_max_length):
    output = BAR[0]
    # print the length of the bar with the defined character
    for i in range(0, int(bar_length)):
        output += BAR[1]
    output += BAR[2]
    # print the defined character to fill the remaining part of the bar
    for i in range(abs(int(bar_length) - int(bar_max_length))):
        output += BAR[3]
    output += BAR[4]
    return output
# pack it up boys, it's time to go home
def cleanup():
    stdscr.keypad(0)
    curses.echo();
    curses.nocbreak()
    curses.endwin()
    sys.exit(0)
def print_usage():
    print "Modo de uso: cuenta_atras_es [dias:horas:minutos:segundos]"
    print "    --help, -h    muestra esta ayuda"
def is_data():
    return select.select([sys.stdin], [], [], 0) == ([sys.stdin], [], [])
if __name__ == "__main__":
#    if len(sys.argv) > 1 and not sys.argv[1].isdigit():

    if len(sys.argv) > 1 and sys.argv[1] == ('-h' or '--help'):
        print_usage()
        sys.exit(0)
    elif len(sys.argv) > 1 and not sys.argv[1].split(':')[0].isdigit():
        print_usage()
        sys.exit(0)       
    elif len(sys.argv) > 1:
        try:
            print int(sys.argv[1].split(':')[3])+60*int(sys.argv[1].split(':')[2])+60*60*int(sys.argv[1].split(':')[1])+24*60*60*int(sys.argv[1].split(':')[0])
        except:
            print_usage()
            sys.exit(0)
    atexit.register(cleanup)
    try:
        # Initialize curses
        stdscr = curses.initscr()
        curses.noecho();
        curses.cbreak()
        stdscr.keypad(1)
        main()
    except:
        traceback.print_exc()
    # non blocking input, any key stops the program
    while FLASH:
        if is_data():
            break
        curses.flash()
        # not so intense flashing
        time.sleep(0.9)
    # Normal exit when killed
    signal(SIGTERM, lambda signum, stack_frame: exit(1))


Aún no están comentados los cambios, lo siento.

No hay comentarios:

Publicar un comentario