1 /*
2  * hunt-console eases the creation of beautiful and testable command line interfaces.
3  *
4  * Copyright (C) 2018-2019, HuntLabs
5  *
6  * Website: https://www.huntlabs.net
7  *
8  * Licensed under the Apache-2.0 License.
9  *
10  */
11  
12 module hunt.console.input.ArrayInput;
13 
14 import std.string;
15 import hunt.console.input.InputOption;
16 import hunt.console.error.InvalidArgumentException;
17 import hunt.Integer;
18 import hunt.collection.HashMap;
19 import hunt.collection.LinkedHashMap;
20 import hunt.collection.Map;
21 import hunt.console.input.AbstractInput;
22 import hunt.console.input.InputDefinition;
23 import hunt.text.Common;
24 
25 import hunt.Exceptions;
26 import std.conv;
27 
28 
29 class ArrayInput : AbstractInput
30 {
31     private Map!(string, string) parameters;
32 
33     this()
34     {
35         this(new HashMap!(string, string)());
36     }
37 
38     this(string[] nameValues...)
39     {
40         parameters = new LinkedHashMap!(string, string)();
41         string name = null, value;
42         foreach (string nameOrValue ; nameValues) {
43             if (name is null) {
44                 name = nameOrValue;
45             } else {
46                 value = nameOrValue;
47                 parameters.put(name, value);
48                 name = null;
49             }
50         }
51     }
52 
53     this(Map!(string, string) parameters)
54     {
55         super();
56         this.parameters = parameters;
57     }
58 
59     this(Map!(string, string) parameters, InputDefinition definition)
60     {
61         super(definition);
62         this.parameters = parameters;
63     }
64 
65     override protected void parse()
66     {
67         string key, value;
68         foreach (string k,string v ; parameters) {
69             key = k;
70             value =v;
71             if (key.startsWith("--")) {
72                 addLongOption(key.substring(2), value);
73             } else if (k.startsWith("-")) {
74                 addShortOption(key.substring(1), value);
75             } else {
76                 addArgument(key, value);
77             }
78         }
79     }
80 
81     private void addShortOption(string shortcut, string value)
82     {
83         if (!definition.hasShortcut(shortcut)) {
84             throw new InvalidArgumentException(format("The '-%s' option does not exist.", shortcut));
85         }
86 
87         addLongOption(definition.getOptionForShortcut(shortcut).getName(), value);
88     }
89 
90     private void addLongOption(string name, string value)
91     {
92         if (!definition.hasOption(name)) {
93             throw new InvalidArgumentException(format("The '--%s' option does not exist.", name));
94         }
95 
96         InputOption option = definition.getOption(name);
97 
98         if (value is null) {
99             if (option.isValueRequired()) {
100                 throw new InvalidArgumentException(format("The '--%s' option requires a value.", name));
101             }
102 
103             value = option.isValueOptional() ? option.getDefaultValue() : "true";
104         }
105 
106         options.put(name, value);
107     }
108 
109     private void addArgument(string name, string value)
110     {
111         if (!definition.hasArgument(name)) {
112             throw new InvalidArgumentException(format("The '%s' argument does not exist.", name));
113         }
114 
115         arguments.put(name, value);
116     }
117 
118     override string getFirstArgument()
119     {
120         foreach (string k ,string v ; parameters) {
121             if (k.startsWith("-")) {
122                 continue;
123             }
124             return v;
125         }
126 
127         return null;
128     }
129 
130     override bool hasParameterOption(string[] values, bool onlyParams = false)
131     {
132 
133             implementationMissing(false);
134 
135         foreach (string k ,string v ; parameters) {
136             foreach (string value ; values) {
137                 if (k == value) {
138                     return true;
139                 }
140             }
141         }
142 
143         return false;
144     }
145 
146     // string getParameterOption(string value)
147     // {
148     //     return getParameterOption(value, null);
149     // }
150 
151     // string getParameterOption(string value, string defaultValue)
152     // {
153     //     foreach (string k , string v ; parameters) {
154     //         if (k == value) {
155     //             return v;
156     //         }
157     //     }
158 
159     //     return defaultValue;
160     // }
161     override string getParameterOption(string[] values, string defaultValue, bool onlyParams = false) {
162         foreach (string k , string v ; parameters) {
163             if(onlyParams && (k == "--" || (isInt(k) && v ==  "--")))
164                 return defaultValue;
165 
166             // if (k == value) {
167             //     return v;
168             // }
169             // TODO: Tasks pending completion -@zhangxueping at 2020-07-10T11:27:11+08:00
170             // 
171             implementationMissing(false);
172         }
173 
174         return defaultValue;        
175     }
176 
177     static bool isInt(string value) {
178         try {
179             int v = to!int(value);
180             return true;
181         } catch(Throwable) {
182             return false;
183         }
184     }
185 }