580 lines · 16.4 KB · Rust
RawDownload
// FluentBuilder// pub use gpui_util::{FutureExt, Timeout, arc_cow::ArcCow}; use std::{    env,    ffi::OsStr,    ops::AddAssign,    panic::Location,    pin::Pin,    sync::OnceLock,    task::{Context, Poll},    time::Instant,}; pub mod arc_cow; #[cfg(target_os = "windows")]const CREATE_NO_WINDOW: u32 = 0x0800_0000_u32; #[cfg(target_os = "windows")]pub fn new_std_command(program: impl AsRef<OsStr>) -> std::process::Command {    use std::os::windows::process::CommandExt;     let mut command = std::process::Command::new(program);    command.creation_flags(CREATE_NO_WINDOW);    command} #[cfg(not(target_os = "windows"))]pub fn new_std_command(program: impl AsRef<OsStr>) -> std::process::Command {    std::process::Command::new(program)} #[cfg(target_os = "windows")]pub fn get_windows_system_shell() -> String {    use std::path::PathBuf;     fn find_pwsh_in_programfiles(find_alternate: bool, find_preview: bool) -> Option<PathBuf> {        #[cfg(target_pointer_width = "64")]        let env_var = if find_alternate {            "ProgramFiles(x86)"        } else {            "ProgramFiles"        };         #[cfg(target_pointer_width = "32")]        let env_var = if find_alternate {            "ProgramW6432"        } else {            "ProgramFiles"        };         let install_base_dir = PathBuf::from(std::env::var_os(env_var)?).join("PowerShell");        install_base_dir            .read_dir()            .ok()?            .filter_map(Result::ok)            .filter(|entry| matches!(entry.file_type(), Ok(ft) if ft.is_dir()))            .filter_map(|entry| {                let dir_name = entry.file_name();                let dir_name = dir_name.to_string_lossy();                 let version = if find_preview {                    let dash_index = dir_name.find('-')?;                    if &dir_name[dash_index + 1..] != "preview" {                        return None;                    };                    dir_name[..dash_index].parse::<u32>().ok()?                } else {                    dir_name.parse::<u32>().ok()?                };                 let exe_path = entry.path().join("pwsh.exe");                if exe_path.exists() {                    Some((version, exe_path))                } else {                    None                }            })            .max_by_key(|(version, _)| *version)            .map(|(_, path)| path)    }     fn find_pwsh_in_msix(find_preview: bool) -> Option<PathBuf> {        let msix_app_dir =            PathBuf::from(std::env::var_os("LOCALAPPDATA")?).join("Microsoft\\WindowsApps");        if !msix_app_dir.exists() {            return None;        }         let prefix = if find_preview {            "Microsoft.PowerShellPreview_"        } else {            "Microsoft.PowerShell_"        };        msix_app_dir            .read_dir()            .ok()?            .filter_map(|entry| {                let entry = entry.ok()?;                if !matches!(entry.file_type(), Ok(ft) if ft.is_dir()) {                    return None;                }                 if !entry.file_name().to_string_lossy().starts_with(prefix) {                    return None;                }                 let exe_path = entry.path().join("pwsh.exe");                exe_path.exists().then_some(exe_path)            })            .next()    }     fn find_pwsh_in_scoop() -> Option<PathBuf> {        let pwsh_exe =            PathBuf::from(std::env::var_os("USERPROFILE")?).join("scoop\\shims\\pwsh.exe");        pwsh_exe.exists().then_some(pwsh_exe)    }     static SYSTEM_SHELL: std::sync::LazyLock<String> = std::sync::LazyLock::new(|| {        let locations = [            || find_pwsh_in_programfiles(false, false),            || find_pwsh_in_programfiles(true, false),            || find_pwsh_in_msix(false),            || find_pwsh_in_programfiles(false, true),            || find_pwsh_in_msix(true),            || find_pwsh_in_programfiles(true, true),            || find_pwsh_in_scoop(),            || which::which_global("pwsh.exe").ok(),            || which::which_global("powershell.exe").ok(),        ];         locations            .into_iter()            .find_map(|f| f())            .map(|p| p.to_string_lossy().trim().to_owned())            .inspect(|shell| log::info!("Found powershell in: {}", shell))            .unwrap_or_else(|| {                log::warn!("Powershell not found, falling back to `cmd`");                "cmd.exe".to_string()            })    });     (*SYSTEM_SHELL).clone()} pub fn post_inc<T: From<u8> + AddAssign<T> + Copy>(value: &mut T) -> T {    let prev = *value;    *value += T::from(1);    prev} pub fn measure<R>(label: &str, f: impl FnOnce() -> R) -> R {    static ZED_MEASUREMENTS: OnceLock<bool> = OnceLock::new();    let zed_measurements = ZED_MEASUREMENTS.get_or_init(|| {        env::var("ZED_MEASUREMENTS")            .map(|measurements| measurements == "1" || measurements == "true")            .unwrap_or(false)    });     if *zed_measurements {        let start = Instant::now();        let result = f();        let elapsed = start.elapsed();        eprintln!("{}: {:?}", label, elapsed);        result    } else {        f()    }} #[macro_export]macro_rules! debug_panic {    ( $($fmt_arg:tt)* ) => {        if cfg!(debug_assertions) {            panic!( $($fmt_arg)* );        } else {            let backtrace = std::backtrace::Backtrace::capture();            log::error!("{}\n{:?}", format_args!($($fmt_arg)*), backtrace);        }    };} #[track_caller]pub fn some_or_debug_panic<T>(option: Option<T>) -> Option<T> {    #[cfg(debug_assertions)]    if option.is_none() {        panic!("Unexpected None");    }    option} /// Expands to an immediately-invoked function expression. Good for using the ? operator/// in functions which do not return an Option or Result.////// Accepts a normal block, an async block, or an async move block.#[macro_export]macro_rules! maybe {    ($block:block) => {        (|| $block)()    };    (async $block:block) => {        (async || $block)()    };    (async move $block:block) => {        (async move || $block)()    };}pub trait ResultExt<E> {    type Ok;     fn log_err(self) -> Option<Self::Ok>;    /// Like [`ResultExt::log_err`], but uses `{:?}` formatting so `anyhow::Error` values emit their    /// full backtrace. Reach for this only when a backtrace is genuinely wanted — most call sites    /// should stick with `log_err` / `warn_on_err`, whose output is a single chained error message.    fn log_err_with_backtrace(self) -> Option<Self::Ok>    where        E: std::fmt::Debug;    /// Assert that this result should never be an error in development or tests.    fn debug_assert_ok(self, reason: &str) -> Self;    fn warn_on_err(self) -> Option<Self::Ok>;    fn log_with_level(self, level: log::Level) -> Option<Self::Ok>;    fn anyhow(self) -> anyhow::Result<Self::Ok>    where        E: Into<anyhow::Error>;} impl<T, E> ResultExt<E> for Result<T, E>where    E: std::fmt::Display,{    type Ok = T;     #[track_caller]    fn log_err(self) -> Option<T> {        self.log_with_level(log::Level::Error)    }     #[track_caller]    fn log_err_with_backtrace(self) -> Option<T>    where        E: std::fmt::Debug,    {        match self {            Ok(value) => Some(value),            Err(error) => {                log_error_with_caller(                    *Location::caller(),                    DebugAsDisplay(&error),                    log::Level::Error,                );                None            }        }    }     #[track_caller]    fn debug_assert_ok(self, reason: &str) -> Self {        if let Err(error) = &self {            debug_panic!("{reason} - {error:#}");        }        self    }     #[track_caller]    fn warn_on_err(self) -> Option<T> {        self.log_with_level(log::Level::Warn)    }     #[track_caller]    fn log_with_level(self, level: log::Level) -> Option<T> {        match self {            Ok(value) => Some(value),            Err(error) => {                log_error_with_caller(*Location::caller(), error, level);                None            }        }    }     fn anyhow(self) -> anyhow::Result<T>    where        E: Into<anyhow::Error>,    {        self.map_err(Into::into)    }} fn log_error_with_caller<E>(caller: core::panic::Location<'_>, error: E, level: log::Level)where    E: std::fmt::Display,{    #[cfg(not(windows))]    let file = caller.file();    #[cfg(windows)]    let file = caller.file().replace('\\', "/");    // In this codebase all crates reside in a `crates` directory,    // so discard the prefix up to that segment to find the crate name    let file = file.split_once("crates/");    let target = file.as_ref().and_then(|(_, s)| s.split_once("/src/"));     let module_path = target.map(|(krate, module)| {        if module.starts_with(krate) {            module.trim_end_matches(".rs").replace('/', "::")        } else {            krate.to_owned() + "::" + &module.trim_end_matches(".rs").replace('/', "::")        }    });    let file = file.map(|(_, file)| format!("crates/{file}"));    log::logger().log(        &log::Record::builder()            .target(module_path.as_deref().unwrap_or(""))            .module_path(file.as_deref())            .args(format_args!("{:#}", error))            .file(Some(caller.file()))            .line(Some(caller.line()))            .level(level)            .build(),    );} pub fn log_err<E: std::fmt::Display>(error: &E) {    log_error_with_caller(*Location::caller(), error, log::Level::Error);} // Forces `{:?}` formatting through a `Display`-bounded logging helper so `anyhow::Error` emits a// backtrace instead of the single-line chained message produced by its `Display`/`{:#}` forms.struct DebugAsDisplay<'a, E>(&'a E); impl<E: std::fmt::Debug> std::fmt::Display for DebugAsDisplay<'_, E> {    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {        write!(f, "{:?}", self.0)    }} pub trait TryFutureExt {    fn log_err(self) -> LogErrorFuture<Self>    where        Self: Sized;     fn log_tracked_err(self, location: core::panic::Location<'static>) -> LogErrorFuture<Self>    where        Self: Sized;     fn warn_on_err(self) -> LogErrorFuture<Self>    where        Self: Sized;    fn unwrap(self) -> UnwrapFuture<Self>    where        Self: Sized;} /// `{:?}`-formatting companion to [`TryFutureExt`]; emits a backtrace for `anyhow::Error`. Prefer/// [`TryFutureExt`] unless a backtrace is genuinely wanted.pub trait TryFutureExtBacktrace {    fn log_err_with_backtrace(self) -> LogErrorWithBacktraceFuture<Self>    where        Self: Sized;     fn log_tracked_err_with_backtrace(        self,        location: core::panic::Location<'static>,    ) -> LogErrorWithBacktraceFuture<Self>    where        Self: Sized;} impl<F, T, E> TryFutureExt for Fwhere    F: Future<Output = Result<T, E>>,    E: std::fmt::Display,{    #[track_caller]    fn log_err(self) -> LogErrorFuture<Self>    where        Self: Sized,    {        let location = Location::caller();        LogErrorFuture(self, log::Level::Error, *location)    }     fn log_tracked_err(self, location: core::panic::Location<'static>) -> LogErrorFuture<Self>    where        Self: Sized,    {        LogErrorFuture(self, log::Level::Error, location)    }     #[track_caller]    fn warn_on_err(self) -> LogErrorFuture<Self>    where        Self: Sized,    {        let location = Location::caller();        LogErrorFuture(self, log::Level::Warn, *location)    }     fn unwrap(self) -> UnwrapFuture<Self>    where        Self: Sized,    {        UnwrapFuture(self)    }} impl<F, T, E> TryFutureExtBacktrace for Fwhere    F: Future<Output = Result<T, E>>,    E: std::fmt::Debug,{    #[track_caller]    fn log_err_with_backtrace(self) -> LogErrorWithBacktraceFuture<Self>    where        Self: Sized,    {        let location = Location::caller();        LogErrorWithBacktraceFuture(self, log::Level::Error, *location)    }     fn log_tracked_err_with_backtrace(        self,        location: core::panic::Location<'static>,    ) -> LogErrorWithBacktraceFuture<Self>    where        Self: Sized,    {        LogErrorWithBacktraceFuture(self, log::Level::Error, location)    }} #[must_use]pub struct LogErrorFuture<F>(F, log::Level, core::panic::Location<'static>); impl<F, T, E> Future for LogErrorFuture<F>where    F: Future<Output = Result<T, E>>,    E: std::fmt::Display,{    type Output = Option<T>;     fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {        let level = self.1;        let location = self.2;        let inner = unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().0) };        match inner.poll(cx) {            Poll::Ready(output) => Poll::Ready(match output {                Ok(output) => Some(output),                Err(error) => {                    log_error_with_caller(location, error, level);                    None                }            }),            Poll::Pending => Poll::Pending,        }    }} #[must_use]pub struct LogErrorWithBacktraceFuture<F>(F, log::Level, core::panic::Location<'static>); impl<F, T, E> Future for LogErrorWithBacktraceFuture<F>where    F: Future<Output = Result<T, E>>,    E: std::fmt::Debug,{    type Output = Option<T>;     fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {        let level = self.1;        let location = self.2;        let inner = unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().0) };        match inner.poll(cx) {            Poll::Ready(output) => Poll::Ready(match output {                Ok(output) => Some(output),                Err(error) => {                    log_error_with_caller(location, DebugAsDisplay(&error), level);                    None                }            }),            Poll::Pending => Poll::Pending,        }    }} pub struct UnwrapFuture<F>(F); impl<F, T, E> Future for UnwrapFuture<F>where    F: Future<Output = Result<T, E>>,    E: std::fmt::Debug,{    type Output = T;     fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {        let inner = unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().0) };        match inner.poll(cx) {            Poll::Ready(result) => Poll::Ready(result.unwrap()),            Poll::Pending => Poll::Pending,        }

Lines 1–500 of 580.