#!/usr/bin/env python3 import curses import os import sys import termios import tty import argparse class getch: def get(self): fd = sys.stdin.fileno() old_settings = termios.tcgetattr(fd) try: tty.setraw(sys.stdin.fileno()) ch = sys.stdin.read(1) finally: termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) return ch def get_opts(): parser = argparse.ArgumentParser( description='Colorful password dialog', epilog="Dialog printed to stderr, user input echoed to stdout, i.e. input=$( qaskpass )") parser.add_argument('--title','-t', action='store', default=None, help="Title for dialog") parser.add_argument('-w', action='store', type=int, default=5, help="Width of display area. 0 to disable display.") parser.add_argument('--no-color', action='store_true', default=False, help="Disable colors") args = parser.parse_args() return args def termsize(): rows, columns = os.popen("stty size", "r").read().split() return (int(rows), int(columns)) class bc: m = "\033[95m" b = "\033[94m" g = "\033[92m" y = "\033[93m" r = "\033[91m" c = "\033[96m" B = "\033[1m" z = "\033[0m" def disable(self): for x in "rgbcmyBz": setattr(self, x, "") def animchar(i, pos, colorpos, width,c): if i < 0: return " " if pos == colorpos: clr = c.c else: if i < 10: clr = c.r elif i < 20: clr = c.y else: clr = c.g return clr + "▁▂▃▄▅▆▇█▇▆▅▄▃▂"[int(i / width) % 14] def pquit(s="", e=0): print("", file=sys.stderr) print(s, end="", file=sys.stdout if e == 0 else sys.stderr) sys.exit(e) if __name__ == "__main__": opts = get_opts() # 3= ctrl-c, 13=enter # 127 = backspace ch = getch() user_input = "" display = "**** ****" c = bc() if opts.no_color: c.disable() if opts.title: print(f"{c.y}{c.B}{opts.title}{c.z}", file=sys.stderr) while True: try: if opts.w>0: colorpos = len(user_input) % opts.w display = c.m + "•••• " for i in range(opts.w): display += animchar(len(user_input) - i, i, colorpos,opts.w,c) display += c.m + " ••••" + c.z print("\r" + display, file=sys.stderr, end="") sys.stderr.flush() key = ch.get() if ord(key) == 3: # ctrl-c pquit(e=1) if ord(key) == 13: # enter pquit(user_input, e=0) if ord(key) == 27: # esc (also starts control characters key = ch.get() if ord(key) == 27: pquit(e=1) continue if ord(key) == 127: # backspace user_input = user_input[0:-1] else: user_input += key # ~ print(f'-{key}-',file=sys.stderr) # ~ print(f'-{ord(key)}-',file=sys.stderr) except Exception as e: pquit(s=str(e),e=1)