1 /** 2 * Consoleur: a package for interaction with character-oriented terminal emulators 3 * 4 * Copyright: Maxim Freck, 2017. 5 * Authors: Maxim Freck <maxim@freck.pp.ru> 6 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 7 */ 8 module consoleur.cli.password; 9 10 /** 11 * Reads password from the user with echo 12 * 13 * Params: 14 * mask = Typed character mask 15 * 16 * Returns: Password 17 */ 18 string getPassword(string prompt = "Password: ", int maxLength = 0, dchar mask = '•') @trusted 19 { 20 import consoleur.cli.util: delchar, utf8length; 21 import consoleur.core.termparam: setTermparam, Term; 22 import consoleur.core: flushStdin; 23 import consoleur.input.key: Command, getKeyPressed, KeyModifier, KeyType; 24 import std.stdio: stdout, write; 25 26 string ret; 27 immutable tparam = setTermparam(Term.quiet|Term.raw); 28 29 write(prompt); 30 stdout.flush; 31 32 while (true) { 33 auto code = getKeyPressed(); 34 35 if (code.type == KeyType.COMMAND && code.content.code == Command.del && ret.length > 0) { 36 ret = ret.delchar; 37 write("\b \b"); 38 stdout.flush; 39 } 40 if ( ( (code.type == KeyType.COMMAND && code.content.code == Command.escape ) || 41 (code.type == KeyType.COMMAND && code.content.code == Command.del && (code.modifier & KeyModifier.alt) ) ) 42 && ret.length > 0 43 ) { 44 foreach (_; 0 .. ret.utf8length) write("\b \b"); 45 stdout.flush; 46 ret.length = 0; 47 } 48 49 if (code.type == KeyType.COMMAND && code.content.code == Command.lineFeed) break; 50 51 if (maxLength > 0 && ret.length == maxLength) continue; 52 53 if (code.type == KeyType.ASCII || code.type == KeyType.UTF8) { 54 ret ~= cast(string)(code); 55 write(mask); 56 stdout.flush; 57 } 58 } 59 60 flushStdin(); 61 return ret; 62 }