module Opts = struct open Arg type lasttype = NAME | SYMB | NUMB (** Positional arguments search based on the last type searched. *) let ltype = ref NAME (** Json file that generates the Sqlite3 database. *) let jsonf = ref "" (** Limit the amount of matches. *) let maxmatch = ref 1 (** Lists to search. *) let match_name : string list ref = ref [] let match_symb : string list ref = ref [] let match_numb : int list ref = ref [] let dbfile = ref "elements.sqlite3" let add_name s = match_name := s::!match_name; ltype := NAME let add_symb s = match_symb := s::!match_symb; ltype := SYMB let add_numb i = match_numb := i::!match_numb; ltype := NUMB let add_def s = match !ltype with | NAME -> add_name s | SYMB -> add_symb s | NUMB -> add_numb (match int_of_string_opt s with | None -> raise (Bad (Printf.sprintf "expected integer, got '%s'" s)) | Some x -> x ) let msg = "Periodic table search\n\ elements -gendb file [-dbfile outfile]\n\ elements [-maxmatch n] [-dbfile search] [-name ...] [-symb ...]\n\ " let setfile name v f = if f = "" then raise (Bad (Printf.sprintf "%s requires a filename" name)) else v := f let spec = [ "-gendb", String (setfile "-gendb" jsonf), "Generate DB file"; "-maxmatch", Set_int maxmatch, "Limit the amount of matches (def. 3)"; "-dbfile", String (setfile "-dbfile" dbfile), "Set the DB filename"; "-name", String add_name, "Search by name (default)"; "-symb", String add_symb, "Search by symbol"; "-num", Int add_numb, "Search by atomic number" ] let exec() = parse spec add_def msg end let () = Opts.exec() let db = Sqlite3.db_open !Opts.dbfile let _ = if !Opts.jsonf <> "" then Makedb.makedb db (if !Opts.jsonf = "-" then Yojson.Basic.from_channel stdin else Yojson.Basic.from_file !Opts.jsonf ) let () = if !Opts.match_name <> [] then Elements_search.print_by_name db !Opts.maxmatch (List.rev !Opts.match_name)