shell function

Future<Process> shell({
  1. required String executable,
  2. required List<String> arguments,
  3. String? workingDirectory,
  4. Map<String, String>? environment,
  5. bool includeParentEnvironment = true,
  6. bool runInShell = true,
  7. ProcessStartMode mode = ProcessStartMode.normal,
  8. required void onStdout(
    1. List<int> data,
    2. String executable,
    3. List<String> arguments,
    4. String? workingDirectory,
    5. Map<String, String>? environment,
    6. bool includeParentEnvironment,
    7. bool runInShell,
    8. ProcessStartMode mode,
    ),
  9. required void onStderr(
    1. List<int> data,
    2. String executable,
    3. List<String> arguments,
    4. String? workingDirectory,
    5. Map<String, String>? environment,
    6. bool includeParentEnvironment,
    7. bool runInShell,
    8. ProcessStartMode mode,
    ),
  10. required void onComplete(
    1. Process shell,
    2. String executable,
    3. List<String> arguments,
    4. String? workingDirectory,
    5. Map<String, String>? environment,
    6. bool includeParentEnvironment,
    7. bool runInShell,
    8. ProcessStartMode mode,
    ),
  11. bool isFuture = false,
})

Implementation

Future<Process> shell({
  required String executable,
  required List<String> arguments,
  String? workingDirectory,
  Map<String, String>? environment,
  bool includeParentEnvironment = true,
  bool runInShell = true,
  ProcessStartMode mode = ProcessStartMode.normal,
  required void Function(
    List<int> data,
    String executable,
    List<String> arguments,
    String? workingDirectory,
    Map<String, String>? environment,
    bool includeParentEnvironment,
    bool runInShell,
    ProcessStartMode mode,
  ) onStdout,
  required void Function(
    List<int> data,
    String executable,
    List<String> arguments,
    String? workingDirectory,
    Map<String, String>? environment,
    bool includeParentEnvironment,
    bool runInShell,
    ProcessStartMode mode,
  ) onStderr,
  required void Function(
    Process shell,
    String executable,
    List<String> arguments,
    String? workingDirectory,
    Map<String, String>? environment,
    bool includeParentEnvironment,
    bool runInShell,
    ProcessStartMode mode,
  ) onComplete,
  bool isFuture = false,
}) async {
  bool is_complete = false;
  Process shell = await Process.start(
    executable,
    arguments,
    workingDirectory: workingDirectory,
    environment: environment,
    includeParentEnvironment: includeParentEnvironment,
    runInShell: runInShell,
    mode: mode,
  );

  var stdout_shell = shell.stdout.listen(
    (List<int> data) {
      onStdout(data, executable, arguments, workingDirectory, environment,
          includeParentEnvironment, runInShell, mode);
    },
    onDone: () {
      is_complete = true;
      onComplete(
        shell,
        executable,
        arguments,
        workingDirectory,
        environment,
        includeParentEnvironment,
        runInShell,
        mode,
      );
    },
    cancelOnError: true,
  );
  var stderr_shell = shell.stderr.listen(
    (List<int> data) {
      onStderr(data, executable, arguments, workingDirectory, environment,
          includeParentEnvironment, runInShell, mode);
    },
    onDone: () {
      is_complete = true;
      onComplete(
        shell,
        executable,
        arguments,
        workingDirectory,
        environment,
        includeParentEnvironment,
        runInShell,
        mode,
      );
    },
    cancelOnError: true,
  );

  if (isFuture) {
    return shell;
  } else {
    while (true) {
      await Future.delayed(const Duration(milliseconds: 1));

      if (is_complete) {
        await Future.delayed(const Duration(milliseconds: 500));
        // await stdin_shell.cancel();
        await stdout_shell.cancel();

        await Future.delayed(const Duration(milliseconds: 500));
        await stderr_shell.cancel();

        await Future.delayed(const Duration(milliseconds: 500));
        shell.kill(ProcessSignal.sigkill);
        return shell;
      }
    }
  }
}