diff --git a/examples/README.md b/examples/README.md index 2b5234c..0a558fa 100644 --- a/examples/README.md +++ b/examples/README.md @@ -1,5 +1,6 @@ # Example Programs - [file.tm](file.tm): A file handling module. +- [ini.tm](ini.tm): An INI configuration file reader tool. - [vectors.tm](vectors.tm): A math vector library. - [wrap.tm](wrap.tm): A command-line program to wrap text. diff --git a/examples/example.ini b/examples/example.ini new file mode 100644 index 0000000..782dc76 --- /dev/null +++ b/examples/example.ini @@ -0,0 +1,8 @@ +[ Book ] +title = Dirk Gently's Holistic Detective Agency +author = Douglas Adams +published = 1987 + +[ Protagonist ] +name = Dirk Gently +age = 42 diff --git a/examples/ini.tm b/examples/ini.tm new file mode 100644 index 0000000..f8f801d --- /dev/null +++ b/examples/ini.tm @@ -0,0 +1,60 @@ +USAGE := " + Usage: ini "[section[/key]]" +" +HELP := " + ini: A .ini config file reader tool. + $USAGE +" + +file := use ./file.tm + +func parse_ini(filename:Text)->{Text:{Text:Text}}: + when file.read(filename) is Failure(err): fail(err) + is Success(text): + sections := {:Text:@{Text:Text}} + current_section := @{:Text:Text} + sections:set("", current_section) + + # Line wraps: + text = text:replace($/\{1 nl}{0+space}/, " ") + + for line in text:lines(): + line = line:trim() + if line:matches($/{0+space}[{..}]/): + section_name := line:replace($/{0+space}[{..}]{..}/, "\2"):trim():lower() + current_section = @{:Text:Text} + sections:set(section_name, current_section) + else if line:matches($/{..}={..}/): + key := line:replace($/{..}={..}/, "\1"):trim():lower() + value := line:replace($/{..}={..}/, "\2"):trim() + current_section:set(key, value) + + return {k:v[] for k,v in sections} + +func main(filename:Text, key:Text): + keys := key:split($Pattern"/") + if keys.length > 2: + fail(" + Too many arguments! + $USAGE + ") + + data := parse_ini(filename) + if keys.length < 1 or keys[1] == '*': + !! $data + return + + section := keys[1]:lower() + if not data:has(section): + fail("Invalid section name: $section; valid names: $(", ":join([k:quoted() for k in data.keys]))") + + section_data := data:get(section) + if keys.length < 2 or keys[2] == '*': + !! $section_data + return + + section_key := keys[2]:lower() + if not section_data:has(section_key): + fail("Invalid key: $section_key; valid keys: $(", ":join(section_data.keys))") + + say(section_data:get(section_key))