@@ -48,6 +48,117 @@ will get:
48
48
49
49
## Using the Arg module
50
50
51
+ The OCaml standard library has a module for writing command line interfaces, so
52
+ we do not have to use ` Sys.argv ` directly. We shall consider the example from
53
+ the OCaml documentation, a program for appending files.
54
+
55
+ First, we set up the usage message to be printed in the case of a malformed
56
+ command line, or when help is requested:
57
+
58
+ ``` ocaml
59
+ let usage_msg = "append [-verbose] <file1> [<file2>] ... -o <output>"
60
+ ```
61
+
62
+ Now, we create some references to hold the information gathered from the
63
+ command line. The ` Arg ` module will fill these in for us as the command line is
64
+ read.
65
+
66
+ ``` ocaml
67
+ let verbose = ref false
68
+
69
+ let input_files = ref []
70
+
71
+ let output_file = ref ""
72
+ ```
73
+
74
+ We have a boolean reference for the ` -verbose ` flag with a default value of
75
+ ` false ` . Then we have a reference to a list which will hold the names of all
76
+ the input files. Finally, we have a string reference into which the single
77
+ output file name specified by ` -o ` will be placed.
78
+
79
+ We will need a function to handle the anonymous inputs, that is to say the ones
80
+ with no flag before them. In this case these are our input file names. Our
81
+ function simply adds the file name to the reference defined earlier.
82
+
83
+ ``` ocaml
84
+ let anon_fun filename =
85
+ input_files := filename :: !input_files
86
+ ```
87
+
88
+ Finally we build the list of command line flag specifcations. Each is a tuple
89
+ of the flag name, the action to be taken when it is encountered, and the help
90
+ string.
91
+
92
+ ``` ocaml
93
+ let speclist =
94
+ [("-verbose", Arg.Set verbose, "Output debug information");
95
+ ("-o", Arg.Set_string output_file, "Set output file name")]
96
+ ```
97
+
98
+ We have two kinds of action here: the ` Arg.Set ` action which sets a boolean
99
+ reference, and the ` Arg.Set_string ` action which sets a string reference. Our
100
+ ` input_files ` reference will of course be updated by the ` anon_fun ` function
101
+ already defined.
102
+
103
+ We can now call ` Arg.parse ` , giving it our specification list, anonymous
104
+ function, and usage message. Once it returns, the references will be filled
105
+ with all the information required to append our files.
106
+
107
+ ``` ocaml
108
+ let () =
109
+ Arg.parse speclist anon_fun usage_msg;
110
+ (* Main functionality here *)
111
+ ```
112
+
113
+ Let's save our program as ` append.ml ` and compile it with `ocamlopt -o append
114
+ append.ml` and try it out:
115
+
116
+ ``` shell
117
+ $./append -verbose one.txt two.txt -o three.txt
118
+
119
+ $./append one.txt two.txt
120
+
121
+ $./append -quiet
122
+ ./append: unknown option ' -quiet' .
123
+ append [-verbose] < file1> [< file2> ] ... -o < output>
124
+ -verbose Output debug information
125
+ -o Set output file name
126
+ -help Display this list of options
127
+ --help Display this list of options
128
+
129
+ $./append -help
130
+ append [-verbose] < file1> [< file2> ] ... -o < output>
131
+ -verbose Output debug information
132
+ -o Set output file name
133
+ -help Display this list of options
134
+ --help Display this list of options
135
+ ```
136
+
137
+ Here is the whole program:
138
+
139
+ ``` ocaml
140
+ let usage_msg = "append [-verbose] <file1> [<file2>] ... -o <output>"
141
+
142
+ let verbose = ref false
143
+
144
+ let input_files = ref []
145
+
146
+ let output_file = ref ""
147
+
148
+ let anon_fun filename =
149
+ input_files := filename :: !input_files
150
+
151
+ let speclist =
152
+ [("-verbose", Arg.Set verbose, "Output debug information");
153
+ ("-o", Arg.Set_string output_file, "Set output file name")]
154
+
155
+ let () =
156
+ Arg.parse speclist anon_fun usage_msg;
157
+ (* Main functionality here *)
158
+ ```
159
+
160
+ The ` Arg ` module has many more actions than just ` Set ` and ` Set_string ` , and
161
+ some lower-level function for parsing more complicated command lines.
51
162
52
163
## Other tools for parsing command-line options
53
164
0 commit comments