Source file owl_zoo_cmd.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
(*
 * OWL - an OCaml numerical library for scientific computing
 * Copyright (c) 2016-2018 Liang Wang <liang.wang@cl.cam.ac.uk>
 *)

open Owl


let dir = Owl_zoo_path.dir


let eval cmd = cmd
  |> Lexing.from_string
  |> !Toploop.parse_toplevel_phrase
  |> Toploop.execute_phrase true Format.err_formatter
  |> ignore


let preprocess script =
  let prefix = "." ^ (Filename.basename script) in
  let tmp_script = Filename.temp_file prefix ".ml" in
  let content =
    "#!/usr/bin/env owl\n" ^
    "#use \"topfind\"\n" ^
    "#require \"owl\"\n" ^
    "#require \"owl-zoo\"\n" ^
    "let load_file = Owl_zoo_cmd.load_file;;\n" ^
    Printf.sprintf "#use \"%s\"\n" script
  in
  Owl_io.write_file tmp_script content;
  tmp_script


let remove_gist gid =
  let path = dir ^ "/" ^ gid ^ "/" in
  let cmd = Printf.sprintf "rm -rf %s" path in
  let ret = Sys.command cmd in
  if ret = 0 then (
    Owl_zoo_ver.remove gid;
    Owl_log.debug "owl-zoo: %s removed" gid
  )
  else Owl_log.debug "owl-zoo: Error remvoing gist %s" gid


let upload_gist gist_dir =
  Owl_log.debug "owl-zoo: %s uploading" gist_dir;
  let cmd = Printf.sprintf "owl_upload_gist.sh %s" gist_dir in
  Sys.command cmd |> ignore;
  let gist_arr = Owl_io.read_file (gist_dir ^ "/gist.id") in
  gist_arr.(0)


let download_gist ?vid gid =
  let vid = match vid with
  | Some a -> a
  | None   -> Owl_zoo_ver.get_remote_vid gid
  in
  if (Owl_zoo_ver.exist gid vid) = true then
    Owl_log.info "owl-zoo: %s/%s cached" gid vid
  else (
    Owl_log.debug "owl-zoo: %s/%s missing; downloading" gid vid;
    let cmd = Printf.sprintf "owl_download_gist.sh %s %s" gid vid in
    let ret = Sys.command cmd in
    if ret = 0 then (Owl_zoo_ver.update gid vid)
    else Owl_log.debug "owl-zoo: Error downloading gist %s%s" gid vid
  )


let list_gist gid =
  let path = dir ^ "/" ^ gid in
  Owl_log.debug "owl-zoo: %s" path;
  let cmd = Printf.sprintf "owl_list_gist.sh %s" path in
  Sys.command cmd |> ignore


let update_gist gids =
  let gids =
    if Array.length gids = 0 then Sys.readdir dir
    else gids
  in
  Owl_log.debug "owl-zoo: updating %i gists" Array.(length gids);
  Array.iter download_gist gids


let show_info gist =
  let gid, vid, _, _ = Owl_zoo_ver.parse_gist_string gist in
  let dir = Owl_zoo_path.gist_path gid vid in
  let files = Sys.readdir dir
    |> Array.fold_left (fun a s -> a ^ s ^ " ") ""
  in
  let readme = dir ^ "/#readme.md" in
  let info_s =
    if Sys.file_exists readme then (
      Owl_io.read_file readme
      |> Array.fold_left (fun a s -> a ^ s ^ "\n") ""
    )
    else "missing #readme.md"
  in
  let info =
    Printf.sprintf "[gid]   %s\n" gid ^
    Printf.sprintf "[vid]   %s\n" vid ^
    Printf.sprintf "[path]  %s\n" dir ^
    Printf.sprintf "[url]   %s\n" ("https://gist.github.com/" ^
      gid ^ "/" ^ vid) ^
    Printf.sprintf "[files] %s\n" files ^
    Printf.sprintf "[info]  %s" info_s
  in
  print_endline info


let query_path gist =
  let gid, vid, _, _ =
    try Owl_zoo_ver.parse_gist_string gist
    with Owl_exception.ZOO_ILLEGAL_GIST_NAME -> "", "", 0., true
  in
  Owl_zoo_path.extend_zoo_path ~gid ~vid ""


(* f is a file name in the gist, e.g., #readme.md *)
let load_file ?(gist="") f =
  let path = (query_path gist) ^ f in
  Owl_io.read_file_string path


let run args script =
  let new_script = preprocess script in
  Toploop.initialize_toplevel_env ();
  Toploop.run_script Format.std_formatter new_script args
  |> ignore


let run_gist gist =
  let tmp_script = Filename.temp_file "zoo_tmp" ".ml" in
  let content = Printf.sprintf "\n#zoo \"%s\"\n" gist in
  Owl_io.write_file tmp_script content;
  run [|""|] tmp_script |> ignore


let print_info () =
  let info =
    "Owl's Zoo System\n\n" ^
    "Usage: \n" ^
    "  owl [utop options] [script-file]\texecute an Owl script\n" ^
    "  owl -upload [gist-directory]\t\tupload code snippet to gist\n" ^
    "  owl -download [gist-id] [ver-id]\tdownload code snippet from gist; download the latest version if ver-id not specified\n" ^
    "  owl -remove [gist-id]\t\t\tremove a cached gist\n" ^
    "  owl -update [gist-ids]\t\tupdate (all if not specified) gists\n" ^
    "  owl -run [gist-name]\t\t\trun a self-contained gist\n" ^
    "  owl -info [gist-name]\t\t\tshow the basic information of a gist\n" ^
    "  owl -list [gist-id]\t\t\tlist all cached versions of a gist; all the cached gists if not specified\n" ^
    "  owl -help\t\t\t\tprint out help information\n"
  in
  print_endline info


let start_toplevel () =
  print_info ();
  Toploop.initialize_toplevel_env ();
  eval "#use \"topfind\";;";
  eval "Topfind.don't_load_deeply [\"compiler-libs.toplevel\"];;";
  eval "#require \"owl\";;";
  eval "#require \"owl-zoo\";;";
  eval "#require \"owl-top\";;";
  Toploop.loop Format.std_formatter