Skip to content

Commit 5950948

Browse files
jonludlamgpetiot
authored andcommitted
First cut of jupyter output
Signed-off-by: Jon Ludlam <[email protected]>
1 parent 06ca955 commit 5950948

File tree

7 files changed

+203
-2
lines changed

7 files changed

+203
-2
lines changed

CHANGES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
#### Added
44

5+
- Add Jupyter Notebook output (#124, @avsm, @CraigFe, @jonludlam)
6+
57
#### Changed
68

79
#### Deprecated

bin/dune

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,23 @@
11
(library
22
(name cli)
33
(modules cli)
4-
(libraries cmdliner fmt.cli logs.fmt fmt.tty logs.cli mdx))
4+
(libraries cmdliner fmt.cli logs.fmt fmt.tty logs.cli mdx yojson atdgen))
55

66
(executable
77
(name main)
88
(public_name ocaml-mdx)
99
(package mdx)
1010
(modules :standard \ cli)
1111
(libraries cli mdx))
12+
13+
(rule
14+
(targets notebook_j.ml notebook_j.mli)
15+
(deps notebook.atd)
16+
(action
17+
(run atdgen -j -j-std %{deps})))
18+
19+
(rule
20+
(targets notebook_t.ml notebook_t.mli)
21+
(deps notebook.atd)
22+
(action
23+
(run atdgen -t %{deps})))

bin/jupyter.ml

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
open Mdx.Util.Result.Infix
2+
open Cmdliner
3+
4+
let raw t =
5+
Notebook_t.
6+
{
7+
cell_type = `Raw;
8+
metadata = { collapsed = None; scrolled = None };
9+
source = String.concat "\n" t;
10+
outputs = None;
11+
execution_count = None;
12+
}
13+
14+
let txt source =
15+
Notebook_t.
16+
{
17+
cell_type = `Markdown;
18+
metadata = { collapsed = None; scrolled = None };
19+
source;
20+
outputs = None;
21+
execution_count = None;
22+
}
23+
24+
let execution_count = ref 1
25+
26+
let ocaml contents =
27+
let cell =
28+
Notebook_t.
29+
{
30+
cell_type = `Code;
31+
metadata = { collapsed = None; scrolled = None };
32+
source = String.concat "\n" contents;
33+
outputs = Some [];
34+
execution_count = Some !execution_count;
35+
}
36+
in
37+
incr execution_count;
38+
cell
39+
40+
let toplevel x =
41+
let cell =
42+
Notebook_t.
43+
{
44+
cell_type = `Code;
45+
metadata = { collapsed = None; scrolled = None };
46+
source = String.concat "\n" x.Mdx.Toplevel.command;
47+
outputs = Some [];
48+
execution_count = Some !execution_count;
49+
}
50+
in
51+
incr execution_count;
52+
cell
53+
54+
let metadata =
55+
Notebook_t.
56+
{
57+
kernelspec =
58+
{
59+
display_name = "OCaml 4.07.1";
60+
language = "OCaml";
61+
name = "ocaml-jupyter";
62+
};
63+
language_info =
64+
{
65+
name = "OCaml";
66+
version = "4.07.1";
67+
codemirror_mode = Some "text/x-ocaml";
68+
file_extension = ".ml";
69+
mimetype = "text/x-ocaml";
70+
nbconverter_exporter = None;
71+
pygments_lexer = "OCaml";
72+
};
73+
}
74+
75+
let rec collapse_text = function
76+
| Mdx.Text x :: Mdx.Text y :: xs ->
77+
collapse_text (Mdx.Text (x ^ "\n" ^ y) :: xs)
78+
| (Mdx.Section _ as s) :: Mdx.Text y :: xs ->
79+
let s = Mdx.to_string [ s ] in
80+
collapse_text (Mdx.Text (s ^ "\n" ^ y) :: xs)
81+
| (Mdx.Section _ as s) :: xs ->
82+
let s = Mdx.to_string [ s ] in
83+
collapse_text (Mdx.Text s :: xs)
84+
| x :: ys -> x :: collapse_text ys
85+
| [] -> []
86+
87+
let run _setup (`Syntax syntax) (`File file) =
88+
Mdx.run_to_stdout ?syntax file ~f:(fun _file_contents items ->
89+
let syntax =
90+
match syntax with
91+
| Some s -> s
92+
| None -> (
93+
match Mdx.Syntax.infer ~file with
94+
| Some s -> s
95+
| None -> failwith "Couldn't get syntax")
96+
in
97+
let cells =
98+
List.fold_left
99+
(fun acc -> function
100+
| Mdx.Text "" -> acc
101+
| Mdx.Text x -> txt x :: acc
102+
| Mdx.Block { value = OCaml { env = User_defined _; _ }; _ }
103+
| Mdx.Block { value = Toplevel { env = User_defined _; _ }; _ } ->
104+
failwith
105+
"internal error, cannot handle user defined environments"
106+
| Mdx.Block { value = OCaml _; contents; _ } ->
107+
ocaml contents :: acc
108+
| Mdx.Block { value = Toplevel _; contents; loc; _ } ->
109+
let blocks = Mdx.Toplevel.of_lines ~syntax ~loc contents in
110+
let newcells = List.rev_map toplevel blocks in
111+
newcells @ acc
112+
| Mdx.Block { value = Raw _; contents; _ } -> raw contents :: acc
113+
| x ->
114+
failwith
115+
(Printf.sprintf "internal error, cannot handle: %s"
116+
(Mdx.to_string [ x ])))
117+
[] (collapse_text items)
118+
|> List.rev
119+
in
120+
Notebook_j.string_of_notebook
121+
Notebook_t.{ metadata; nbformat = 4; nbformat_minor = 2; cells })
122+
>>! fun () -> 0
123+
124+
let cmd : int Term.t * Term.info =
125+
let doc = "Convert an mdx file to a jupyter notebook." in
126+
(Term.(pure run $ Cli.setup $ Cli.syntax $ Cli.file), Term.info "jupyter" ~doc)

bin/main.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
open Cmdliner
1818

19-
let cmds = [ Test.cmd; Pp.cmd; Deps.cmd; Dune_gen.cmd ]
19+
let cmds = [ Test.cmd; Pp.cmd; Deps.cmd; Dune_gen.cmd; Jupyter.cmd ]
2020

2121
let main (`Setup ()) = `Help (`Pager, None)
2222

bin/notebook.atd

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
type kernelspec = {
2+
display_name : string;
3+
language: string;
4+
name: string;
5+
}
6+
7+
type language_info = {
8+
name: string;
9+
version: string;
10+
codemirror_mode: string nullable;
11+
file_extension: string;
12+
mimetype: string;
13+
nbconverter_exporter: string nullable;
14+
pygments_lexer: string;
15+
}
16+
17+
type metadata = {
18+
kernelspec: kernelspec;
19+
language_info: language_info;
20+
}
21+
22+
type cell_metadata = {
23+
?collapsed: bool nullable;
24+
?scrolled: bool nullable;
25+
}
26+
27+
type cell_type = [
28+
| Code <json name="code">
29+
| Markdown <json name="markdown">
30+
| Raw <json name="raw">
31+
]
32+
33+
type output_type = [
34+
Stream <json name="stream">
35+
| Display_data <json name="display_data">
36+
| Execute_result <json name="execute_result">
37+
| Error <json name="error">
38+
]
39+
40+
type output = {
41+
output_type : output_type;
42+
}
43+
44+
type cell = {
45+
cell_type : cell_type;
46+
metadata: cell_metadata;
47+
source: string;
48+
?outputs: output list nullable;
49+
?execution_count: int option;
50+
} <json keep_nulls false>
51+
52+
type notebook = {
53+
metadata: metadata;
54+
nbformat: int;
55+
nbformat_minor: int;
56+
cells: cell list
57+
}

dune-project

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,14 @@
2727
(csexp
2828
(>= 1.3.2))
2929
astring
30+
atdgen
3031
(logs (>= 0.7.0))
3132
(cmdliner
3233
(>= 1.0.0))
3334
(re
3435
(>= 1.7.2))
3536
result
37+
yojson
3638
(ocaml-version
3739
(>= 2.3.0))
3840
(odoc-parser (>= 0.9.0))

mdx.opam

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,12 @@ depends: [
2525
"cppo" {build}
2626
"csexp" {>= "1.3.2"}
2727
"astring"
28+
"atdgen"
2829
"logs" {>= "0.7.0"}
2930
"cmdliner" {>= "1.0.0"}
3031
"re" {>= "1.7.2"}
3132
"result"
33+
"yojson"
3234
"ocaml-version" {>= "2.3.0"}
3335
"odoc-parser" {>= "0.9.0"}
3436
"lwt" {with-test}

0 commit comments

Comments
 (0)