Skip to content

Commit

Permalink
First cut of jupyter output
Browse files Browse the repository at this point in the history
Signed-off-by: Jon Ludlam <[email protected]>
  • Loading branch information
jonludlam authored and gpetiot committed Sep 28, 2021
1 parent 06ca955 commit 4338055
Show file tree
Hide file tree
Showing 6 changed files with 202 additions and 2 deletions.
14 changes: 13 additions & 1 deletion bin/dune
Original file line number Diff line number Diff line change
@@ -1,11 +1,23 @@
(library
(name cli)
(modules cli)
(libraries cmdliner fmt.cli logs.fmt fmt.tty logs.cli mdx))
(libraries cmdliner fmt.cli logs.fmt fmt.tty logs.cli mdx yojson atdgen))

(executable
(name main)
(public_name ocaml-mdx)
(package mdx)
(modules :standard \ cli)
(libraries cli mdx))

(rule
(targets notebook_j.ml notebook_j.mli)
(deps notebook.atd)
(action
(run atdgen -j -j-std %{deps})))

(rule
(targets notebook_t.ml notebook_t.mli)
(deps notebook.atd)
(action
(run atdgen -t %{deps})))
129 changes: 129 additions & 0 deletions bin/jupyter.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
open Mdx.Util.Result.Infix
open Cmdliner

let raw t =
Notebook_t.
{
cell_type = `Raw;
metadata = { collapsed = None; scrolled = None };
source = String.concat "\n" t;
outputs = None;
execution_count = None;
}

let txt source =
Notebook_t.
{
cell_type = `Markdown;
metadata = { collapsed = None; scrolled = None };
source;
outputs = None;
execution_count = None;
}

let execution_count = ref 1

let ocaml contents =
let cell =
Notebook_t.
{
cell_type = `Code;
metadata = { collapsed = None; scrolled = None };
source = String.concat "\n" contents;
outputs = Some [];
execution_count = Some !execution_count;
}
in
incr execution_count;
cell

let toplevel x =
let cell =
Notebook_t.
{
cell_type = `Code;
metadata = { collapsed = None; scrolled = None };
source = String.concat "\n" x.Mdx.Toplevel.command;
outputs = Some [];
execution_count = Some !execution_count;
}
in
incr execution_count;
cell

let metadata =
Notebook_t.
{
kernelspec =
{
display_name = "OCaml 4.07.1";
language = "OCaml";
name = "ocaml-jupyter";
};
language_info =
{
name = "OCaml";
version = "4.07.1";
codemirror_mode = Some "text/x-ocaml";
file_extension = ".ml";
mimetype = "text/x-ocaml";
nbconverter_exporter = None;
pygments_lexer = "OCaml";
};
}

let rec collapse_text = function
| Mdx.Text x :: Mdx.Text y :: xs ->
collapse_text (Mdx.Text (x ^ "\n" ^ y) :: xs)
| (Mdx.Section _ as s) :: Mdx.Text y :: xs ->
let s = Mdx.to_string [ s ] in
collapse_text (Mdx.Text (s ^ "\n" ^ y) :: xs)
| (Mdx.Section _ as s) :: xs ->
let s = Mdx.to_string [ s ] in
collapse_text (Mdx.Text s :: xs)
| x :: ys -> x :: collapse_text ys
| [] -> []

let run _setup (`Syntax syntax) (`File file) =
let cells = ref [] in
Mdx.run ?syntax file ~f:(fun _file_contents items ->
let syntax =
match syntax with
| Some s -> s
| None -> (
match Mdx.Syntax.infer ~file with
| Some s -> s
| None -> failwith "Couldn't get syntax")
in
List.iter
(function
| Mdx.Text "" -> ()
| Mdx.Text x -> cells := txt x :: !cells
| Mdx.Block { value = OCaml { env = User_defined _; _ }; _ }
| Mdx.Block { value = Toplevel { env = User_defined _; _ }; _ } ->
failwith "internal error, cannot handle user defined environments"
| Mdx.Block { value = OCaml _; contents; _ } ->
cells := ocaml contents :: !cells
| Mdx.Block { value = Toplevel _; contents; loc; _ } ->
let blocks = Mdx.Toplevel.of_lines ~syntax ~loc contents in
let newcells = List.rev_map toplevel blocks in
cells := newcells @ !cells
| Mdx.Block { value = Raw _; contents; _ } ->
cells := raw contents :: !cells
| x ->
failwith
(Printf.sprintf "internal error, cannot handle: %s"
(Mdx.to_string [ x ])))
(collapse_text items);
"OK")
>>! fun () ->
let notebook =
Notebook_t.
{ metadata; nbformat = 4; nbformat_minor = 2; cells = List.rev !cells }
in
Printf.fprintf stdout "%s" (Notebook_j.string_of_notebook notebook);
0

let cmd : int Term.t * Term.info =
let doc = "Convert an mdx file to a jupyter notebook." in
(Term.(pure run $ Cli.setup $ Cli.syntax $ Cli.file), Term.info "jupyter" ~doc)
2 changes: 1 addition & 1 deletion bin/main.ml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

open Cmdliner

let cmds = [ Test.cmd; Pp.cmd; Deps.cmd; Dune_gen.cmd ]
let cmds = [ Test.cmd; Pp.cmd; Deps.cmd; Dune_gen.cmd; Jupyter.cmd ]

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

Expand Down
57 changes: 57 additions & 0 deletions bin/notebook.atd
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
type kernelspec = {
display_name : string;
language: string;
name: string;
}

type language_info = {
name: string;
version: string;
codemirror_mode: string nullable;
file_extension: string;
mimetype: string;
nbconverter_exporter: string nullable;
pygments_lexer: string;
}

type metadata = {
kernelspec: kernelspec;
language_info: language_info;
}

type cell_metadata = {
?collapsed: bool nullable;
?scrolled: bool nullable;
}

type cell_type = [
| Code <json name="code">
| Markdown <json name="markdown">
| Raw <json name="raw">
]

type output_type = [
Stream <json name="stream">
| Display_data <json name="display_data">
| Execute_result <json name="execute_result">
| Error <json name="error">
]

type output = {
output_type : output_type;
}

type cell = {
cell_type : cell_type;
metadata: cell_metadata;
source: string;
?outputs: output list nullable;
?execution_count: int option;
} <json keep_nulls false>

type notebook = {
metadata: metadata;
nbformat: int;
nbformat_minor: int;
cells: cell list
}
1 change: 1 addition & 0 deletions dune-project
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
(csexp
(>= 1.3.2))
astring
atdgen
(logs (>= 0.7.0))
(cmdliner
(>= 1.0.0))
Expand Down
1 change: 1 addition & 0 deletions mdx.opam
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ depends: [
"cppo" {build}
"csexp" {>= "1.3.2"}
"astring"
"atdgen"
"logs" {>= "0.7.0"}
"cmdliner" {>= "1.0.0"}
"re" {>= "1.7.2"}
Expand Down

0 comments on commit 4338055

Please sign in to comment.