code / tomo-commands

Lines334 C249 Tomo74 Markdown11
(96 lines)
1 # Functions for running system commands
3 use ./commands.c
5 enum ExitType(Exited(status:Int32), Signaled(signal:Int32), Failed)
6 func succeeded(e:ExitType -> Bool)
7 when e is Exited(status) return (status == 0)
8 else return no
10 func or_fail(e:ExitType, message:Text?=none)
11 if not e.succeeded()
12 fail(message or "Program failed: $e")
14 struct ProgramResult(output:[Byte], errors:[Byte], exit_type:ExitType)
15 func or_fail(r:ProgramResult, message:Text?=none -> ProgramResult)
16 when r.exit_type is Exited(status)
17 if status != 0
18 fail(message or "Program failed: $r")
19 else fail(message or "Program failed: $r")
20 return r
22 func output_text(r:ProgramResult, trim_newline=yes -> Text?)
23 when r.exit_type is Exited(status)
24 if status == 0
25 if text := Text.from_utf8(r.output)
26 if trim_newline
27 text = text.without_suffix("\n")
28 return text
29 else return none
30 return none
32 func error_text(r:ProgramResult -> Text?)
33 when r.exit_type is Exited(status)
34 if status == 0
35 return Text.from_utf8(r.errors)
36 else return none
37 return none
39 func succeeded(r:ProgramResult -> Bool)
40 when r.exit_type is Exited(status)
41 return (status == 0)
42 else
43 return no
45 struct Command(command:Text, args:[Text]=[], env:{Text=Text}={})
46 func from_path(path:Path, args:[Text]=[], env:{Text=Text}={} -> Command)
47 return Command(Text(path), args, env)
49 func result(command:Command, input="", input_bytes:[Byte]=[] -> ProgramResult)
50 if input.length > 0
51 (&input_bytes).insert_all(input.utf8())
53 output : [Byte]
54 errors : [Byte]
55 status := C_code:Int32`
56 run_command(@(command.command), @(command.args), @(command.env), @input_bytes, &@output, &@errors)
59 if C_code:Bool`WIFEXITED(@status)`
60 return ProgramResult(output, errors, ExitType.Exited(C_code:Int32`WEXITSTATUS(@status)`))
62 if C_code:Bool`WIFSIGNALED(@status)`
63 return ProgramResult(output, errors, ExitType.Signaled(C_code:Int32`WTERMSIG(@status)`))
65 return ProgramResult(output, errors, ExitType.Failed)
67 func run(command:Command, -> ExitType)
68 status := C_code:Int32`
69 run_command(@(command.command), @(command.args), @(command.env), NONE_LIST, NULL, NULL)
72 if C_code:Bool`WIFEXITED(@status)`
73 return ExitType.Exited(C_code:Int32`WEXITSTATUS(@status)`)
75 if C_code:Bool`WIFSIGNALED(@status)`
76 return ExitType.Signaled(C_code:Int32`WTERMSIG(@status)`)
78 return ExitType.Failed
80 func get_output(command:Command, input="", trim_newline=yes -> Text?)
81 return command.result(input=input).output_text(trim_newline=trim_newline)
83 func get_output_bytes(command:Command, input="", input_bytes:[Byte]=[] -> [Byte]?)
84 result := command.result(input=input, input_bytes=input_bytes)
85 when result.exit_type is Exited(status)
86 if status == 0 return result.output
87 return none
88 else return none
90 func by_line(command:Command -> func(->Text?)?)
91 return C_code:func(->Text?)?`
92 command_by_line(@(command.command), @(command.args), @(command.env))
95 func main(cmd:Command)
96 >> cmd.get_output()