Skip to content

Commit 10ca3f4

Browse files
authored
Merge pull request #34 from terrateamio/add-format-markdown
ADD Format markdown support
2 parents 281c4cd + 704579b commit 10ca3f4

File tree

3 files changed

+90
-3
lines changed

3 files changed

+90
-3
lines changed

src/oiq/oiq_pricer.ml

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,3 +370,88 @@ let pretty_to_string t =
370370
| `Add -> "add"
371371
| `Remove -> "remove"))
372372
t.resources)
373+
374+
let to_markdown_string t =
375+
let fmt v = Printf.sprintf "%s$%.2f" (if v >= 0.0 then "" else "-") (CCFloat.abs v) in
376+
(* Initial header *)
377+
let lines = [ "### 💸 OpenInfraQuote Cost Estimate\n" ] in
378+
(* Price difference section *)
379+
let delta_min = t.price_diff.Oiq_range.min in
380+
let delta_max = t.price_diff.Oiq_range.max in
381+
let lines =
382+
if delta_min = 0.0 && delta_max = 0.0 then lines
383+
else
384+
lines
385+
@ [
386+
Printf.sprintf
387+
"Monthly cost is projected to **%s** by **%s - %s**\n"
388+
(if delta_max < 0.0 then "decrease" else "increase")
389+
(fmt (CCFloat.abs delta_min))
390+
(fmt (CCFloat.abs delta_max));
391+
]
392+
in
393+
(* Summary table *)
394+
let lines =
395+
lines
396+
@ [
397+
"\n| Monthly Estimate | Amount |";
398+
"|------------------|--------------------|";
399+
Printf.sprintf
400+
"| After changes | %s - %s |"
401+
(fmt t.price.Oiq_range.min)
402+
(fmt t.price.Oiq_range.max);
403+
Printf.sprintf
404+
"| Before changes | %s - %s |\n"
405+
(fmt t.prev_price.Oiq_range.min)
406+
(fmt t.prev_price.Oiq_range.max);
407+
]
408+
in
409+
(* Group resources by change type *)
410+
let adds, removes, existing =
411+
CCList.fold_left
412+
(fun (a, r, e) resource ->
413+
match resource.Resource.change with
414+
| `Add -> (resource :: a, r, e)
415+
| `Remove -> (a, resource :: r, e)
416+
| `Noop -> (a, r, resource :: e))
417+
([], [], [])
418+
t.resources
419+
in
420+
(* Helper to render a section of resources *)
421+
let render_section title resources =
422+
if CCList.is_empty resources then ""
423+
else
424+
let header = Printf.sprintf "<details>\n<summary>%s</summary>\n\n" title in
425+
let table =
426+
"| Resource | Type | Before changes | After changes |\n\
427+
|----------|------|----------------|----------------|\n"
428+
in
429+
let rows =
430+
CCString.concat
431+
"\n"
432+
(CCList.map
433+
(fun r ->
434+
let name = r.Resource.name in
435+
let typ = r.Resource.type_ in
436+
let est_min = r.Resource.price.Oiq_range.min in
437+
let est_max = r.Resource.price.Oiq_range.max in
438+
Printf.sprintf
439+
"| %s | %s | %s - %s | %s - %s |"
440+
name
441+
typ
442+
(fmt t.prev_price.Oiq_range.min)
443+
(fmt t.prev_price.Oiq_range.max)
444+
(fmt est_min)
445+
(fmt est_max))
446+
resources)
447+
in
448+
header ^ table ^ rows ^ "\n</details>\n"
449+
in
450+
CCString.concat
451+
"\n"
452+
(lines
453+
@ [
454+
render_section "🟢 Added resources" adds;
455+
render_section "🔴 Removed resources" removes;
456+
render_section "⚪ Existing resources" existing;
457+
])

src/oiq/oiq_pricer.mli

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ type t [@@deriving to_yojson]
22

33
val price : ?match_query:Oiq_match_query.t -> usage:Oiq_usage.t -> Oiq_match_file.t -> t
44
val pretty_to_string : t -> string
5+
val to_markdown_string : t -> string

src/oiq_cli/oiq_cli.ml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@ module Cli = struct
2323

2424
let output_format =
2525
let docv = "FORMAT" in
26-
let doc = "Format of output (text or json)." in
26+
let doc = "Format of output (text, json, or markdown)." in
2727
C.Arg.(
2828
value
29-
& opt (enum [ ("text", `Text); ("json", `Json) ]) `Text
29+
& opt (enum [ ("text", `Text); ("json", `Json); ("markdown", `Markdown) ]) `Text
3030
& info [ "f"; "format" ] ~docv ~doc)
3131

3232
let match_query =
@@ -144,7 +144,8 @@ let price usage input output_format match_query regions =
144144
| Ok priced -> (
145145
match output_format with
146146
| `Text -> print_endline @@ Oiq_pricer.pretty_to_string priced
147-
| `Json -> print_endline @@ Yojson.Safe.pretty_to_string @@ Oiq_pricer.to_yojson priced)
147+
| `Json -> print_endline @@ Yojson.Safe.pretty_to_string @@ Oiq_pricer.to_yojson priced
148+
| `Markdown -> print_endline @@ Oiq_pricer.to_markdown_string priced)
148149
| Error (#Oiq_match_query.err as err) ->
149150
Logs.err (fun m -> m "%a" Oiq_match_query.pp_err err);
150151
exit 1

0 commit comments

Comments
 (0)