Skip to content

Commit 1cd5dd7

Browse files
committed
Merge branch 'master' of github.com:realworldocaml/mdx into jupyter
2 parents e68bf4c + 55f7d5f commit 1cd5dd7

34 files changed

+500
-171
lines changed

.travis.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@ env:
77
- TO_TEST=tests OPAMBUILDTEST=true OCAML_VERSION=4.04.2
88
- TO_TEST=tests OPAMBUILDTEST=true OCAML_VERSION=4.05.0
99
- TO_TEST=tests OPAMBUILDTEST=true OCAML_VERSION=4.06.1
10-
- TO_TEST=tests OPAMBUILDTEST=true OCAML_VERSION=4.07.0
10+
- TO_TEST=tests OPAMBUILDTEST=true OCAML_VERSION=4.07.1
11+
- TO_TEST=tests OPAMBUILDTEST=true OCAML_VERSION=4.08.0
1112
before_install:
1213
# Download and use opam2
13-
- wget -O ${HOME}/opam https://github.com/ocaml/opam/releases/download/2.0.2/opam-2.0.2-x86_64-linux
14+
- wget -O ${HOME}/opam https://github.com/ocaml/opam/releases/download/2.0.4/opam-2.0.4-x86_64-linux
1415
- chmod +x ${HOME}/opam
1516
# Some opam boilerplate
1617
- export OPAMYES=1

CHANGES.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
### 1.4.0 (2019-06-11)
2+
- Add `--force-output` option to force generation of diff file (#118 @clecat)
3+
- Support OCaml 4.08.0 (#121 @xclerc)
4+
- README and documentation fixes (#122 #118 @andreypopp @clecat @samoht)
5+
- Use latest ocaml-migrate-parsetree interfaces (@avsm)
6+
17
### 1.3.0 (2019-03-01)
28
- Updated readme file with the new features: dune rules, named environment and
39
ocaml versions, Some grammar correction too (@gpetiot, #101, aantron, #102)

README.md

Lines changed: 36 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,16 @@
44

55
`mdx` allows to execute code blocks inside markdown files.
66
There are (currently) two sub-commands, corresponding
7-
to two modes of operations: pre-processing (`mdx pp`)
8-
and tests (`mdx test`).
7+
to two modes of operations: pre-processing (`ocaml-mdx pp`)
8+
and tests (`ocaml-mdx test`).
99

1010
The pre-processor mode allows to mix documentation and code,
1111
and to practice "literate programming" using markdown and OCaml.
1212

1313
The test mode allows to ensure that shell scripts and OCaml fragments
1414
in the documentation always stays up-to-date.
1515

16-
`mdx` is released as a single binary (called `mdx`) and
16+
`mdx` is released as a single binary (called `ocaml-mdx`) and
1717
can be installed using opam:
1818

1919
```sh
@@ -24,7 +24,7 @@ $ opam install mdx
2424

2525
#### Shell Scripts
2626

27-
`mdx` interprets shell scripts inside `sh` code blocks as cram-like tests. The
27+
`ocaml-mdx` interprets shell scripts inside `sh` code blocks as cram-like tests. The
2828
syntax is the following:
2929

3030
- Lines beginning with a dollar sign and a space are
@@ -63,7 +63,7 @@ with a padding of 3:
6363
10
6464
```
6565

66-
`mdx` will also consider exit codes when the syntax `[<exit code>]`is used:
66+
`ocaml-mdx` will also consider exit codes when the syntax `[<exit code>]`is used:
6767

6868
```sh
6969
$ exit 1
@@ -75,7 +75,7 @@ of success).
7575

7676
#### OCaml Code
7777

78-
`mdx` interprets OCaml fragments. It understands _normal_ code fragments and
78+
`ocaml-mdx` interprets OCaml fragments. It understands _normal_ code fragments and
7979
_toplevel_ code fragments (starting with a `#` sign and optionally ending with
8080
`;;`). Arbitrary whitespace padding is supported, at long as it stays
8181
consistent within a code block.
@@ -97,7 +97,7 @@ Here is an examples of toplevel OCaml code:
9797

9898
### Pre-processing
9999

100-
`mdx pp` allows to transform a markdown file into a valid
100+
`ocaml-mdx pp` allows to transform a markdown file into a valid
101101
OCaml file, which can be passed to OCaml using the `-pp`
102102
option.
103103

@@ -111,7 +111,7 @@ For instance, given the following `file.md` document:
111111
Can be compiled and executed using:
112112

113113
```sh
114-
$ ocamlc -pp 'mdx pp' -impl file.md -o file.exe
114+
$ ocamlc -pp 'ocaml-mdx pp' -impl file.md -o file.exe
115115
$ ./file.exe
116116
42
117117
```
@@ -122,7 +122,7 @@ This can be automated using `dune`:
122122
(rule
123123
((targets (file.ml))
124124
(deps (file.md))
125-
(action (with-stdout-to ${@} (run mdx pp ${<})))))
125+
(action (with-stdout-to ${@} (run ocaml-mdx pp ${<})))))
126126
127127
(executable ((name file)))
128128
```
@@ -131,7 +131,7 @@ This can be automated using `dune`:
131131

132132
#### Cram Tests
133133

134-
Cram tests can be executed and checked with `mdx test <file.md>`.
134+
Cram tests can be executed and checked with `ocaml-mdx test <file.md>`.
135135

136136
```sh
137137
$ for i in `seq 1 10`; do echo $i; done
@@ -145,7 +145,7 @@ If the output is not consistent with what is expected,
145145

146146
#### OCaml
147147

148-
To execute OCaml code and toplevel fragments, uses `mdx test <file.md>`.
148+
To execute OCaml code and toplevel fragments, uses `ocaml-mdx test <file.md>`.
149149

150150
```ocaml
151151
# print_endline "42"
@@ -162,11 +162,11 @@ dune's `diff?` stanza:
162162

163163
```
164164
(alias
165-
((name runtest)
166-
(deps (file.md))
165+
(name runtest)
166+
(deps (:test file.md))
167167
(action (progn
168-
(run mdx test ${<})
169-
(diff? ${<} ${<}.corrected)))))
168+
(run ocaml-mdx test %{test})
169+
(diff? %{test} %{test}.corrected))))
170170
```
171171

172172
This allows to test the consistency of a markdown file using the normal dev
@@ -204,7 +204,7 @@ $ dune promote
204204

205205
**Non-deterministic Outputs**
206206

207-
`mdx test` supports non-deterministic outputs:
207+
`ocaml-mdx test` supports non-deterministic outputs:
208208

209209
```sh non-deterministic=output
210210
$ <command>
@@ -213,19 +213,19 @@ $ dune promote
213213

214214
In that case, `ppx test <file>` will run the command but will not
215215
generate `<file>.corrected` if the new output differs from the one
216-
described in the file. Use `mdx test --non-deterministic <file>` to come
216+
described in the file. Use `ocaml-mdx test --non-deterministic <file>` to come
217217
back to the default behaviour.
218218

219219
**Non-deterministic Commands**
220220

221-
`mdx test` supports non-deterministic commands:
221+
`ocaml-mdx test` supports non-deterministic commands:
222222

223223
```ocaml non-deterministic=command
224224
# Random.int 10;;
225225
- : int = 5
226226
```
227227

228-
In that case, `mdx test <file>` will *not* run the command. Use `mdx test
228+
In that case, `ocaml-mdx test <file>` will *not* run the command. Use `ocaml-mdx test
229229
--non-deterministic <file>` to come back to the default behaviour.
230230

231231
#### Named execution environments (since mdx 1.1.0)
@@ -294,39 +294,39 @@ The version number can be of the following forms:
294294

295295
Environment variables can be declared at the beginning of a block:
296296

297-
```ocaml set-FOO=bar,set-BAR=foo
298-
# print_endline (Sys.getenv "FOO")
299-
bar
300-
- : unit = ()
301-
# print_endline (Sys.getenv "BAR")
302-
foo
303-
- : unit = ()
304-
```
297+
```ocaml set-FOO=bar,set-BAR=foo
298+
# print_endline (Sys.getenv "FOO")
299+
bar
300+
- : unit = ()
301+
# print_endline (Sys.getenv "BAR")
302+
foo
303+
- : unit = ()
304+
```
305305

306306
Those variables are then available in the subsequent blocks
307307

308-
```ocaml
309-
# print_endline (Sys.getenv "FOO")
310-
bar
311-
- : unit = ()
312-
```
308+
```ocaml
309+
# print_endline (Sys.getenv "FOO")
310+
bar
311+
- : unit = ()
312+
```
313313

314314
### Sections
315315

316316
It is possible to test or execute only a subset of the file using
317317
sections using the `--section` option (short name is `-s`). For
318-
instance `mdx pp -s foo` will only consider the section matching the
318+
instance `ocaml-mdx pp -s foo` will only consider the section matching the
319319
perl regular expression `foo`.
320320

321321
### Dune rules (since mdx 1.1.0)
322322

323-
`mdx` can generate `dune` rules to synchronize .md files with .ml files.
323+
`ocaml-mdx` can generate `dune` rules to synchronize .md files with .ml files.
324324

325325
Consider the test/dune_rules.md file that contains blocks referring to files
326326
dune_rules_1.ml and dune_rules_2.ml, running:
327327

328328
```
329-
$ mdx rule test/dune_rules.md
329+
$ ocaml-mdx rule test/dune_rules.md
330330
```
331331

332332
generates the following `dune` rules on the standard output:
@@ -338,7 +338,7 @@ generates the following `dune` rules on the standard output:
338338
(:y0 dune_rules_2.ml)
339339
(source_tree foo))
340340
(action (progn
341-
(run mdx test --direction=infer-timestamp %{x})
341+
(run ocaml-mdx test --direction=infer-timestamp %{x})
342342
(diff? %{x} %{x}.corrected)
343343
(diff? %{y1} %{y1}.corrected)
344344
(diff? %{y0} %{y0}.corrected))))

bin/rule.ml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,11 @@ let print_rule ~nd ~prelude ~md_file ~ml_files ~dirs ~root options =
7979
"\
8080
(alias\n\
8181
\ (name %s)\n\
82-
\ (deps (:x %s)%s)\n\
82+
\ (deps (:x %s)\n\
83+
\ (package mdx)%s)\n\
8384
\ (action (progn\n\
84-
\ (run ocaml-mdx test %a %s%s%%{x})\n\
85-
\ (diff? %%{x} %%{x}.corrected)\n%a)))\n"
85+
\ (run ocaml-mdx test %a %s%s%%{x})\n%a\n\
86+
\ (diff? %%{x} %%{x}.corrected))))\n"
8687
name
8788
md_file
8889
deps

bin/test/main.ml

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,24 @@ let with_dir root f =
7474
Sys.chdir old_d;
7575
raise e
7676

77-
let run_test ?root temp_file t =
77+
let get_env blacklist =
78+
let blacklist = "INSIDE_DUNE"::blacklist in
79+
let env = Array.to_list (Unix.environment ()) in
80+
let env = List.map (String.split_on_char '=') env in
81+
let f env var =
82+
let g l = String.compare (List.nth l 0) var <> 0 in
83+
List.filter g env
84+
in
85+
let env = List.fold_left f env blacklist in
86+
Array.of_list (List.map (String.concat "=") env)
87+
88+
let run_test ?root blacklist temp_file t =
7889
let cmd = Cram.command_line t in
90+
let env = get_env blacklist in
7991
Log.info (fun l -> l "exec: %S" cmd);
8092
let fd = Unix.openfile temp_file [O_WRONLY; O_TRUNC] 0 in
8193
let pid = with_dir root (fun () ->
82-
Unix.create_process "sh" [| "sh"; "-c"; cmd |] Unix.stdin fd fd
94+
Unix.create_process_env "sh" [| "sh"; "-c"; cmd |] env Unix.stdin fd fd
8395
) in
8496
Unix.close fd;
8597
match snd (Unix.waitpid [] pid) with
@@ -102,7 +114,8 @@ let run_cram_tests ?syntax t ?root ppf temp_file pad tests =
102114
in
103115
List.iter (fun test ->
104116
let root = root_dir ?root t in
105-
let n = run_test ?root temp_file test in
117+
let blacklist = Block.unset_variables t in
118+
let n = run_test ?root blacklist temp_file test in
106119
let lines = read_lines temp_file in
107120
let output =
108121
let output = List.map (fun x -> `Output x) lines in
@@ -182,9 +195,9 @@ type file = { first: Mdx_top.Part.file; current: Mdx_top.Part.file }
182195

183196
let files: (string, file) Hashtbl.t = Hashtbl.create 8
184197

185-
let has_changed { first; current } =
198+
let has_changed ~force_output { first; current } =
186199
let contents = Mdx_top.Part.contents current in
187-
if contents = Mdx_top.Part.contents first
200+
if contents = Mdx_top.Part.contents first && force_output = false
188201
then None
189202
else Some contents
190203

@@ -196,9 +209,9 @@ let read_parts file =
196209
Hashtbl.add files file f;
197210
f
198211

199-
let write_parts file parts =
212+
let write_parts ~force_output file parts =
200213
let output_file = file ^ ".corrected" in
201-
match has_changed parts with
214+
match has_changed ~force_output parts with
202215
| None -> if Sys.file_exists output_file then Sys.remove output_file
203216
| Some c ->
204217
let oc = open_out output_file in
@@ -306,10 +319,12 @@ let run_exn ()
306319
| Section _
307320
| Text _ as t -> Mdx.pp_line ?syntax ppf t
308321
| Block t ->
309-
List.iter (fun (k, v) -> Unix.putenv k v) (Block.variables t);
322+
List.iter (fun (k, v) -> Unix.putenv k v) (Block.set_variables t);
310323
Mdx_top.in_env (Block.environment t)
311324
(fun () ->
312-
let active = active t && (not (Block.skip t)) in
325+
let active =
326+
active t && Block.version_enabled t && (not (Block.skip t))
327+
in
313328
match active, non_deterministic, Block.mode t, Block.value t with
314329
(* Print errors *)
315330
| _, _, _, Error _ -> Block.pp ?syntax ppf t
@@ -323,8 +338,9 @@ let run_exn ()
323338
non-deterministic; run it but keep the old output. *)
324339
| true, false, `Non_det `Output, Cram { tests; _ } ->
325340
Block.pp ?syntax ppf t;
341+
let blacklist = Block.unset_variables t in
326342
List.iter (fun t ->
327-
let _: int = run_test ?root temp_file t in ()
343+
let _: int = run_test ?root blacklist temp_file t in ()
328344
) tests
329345
| true, false, `Non_det `Output, Toplevel tests ->
330346
assert (syntax <> Some Cram);
@@ -340,32 +356,28 @@ let run_exn ()
340356
(* Run raw OCaml code *)
341357
| true, _, _, OCaml ->
342358
assert (syntax <> Some Cram);
343-
let version_enabled = Block.version_enabled t in
344359
(match Block.file t with
345-
| Some ml_file when version_enabled ->
360+
| Some ml_file ->
346361
update_file_or_block ?root ppf file ml_file t direction
347-
| None when version_enabled ->
362+
| None ->
348363
eval_raw t ?root c ~line:t.line t.contents;
349-
Block.pp ppf t
350-
| _ -> Block.pp ppf t )
364+
Block.pp ppf t )
351365
(* Cram tests. *)
352366
| true, _, _, Cram { tests; pad } ->
353367
run_cram_tests ?syntax t ?root ppf temp_file pad tests
354368
(* Top-level tests. *)
355369
| true, _, _, Toplevel tests ->
356370
assert (syntax <> Some Cram);
357-
let version_enabled = Block.version_enabled t in
358371
match Block.file t with
359-
| Some ml_file when version_enabled ->
372+
| Some ml_file ->
360373
update_file_or_block ?root ppf file ml_file t direction
361-
| None when version_enabled ->
374+
| None ->
362375
run_toplevel_tests ?root c ppf tests t
363-
| _ -> Block.pp ppf t
364376
)
365377
) items;
366378
Format.pp_print_flush ppf ();
367379
Buffer.contents buf);
368-
Hashtbl.iter write_parts files;
380+
Hashtbl.iter (write_parts ~force_output) files;
369381
0
370382

371383
let run ()

0 commit comments

Comments
 (0)