Skip to content

Commit f5db05a

Browse files
Merge branch 'master' of https://github.com/ocaml/ocaml.org
2 parents a71b07e + cc77bbe commit f5db05a

File tree

3 files changed

+191
-45
lines changed

3 files changed

+191
-45
lines changed

site/404.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<!-- ((! set title Docs !)) ((! set documentation !)) ((! set nobreadcrumb !)) -->
2+
3+
<div class="center">
4+
<div class="head">
5+
<h1><b>404</b></h1>
6+
<h5><b>Oops, page not found!</b> <br>The page doesn't exist or some other error occurred.</h5>
7+
<a href="https://ocaml.org/" class="btn">Home</a>
8+
</div>
9+
</div>

site/css/ocamlorg.css

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,16 @@ ul.translations:after { content: "]"; }
549549
height: 0px;
550550
}
551551
}
552+
.center{
553+
display: table;
554+
text-align: center;
555+
width: 100%;
556+
height:53vh;
557+
}
558+
.head{
559+
display: table-cell;
560+
vertical-align:middle;
561+
}
552562

553563
/* Footer
554564
***********************************************************************/

site/learn/tutorials/command-line_arguments.md

Lines changed: 172 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2,51 +2,178 @@
22
<!-- ((! set center !)) -->
33

44
# Command-line arguments
5-
This is a short tutorial for those who are writing their first OCaml
6-
program and are wondering how to read arguments that are passed on the
7-
command line.
8-
9-
## argv
10-
Like in the C programming language, the arguments that are passed to a
11-
given program are stored in an array. Following the tradition, this
12-
array is named `argv`. It is found in the `Sys` module of the standard
13-
library, therefore its full name is `Sys.argv`. The number of arguments
14-
including the name of the program itself is simply the length of the
15-
array. It is obtained using the `Array.length` function.
16-
17-
## Simple example
18-
The following program displays the arguments with their position in
19-
`Sys.argv`:
5+
6+
In this tutorial we learn how to read command line arguments directly, using
7+
OCaml's `Sys.argv` array, and then how to do so more easily using the standard
8+
library's `Arg` module.
9+
10+
## Sys.argv
11+
12+
Like in C and many other languages, the arguments that are passed to a given
13+
program on the command line are stored in an array. Following tradition, this
14+
array is named `argv`. It is found in the `Sys` module of the standard library,
15+
therefore its full name is `Sys.argv`. The number of arguments including the
16+
name of the program itself is simply the length of the array. It is obtained
17+
using the `Array.length` function.
18+
19+
The following program displays the arguments with their position in `Sys.argv`:
20+
21+
```ocaml
22+
for i = 0 to Array.length Sys.argv - 1 do
23+
Printf.printf "[%i] %s\n" i Sys.argv.(i)
24+
done
25+
```
26+
27+
If you save the program above as `args.ml`, and run `ocaml args.ml arg1 arg2
28+
arg3`, here is what you get:
29+
30+
```
31+
[0] args.ml
32+
[1] arg1
33+
[2] arg2
34+
[3] arg3
35+
```
36+
37+
Note that `ocaml` launched a subprocess that actually runs the program where
38+
argv is `args.ml arg1 arg2 arg3`. You can also compile your program using
39+
`ocamlopt -o args args.ml`, and then running `./args arg1 arg2 arg3` and you
40+
will get:
41+
42+
```
43+
[0] ./args
44+
[1] arg1
45+
[2] arg2
46+
[3] arg3
47+
```
48+
49+
## Using the Arg module
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.
20106

21107
```ocaml
22108
let () =
23-
for i = 0 to Array.length Sys.argv - 1 do
24-
Printf.printf "[%i] %s\n" i Sys.argv.(i)
25-
done
26-
```
27-
If you save the program above as `args.ml`, and run
28-
`ocaml args.ml arg1 arg2 arg3`, here is what you get:
29-
30-
[0] args.ml
31-
[1] arg1
32-
[2] arg2
33-
[3] arg3
34-
35-
Note that `ocaml` launched a subprocess that actually runs the program
36-
where argv is `args.ml arg1 arg2 arg3`. You can also compile your
37-
program using `ocamlopt -o args args.ml`, and then run
38-
`./args arg1 arg2 arg3` and you will get:
39-
40-
[0] ./args
41-
[1] arg1
42-
[2] arg2
43-
[3] arg3
44-
45-
## Tools for parsing command-line options
46-
There are libraries that let you process command-line arguments
47-
without having to scan the `Sys.argv` array yourself:
48-
49-
* `Arg` is a module of the standard library.
50-
* [Getopt](https://opam.ocaml.org/packages/getopt/)
51-
for OCaml is similar to [GNU
52-
getopt](http://www.gnu.org/software/libc/manual/html_node/Getopt.html).
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.
162+
163+
## Other tools for parsing command-line options
164+
165+
There are libraries with facilities different from or more extensive than the
166+
built-in `Arg` module:
167+
168+
* [Cmdliner](https://erratique.ch/software/cmdliner/doc/Cmdliner) is a modern
169+
interface for command line processing, which also generates UNIX man pages
170+
automatically.
171+
172+
* [Clap](https://opam.ocaml.org/packages/clap/) is an imperative command line
173+
parser.
174+
175+
* [Minicli](https://opam.ocaml.org/packages/minicli/) has good support for
176+
rejecting malformed command lines which others might sliently accept.
177+
178+
* [Getopt](https://opam.ocaml.org/packages/getopt/) for OCaml is similar to
179+
[GNU getopt](http://www.gnu.org/software/libc/manual/html_node/Getopt.html).

0 commit comments

Comments
 (0)