#
cargo/util/
open.rs

    1//! For opening files or URLs with the preferred application.
    2
    3use std::path::Path;
    4use std::path::PathBuf;
    5use std::process::Command;
    6
    7use crate::CargoResult;
    8use crate::GlobalContext;
    9use crate::util::context::PathAndArgs;
    10
    11/// Opens a file path using the preferred application.
    12///
    13/// 1. Try `doc.browser` config first
    14/// 2. Then `$BROWSER`
    15/// 3. Finally system default opener
    16pub fn open(path: &Path, gctx: &GlobalContext) -> CargoResult<()> {
    17    let config_browser = {
    18        let cfg: Option<PathAndArgs> = gctx.get("doc.browser")?;
    19        cfg.map(|path_args| (path_args.path.resolve_program(gctx), path_args.args))
    20    };
    21
    22    let mut shell = gctx.shell();
    23    let link = shell.err_file_hyperlink(&path);
    24    shell.status("Opening", format!("{link}{}{link:#}", path.display()))?;
    25
    26    let browser =
    27        config_browser.or_else(|| Some((PathBuf::from(gctx.get_env_os("BROWSER")?), Vec::new())));
    28
    29    match browser {
    30        Some((browser, initial_args)) => {
    31            if let Err(e) = Command::new(&browser).args(initial_args).arg(path).status() {
    32                shell.warn(format!(
    33                    "Couldn't open docs with {}: {}",
    34                    browser.to_string_lossy(),
    35                    e
    36                ))?;
    37            }
    38        }
    39        None => {
    40            if let Err(e) = opener::open(&path) {
    41                let e = e.into();
    42                crate::display_warning_with_error("couldn't open docs", &e, &mut shell);
    43            }
    44        }
    45    };
    46
    47    Ok(())
    48}