diff options
author | sternenseemann <git@lukasepple.de> | 2017-02-17 22:49:07 +0100 |
---|---|---|
committer | sternenseemann <git@lukasepple.de> | 2017-02-17 22:49:07 +0100 |
commit | 3b5d541fb8cf320783ad07776f88ce5b9aa8431c (patch) | |
tree | 7522c34eaf0c69e0789c429d41a8318c33db2f6d | |
parent | 61f32a011b2eeecbd9ba2dcc36cb42b117fb1e87 (diff) |
Introduce logbook command line for generating HTML files of log files
-rw-r--r-- | README.md | 9 | ||||
-rw-r--r-- | _tags | 3 | ||||
-rw-r--r-- | example.log | 20 | ||||
-rw-r--r-- | opam | 2 | ||||
-rw-r--r-- | pkg/META | 2 | ||||
-rwxr-xr-x | pkg/pkg.ml | 3 | ||||
-rw-r--r-- | src/log.ml | 8 | ||||
-rw-r--r-- | src/log.mli | 2 | ||||
-rw-r--r-- | src/logbook.ml | 34 | ||||
-rw-r--r-- | src/logbook_models.ml | 21 | ||||
-rw-r--r-- | src/logbook_template.ml | 25 |
11 files changed, 116 insertions, 13 deletions
diff --git a/README.md b/README.md index 75304fd..1874b0f 100644 --- a/README.md +++ b/README.md @@ -14,10 +14,15 @@ The 42nd day of the year. + Public information. foo bar - - Private information. Additional block - * Semi-private information. More text! ``` + +## Installation & Usage + +``` +opam pin add logbook https://gitlab.glaxx.net/sternenseemann/logbook.git +logbook --file example.log [ --private | --public | --semi-private ] +``` diff --git a/_tags b/_tags index 0dcebae..c94104e 100644 --- a/_tags +++ b/_tags @@ -1,3 +1,4 @@ true : bin_annot, safe_string, package(bytes ptime angstrom astring) - <src> : include + +<src/logbook*> : package(lwt lwt.unix jingoo) diff --git a/example.log b/example.log index 0c19185..1d23a9f 100644 --- a/example.log +++ b/example.log @@ -1,9 +1,17 @@ [2017-02-14] -Test +Got the log parser into a working state -+ Hi this is a test - Hi? - Is this working? ++ Implemented Angstrom parsers + Still kinda ugly and not perfect, need a bit of work. +- This is private + Well not really, just testing this out… -- private - foobar? +[2017-02-17] +Implemented logbook cli + ++ Open & parse file with Lwt + Why is it so hard to even open a file in OCaml? ++ Reworked parser + I applied more applicative style, making the parser much better. + Also I fixed an annoying bug, where you could not omit the empty line between items. + Still not working are substitutes and proper failure whilst parsing. diff --git a/opam b/opam index 594bc29..7f99fd2 100644 --- a/opam +++ b/opam @@ -15,6 +15,8 @@ depends: [ "ptime" "angstrom" "astring" + "lwt" + "jingoo" ] depopts: [] build: [ diff --git a/pkg/META b/pkg/META index 37cd0b8..bb2b70f 100644 --- a/pkg/META +++ b/pkg/META @@ -1,6 +1,6 @@ description = "tool for personal log files" version = "%%VERSION_NUM%%" -requires = "ptime angstrom astring" +requires = "ptime angstrom astring lwt jingoo" archive(byte) = "logbook.cma" archive(native) = "logbook.cmxa" plugin(byte) = "logbook.cma" diff --git a/pkg/pkg.ml b/pkg/pkg.ml index ec3d818..0909c4d 100755 --- a/pkg/pkg.ml +++ b/pkg/pkg.ml @@ -5,4 +5,5 @@ open Topkg let () = Pkg.describe "logbook" @@ fun c -> - Ok [ Pkg.mllib "src/log.mllib"; ] + Ok [ Pkg.mllib "src/log.mllib"; + Pkg.bin "src/logbook" ~dst:"logbook"; ] diff --git a/src/log.ml b/src/log.ml index d02fc8f..3a4b95a 100644 --- a/src/log.ml +++ b/src/log.ml @@ -22,6 +22,9 @@ let privacy_level_of_char = function type item = Item of privacy_level * string * string +let filter_privacy_level mode items = + List.filter (fun (Item (p, _, _)) -> compatible_privacy p mode) items + type log_entry = Log_entry of Ptime.date * string * item list type log = log_entry list @@ -75,9 +78,10 @@ let log_entryp = <*> (skip_many empty_line *> spaced_list itemp) (* Parser TODO - * - test edge cases (omitted, added parts, empty lines etc.) * - substitutions - * - clean up block parser + * - markdown/other markup + * - proper failure if not + * the whole output is consumed * … *) let log_parser = diff --git a/src/log.mli b/src/log.mli index a4bde39..e62acea 100644 --- a/src/log.mli +++ b/src/log.mli @@ -32,6 +32,8 @@ val compatible_privacy : privacy_level -> privacy_level -> bool (** Get the corresponding privacy level for a char *) val privacy_level_of_char : char -> privacy_level option +val filter_privacy_level : privacy_level -> item list -> item list + (** {2 Log Parsing} log files are parsed using {{:https://github.com/inhabitedtype/angstrom}angstrom}. diff --git a/src/logbook.ml b/src/logbook.ml new file mode 100644 index 0000000..baef3ef --- /dev/null +++ b/src/logbook.ml @@ -0,0 +1,34 @@ +open Lwt +open Lwt.Infix + +let parse_file f = + Lwt_io.with_file Lwt_io.Input f (fun c -> + Lwt_io.read c >>= (fun s -> + return (Angstrom.parse_only Log.log_parser (`String s)))) + +let input_file = ref None +let privacy = ref Log.Public + +let arglist = + [ ("--file", Arg.String (fun f -> input_file := Some f), "log file to use"); + ("--private", Arg.Unit (fun () -> privacy := Log.Private), + "set privacy level of output to private"); + ("--public", Arg.Unit (fun () -> privacy := Log.Public), + "set privacy level of output to public"); + ("--semi-private", Arg.Unit (fun () -> privacy := Log.Semi_private), + "set privacy level of output to semi-private"); + ] + +let usage = Sys.argv.(0) ^ " --file [file.log] [other args]" + +let _ = + Arg.parse arglist (fun _ -> ()) usage; + match !input_file with + | None -> print_endline "No file supplied" + | Some f -> let log = Lwt_main.run (parse_file f >>= fun log -> + match log with + | Result.Error msg -> failwith msg + | Result.Ok log -> return log) + in print_string (Jg_template.from_string + Logbook_template.template + ~models:(Logbook_models.model_of_log !privacy log)) diff --git a/src/logbook_models.ml b/src/logbook_models.ml new file mode 100644 index 0000000..6f64bac --- /dev/null +++ b/src/logbook_models.ml @@ -0,0 +1,21 @@ +open Jg_types + +let string_of_date (y, m, d) = + string_of_int y ^ "-" ^ string_of_int m ^ "-" ^ string_of_int d + +let data_model_of_items mode items = + Log.filter_privacy_level mode items + |> List.map (fun (Log.Item (_, tt, tx)) -> + Tobj [ ("title", Tstr tt); ("text", Tstr tx); ]) + +let model_of_log level log = + [ ("entries", Tlist (List.map + (fun (Log.Log_entry (date, summary, items)) -> + Tobj [ + ("summary", Tstr summary); + ("date", Tstr (string_of_date date)); + ("items", Tlist (data_model_of_items level items)); + ]) + log)) + ] + diff --git a/src/logbook_template.ml b/src/logbook_template.ml new file mode 100644 index 0000000..36fbc5f --- /dev/null +++ b/src/logbook_template.ml @@ -0,0 +1,25 @@ +let template = "<!doctype html> +<html> +<head> + <meta charset=\"utf-8\"> + <title>log</title> +</head> +<body> + <main> + <h1>log</h1> + {% for entry in entries %} + <article> + <h2>{{ entry.date }}</h2> + <p>{{ entry.summary }}</p> + <ul> + {% for item in entry.items %} + <li> + <p><em>{{ item.title }}</em></p> + <p>{{ item.text }}</p> + </li> + {% endfor %} + </ul> + </article> + {% endfor %} + </main> +</body>" |