Index: rosshil.ml ================================================================== --- rosshil.ml +++ rosshil.ml @@ -1,21 +1,36 @@ (* [ʞ] rosshil.ml - tasshila semes sirvos * ~ lexi hale * $ ocamlopt.opt rosshil.ml -o rosshil - * © AGPL + * © GNU GPLv3 + * ? rosshil is a tool for transforming various dates in the + * calendar systems of Spirals into other representations. + * feel free to copy it and use it for your own settings + * if you're as much of a perfectionist dweeb as me; just + * make sure you change the name of the utility so it's + * not in Ranuir *) (* basic units *) type timespan = int (* earth seconds are current tick unit *) type timepoint = int type quantity = int type proportion = float -type runopt = NoOpt | NoANSI | ASCII +type runopt = NoOpt | NoANSI | ASCII | Debug | OutOnly let optstrs = [ - NoANSI, "noansi"; - ASCII, "ascii"; + NoANSI, "-plain"; + NoANSI, "p"; + + ASCII, "-ascii"; + ASCII, "a"; + + Debug, "-verbose"; + Debug, "v"; + + OutOnly, "-out"; + OutOnly, "o"; ] let is_opt str = List.exists (fun (_,s) -> ("-"^s) = str) optstrs let opt_of_str str = let (opt,_) = List.find (fun (_,s) -> ("-"^s) = str) optstrs in opt; @@ -207,26 +222,10 @@ League.Span.(fmt(calc span)) ^" from Creation →\n\t"; League.Cal.(fmt(calc time)) ^"\n"; ] *) -let usage arrow ansi hl bin = - let heading = "usage: " in - let syntax = [ - " [year ] [day ] to ", - "convert a calendar date"; - " (days | years [ days]) to ", - "convert a span of time"; - ] in - let spacing = String.make (String.length heading) ' ' in - let mkrow (s,d) = bin ^ " " ^ (ansi "96" s) ^"\n" ^ - spacing ^ ((ansi "3;95" (" "^arrow^" " ^ d))^"\n") in - let space s = spacing ^ (mkrow s) in - let fst = (hl heading) ^ (mkrow (List.hd syntax)) in - let rst = List.map space (List.tl syntax) in - List.fold_left (^) fst rst;; - type funcset = { calc : int -> date; fmt : date -> string; equiv : date -> int; } @@ -239,11 +238,11 @@ } let funcs : funcrow list = [ (* Society *) { - names=["society"; "shil"; "ranshil"; "rs"]; + names=["Society of Worlds"; "society"; "shil"; "ranshil"; "rs"]; fmt="92"; span = { calc=Society.Span.calc; fmt=Society.Span.fmt; equiv=Society.Span.equiv; @@ -253,11 +252,11 @@ fmt=Society.Cal.fmt; equiv=Society.Cal.equiv; }; }; (* Empire *) { - names=["empire"; "ziapha"; "zp"; "imperial"]; + names=["Heavenly Empire of a Thousand Suns"; "empire"; "imperial";"ziapha"; "zp"]; fmt="91"; span = { calc =Empire.Span.calc; fmt =Empire.Span.fmt; equiv=Empire.Span.equiv; @@ -267,11 +266,11 @@ fmt =Empire.Cal.fmt; equiv =Empire.Cal.equiv; }; }; (* League *) { - names=["league"; "ly"]; + names=["Socialist League"; "league"; "ly"]; fmt="96"; span = { calc =League.Span.calc; fmt =League.Span.fmt; equiv=League.Span.equiv; @@ -281,11 +280,11 @@ fmt =League.Cal.fmt; equiv =League.Cal.equiv; }; }; (* Gregorian *) { - names=["gregorian"; "terrestrial"; "earth"; "gy"]; + names=["Gregorian calendar"; "gregorian"; "terrestrial"; "earth"; "gy"; "ce";]; fmt="95"; span = { calc = Gregorian.Span.calc; fmt = Gregorian.Span.fmt; equiv = Gregorian.Span.equiv; @@ -299,10 +298,68 @@ fmt = bad_dim; equiv = bad_dim; }; }; ] + + +let usage arrow ansi hl bin = + let caltext = ( + let heading = "calendars: " in + let desc (cal: funcrow) : string =( + let name = List.hd cal.names in + let aliases = List.tl cal.names in + let append a b = if a = "" then b else (a^", "^b) in + let fmt = cal.fmt in + (ansi fmt (hl name)) ^ + (ansi fmt (" [" ^ (List.fold_left append "" aliases) ^"]") ^"\n")) + in let spacing = String.make (String.length heading) ' ' in + let space s = spacing ^ (desc s) in + let fst = (hl heading) ^ (desc (List.hd funcs)) in + let rst = List.map space (List.tl funcs) in + (List.fold_left (^) fst rst) + ) in + + let heading = "usage: " in + let opts = " [options] " in + let syntax = [ + " [year ] [day ] to ", + "convert a calendar date"; + " (days | years [ days]) to ", + "convert a span of time"; + " ticks years days", + "count temporal ticks corresponding to a timespan"; + " epoch day ", + "get the Spirals epoch for a particular date"; + "epoch to ", + "convert a Spirals epoch to a calendar date"; + " ticks to ", + "convert a tick count to a span of time in a given calendar"; + ] in + let spacing = String.make (String.length heading) ' ' in + let mkrow (s,d) = bin ^ opts ^ (ansi "94" s) ^"\n" ^ + spacing ^ ((ansi "3;95" (" "^arrow^" " ^ d))^"\n") in + let space s = spacing ^ (mkrow s) in + let opt_heading = "options: " in + let optdesc = [ + "o","out", "only print what the date is converted into"; + "p","plain", "do not format output with ansi escape codes"; + "v","verbose", "output extra debugging information"; + "a","ascii", "use only ASCII in output (instead of UTF-8)"; + ] in + let opt_spacing = String.make (String.length opt_heading) ' ' in + let mkopt (s,l,d) = "-"^s^" "^(ansi "94" ("(--"^l^")"))^": "^(ansi "95" d)^"\n" in + let spaceopt s = opt_spacing ^ (mkopt s) in + + let fst_opt = (hl opt_heading) ^ (mkopt (List.hd optdesc)) in + let rst_opt = List.map spaceopt (List.tl optdesc) in + let opt_body = List.fold_left (^) fst_opt rst_opt in + + let fst = (hl heading) ^ (mkrow (List.hd syntax)) in + let rst = List.map space (List.tl syntax) in + (List.fold_left (^) fst rst) ^"\n"^ opt_body ^"\n" ^ caltext;; + let contains ar v : bool = List.exists (fun a -> a = v) ar let getfuncs (tag: string) : funcrow = List.find (* pred *) (fun (a:funcrow) -> contains a.names tag) @@ -321,11 +378,11 @@ let indate = {years = years; days = days} in let time = from_sys.equiv indate in let outdate = to_sys.calc time in let instr = from_sys.fmt indate in let outstr = to_sys.fmt outdate in - (from_funcs.fmt, instr, to_funcs.fmt, outstr) + (from_funcs.fmt, instr, to_funcs.fmt, outstr, time) let rec parse (opts: runopt list) (args: string list) (bin: string) = let has_opt o = List.exists (fun a -> a = o) opts in let switch o a b = if has_opt o then a else b in @@ -332,36 +389,69 @@ let ansi (fmt: string) (str: string) = switch NoANSI str ("\x1b["^fmt^"m"^str^"\x1b[m") in let hl txt = switch NoANSI txt ("\x1b[1m" ^ txt ^ "\x1b[21m") in + let arrow = (switch ASCII "->" "→") in + let dbg msg : unit = (if has_opt Debug then print_string + (ansi "35;3" ((hl " -- ") ^ msg ^ "\n")) else ()) in + let op msg o = dbg msg; o in - let res_fmt (inf,ind,outf,outd) = - (ansi inf ind) ^ (switch ASCII " -> " " → ") ^ (ansi outf (hl outd)) in + let res_fmt (inf,ind,outf,outd,_) = + (switch OutOnly "" ((ansi inf ind) ^" "^ arrow ^" "))^ (ansi outf (hl outd)) in + let epoch (_,_,_,_,time) = time in match args with | opt :: rst when is_opt opt -> let o = opt_of_str opt in - (* (print_string ("running conv with flag "^opt^"!\n")); *) - parse (o :: opts) rst bin - | [fromcal; "to"; calendar] -> - (res_fmt (conv Timespan fromcal calendar 1 0))^"\n" ^ - (res_fmt (conv Timespan fromcal calendar 0 1))^"\n" + (op ("saw flag " ^opt^ ", adding to option set and restarting parse") + parse (o :: opts) rst bin) + + (* convert timepoints between different calendars *) | [fromcal; "date"; date; "to"; calendar] | [fromcal; "year"; date; "to"; calendar] -> (res_fmt (conv Calendar fromcal calendar (int_of_string date) 0))^"\n" | [fromcal; "year"; years; "day"; days; "to"; calendar] -> (res_fmt (conv Calendar fromcal calendar (int_of_string years) (int_of_string days)))^"\n" + + (* absolute values - maybe useful for scripting, e.g. + * comparing or sorting lists of dates in different + * systems. *) + | [cal; "epoch"; years; "day"; days;] -> + (string_of_int (epoch (conv Calendar cal cal + (int_of_string years) + (int_of_string days))))^"\n" + | [cal; "ticks"; years; "years"; days; "days"] -> + (string_of_int (epoch (conv Timespan cal cal + (int_of_string years) + (int_of_string days))))^"\n" + + (* absolute values - convert timepoints/spans to dates *) + | ["epoch"; epoch; "to"; system;] -> + let fns = getfuncs system in + (res_fmt ("3", "EPOCH "^epoch, fns.fmt, + (fns.cal.fmt (fns.cal.calc (int_of_string epoch))), 0))^"\n" + | [ticks; "ticks"; "to"; system;] -> + let fns = getfuncs system in + (res_fmt ("3", ticks^" TICKS", fns.fmt, + (fns.span.fmt (fns.span.calc (int_of_string ticks))), 0))^"\n" + + (* get conversion factors between different days & years *) + | [fromcal; "to"; calendar] -> + (res_fmt (conv Timespan fromcal calendar 1 0))^"\n" ^ + (res_fmt (conv Timespan fromcal calendar 0 1))^"\n" + + (* convert timespans of one calendar system to another *) | [count; from; "years"; "to"; system] -> (res_fmt (conv Timespan from system (int_of_string count) 0))^"\n" | [count; from; "days"; "to"; system] -> (res_fmt (conv Timespan from system 0 (int_of_string count)))^"\n" | [years; from; "years"; days; "days"; "to"; system] -> (res_fmt (conv Timespan from system (int_of_string years) (int_of_string days)))^"\n" - | _ -> (usage (switch ASCII "->" "→") ansi hl bin);; + | _ -> (usage arrow ansi hl bin);; let () = print_string (match (Array.to_list Sys.argv) with | bin :: rst -> parse [] rst bin | _ -> "buddy ya fucked up BAD");;