Ajout de fonctionnalités, et passage en "tout unicode".
This commit is contained in:
parent
491ea7fa39
commit
80874c7a8f
1 changed files with 169 additions and 103 deletions
|
@ -15,8 +15,8 @@
|
||||||
# Fonctions :
|
# Fonctions :
|
||||||
# getTerminalSize(), une fonction qui récupère le couple
|
# getTerminalSize(), une fonction qui récupère le couple
|
||||||
# largeur, hauteur du terminal courant.
|
# largeur, hauteur du terminal courant.
|
||||||
# cap_text(text, length), un raccourci pour couper un texte
|
# cap_text(data, length, dialog=False), un raccourci pour couper un texte
|
||||||
# trop long en mettant …
|
# trop long en mettant *
|
||||||
# format_percent(percent), un raccourci qui fait en sorte
|
# format_percent(percent), un raccourci qui fait en sorte
|
||||||
# qu'un pourcentage prenne toujours autant de caractères
|
# qu'un pourcentage prenne toujours autant de caractères
|
||||||
# en ajoutant des espaces (c'est pour les prints dynamiques)
|
# en ajoutant des espaces (c'est pour les prints dynamiques)
|
||||||
|
@ -32,6 +32,8 @@
|
||||||
# Classes :
|
# Classes :
|
||||||
# Animation, une classe générant les animations type "progress bar".
|
# Animation, une classe générant les animations type "progress bar".
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import fcntl
|
import fcntl
|
||||||
|
@ -41,17 +43,59 @@ import functools
|
||||||
import time
|
import time
|
||||||
import re
|
import re
|
||||||
|
|
||||||
oct_names = ["Pio", "Tio", "Gio", "Mio", "Kio"]
|
from locale import getpreferredencoding
|
||||||
oct_sizes = [1024**(len(oct_names) - i) for i in xrange(0, len(oct_names))]
|
|
||||||
term_format = '\x1b\[[0-1];([0-9]|[0-9][0-9])m'
|
OCT_NAMES = ["Pio", "Tio", "Gio", "Mio", "Kio"]
|
||||||
dialog_format = '\\\Z.'
|
OCT_SIZES = [1024**(len(OCT_NAMES) - i) for i in xrange(0, len(OCT_NAMES))]
|
||||||
sep_col = u"|"
|
TERM_FORMAT = '\x1b\[[0-1];([0-9]|[0-9][0-9])m'
|
||||||
|
DIALOG_FORMAT = '\\\Z.'
|
||||||
|
SEP_COL = "|"
|
||||||
|
|
||||||
|
def try_decode(string):
|
||||||
|
"""Essaye de décoder dans les deux formats plausibles qu'on peut
|
||||||
|
avoir en réception.
|
||||||
|
|
||||||
|
"""
|
||||||
|
unicode_str = ""
|
||||||
|
try:
|
||||||
|
return string.decode("UTF-8")
|
||||||
|
except UnicodeDecodeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
return string.decode("ISO-8859-15")
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def guess_preferred_encoding():
|
||||||
|
"""On essaye de deviner l'encodage favori de l'utilisateur.
|
||||||
|
C'est inspiré d'affich_tools.
|
||||||
|
|
||||||
|
Il faudrait l'améliorer si nécessaire.
|
||||||
|
|
||||||
|
"""
|
||||||
|
encoding = None
|
||||||
|
try:
|
||||||
|
encoding = getpreferredencoding()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if not encoding:
|
||||||
|
encoding = sys.stdin.encoding or 'UTF-8'
|
||||||
|
|
||||||
|
if encoding == "ANSI_X3.4-1968":
|
||||||
|
encoding = 'UTF-8'
|
||||||
|
|
||||||
|
return encoding
|
||||||
|
|
||||||
def static_var(couples):
|
def static_var(couples):
|
||||||
"""Decorator setting static variable
|
"""Decorator setting static variable
|
||||||
to a function.
|
to a function.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
# Using setattr magic, we set static
|
||||||
|
# variable on function. This avoid
|
||||||
|
# computing stuff again.
|
||||||
def decorate(fun):
|
def decorate(fun):
|
||||||
functools.wraps(fun)
|
functools.wraps(fun)
|
||||||
for (name, val) in couples:
|
for (name, val) in couples:
|
||||||
|
@ -67,14 +111,24 @@ def getTerminalSize():
|
||||||
portable.
|
portable.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
env = os.environ
|
|
||||||
def ioctl_GWINSZ(fd):
|
def ioctl_GWINSZ(fd):
|
||||||
try:
|
try:
|
||||||
cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ, '1234'))
|
# unpack C structure, the first argument says that we will get two short
|
||||||
|
# integers (h).
|
||||||
|
# ioctl is a C function which do an operation on a file descriptor, the operation
|
||||||
|
# here is termios.TIOCGWINSZ which will get the return to be term size. The third
|
||||||
|
# argument is a buffer passed to ioctl. Its size is used to define the size of the
|
||||||
|
# the return
|
||||||
|
cr = struct.unpack(b'hh', fcntl.ioctl(fd, termios.TIOCGWINSZ, b'1234'))
|
||||||
except:
|
except:
|
||||||
return
|
return
|
||||||
return cr
|
return cr
|
||||||
|
|
||||||
|
# First, we use this magic function on stdin/stdout/stderr.
|
||||||
cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2)
|
cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2)
|
||||||
|
|
||||||
|
# If that didn't work, we try to do this on a custom file descriptor.
|
||||||
if not cr:
|
if not cr:
|
||||||
try:
|
try:
|
||||||
fd = os.open(os.ctermid(), os.O_RDONLY)
|
fd = os.open(os.ctermid(), os.O_RDONLY)
|
||||||
|
@ -82,25 +136,12 @@ def getTerminalSize():
|
||||||
os.close(fd)
|
os.close(fd)
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
# If that failed, we use os.environ, and if that fails, we set default values.
|
||||||
if not cr:
|
if not cr:
|
||||||
cr = (env.get('LINES', 25), env.get('COLUMNS', 80))
|
cr = (os.environ.get('LINES', 25), os.environ.get('COLUMNS', 80))
|
||||||
|
|
||||||
### Use get(key[, default]) instead of a try/catch
|
|
||||||
#try:
|
|
||||||
# cr = (env['LINES'], env['COLUMNS'])
|
|
||||||
#except:
|
|
||||||
# cr = (25, 80)
|
|
||||||
return int(cr[1]), int(cr[0])
|
return int(cr[1]), int(cr[0])
|
||||||
|
|
||||||
def cap_text(text, length):
|
|
||||||
"""Cap text length to length-1
|
|
||||||
|
|
||||||
"""
|
|
||||||
if len(text) >= length:
|
|
||||||
return text[0:length-1] + "…"
|
|
||||||
else:
|
|
||||||
return text
|
|
||||||
|
|
||||||
def format_percent(percent):
|
def format_percent(percent):
|
||||||
"""Formatte les pourcentages en ajoutant des espaces si
|
"""Formatte les pourcentages en ajoutant des espaces si
|
||||||
nécessaire.
|
nécessaire.
|
||||||
|
@ -123,11 +164,11 @@ def rojv(percent, seuils=(100, 75, 50, 25), couls=("cyan", "vert", "jaune", "ora
|
||||||
"""
|
"""
|
||||||
lens = len(seuils)
|
lens = len(seuils)
|
||||||
lenc = len(couls)
|
lenc = len(couls)
|
||||||
if lens+1 == lenc:
|
if lens + 1 == lenc:
|
||||||
coul = couls[0]
|
coul = couls[0]
|
||||||
for i in range(lens):
|
for i in range(lens):
|
||||||
if percent < seuils[i]:
|
if percent < seuils[i]:
|
||||||
coul = couls[i+1]
|
coul = couls[i + 1]
|
||||||
else:
|
else:
|
||||||
raise EnvironmentError("Seuils doit contenir une variable de moins par rapport à couls")
|
raise EnvironmentError("Seuils doit contenir une variable de moins par rapport à couls")
|
||||||
return coul
|
return coul
|
||||||
|
@ -169,21 +210,37 @@ class Animation(object):
|
||||||
self.beginTime = time.time()
|
self.beginTime = time.time()
|
||||||
cols, _ = getTerminalSize()
|
cols, _ = getTerminalSize()
|
||||||
|
|
||||||
|
# La seule façon efficace de faire de l'affichage de barres de chargement ou autres dynamiquement
|
||||||
|
# est d'utiliser sys.stdout. C'est pas super propre, mais de toute façon, les trucs kikoo c'est
|
||||||
|
# rarement propre, d'abord.
|
||||||
|
|
||||||
|
# Si le nombre de cycles est indéfini, on affiche une "barre de chargement" non bornée.
|
||||||
if not self.nb_cycles > 0:
|
if not self.nb_cycles > 0:
|
||||||
sys.stdout.write("\r%s ..... %s" % (cap_text(self.texte, cols - 10), "\|/-"[self.step%4]))
|
proceeding = "\r%s ..... %s" % (cap_text(self.texte, cols - 10), "\|/-"[self.step % 4])
|
||||||
|
sys.stdout.write(proceeding.encode(guess_preferred_encoding()))
|
||||||
|
|
||||||
|
# Sinon, on affiche un truc avec une progression/un pourcentage
|
||||||
else:
|
else:
|
||||||
percent = int((self.step+1.0)/self.nb_cycles*100)
|
percent = int((self.step + 1.0)/self.nb_cycles * 100)
|
||||||
|
|
||||||
|
# Quand on manque de colonnes, on évite les trucs trop verbeux, idem si la kikooness
|
||||||
|
# n'est pas demandée.
|
||||||
if not self.kikoo or cols <= 55:
|
if not self.kikoo or cols <= 55:
|
||||||
if self.couleur:
|
if self.couleur:
|
||||||
|
# Avec de la couleur.
|
||||||
percent = style("%s %%" % (format_percent(percent),), rojv(percent))
|
percent = style("%s %%" % (format_percent(percent),), rojv(percent))
|
||||||
else:
|
else:
|
||||||
|
# Sans couleur (so sad)
|
||||||
percent = "%s %%" % (format_percent(percent),)
|
percent = "%s %%" % (format_percent(percent),)
|
||||||
sys.stdout.write("\r%s : %s" % (cap_text(self.texte, cols - 10), percent))
|
proceeding = "\r%s : %s" % (cap_text(self.texte, cols - 10), percent)
|
||||||
|
sys.stdout.write(proceeding.encode(guess_preferred_encoding()))
|
||||||
|
|
||||||
|
# Du kikoo ! Du kikoo !
|
||||||
else:
|
else:
|
||||||
# La kikoo bar est une barre de la forme [======> ]
|
# La kikoo bar est une barre de la forme [======> ]
|
||||||
# Nombre de =
|
# Nombre de =
|
||||||
amount = percent/4
|
amount = percent/4
|
||||||
# On remplit le reste avec des espaces.
|
|
||||||
if self.couleur:
|
if self.couleur:
|
||||||
# kikoo_print contient la barre et le pourcentage, colorés en fonction du pourcentage
|
# kikoo_print contient la barre et le pourcentage, colorés en fonction du pourcentage
|
||||||
kikoo_print = style("[%s%s%s] %s %%" % (amount * '=',
|
kikoo_print = style("[%s%s%s] %s %%" % (amount * '=',
|
||||||
|
@ -197,34 +254,31 @@ class Animation(object):
|
||||||
">",
|
">",
|
||||||
(25-amount) * ' ',
|
(25-amount) * ' ',
|
||||||
format_percent(percent))
|
format_percent(percent))
|
||||||
sys.stdout.write("\r%s %s" % (cap_text(self.texte, cols - 45),
|
proceeding = "\r%s %s" % (cap_text(self.texte, cols - 45), kikoo_print)
|
||||||
kikoo_print))
|
sys.stdout.write(proceeding.encode(guess_preferred_encoding()))
|
||||||
|
|
||||||
|
# What if we add more kikoo?
|
||||||
if self.timer:
|
if self.timer:
|
||||||
self.elapsedTime = time.time() - self.beginTime
|
self.elapsedTime = time.time() - self.beginTime
|
||||||
sys.stdout.write(" (temps écoulé : %ds)" % (self.elapsedTime))
|
proceeding = " (temps écoulé : %ds)" % (self.elapsedTime)
|
||||||
|
sys.stdout.write(proceeding.encode(guess_preferred_encoding()))
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
self.step += 1
|
self.step += 1
|
||||||
|
|
||||||
def end(self):
|
def end(self):
|
||||||
"""Prints a line return
|
"""Prints a line return"""
|
||||||
|
sys.stdout.write("\n".encode(guess_preferred_encoding()))
|
||||||
"""
|
|
||||||
sys.stdout.write("\n")
|
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
|
|
||||||
def nostyle(dialog=False):
|
def nostyle(dialog=False):
|
||||||
"""
|
"""Annule tout style précédent."""
|
||||||
Annule tout style précédent.
|
|
||||||
"""
|
|
||||||
if dialog:
|
if dialog:
|
||||||
return "\Zn"
|
return "\Zn"
|
||||||
return "\033[1;0m"
|
return "\033[1;0m"
|
||||||
|
|
||||||
@static_var([("styles", {})])
|
@static_var([("styles", {})])
|
||||||
def style(texte, what=None, dialog=False):
|
def style(texte, what=None, dialog=False):
|
||||||
"""
|
"""Pretty text is pretty
|
||||||
Pretty text is pretty
|
|
||||||
On peut appliquer plusieurs styles d'affilée, ils seront alors traités
|
On peut appliquer plusieurs styles d'affilée, ils seront alors traités
|
||||||
de gauche à droite (les plus à droite sont donc ceux appliqués en dernier,
|
de gauche à droite (les plus à droite sont donc ceux appliqués en dernier,
|
||||||
et les plus à gauche en premier, ce qui veut dire que les plus à droite
|
et les plus à gauche en premier, ce qui veut dire que les plus à droite
|
||||||
|
@ -250,36 +304,47 @@ def style(texte, what=None, dialog=False):
|
||||||
if dialog:
|
if dialog:
|
||||||
return dialogStyle(texte, what)
|
return dialogStyle(texte, what)
|
||||||
|
|
||||||
if isinstance(what, str):
|
if isinstance(what, unicode):
|
||||||
what = [what]
|
what = [what]
|
||||||
|
if isinstance(what, str):
|
||||||
|
what = [try_decode(what)]
|
||||||
|
|
||||||
if not what:
|
if not what:
|
||||||
return texte
|
return texte
|
||||||
|
|
||||||
|
# Si la variable statique styles n'est pas peuplée…
|
||||||
if style.styles == {}:
|
if style.styles == {}:
|
||||||
zeros = {'noir' : 30,
|
zeros = {
|
||||||
'rougefonce': 31,
|
'noir' : 30,
|
||||||
'vertfonce' : 32,
|
'rougefonce': 31,
|
||||||
'orange' : 33,
|
'vertfonce' : 32,
|
||||||
'bleufonce' : 34,
|
'orange' : 33,
|
||||||
'violet' : 35,
|
'bleufonce' : 34,
|
||||||
'cyanfonce' : 36,
|
'violet' : 35,
|
||||||
'grisclair' : 37,
|
'cyanfonce' : 36,
|
||||||
}
|
'grisclair' : 37,
|
||||||
|
}
|
||||||
|
|
||||||
|
# Méthode "automatisée" pour remplir la version "background" des codes
|
||||||
|
# couleur du shell.
|
||||||
f_zeros = { "f_"+coul : val+10 for (coul, val) in zeros.iteritems() }
|
f_zeros = { "f_"+coul : val+10 for (coul, val) in zeros.iteritems() }
|
||||||
zeros.update(f_zeros)
|
zeros.update(f_zeros)
|
||||||
zeros = { coul: "0;%s" % (val,) for (coul, val) in zeros.items() }
|
zeros = { coul: "0;%s" % (val,) for (coul, val) in zeros.items() }
|
||||||
|
|
||||||
ones = { 'gris': 30,
|
# Plus de couleurs (les codes sont de la forme \033[0;blah ou \033[1;blah, donc
|
||||||
'rouge': 31,
|
# ici on remplit la partie 1;.
|
||||||
'vert': 32,
|
ones = {
|
||||||
'jaune': 33,
|
'gris': 30,
|
||||||
'bleu': 34,
|
'rouge': 31,
|
||||||
'magenta': 35,
|
'vert': 32,
|
||||||
'cyan': 36,
|
'jaune': 33,
|
||||||
'blanc': 37,
|
'bleu': 34,
|
||||||
'gras': 50,
|
'magenta': 35,
|
||||||
}
|
'cyan': 36,
|
||||||
|
'blanc': 37,
|
||||||
|
'gras': 50,
|
||||||
|
}
|
||||||
|
|
||||||
f_ones = { "f_"+coul : val+10 for (coul, val) in ones.iteritems() }
|
f_ones = { "f_"+coul : val+10 for (coul, val) in ones.iteritems() }
|
||||||
ones.update(f_ones)
|
ones.update(f_ones)
|
||||||
ones = { coul: "1;%s" % (val,) for (coul, val) in ones.items() }
|
ones = { coul: "1;%s" % (val,) for (coul, val) in ones.items() }
|
||||||
|
@ -287,11 +352,11 @@ def style(texte, what=None, dialog=False):
|
||||||
style.styles.update(zeros)
|
style.styles.update(zeros)
|
||||||
style.styles.update(ones)
|
style.styles.update(ones)
|
||||||
style.styles["none"] = "1;0"
|
style.styles["none"] = "1;0"
|
||||||
|
|
||||||
for element in what:
|
for element in what:
|
||||||
texte = "\033[%sm%s\033[1;0m" % (style.styles[element], texte)
|
texte = "\033[%sm%s\033[1;0m" % (style.styles[element], texte)
|
||||||
return texte
|
return texte
|
||||||
|
|
||||||
# WARNING! TOO MANY UPPER CASES.
|
|
||||||
OK = style('Ok', 'vert')
|
OK = style('Ok', 'vert')
|
||||||
WARNING = style('Warning', 'jaune')
|
WARNING = style('Warning', 'jaune')
|
||||||
ERREUR = style('Erreur', 'rouge')
|
ERREUR = style('Erreur', 'rouge')
|
||||||
|
@ -308,15 +373,16 @@ def dialogStyle(texte, what):
|
||||||
what = [what]
|
what = [what]
|
||||||
|
|
||||||
dialog_styles = {
|
dialog_styles = {
|
||||||
'rouge': 1,
|
'rouge': 1,
|
||||||
'orange': 1,
|
'orange': 1,
|
||||||
'vert': 2,
|
'vert': 2,
|
||||||
'jaune': 3,
|
'jaune': 3,
|
||||||
'bleu': 4,
|
'bleu': 4,
|
||||||
'violet': 5,
|
'violet': 5,
|
||||||
'cyan': 6,
|
'cyan': 6,
|
||||||
'gris': 0,
|
'gris': 0,
|
||||||
'gras': 'b' }
|
'gras': 'b',
|
||||||
|
}
|
||||||
|
|
||||||
for elem in what:
|
for elem in what:
|
||||||
texte = "\Z%s%s\Zn" % (dialog_styles[elem], texte)
|
texte = "\Z%s%s\Zn" % (dialog_styles[elem], texte)
|
||||||
|
@ -336,30 +402,30 @@ def prettyDoin(what, status):
|
||||||
sys.stdout.write("\r[%s] %s\n" % (ERREUR, what))
|
sys.stdout.write("\r[%s] %s\n" % (ERREUR, what))
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
|
|
||||||
def tronque(data, largeur, dialog):
|
def cap_text(data, length, dialog=False):
|
||||||
"""
|
"""Tronque une chaîne à une certaine longueur en excluant
|
||||||
Tronque une chaîne à une certaine longueur en excluant
|
|
||||||
les commandes de style.
|
les commandes de style.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
# découpage d'une chaine trop longue
|
# découpage d'une chaine trop longue
|
||||||
regexp = re.compile(dialog_format if dialog else term_format)
|
regexp = re.compile(DIALOG_FORMAT if dialog else TERM_FORMAT)
|
||||||
new_data = u''
|
new_data = ''
|
||||||
new_len = 0
|
new_len = 0
|
||||||
|
|
||||||
# On laisse la mise en forme et on coupe les caratères affichés
|
# On laisse la mise en forme et on coupe les caratères affichés
|
||||||
while True :
|
while True :
|
||||||
s = regexp.search(data)
|
s = regexp.search(data)
|
||||||
if s:
|
if s:
|
||||||
if s.start() + new_len > largeur:
|
if s.start() + new_len > length:
|
||||||
new_data += data[:largeur - new_len - 1] + nostyle() + '*'
|
new_data += data[:length - new_len - 1] + nostyle() + '*'
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
new_data += data[:s.end()]
|
new_data += data[:s.end()]
|
||||||
data = data[s.end():]
|
data = data[s.end():]
|
||||||
new_len += s.start()
|
new_len += s.start()
|
||||||
else:
|
else:
|
||||||
if new_len + len(data) > largeur:
|
if new_len + len(data) > length:
|
||||||
new_data += data[:largeur - new_len - 1] + '*'
|
new_data += data[:length - new_len - 1] + '*'
|
||||||
data = ""
|
data = ""
|
||||||
else:
|
else:
|
||||||
new_data += data
|
new_data += data
|
||||||
|
@ -371,23 +437,23 @@ def tronque(data, largeur, dialog):
|
||||||
|
|
||||||
def aligne(data, alignement, largeur, dialog) :
|
def aligne(data, alignement, largeur, dialog) :
|
||||||
# Longeur sans les chaines de formatage
|
# Longeur sans les chaines de formatage
|
||||||
longueur = len(re.sub(dialog_format if dialog else term_format, '', data))
|
longueur = len(re.sub(DIALOG_FORMAT if dialog else TERM_FORMAT, '', data))
|
||||||
|
|
||||||
# Alignement
|
# Alignement
|
||||||
if longueur > largeur:
|
if longueur > largeur:
|
||||||
return tronque(data, largeur, dialog)
|
return cap_text(data, largeur, dialog)
|
||||||
|
|
||||||
elif longueur == largeur :
|
elif longueur == largeur :
|
||||||
return data
|
return data
|
||||||
|
|
||||||
elif alignement == 'g':
|
elif alignement == 'g':
|
||||||
return u' ' + data + u' '*(largeur-longueur-1)
|
return ' ' + data + ' '*(largeur-longueur-1)
|
||||||
|
|
||||||
elif alignement == 'd':
|
elif alignement == 'd':
|
||||||
return u' '*(largeur-longueur-1) + data + u' '
|
return ' '*(largeur-longueur-1) + data + ' '
|
||||||
|
|
||||||
else:
|
else:
|
||||||
return u' '*((largeur-longueur)/2) + data + u' '*((largeur-longueur+1)/2)
|
return ' '*((largeur-longueur)/2) + data + ' '*((largeur-longueur+1)/2)
|
||||||
|
|
||||||
def format_data(data, format):
|
def format_data(data, format):
|
||||||
if format == 's':
|
if format == 's':
|
||||||
|
@ -395,9 +461,9 @@ def format_data(data, format):
|
||||||
|
|
||||||
elif format == 'o':
|
elif format == 'o':
|
||||||
data = float(data)
|
data = float(data)
|
||||||
for i in xrange(0, len(oct_names)):
|
for i in xrange(0, len(OCT_NAMES)):
|
||||||
if data > oct_sizes[i]:
|
if data > OCT_SIZES[i]:
|
||||||
return "%.2f %s" % (data/oct_sizes[i], oct_names[i])
|
return "%.2f %s" % (data/OCT_SIZES[i], OCT_NAMES[i])
|
||||||
return "%.0f o" % (data)
|
return "%.0f o" % (data)
|
||||||
|
|
||||||
def tableau(data, titre=None, largeur=None, alignement=None, format=None, dialog=False, width=None, styles=None, swap=None):
|
def tableau(data, titre=None, largeur=None, alignement=None, format=None, dialog=False, width=None, styles=None, swap=None):
|
||||||
|
@ -434,7 +500,7 @@ def tableau(data, titre=None, largeur=None, alignement=None, format=None, dialog
|
||||||
if data and isinstance(data, list):
|
if data and isinstance(data, list):
|
||||||
nb_cols = len(data[0])
|
nb_cols = len(data[0])
|
||||||
else:
|
else:
|
||||||
return u""
|
return ""
|
||||||
|
|
||||||
if format is None:
|
if format is None:
|
||||||
format = ['s'] * nb_cols
|
format = ['s'] * nb_cols
|
||||||
|
@ -449,8 +515,8 @@ def tableau(data, titre=None, largeur=None, alignement=None, format=None, dialog
|
||||||
|
|
||||||
data = [[format_data(ligne[i], format[i]) for i in xrange(nb_cols)] for ligne in data]
|
data = [[format_data(ligne[i], format[i]) for i in xrange(nb_cols)] for ligne in data]
|
||||||
|
|
||||||
if not largeur :
|
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)]
|
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:
|
elif '*' in largeur or -1 in largeur:
|
||||||
for i in xrange(0, len(largeur)):
|
for i in xrange(0, len(largeur)):
|
||||||
if largeur[i] is not None:
|
if largeur[i] is not None:
|
||||||
|
@ -477,22 +543,22 @@ def tableau(data, titre=None, largeur=None, alignement=None, format=None, dialog
|
||||||
##########
|
##########
|
||||||
if titre :
|
if titre :
|
||||||
# ligne de titre
|
# ligne de titre
|
||||||
chaine = sep_col + sep_col.join([style(aligne(titre[i], 'c', largeur[i], dialog), styles[i]) for i in range(nb_cols)]) + sep_col + u'\n'
|
chaine = SEP_COL + SEP_COL.join([style(aligne(titre[i], 'c', largeur[i], dialog), styles[i]) for i in range(nb_cols)]) + SEP_COL + '\n'
|
||||||
# ligne de séparation
|
# ligne de séparation
|
||||||
chaine += sep_col + u'+'.join([u'-'*largeur[i] for i in range(nb_cols)]) + sep_col + u'\n'
|
chaine += SEP_COL + '+'.join(['-'*largeur[i] for i in range(nb_cols)]) + SEP_COL + '\n'
|
||||||
else :
|
else :
|
||||||
chaine = u''
|
chaine = ''
|
||||||
|
|
||||||
# Les données
|
# Les données
|
||||||
#############
|
#############
|
||||||
j = 0
|
j = 0
|
||||||
for ligne in data:
|
for ligne in data:
|
||||||
chaine += u"%s" % (sep_col,)
|
chaine += "%s" % (SEP_COL,)
|
||||||
if swap:
|
if swap:
|
||||||
chaine += sep_col.join([style(ligne[i], swap[j]) for i in range(nb_cols)])
|
chaine += SEP_COL.join([style(ligne[i], swap[j]) for i in range(nb_cols)])
|
||||||
else:
|
else:
|
||||||
chaine += sep_col.join([style(ligne[i], styles[i]) for i in range(nb_cols)])
|
chaine += SEP_COL.join([style(ligne[i], styles[i]) for i in range(nb_cols)])
|
||||||
chaine += u"%s\n" % (sep_col,)
|
chaine += "%s\n" % (SEP_COL,)
|
||||||
j = (j + 1) % len(swap)
|
j = (j + 1) % len(swap)
|
||||||
|
|
||||||
return chaine
|
return chaine
|
||||||
|
@ -508,7 +574,7 @@ if __name__ == "__main__":
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
prettyDoin("Les carottes sont cuites." , "Ok")
|
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"]]
|
data = [[style("Durand", "rouge"), "Toto", "40", "50 rue Döp"], ["Dupont", "Robert", "50", "42" + style(" avenue ", "vert") + style("dumotel", 'rouge')], [style("znvuzbvzruobouzb", ["gras", "vert"]), "pppoe", "1", "poiodur 50 pepe"]]
|
||||||
titres = (u"Nom", u"Prénom", u"Âge", u"Adresse")
|
titres = ("Nom", "Prénom", "Âge", "Adresse")
|
||||||
longueurs = [25, 25, '*', '*']
|
longueurs = [25, 25, '*', '*']
|
||||||
print tableau(data, titres, longueurs)
|
print tableau(data, titres, longueurs).encode(guess_preferred_encoding())
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue