Builder3/Window.js
[app.Builder.js] / Options.js
1 //<script type="text/javascript">
2
3 XObject = imports.XObject.XObject
4  
5 /**
6  * Options parsing is needed as GLib's built in GOptionGroup is not feasible to use in an introspected way at present.
7  * 
8  * usage :
9  * 
10  * o = new Options(
11  *    help_desription : 'Help about this',
12  *    options : [
13  *        { arg_short : 'a', arg_long: 'test', description : 'a test', flag_array: true , flag_boolean : false, arg_default: 'fred'}
14  *    ]
15  * );
16  * cfg = o.parse(Seed.argv);
17  * 
18  * Currently only supports simple parsing
19  * eg. --longarg test -b test
20  * 
21  * Does not support --aaaaa=bbbb
22  */
23 Options  = XObject.define(
24     function (cfg) {
25         options = []; // default.
26         XObject.extend(this,cfg);
27         if (this.help_description.length) {
28             this.options.push({ arg_short : 'h', arg_long: 'help', description : 'Show Help', flag_boolean : true});
29             
30         }
31     },
32     Object,
33     {
34         /**
35          * @cfg {String} help_description what appears at the start of the help message.
36          */
37         help_description: '',
38         /**
39          * @cfg {Boolean} If extra arguments are allowed.
40          */
41         allow_extra : false,
42         /**
43          * @param {Object} Resulting key/value of data.
44          */
45         result : false,
46         /**
47          * @prop {Array} the arguments
48          */
49         args: false,
50         /**
51          * @prop {Array} extra the arguments that are not accounted for.
52          */
53         extra: false,
54         /**
55          * parse the argv
56          * usage: options.parse(Seed.argv)
57          */
58         parse: function (argv)
59         {
60             var _this = this;
61             this.result = {};
62             this.options.forEach(function(a) {
63                 
64                 if (typeof(a.arg_default) != 'undefined') {
65                     _this.result[a.arg_long] = a.arg_default;
66                     return;
67                 }
68                 
69                 if (a.flag_boolean) {
70                     _this.result[a.arg_long] = false;
71                     return;
72                 }
73                 if (a.flag_array) {
74                     _this.result[a.arg_long] = [];
75                     return;
76                 }
77                 
78             })
79             
80             this.extra = {};
81             var args = Array.prototype.slice.call(Seed.argv);
82             args.shift(); //seed
83             args.shift(); //script..
84         
85             for(var i =0; i < args.length;i++) {
86                 
87                 var a= this.findArg(args[i]);
88                 
89                 if (!a) {
90                     if (!this.allow_extra) {
91                         throw {
92                             name: "ArgumentError", 
93                             message: "Unknown argument: " + args[i] 
94                         };
95                     }
96                     this.extra.push(args[i]);
97                 }
98                 
99                 if (a.arg_long == 'help' ) {
100                     print("Help Message Requested");
101                     this.showHelp();
102                     Seed.quit();
103                     return;
104                 }
105                 
106                 if (a.flag_boolean) {
107                     this.result[a.arg_long] = true;
108                     continue;
109                 }
110                 var next = args[i+1];
111                 if (this.findArg(next)) {
112                     throw {
113                         name: "ArgumentError", 
114                         message: "Invalid argument sequence: " + args[i] + ' ' + next
115                     };
116                 }
117                 // type juggling -- fixme...
118                 
119                 if (a.flag_array) {
120                     this.result[a.arg_long].push(next);
121                     i++;
122                     continue;
123                 }
124             
125                 if (typeof(this.result[a.arg_long]) != 'undefined') {
126                     throw {
127                         name: "ArgumentError", 
128                         message: "Invalid argument duplicate: " + args[i] + ' ' + next
129                     };
130                 }
131                 
132                 this.result[a.arg_long] = next;
133                 i++;
134             }
135             // validate results..
136             this.options.forEach(function(a) {
137                 if (typeof(a.arg_default) != 'undefined') {
138                     return;
139                 }
140                 if (a.flag_boolean) {
141                     return; 
142                 }
143                 if (typeof(_this.result[a.arg_long]) != 'undefined') {
144                     return;
145                 }
146                 _this.showHelp();
147                 throw {
148                     name: "ArgumentError", 
149                     message: "Missing Argument: --" + a.arg_long
150                 };
151             });
152             
153             
154             return this.result;
155         },
156             
157              
158         findArg : function(str)
159         {
160             var ret = false;
161             var type = str.substring(0,1) == '-' ? 'arg_short' : '';
162             type = str.substring(0,2) == '--' ? 'arg_long' : type;
163             if (type == '') {
164                 return false; // not an arg..
165             }
166             var match = str.substring(type =='arg_long' ? 2 : 1);
167             
168             this.options.forEach(function(o) {
169                 if (ret) {
170                     return; // no more parsing.
171                 }
172                 if (o[type] == match) {
173                     ret = o;
174                 }
175                 
176             });
177             return ret;
178             
179         },
180         
181         
182         showHelp: function()
183         {
184             print(this.help_description);
185             this.options.forEach(function(o) {
186                 // fixme needs tidying up..
187                 print('  --' + o.arg_long + '   (-' + o.arg_short + ')  ' + o.description);
188             });
189             
190                 
191         }
192     }
193 );