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

Code before:
                _ => None,
            })
            .map(|variable| match variable {
                "version" => {
                    let node_ver = nodejs_version
                        .deref()
                        .as_ref()?
                        .trim_start_matches('v')
                        .trim();

                    VersionFormatter::format_module_version(
                        module.get_name(),
                        node_ver,
                        config.version_format,
                    )
                    .map(Ok)
                }
                "engines_version" => {
                    let node_ver = nodejs_version.as_deref();
                    let eng_ver = get_engines_version(context);
                    let in_engines_range = check_engines_version(node_ver, eng_ver.clone());

                    match (eng_ver, in_engines_range) {
                        (Some(ver), false) => Some(Ok(ver)),
                        _ => None,
                    }
                }
                _ => None,
            })
            .parse(None, Some(context))
    });

    module.set_segments(match parsed {
        Ok(segments) => segments,
        Err(error) => {
            log::warn!("Error in module `nodejs`:\n{}", error);
            return None;
        }
    });

    Some(module)
}

fn get_engines_version(context: &Context) -> Option<String> {
    let json_str = context.read_file_from_pwd("package.json")?;
    let package_json: json::Value = json::from_str(&json_str).ok()?;
    let raw_version = package_json.get("engines")?.get("node")?.as_str()?;

    Some(raw_version.to_string())
}


Review comment (suggestion):
On second look, this would look a bit better:
```suggestion
                    let eng_ver = get_engines_version(context)?;
                    let in_engines_range = check_engines_version(node_ver, Some(&eng_ver));
                    (!in_engines_range).then_some(Ok(eng_ver))
```

To get rid of the `clone` change the signature to `Option<&str>` and use `as_deref` at the other call-site.

Code after:
                        Some(Ok(config.not_capable_style))
                    }
                }
                _ => None,
            })
            .map(|variable| match variable {
                "version" => {
                    let node_ver = nodejs_version
                        .deref()
                        .as_ref()?
                        .trim_start_matches('v')
                        .trim();

                    VersionFormatter::format_module_version(
                        module.get_name(),
                        node_ver,
                        config.version_format,
                    )
                    .map(Ok)
                }
                "engines_version" => {
                    let in_engines_range = check_engines_version(
                        nodejs_version.as_deref(),
                        engines_version.as_deref(),
                    );
                    let eng_ver = engines_version.as_deref()?.to_string();

                    (!in_engines_range).then_some(Ok(eng_ver))
                }
                _ => None,
            })
            .parse(None, Some(context))
    });

    module.set_segments(match parsed {
        Ok(segments) => segments,
        Err(error) => {
            log::warn!("Error in module `nodejs`:\n{}", error);
            return None;
        }
    });

    Some(module)
}

fn get_engines_version(context: &Context) -> Option<String> {
    let json_str = context.read_file_from_pwd("package.json")?;
    let package_json: json::Value = json::from_str(&json_str).ok()?;
    let raw_version = package_json.get("engines")?.get("node")?.as_str()?;

    Some(raw_version.to_string())