Skip to content

Commit f537765

Browse files
committed
using our own command line parsing for tweaks later
1 parent b419eb7 commit f537765

File tree

3 files changed

+253
-51
lines changed

3 files changed

+253
-51
lines changed

jscomp/bsb/bsb_arg.ml

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
(* Copyright (C) 2020- Authors of BuckleScript
2+
*
3+
* This program is free software: you can redistribute it and/or modify
4+
* it under the terms of the GNU Lesser General Public License as published by
5+
* the Free Software Foundation, either version 3 of the License, or
6+
* (at your option) any later version.
7+
*
8+
* In addition to the permissions granted to you by the LGPL, you may combine
9+
* or link a "work that uses the Library" with a publicly distributed version
10+
* of this file to produce a combined library or application, then distribute
11+
* that combined work under the terms of your choosing, with no requirement
12+
* to comply with the obligations normally placed on you by section 4 of the
13+
* LGPL version 3 (or the corresponding section of a later version of the LGPL
14+
* should you choose to use a later version).
15+
*
16+
* This program is distributed in the hope that it will be useful,
17+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
18+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19+
* GNU Lesser General Public License for more details.
20+
*
21+
* You should have received a copy of the GNU Lesser General Public License
22+
* along with this program; if not, write to the Free Software
23+
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *)
24+
25+
26+
27+
28+
type key = string
29+
type doc = string
30+
type anon_fun = rev_args:string list -> unit
31+
32+
type string_action =
33+
| String_call of (string -> unit)
34+
| String_set of string ref
35+
36+
type unit_action =
37+
| Unit_call of (unit -> unit)
38+
| Unit_set of bool ref
39+
40+
type spec =
41+
| Unit of unit_action
42+
| String of string_action
43+
44+
45+
exception Bad of string
46+
47+
48+
type error =
49+
| Unknown of string
50+
| Missing of string
51+
52+
type t = (string * spec * string) list
53+
54+
let rec assoc3 (x : string) (l : t) =
55+
match l with
56+
| [] -> None
57+
| (y1, y2, _) :: _ when y1 = x -> Some y2
58+
| _ :: t -> assoc3 x t
59+
;;
60+
61+
62+
let (+>) = Ext_buffer.add_string
63+
64+
let usage_b (buf : Ext_buffer.t) ~usage speclist =
65+
buf +> usage;
66+
buf +> "\nOptions:\n";
67+
let max_col = ref 0 in
68+
Ext_list.iter speclist (fun (key,_,_) ->
69+
if String.length key > !max_col then
70+
max_col := String.length key
71+
);
72+
Ext_list.iter speclist (fun (key,_,doc) ->
73+
buf +> " ";
74+
buf +> key ;
75+
buf +> (String.make (!max_col - String.length key + 2 ) ' ');
76+
buf +> doc;
77+
buf +> "\n"
78+
)
79+
;;
80+
81+
82+
83+
let stop_raise ~usage ~(error : error) speclist =
84+
let b = Ext_buffer.create 200 in
85+
begin match error with
86+
| Unknown ("-help" | "--help" | "-h") ->
87+
usage_b b ~usage speclist ;
88+
Ext_buffer.output_buffer stdout b;
89+
exit 0
90+
| Unknown s ->
91+
b +> "unknown option: '";
92+
b +> s ;
93+
b +> "'.\n"
94+
| Missing s ->
95+
b +> "option '";
96+
b +> s;
97+
b +> "' needs an argument.\n"
98+
end;
99+
usage_b b ~usage speclist ;
100+
raise (Bad (Ext_buffer.contents b))
101+
102+
103+
let parse_exn ~usage ~argv ~start (speclist : t) anonfun =
104+
let l = Array.length argv in
105+
let current = ref start in
106+
let rev_list = ref [] in
107+
while !current < l do
108+
let s = argv.(!current) in
109+
incr current;
110+
if s <> "" && s.[0] = '-' then begin
111+
match assoc3 s speclist with
112+
| Some action -> begin
113+
begin match action with
114+
| Unit r ->
115+
begin match r with
116+
| Unit_set r -> r.contents <- true
117+
| Unit_call f -> f ()
118+
end
119+
| String f ->
120+
if !current >= l then stop_raise ~usage ~error:(Missing s) speclist
121+
else begin
122+
let arg = argv.(!current) in
123+
incr current;
124+
match f with
125+
| String_call f ->
126+
f arg
127+
| String_set u -> u.contents <- arg
128+
end
129+
end;
130+
end;
131+
| None -> stop_raise ~usage ~error:(Unknown s) speclist
132+
end else begin
133+
rev_list := s :: !rev_list;
134+
end;
135+
done;
136+
anonfun ~rev_args:!rev_list
137+
;;
138+
139+
140+

jscomp/bsb/bsb_arg.mli

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
(* Copyright (C) 2020- Authors of BuckleScript
2+
*
3+
* This program is free software: you can redistribute it and/or modify
4+
* it under the terms of the GNU Lesser General Public License as published by
5+
* the Free Software Foundation, either version 3 of the License, or
6+
* (at your option) any later version.
7+
*
8+
* In addition to the permissions granted to you by the LGPL, you may combine
9+
* or link a "work that uses the Library" with a publicly distributed version
10+
* of this file to produce a combined library or application, then distribute
11+
* that combined work under the terms of your choosing, with no requirement
12+
* to comply with the obligations normally placed on you by section 4 of the
13+
* LGPL version 3 (or the corresponding section of a later version of the LGPL
14+
* should you choose to use a later version).
15+
*
16+
* This program is distributed in the hope that it will be useful,
17+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
18+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19+
* GNU Lesser General Public License for more details.
20+
*
21+
* You should have received a copy of the GNU Lesser General Public License
22+
* along with this program; if not, write to the Free Software
23+
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *)
24+
25+
type string_action =
26+
| String_call of (string -> unit)
27+
| String_set of string ref
28+
29+
type unit_action =
30+
| Unit_call of (unit -> unit)
31+
| Unit_set of bool ref
32+
33+
exception Bad of string
34+
35+
type spec =
36+
| Unit of unit_action
37+
| String of string_action
38+
39+
type key = string
40+
type doc = string
41+
42+
type anon_fun = rev_args:string list -> unit
43+
44+
val parse_exn :
45+
usage:string ->
46+
argv:string array ->
47+
start:int ->
48+
(key * spec * doc) list ->
49+
anon_fun -> unit

jscomp/main/bsb_main.ml

Lines changed: 64 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -23,72 +23,72 @@
2323
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *)
2424

2525
let () = Bsb_log.setup ()
26-
27-
let force_regenerate = ref false
28-
2926
let current_theme = ref "basic"
30-
let set_theme s = current_theme := s
3127
let generate_theme_with_path = ref None
3228
let regen = "-regen"
3329
let separator = "--"
3430
let watch_mode = ref false
3531
let make_world = ref false
3632
let do_install = ref false
37-
let set_make_world () = make_world := true
3833
let bs_version_string = Bs_version.version
39-
4034
let print_version_string () =
4135
print_string bs_version_string;
4236
print_newline ();
4337
exit 0
38+
type spec = Bsb_arg.spec
4439

45-
let bsb_main_flags : (string * Arg.spec * string) list=
40+
let call_spec f : spec = Unit (Unit_call f )
41+
let unit_set_spec b : spec = Unit (Unit_set b)
42+
43+
44+
let force_regenerate = ref false
45+
let bsb_main_flags : (string * spec * string) list=
4646
[
47-
"-v", Unit print_version_string,
48-
" Print version and exit";
49-
"-version", Unit print_version_string,
50-
" Print version and exit";
51-
"-verbose", Unit Bsb_log.verbose,
52-
" Set the output(from bsb) to be verbose";
53-
"-w", Set watch_mode,
54-
" Watch mode" ;
55-
"-clean-world", Unit (fun _ ->
47+
"-v", call_spec print_version_string,
48+
"Print version and exit";
49+
"-version", call_spec print_version_string,
50+
"Print version and exit";
51+
"-verbose", call_spec Bsb_log.verbose,
52+
"Set the output(from bsb) to be verbose";
53+
"-w", unit_set_spec watch_mode,
54+
"Watch mode" ;
55+
"-clean-world",call_spec (fun _ ->
5656
Bsb_clean.clean_bs_deps Bsb_global_paths.cwd),
57-
" Clean all bs dependencies";
58-
"-clean", Unit (fun _ ->
57+
"Clean all bs dependencies";
58+
"-clean", call_spec (fun _ ->
5959
Bsb_clean.clean_self Bsb_global_paths.cwd),
60-
" Clean only current project";
61-
"-make-world", Unit set_make_world,
62-
" Build all dependencies and itself ";
63-
"-install", Set do_install,
64-
" Install public interface files into lib/ocaml";
65-
"-init", String (fun path -> generate_theme_with_path := Some path),
66-
" Init sample project to get started. Note (`bsb -init sample` will create a sample project while `bsb -init .` will reuse current directory)";
67-
"-theme", String set_theme,
68-
" The theme for project initialization, default is basic(https://github.com/bucklescript/bucklescript/tree/master/jscomp/bsb/templates)";
60+
"Clean only current project";
61+
"-make-world", unit_set_spec make_world,
62+
"Build all dependencies and itself ";
63+
"-install", unit_set_spec do_install,
64+
"Install public interface files into lib/ocaml";
65+
"-init", String (String_call (fun path -> generate_theme_with_path := Some path)),
66+
"Init sample project to get started. Note (`bsb -init sample` will create a sample project while `bsb -init .` will reuse current directory)";
67+
"-theme", String (String_set current_theme),
68+
"The theme for project initialization, default is basic(https://github.com/bucklescript/bucklescript/tree/master/jscomp/bsb/templates)";
6969

70-
regen, Set force_regenerate,
71-
" (internal) Always regenerate build.ninja no matter bsconfig.json is changed or not (for debugging purpose)";
72-
"-themes", Unit Bsb_theme_init.list_themes,
73-
" List all available themes";
70+
regen, unit_set_spec force_regenerate,
71+
"(internal) Always regenerate build.ninja no matter bsconfig.json is changed or not (for debugging purpose)";
72+
"-themes", call_spec Bsb_theme_init.list_themes,
73+
"List all available themes";
7474
"-where",
75-
Unit (fun _ ->
75+
call_spec (fun _ ->
7676
print_endline (Filename.dirname Sys.executable_name)),
77-
" Show where bsb.exe is located";
77+
"Show where bsb.exe is located";
7878
(** Below flags are only for bsb script, it is not available for bsb.exe
7979
we make it at this time to make `bsb -help` easier
8080
*)
81-
"-ws", Bool ignore,
82-
" [host:]port specify a websocket number (and optionally, a host). When a build finishes, we send a message to that port. For tools that listen on build completion." ;
81+
"-ws", call_spec ignore,
82+
"[host:]port specify a websocket number (and optionally, a host). When a build finishes, we send a message to that port. For tools that listen on build completion." ;
8383
#if BS_NATIVE then
84-
"-backend", String (fun s ->
84+
"-backend", String (String_call (fun s ->
8585
match s with
8686
| "js" -> Bsb_global_backend.set_backend Bsb_config_types.Js
8787
| "native" -> Bsb_global_backend.set_backend Bsb_config_types.Native
8888
| "bytecode" -> Bsb_global_backend.set_backend Bsb_config_types.Bytecode
8989
| _ -> failwith "-backend should be one of: 'js', 'bytecode' or 'native'."
90-
),
91-
" Builds the entries specified in the bsconfig that match the given backend. Can be either 'js', 'bytecode' or 'native'.";
90+
)),
91+
"Builds the entries specified in the bsconfig that match the given backend. Can be either 'js', 'bytecode' or 'native'.";
9292
#end
9393
]
9494

@@ -135,13 +135,16 @@ let ninja_command_exit ninja_args =
135135
ninja -C _build
136136
*)
137137
let usage = "Usage : bsb.exe <bsb-options> -- <ninja_options>\n\
138-
For ninja options, try ninja -h \n\
138+
For ninja options, try bsb.exe -- -h. \n\
139+
Note they are supposed to be internals and not reliable.\n\
139140
ninja will be loaded either by just running `bsb.exe' or `bsb.exe .. -- ..`\n\
140-
It is always recommended to run ninja via bsb.exe \n\
141-
Bsb options are:"
141+
It is always recommended to run ninja via bsb.exe"
142142

143-
let handle_anonymous_arg arg =
144-
raise (Arg.Bad ("Unknown arg \"" ^ arg ^ "\""))
143+
let handle_anonymous_arg ~rev_args =
144+
match rev_args with
145+
| [] -> ()
146+
| arg:: _ ->
147+
raise (Bsb_arg.Bad ("Unknown arg \"" ^ arg ^ "\""))
145148

146149

147150
let program_exit () =
@@ -199,10 +202,16 @@ let () =
199202
| `No_split
200203
->
201204
begin
202-
Arg.parse bsb_main_flags handle_anonymous_arg usage;
205+
Bsb_arg.parse_exn
206+
~usage
207+
~argv
208+
~start:1
209+
bsb_main_flags
210+
handle_anonymous_arg
211+
;
203212
(* first, check whether we're in boilerplate generation mode, aka -init foo -theme bar *)
204213
match !generate_theme_with_path with
205-
| Some path -> Bsb_theme_init.init_sample_project ~cwd:Bsb_global_paths.cwd ~theme:!current_theme path
214+
| Some path -> Bsb_theme_init.init_sample_project ~cwd:Bsb_global_paths.cwd ~theme:!current_theme path
206215
| None ->
207216
(* [-make-world] should never be combined with [-package-specs] *)
208217
let make_world = !make_world in
@@ -240,17 +249,21 @@ let () =
240249
| `Split (bsb_args,ninja_args)
241250
-> (* -make-world all dependencies fall into this category *)
242251
begin
243-
Arg.parse_argv bsb_args bsb_main_flags handle_anonymous_arg usage ;
244-
let config_opt =
245-
Bsb_ninja_regen.regenerate_ninja
252+
Bsb_arg.parse_exn
253+
~usage
254+
~argv:bsb_args
255+
~start:1
256+
bsb_main_flags handle_anonymous_arg ;
257+
let config_opt = lazy
258+
(Bsb_ninja_regen.regenerate_ninja
246259
~toplevel_package_specs:None
247260
~per_proj_dir:Bsb_global_paths.cwd
248-
~forced:!force_regenerate in
261+
~forced:!force_regenerate) in
249262
(* [-make-world] should never be combined with [-package-specs] *)
250263
if !make_world then
251-
Bsb_world.make_world_deps Bsb_global_paths.cwd config_opt ninja_args;
264+
Bsb_world.make_world_deps Bsb_global_paths.cwd (Lazy.force config_opt) ninja_args;
252265
if !do_install then
253-
install_target config_opt;
266+
install_target (Lazy.force config_opt);
254267
if !watch_mode then program_exit ()
255268
else ninja_command_exit ninja_args
256269
end

0 commit comments

Comments
 (0)