run method
Runs executable to the end and returns what it printed.
It runs in its own process group, so the Ctrl+C that stops a playbook doesn't also cut short ffmpeg saving the video, or adb copying it.
Implementation
Future<ProcessResult> run(String executable, List<String> arguments) async {
if (Platform.isWindows) return Process.run(executable, arguments);
// A detached process has no exit code of its own, so a shell reports it.
final Process process = await Process.start('/bin/sh', [
'-c',
r'"$@"; echo "nylo-exit:$?" >&2',
'sh',
executable,
...arguments,
], mode: ProcessStartMode.detachedWithStdio);
await process.stdin.close();
const Utf8Decoder decoder = Utf8Decoder(allowMalformed: true);
final List<String> printed = await Future.wait([
process.stdout.transform(decoder).join(),
process.stderr.transform(decoder).join(),
]);
final RegExpMatch? exit = RegExp(
r'nylo-exit:(\d+)\s*$',
).firstMatch(printed[1]);
return ProcessResult(
process.pid,
exit == null ? -1 : int.parse(exit.group(1)!),
printed[0],
exit == null ? printed[1] : printed[1].substring(0, exit.start),
);
}