Repository: starship/starship
File: src/modules/rust.rs (Rust)

Code before:

fn env_rustup_toolchain(context: &Context) -> Option<String> {
    let val = context.get_env("RUSTUP_TOOLCHAIN")?;
    Some(val.trim().to_owned())
}

fn execute_rustup_override_list(cwd: &Path) -> Option<String> {
    let Output { stdout, .. } = create_command("rustup")
        .ok()?
        .args(&["override", "list"])
        .output()
        .ok()?;
    let stdout = String::from_utf8(stdout).ok()?;
    extract_toolchain_from_rustup_override_list(&stdout, cwd)
}

fn execute_rustup_default() -> Option<String> {
    let Output { stdout, .. } = create_command("rustup")
        .ok()?
        .args(&["default"])
        .output()
        .ok()?;
    let stdout = String::from_utf8(stdout).ok()?;

    stdout.split_whitespace().next().map(str::to_owned)
}

fn extract_toolchain_from_rustup_override_list(stdout: &str, cwd: &Path) -> Option<String> {
    if stdout == "no overrides\n" {
        return None;
    }
    stdout
        .lines()
        .filter_map(|line| {
            let mut words = line.split_whitespace();
            let dir = words.next()?;
            let toolchain = words.next()?;
            Some((dir, toolchain))
        })
        .find(|(dir, _)| cwd.starts_with(dir))
        .map(|(_, toolchain)| toolchain.to_owned())
}

fn find_rust_toolchain_file(context: &Context) -> Option<String> {
    // Look for 'rust-toolchain' or 'rust-toolchain.toml' as rustup does.
    // for more information:
    // https://rust-lang.github.io/rustup/overrides.html#the-toolchain-file
    // for the implementation in 'rustup':
    // https://github.com/rust-lang/rustup/blob/a45e4cd21748b04472fce51ba29999ee4b62bdec/src/config.rs#L631

    #[derive(Deserialize)]

Review comment (refactor):
Not a blocker but if possible can you use the `exec_cmd` here since it will also provide some additional logging and automatically kill the command if it takes too long e.g

```suggestion
fn execute_rustup_default(context: &Context) -> Option<String> {
    context
        .exec_cmd("rustup", &["default"])?
        .stdout
        .split_whitespace()
        .next()
        .map(str::to_owned)
}
```

Code after:

fn env_rustup_toolchain(context: &Context) -> Option<String> {
    let val = context.get_env("RUSTUP_TOOLCHAIN")?;
    Some(val.trim().to_owned())
}

fn execute_rustup_override_list(context: &Context) -> Option<String> {
    extract_toolchain_from_rustup_override_list(
        &context.exec_cmd("rustup", &["override", "list"])?.stdout,
        &context.current_dir,
    )
}

fn execute_rustup_default(context: &Context) -> Option<String> {
    // `rustup default` output is:
    //    stable-x86_64-apple-darwin (default)
    context
        .exec_cmd("rustup", &["default"])?
        .stdout
        .split_whitespace()
        .next()
        .map(str::to_owned)
}

fn extract_toolchain_from_rustup_override_list(stdout: &str, cwd: &Path) -> Option<String> {
    if stdout == "no overrides\n" {
        return None;
    }
    stdout
        .lines()
        .filter_map(|line| {
            let mut words = line.split_whitespace();
            let dir = words.next()?;
            let toolchain = words.next()?;
            Some((dir, toolchain))
        })
        .find(|(dir, _)| cwd.starts_with(dir))
        .map(|(_, toolchain)| toolchain.to_owned())
}

fn find_rust_toolchain_file(context: &Context) -> Option<String> {
    // Look for 'rust-toolchain' or 'rust-toolchain.toml' as rustup does.
    // for more information:
    // https://rust-lang.github.io/rustup/overrides.html#the-toolchain-file
    // for the implementation in 'rustup':
    // https://github.com/rust-lang/rustup/blob/a45e4cd21748b04472fce51ba29999ee4b62bdec/src/config.rs#L631

    #[derive(Deserialize)]
    struct OverrideFile {
        toolchain: ToolchainSection,
    }