# -*- 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!")