diff --git a/gestion/interactive.py b/gestion/interactive.py new file mode 100644 index 00000000..75e9c9b1 --- /dev/null +++ b/gestion/interactive.py @@ -0,0 +1,96 @@ +# -*- coding: utf-8 -*- +# +# interactive.py +# -------------- +# +# Copyright (C) 2007 Jeremie Dimino +# +# This file 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 2 of the License, or +# (at your option) any later version. +# +# This file 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, write to the Free Software +# Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. + +'''Utilitaire pour poser des questions de manières interactives +à l'utilisateur, à la manière de darcs.''' + +import os, sys, tty, termios +from affich_tools import cprint + +__all__ = ["getch", "ask", "Exit"] + +def getch(): + fd = sys.stdin.fileno() + mode = termios.tcgetattr(fd) + try: + tty.setraw(fd) + return os.read(fd, 1) + finally: + termios.tcsetattr(fd, termios.TCSAFLUSH, mode) + +# Constantes de choix +Exit = ("q", "quitter le programme", None, lambda: sys.exit(0)) + +def ask(message, choices): + '''Pose une question à l'utilisateur. +choices est une liste d'élément de la forme (choix) ou (choix, doc) +ou (choix, doc, valeur) ou encore (choix, doc, valeur, operation), où: +- choix sont les lettres pour le choix, si une est en majuscule alors + ce choix est celui par défaut. +- doc est une description du choix +- valeur est la valeur renvoyée si ce choix est fait, par défaut c'est choix[0].lower() +- operation est soit une fonction, auquel cas elle est éxécutée si le choix est fait + (et le questionnement continue si elle renoie vrai), + soit un tuple sur lequel ask est éxécutée, + soit une chaîne qui est affichée''' + while True: + cprint("%s [%s], ou ? pour l'aide: " % (message, "".join([c[0] for c in choices])), "bleu", newline=False) + sys.stdout.flush() + answer = getch() + sys.stdout.write(answer+"\n") + if answer in ['\x03', '\x04']: + raise KeyboardInterrupt() + if answer == " ": + for choice in choices: + if choice[0].lower != choix[0]: + answer = choice[0][0].lower() + break + cprint("Aucun choix par défaut!") + else: + answer = answer.lower() + for choice in choices: + if answer in choice[0].lower(): + answer = choice[0][0].lower() + break + if choices and answer == choice[0][0].lower(): + if len(choice) <= 2: + return answer + elif len(choice) == 3: + return choice[2] + elif type(choice[3]) == tuple: + (message, choices) = choice[3] + elif type(choice[3]) == str: + print + print choice[3] + elif not choice[3](): + return choice[2] + if answer in ["h", "?"]: + print + cprint("Réponses possible:") + for choice in choices: + cprint("%s: %s" % (" ou ".join(list(choice[0])), + ((len(choice) >= 2) and choice[1]) or "non documentée")) + cprint("h ou ?: afficher cette aide") + print + cprint(": accepter le choix par défault (celui qui est en majuscule)") + print + else: + cprint("Choix invalide, essaies encore!")