1 /**
2  * Copyright: Copyright (c) 2011 Nick Sabalausky. All rights reserved.
3  * Authors: Nick Sabalausky
4  * Version: Initial created: Jun 4, 2011
5  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
6  */
7 module dvm.io.Console;
8 
9 import std.exception : assumeUnique;
10 import std.stdio : writeln;
11 import std.uni : toLower;
12 
13 import tango.io.Console;
14 import tango.io.Stdout;
15 import tango.text.Util;
16 
17 import dvm.dvm.Options;
18 import dvm.util.Util;
19 
20 /++
21 Easy general-purpose function to prompt user for input.
22 Optionally supports custom validation.
23 
24 Get input from the user:
25     auto result = prompt("Enter Text>");
26 
27 Get validated input. Won't return until user enters valid input:
28     bool accept(string input)
29     {
30         input = toLower(input);
31         return input == "coffee" || input == "tea";
32     }
33     auto result = prompt("What beverage?", &accept, "Not on menu, try again!");
34 +/
35 string prompt(string promptMsg, bool delegate(const(char)[]) accept=null, string rejectedMsg="")
36 {
37     char[] input;
38     while (true)
39     {
40         Stdout(promptMsg).flush;
41         Cin.readln(input);
42         input = trim(input);
43 
44         if (accept is null)
45             break;
46         else
47         {
48             if (accept(input))
49                 break;
50             else
51             {
52                 Stdout.newline;
53                 if (rejectedMsg != "")
54                     Stdout.formatln(rejectedMsg, input);
55             }
56         }
57     }
58 
59     return input.assumeUnique;
60 }
61 
62 /// Returns 'true' for "Yes"
63 /// Obeys --force and --decline
64 bool promptYesNo()
65 {
66     bool matches(char ch, const(char)[] str)
67     {
68         str = toLower(str);
69         return str != "" && str[0] == ch;
70     }
71 
72     bool accept(const(char)[] str)
73     {
74         return matches('y', str) || matches('n', str);
75     }
76 
77     auto options = Options.instance;
78 
79     if (options.decline)
80     {
81         writeln("[Declining, 'no']");
82         return false;
83     }
84 
85     if (options.force)
86     {
87         writeln("[Forcing, 'yes']");
88         return true;
89     }
90 
91     auto response = prompt("Yes/No?>", &accept);
92     return matches('y', response);
93 }