Repository: zellij-org/zellij
File: zellij-server/src/os_input_output.rs (Rust)

Code before:
/// Read from a pipe given both file descriptors
///
/// # Panics
///
/// This function will panic if a close operation on one of the file descriptors fails or if the
/// read operation fails.
fn read_from_pipe(parent_fd: RawFd, child_fd: RawFd) -> u32 {
    let mut buffer = [0; 4];
    unistd::close(child_fd).expect("Read: couldn't close child_fd");
    match unistd::read(parent_fd, &mut buffer) {
        Ok(_) => {}
        Err(e) => {
            panic!("Read operation failed: {:?}", e);
        }
    }
    unistd::close(parent_fd).expect("Read: couldn't close parent_fd");
    u32::from_be_bytes(buffer)
}

/// If a [`TerminalAction::OpenFile(file)`] is given, the text editor specified by environment variable `EDITOR`
/// (or `VISUAL`, if `EDITOR` is not set) will be started in the new terminal, with the given
/// file open.
/// If [`TerminalAction::RunCommand(RunCommand)`] is given, the command will be started
/// in the new terminal.
/// If None is given, the shell specified by environment variable `SHELL` will
/// be started in the new terminal.
///
/// # Panics
///
/// This function will panic if both the `EDITOR` and `VISUAL` environment variables are not
/// set.
pub fn spawn_terminal(
    terminal_action: TerminalAction,
    orig_termios: termios::Termios,
) -> (RawFd, Pid, RawFd) {
    let cmd = match terminal_action {
        TerminalAction::OpenFile(file_to_open) => {
            if env::var("EDITOR").is_err() && env::var("VISUAL").is_err() {
                panic!("Can't edit files if an editor is not defined. To fix: define the EDITOR or VISUAL environment variables with the path to your editor (eg. /usr/bin/vim)");
            }
            let command =
                PathBuf::from(env::var("EDITOR").unwrap_or_else(|_| env::var("VISUAL").unwrap()));

            let args = vec![file_to_open
                .into_os_string()
                .into_string()
                .expect("Not valid Utf8 Encoding")];
            RunCommand {
                command,
                args,
                cwd: None,

Review comment (suggestion):
Removing the `Option` here and using the `TerminalAction` to move the `cwd` around is a really elegant solution.

Code after:
    if unistd::close(child_fd).is_err() {
        return None;
    }
    if unistd::read(parent_fd, &mut buffer).is_err() {
        return None;
    }
    if unistd::close(parent_fd).is_err() {
        return None;
    }
    Some(u32::from_be_bytes(buffer))
}

/// If a [`TerminalAction::OpenFile(file)`] is given, the text editor specified by environment variable `EDITOR`
/// (or `VISUAL`, if `EDITOR` is not set) will be started in the new terminal, with the given
/// file open.
/// If [`TerminalAction::RunCommand(RunCommand)`] is given, the command will be started
/// in the new terminal.
/// If None is given, the shell specified by environment variable `SHELL` will
/// be started in the new terminal.
///
/// # Panics
///
/// This function will panic if both the `EDITOR` and `VISUAL` environment variables are not
/// set.
pub fn spawn_terminal(
    terminal_action: TerminalAction,
    orig_termios: termios::Termios,
) -> (RawFd, ChildId) {
    let cmd = match terminal_action {
        TerminalAction::OpenFile(file_to_open) => {
            if env::var("EDITOR").is_err() && env::var("VISUAL").is_err() {
                panic!("Can't edit files if an editor is not defined. To fix: define the EDITOR or VISUAL environment variables with the path to your editor (eg. /usr/bin/vim)");
            }
            let command =
                PathBuf::from(env::var("EDITOR").unwrap_or_else(|_| env::var("VISUAL").unwrap()));

            let args = vec![file_to_open
                .into_os_string()
                .into_string()
                .expect("Not valid Utf8 Encoding")];
            RunCommand {
                command,
                args,
                cwd: None,
            }
        }
        TerminalAction::RunCommand(command) => command,
    };

    handle_terminal(cmd, orig_termios)
}