5 Usage: ini <filename> "[section[/key]]"
8 ini: A .ini config file reader tool.
12 func parse_ini(path:Path -> {Text:{Text:Text}})
13 text := path.read() or exit("Could not read INI file: \[31;1]$(path)\[]")
14 sections : @{Text:@{Text:Text}}
15 current_section : @{Text:Text}
18 text = $Pat"\\{1 nl}{0+space}".replace(text, " ")
20 for line in text.lines()
22 skip if line.starts_with(";") or line.starts_with("#")
23 if m := $Pat"[?]".match(line)
24 section_name := m.captures[1]!.trim().lower()
26 sections[section_name] = current_section
27 else if m := $Pat"{..}={..}".match(line)
28 key := m.captures[1]!.trim().lower()
29 value := m.captures[2]!.trim()
30 current_section[key] = value
32 return {k:v[] for k,v in sections[]}
34 func main(path:Path, key:Text?)
35 keys := (key or "").split("/")
42 data := parse_ini(path)
44 section := (keys[1] or '*').lower()
49 section_data := data[section] or exit("
50 Invalid section name: \[31;1]$section\[]
51 Valid names: \[1]$(", ".join([k.quoted() for k in data.keys]))\[]
54 section_key := (keys[2] or '*').lower()
59 value := section_data[section_key] or exit("
60 Invalid key: \[31;1]$section_key\[]
61 Valid keys: \[1]$(", ".join([s.quoted() for s in section_data.keys]))\[]