[affichage] Fonction tableau et quelques correctifs

This commit is contained in:
Pierre-Elliott Bécue 2014-06-01 02:08:29 +02:00
parent 32537ffe30
commit ee134b4d84

View file

@ -39,6 +39,13 @@ import termios
import struct
import functools
import time
import re
oct_names = ["Pio", "Tio", "Gio", "Mio", "Kio", "o"]
oct_sizes = [1024**(len(oct_names) - i - 1) for i in xrange(0, len(oct_names))]
term_format = '\x1b\[[0-1];([0-9]|[0-9][0-9])m'
dialog_format = '\\\Z.'
sep_col = u"|"
def static_var(name, val):
"""Decorator setting static variable
@ -205,8 +212,16 @@ class Animation(object):
sys.stdout.write("\n")
sys.stdout.flush()
def nostyle(dialog=False):
"""
Annule tout style précédent.
"""
if dialog:
return "\Zn"
return "\033[1;0m"
@static_var("styles", {})
def style(texte, what=[]):
def style(texte, what=[], dialog=False):
"""
Pretty text is pretty
On peut appliquer plusieurs styles d'affilée, ils seront alors traités
@ -228,6 +243,9 @@ def style(texte, what=[]):
UPPER, parce que c'est inutile, donc kewl.
"""
if dialog:
return dialogStyle(texte, what)
if isinstance(what, str):
what = [what]
@ -264,6 +282,7 @@ def style(texte, what=[]):
style.styles.update(zeros)
style.styles.update(ones)
style.styles["none"] = "1;0"
for element in what:
texte = "\033[%sm%s\033[1;0m" % (style.styles[element], texte)
return texte
@ -312,6 +331,140 @@ def prettyDoin(what, status):
sys.stdout.write("\r[%s] %s\n" % (ERREUR, what))
sys.stdout.flush()
def tronque(data, largeur, dialog):
"""
Tronque une chaîne à une certaine longueur en excluant
les commandes de style.
"""
# découpage d'une chaine trop longue
regexp = re.compile(dialog_format if dialog else term_format)
new_data = u''
new_len = 0
# On laisse la mise en forme et on coupe les caratères affichés
while True :
s = regexp.search(data)
if s:
if s.start() + new_len > largeur:
new_data += data[:largeur - new_len - 1] + nostyle() + '*'
break
else:
new_data += data[:s.end()]
data = data[s.end():]
new_len += s.start()
else:
if new_len + len(data) > largeur:
new_data += data[:largeur - new_len - 1] + '*'
data = ""
else:
new_data += data
data = ""
if not data:
break
return new_data
def aligne(data, alignement, largeur, dialog) :
# Longeur sans les chaines de formatage
longueur = len(re.sub(dialog_format if dialog else term_format, '', data))
# Alignement
if longueur > largeur:
return tronque(data, largeur, dialog)
elif longueur == largeur :
return data
elif alignement == 'g':
return u' ' + data + u' '*(largeur-longueur-1)
elif alignement == 'd':
return u' '*(largeur-longueur-1) + data + u' '
else:
return u' '*((largeur-longueur)/2) + data + u' '*((largeur-longueur+1)/2)
def format_data(data, format):
if format == 's':
return unicode(data)
elif format == 'o':
data = float(data)
for i in xrange(0, len(oct_names)):
if data > oct_sizes[i]:
return "%.2f %s" % (data/oct_sizes[i], oct_names[i])
def tableau(data, titre=None, largeur=None, alignement=None, format=None, dialog=False, width=None):
"""
Retourne une chaine formatée repésentant un tableau.
data : liste de listes, chacune contenant les valeurs d'une ligne
titre : liste des titres
Si none, n'affiche pas de ligne de titre
largeur : liste des largeurs des colonnes, '*' met la plus grande
largeur possible.
Si None, réduit aux max chaque colonne
alignement : liste des alignements : c = centrer
g = gauche
d = droit
Si None, met c pour chaque colonne
format : liste des formats : s = string
o = octet
Si None, s pour chaque colonne
width : force la largeur
"""
if data and isinstance(data, list):
nb_cols = len(data[0])
else:
return u""
if format is None:
format = ['s'] * nb_cols
data = [[format_data(ligne[i], format[i]) for i in xrange(nb_cols)] for ligne in data]
if not largeur :
largeur = [max([len(re.sub(dialog_format if dialog else term_format, '', ligne[i])) for ligne in data]) for i in range(nb_cols)]
elif '*' in largeur or -1 in largeur:
sum_larg = sum([l for l in largeur if l != '*'])
if width:
cols = width
else:
cols, rows = getTerminalSize()
if dialog:
cols = cols - 6
stars = largeur.count('*') + largeur.count(-1)
for i in range(nb_cols):
if largeur[i] in ['*', -1] :
largeur[i] = max(cols - sum_larg - nb_cols - 1, 3)/stars
print largeur
if alignement is None:
alignement = ['c'] * nb_cols
data = [[aligne(ligne[i], alignement[i], largeur[i], dialog) for i in range(nb_cols)] for ligne in data]
# Le titre
##########
if titre :
# ligne de titre
chaine = sep_col + sep_col.join([aligne(titre[i], 'c', largeur[i], dialog) for i in range(nb_cols)]) + sep_col + u'\n'
# ligne de séparation
chaine += sep_col + u'+'.join([u'-'*largeur[i] for i in range(nb_cols)]) + sep_col + u'\n'
else :
chaine = u''
# Les données
#############
chaine += u'\n'.join([sep_col + sep_col.join([ligne[i] for i in range(nb_cols)]) + sep_col for ligne in data])
return chaine
if __name__ == "__main__":
import time
a = Animation(texte="Test de l'animation", nb_cycles=10000, couleur=True, kikoo=True)
@ -322,3 +475,8 @@ if __name__ == "__main__":
prettyDoin("Je cuis des carottes.", "...")
time.sleep(1)
prettyDoin("Les carottes sont cuites." , "Ok")
data = [[style("Durand", "rouge"), u"Toto", u"40", u"50 rue caca"], [u"Dupont", "Robert", u"50", "42" + style(" avenue ", "vert") + style("dumotel", 'rouge')], [style("znvuzbvzruobouzb", ["gras", "vert"]), u"pppoe", u"1", u"poiodur 50 pepe"]]
titres = (u"Nom", u"Prénom", u"Âge", u"Adresse")
longueurs = [25, 25, '*', '*']
print tableau(data, titres, longueurs)