diff options
| author | Rose Hogenson <rosehogenson@posteo.net> | 2025-05-16 16:54:17 -0700 |
|---|---|---|
| committer | Rose Hogenson <rosehogenson@posteo.net> | 2025-05-16 16:54:17 -0700 |
| commit | 5582235bd300f8de997192f9109d596d12df4bbe (patch) | |
| tree | d219a6c0a3d96052eec422527cd05775354abf76 /Opts.sml | |
| parent | ff12ef4eea67453c1a6c1fa4614b74adf7c3caca (diff) | |
| download | sml-5582235bd300f8de997192f9109d596d12df4bbe.tar.zst | |
Fix spelling of file names
Diffstat (limited to 'Opts.sml')
| -rw-r--r-- | Opts.sml | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/Opts.sml b/Opts.sml new file mode 100644 index 0000000..f5be8c4 --- /dev/null +++ b/Opts.sml @@ -0,0 +1,81 @@ +structure Opts = +struct + datatype 'a optDesc = BoolOpt of bool -> unit + | StringOpt of string -> unit + + structure StringMap = Map(type k = string val cmp = String.compare) + + fun error (msg : string) : 'a = + (print msg ; + OS.Process.exit (OS.Process.failure)) + + fun boolFromString s = + case s of + "1" => true + | "t" => true + | "T" => true + | "true" => true + | "TRUE" => true + | "True" => true + | "0" => false + | "f" => false + | "F" => false + | "false" => false + | "FALSE" => false + | "False" => false + | _ => error "invalid boolean value" + + fun getOpt (desc : (string * 'a optDesc) list) (args : string list) : string list = + let + val parsers = StringMap.fromList desc + fun go [] = [] + | go (arg :: args) = + if arg = "-" orelse not (String.isPrefix "-" arg) + then arg :: args + else if arg = "--" + then args + else + let + val name = + if String.isPrefix "--" arg + then String.extract (arg, 2, NONE) + else String.extract (arg, 1, NONE) + val _ = + if String.isPrefix "-" name orelse String.isPrefix "=" name + then error "bad flag syntax" + else () + (* It's a flag. Does it have an argument? *) + val (name', value) = + case CharVector.findi (fn (_, x) => x = #"=") name of + SOME (i, _) => (substring (name, 0, i), String.extract (name, i + 1, NONE)) + | NONE => (name, "") + val parser = + case StringMap.lookup name' parsers of + SOME x => x + | NONE => error ("flag provided but not defined: " ^ String.toString name') + in + case parser of + BoolOpt func => + if value = "" + then + (func true ; + go args) + else + (func (boolFromString value) ; + go args) + | StringOpt func => + (* It must have a value, which might be the next argument. *) + if value = "" andalso not (null args) + then + (func (hd args) ; + go (tl args)) + else if value = "" + then error ("flag needs an argument: " ^ String.toString name') + else + (func value ; + go args) + end + in + go args + end +end |
