Skip to repository content581 lines · 16.8 KB · rust
tenant.openagents/omega
No repository description is available.
OpenAgents Git authority 2026-07-28T02:36:36.334Z Public web read
NIP-34 coordinate
30617:7649603503856e5148d571eac2766b288a8ff1e9e35d380337a1d2b0015b4f92:omegaMaintainersHidden in public view
References2 branches · 1 tag
Read-only clone
git clone https://openagents.com/git/tenant.openagents/omega.gitBrowse files
lib.rs
1// FluentBuilder
2// pub use gpui_util::{FutureExt, Timeout, arc_cow::ArcCow};
3
4use std::{
5 env,
6 ffi::OsStr,
7 ops::AddAssign,
8 panic::Location,
9 pin::Pin,
10 sync::OnceLock,
11 task::{Context, Poll},
12 time::Instant,
13};
14
15pub mod arc_cow;
16
17#[cfg(target_os = "windows")]
18const CREATE_NO_WINDOW: u32 = 0x0800_0000_u32;
19
20#[cfg(target_os = "windows")]
21pub fn new_std_command(program: impl AsRef<OsStr>) -> std::process::Command {
22 use std::os::windows::process::CommandExt;
23
24 let mut command = std::process::Command::new(program);
25 command.creation_flags(CREATE_NO_WINDOW);
26 command
27}
28
29#[cfg(not(target_os = "windows"))]
30pub fn new_std_command(program: impl AsRef<OsStr>) -> std::process::Command {
31 std::process::Command::new(program)
32}
33
34#[cfg(target_os = "windows")]
35pub fn get_windows_system_shell() -> String {
36 use std::path::PathBuf;
37
38 fn find_pwsh_in_programfiles(find_alternate: bool, find_preview: bool) -> Option<PathBuf> {
39 #[cfg(target_pointer_width = "64")]
40 let env_var = if find_alternate {
41 "ProgramFiles(x86)"
42 } else {
43 "ProgramFiles"
44 };
45
46 #[cfg(target_pointer_width = "32")]
47 let env_var = if find_alternate {
48 "ProgramW6432"
49 } else {
50 "ProgramFiles"
51 };
52
53 let install_base_dir = PathBuf::from(std::env::var_os(env_var)?).join("PowerShell");
54 install_base_dir
55 .read_dir()
56 .ok()?
57 .filter_map(Result::ok)
58 .filter(|entry| matches!(entry.file_type(), Ok(ft) if ft.is_dir()))
59 .filter_map(|entry| {
60 let dir_name = entry.file_name();
61 let dir_name = dir_name.to_string_lossy();
62
63 let version = if find_preview {
64 let dash_index = dir_name.find('-')?;
65 if &dir_name[dash_index + 1..] != "preview" {
66 return None;
67 };
68 dir_name[..dash_index].parse::<u32>().ok()?
69 } else {
70 dir_name.parse::<u32>().ok()?
71 };
72
73 let exe_path = entry.path().join("pwsh.exe");
74 if exe_path.exists() {
75 Some((version, exe_path))
76 } else {
77 None
78 }
79 })
80 .max_by_key(|(version, _)| *version)
81 .map(|(_, path)| path)
82 }
83
84 fn find_pwsh_in_msix(find_preview: bool) -> Option<PathBuf> {
85 let msix_app_dir =
86 PathBuf::from(std::env::var_os("LOCALAPPDATA")?).join("Microsoft\\WindowsApps");
87 if !msix_app_dir.exists() {
88 return None;
89 }
90
91 let prefix = if find_preview {
92 "Microsoft.PowerShellPreview_"
93 } else {
94 "Microsoft.PowerShell_"
95 };
96 msix_app_dir
97 .read_dir()
98 .ok()?
99 .filter_map(|entry| {
100 let entry = entry.ok()?;
101 if !matches!(entry.file_type(), Ok(ft) if ft.is_dir()) {
102 return None;
103 }
104
105 if !entry.file_name().to_string_lossy().starts_with(prefix) {
106 return None;
107 }
108
109 let exe_path = entry.path().join("pwsh.exe");
110 exe_path.exists().then_some(exe_path)
111 })
112 .next()
113 }
114
115 fn find_pwsh_in_scoop() -> Option<PathBuf> {
116 let pwsh_exe =
117 PathBuf::from(std::env::var_os("USERPROFILE")?).join("scoop\\shims\\pwsh.exe");
118 pwsh_exe.exists().then_some(pwsh_exe)
119 }
120
121 static SYSTEM_SHELL: std::sync::LazyLock<String> = std::sync::LazyLock::new(|| {
122 let locations = [
123 || find_pwsh_in_programfiles(false, false),
124 || find_pwsh_in_programfiles(true, false),
125 || find_pwsh_in_msix(false),
126 || find_pwsh_in_programfiles(false, true),
127 || find_pwsh_in_msix(true),
128 || find_pwsh_in_programfiles(true, true),
129 || find_pwsh_in_scoop(),
130 || which::which_global("pwsh.exe").ok(),
131 || which::which_global("powershell.exe").ok(),
132 ];
133
134 locations
135 .into_iter()
136 .find_map(|f| f())
137 .map(|p| p.to_string_lossy().trim().to_owned())
138 .inspect(|shell| log::info!("Found powershell in: {}", shell))
139 .unwrap_or_else(|| {
140 log::warn!("Powershell not found, falling back to `cmd`");
141 "cmd.exe".to_string()
142 })
143 });
144
145 (*SYSTEM_SHELL).clone()
146}
147
148pub fn post_inc<T: From<u8> + AddAssign<T> + Copy>(value: &mut T) -> T {
149 let prev = *value;
150 *value += T::from(1);
151 prev
152}
153
154pub fn measure<R>(label: &str, f: impl FnOnce() -> R) -> R {
155 static ZED_MEASUREMENTS: OnceLock<bool> = OnceLock::new();
156 let zed_measurements = ZED_MEASUREMENTS.get_or_init(|| {
157 env::var("ZED_MEASUREMENTS")
158 .map(|measurements| measurements == "1" || measurements == "true")
159 .unwrap_or(false)
160 });
161
162 if *zed_measurements {
163 let start = Instant::now();
164 let result = f();
165 let elapsed = start.elapsed();
166 eprintln!("{}: {:?}", label, elapsed);
167 result
168 } else {
169 f()
170 }
171}
172
173#[macro_export]
174macro_rules! debug_panic {
175 ( $($fmt_arg:tt)* ) => {
176 if cfg!(debug_assertions) {
177 panic!( $($fmt_arg)* );
178 } else {
179 let backtrace = std::backtrace::Backtrace::capture();
180 log::error!("{}\n{:?}", format_args!($($fmt_arg)*), backtrace);
181 }
182 };
183}
184
185#[track_caller]
186pub fn some_or_debug_panic<T>(option: Option<T>) -> Option<T> {
187 #[cfg(debug_assertions)]
188 if option.is_none() {
189 panic!("Unexpected None");
190 }
191 option
192}
193
194/// Expands to an immediately-invoked function expression. Good for using the ? operator
195/// in functions which do not return an Option or Result.
196///
197/// Accepts a normal block, an async block, or an async move block.
198#[macro_export]
199macro_rules! maybe {
200 ($block:block) => {
201 (|| $block)()
202 };
203 (async $block:block) => {
204 (async || $block)()
205 };
206 (async move $block:block) => {
207 (async move || $block)()
208 };
209}
210pub trait ResultExt<E> {
211 type Ok;
212
213 fn log_err(self) -> Option<Self::Ok>;
214 /// Like [`ResultExt::log_err`], but uses `{:?}` formatting so `anyhow::Error` values emit their
215 /// full backtrace. Reach for this only when a backtrace is genuinely wanted — most call sites
216 /// should stick with `log_err` / `warn_on_err`, whose output is a single chained error message.
217 fn log_err_with_backtrace(self) -> Option<Self::Ok>
218 where
219 E: std::fmt::Debug;
220 /// Assert that this result should never be an error in development or tests.
221 fn debug_assert_ok(self, reason: &str) -> Self;
222 fn warn_on_err(self) -> Option<Self::Ok>;
223 fn log_with_level(self, level: log::Level) -> Option<Self::Ok>;
224 fn anyhow(self) -> anyhow::Result<Self::Ok>
225 where
226 E: Into<anyhow::Error>;
227}
228
229impl<T, E> ResultExt<E> for Result<T, E>
230where
231 E: std::fmt::Display,
232{
233 type Ok = T;
234
235 #[track_caller]
236 fn log_err(self) -> Option<T> {
237 self.log_with_level(log::Level::Error)
238 }
239
240 #[track_caller]
241 fn log_err_with_backtrace(self) -> Option<T>
242 where
243 E: std::fmt::Debug,
244 {
245 match self {
246 Ok(value) => Some(value),
247 Err(error) => {
248 log_error_with_caller(
249 *Location::caller(),
250 DebugAsDisplay(&error),
251 log::Level::Error,
252 );
253 None
254 }
255 }
256 }
257
258 #[track_caller]
259 fn debug_assert_ok(self, reason: &str) -> Self {
260 if let Err(error) = &self {
261 debug_panic!("{reason} - {error:#}");
262 }
263 self
264 }
265
266 #[track_caller]
267 fn warn_on_err(self) -> Option<T> {
268 self.log_with_level(log::Level::Warn)
269 }
270
271 #[track_caller]
272 fn log_with_level(self, level: log::Level) -> Option<T> {
273 match self {
274 Ok(value) => Some(value),
275 Err(error) => {
276 log_error_with_caller(*Location::caller(), error, level);
277 None
278 }
279 }
280 }
281
282 fn anyhow(self) -> anyhow::Result<T>
283 where
284 E: Into<anyhow::Error>,
285 {
286 self.map_err(Into::into)
287 }
288}
289
290fn log_error_with_caller<E>(caller: core::panic::Location<'_>, error: E, level: log::Level)
291where
292 E: std::fmt::Display,
293{
294 #[cfg(not(windows))]
295 let file = caller.file();
296 #[cfg(windows)]
297 let file = caller.file().replace('\\', "/");
298 // In this codebase all crates reside in a `crates` directory,
299 // so discard the prefix up to that segment to find the crate name
300 let file = file.split_once("crates/");
301 let target = file.as_ref().and_then(|(_, s)| s.split_once("/src/"));
302
303 let module_path = target.map(|(krate, module)| {
304 if module.starts_with(krate) {
305 module.trim_end_matches(".rs").replace('/', "::")
306 } else {
307 krate.to_owned() + "::" + &module.trim_end_matches(".rs").replace('/', "::")
308 }
309 });
310 let file = file.map(|(_, file)| format!("crates/{file}"));
311 log::logger().log(
312 &log::Record::builder()
313 .target(module_path.as_deref().unwrap_or(""))
314 .module_path(file.as_deref())
315 .args(format_args!("{:#}", error))
316 .file(Some(caller.file()))
317 .line(Some(caller.line()))
318 .level(level)
319 .build(),
320 );
321}
322
323pub fn log_err<E: std::fmt::Display>(error: &E) {
324 log_error_with_caller(*Location::caller(), error, log::Level::Error);
325}
326
327// Forces `{:?}` formatting through a `Display`-bounded logging helper so `anyhow::Error` emits a
328// backtrace instead of the single-line chained message produced by its `Display`/`{:#}` forms.
329struct DebugAsDisplay<'a, E>(&'a E);
330
331impl<E: std::fmt::Debug> std::fmt::Display for DebugAsDisplay<'_, E> {
332 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
333 write!(f, "{:?}", self.0)
334 }
335}
336
337pub trait TryFutureExt {
338 fn log_err(self) -> LogErrorFuture<Self>
339 where
340 Self: Sized;
341
342 fn log_tracked_err(self, location: core::panic::Location<'static>) -> LogErrorFuture<Self>
343 where
344 Self: Sized;
345
346 fn warn_on_err(self) -> LogErrorFuture<Self>
347 where
348 Self: Sized;
349 fn unwrap(self) -> UnwrapFuture<Self>
350 where
351 Self: Sized;
352}
353
354/// `{:?}`-formatting companion to [`TryFutureExt`]; emits a backtrace for `anyhow::Error`. Prefer
355/// [`TryFutureExt`] unless a backtrace is genuinely wanted.
356pub trait TryFutureExtBacktrace {
357 fn log_err_with_backtrace(self) -> LogErrorWithBacktraceFuture<Self>
358 where
359 Self: Sized;
360
361 fn log_tracked_err_with_backtrace(
362 self,
363 location: core::panic::Location<'static>,
364 ) -> LogErrorWithBacktraceFuture<Self>
365 where
366 Self: Sized;
367}
368
369impl<F, T, E> TryFutureExt for F
370where
371 F: Future<Output = Result<T, E>>,
372 E: std::fmt::Display,
373{
374 #[track_caller]
375 fn log_err(self) -> LogErrorFuture<Self>
376 where
377 Self: Sized,
378 {
379 let location = Location::caller();
380 LogErrorFuture(self, log::Level::Error, *location)
381 }
382
383 fn log_tracked_err(self, location: core::panic::Location<'static>) -> LogErrorFuture<Self>
384 where
385 Self: Sized,
386 {
387 LogErrorFuture(self, log::Level::Error, location)
388 }
389
390 #[track_caller]
391 fn warn_on_err(self) -> LogErrorFuture<Self>
392 where
393 Self: Sized,
394 {
395 let location = Location::caller();
396 LogErrorFuture(self, log::Level::Warn, *location)
397 }
398
399 fn unwrap(self) -> UnwrapFuture<Self>
400 where
401 Self: Sized,
402 {
403 UnwrapFuture(self)
404 }
405}
406
407impl<F, T, E> TryFutureExtBacktrace for F
408where
409 F: Future<Output = Result<T, E>>,
410 E: std::fmt::Debug,
411{
412 #[track_caller]
413 fn log_err_with_backtrace(self) -> LogErrorWithBacktraceFuture<Self>
414 where
415 Self: Sized,
416 {
417 let location = Location::caller();
418 LogErrorWithBacktraceFuture(self, log::Level::Error, *location)
419 }
420
421 fn log_tracked_err_with_backtrace(
422 self,
423 location: core::panic::Location<'static>,
424 ) -> LogErrorWithBacktraceFuture<Self>
425 where
426 Self: Sized,
427 {
428 LogErrorWithBacktraceFuture(self, log::Level::Error, location)
429 }
430}
431
432#[must_use]
433pub struct LogErrorFuture<F>(F, log::Level, core::panic::Location<'static>);
434
435impl<F, T, E> Future for LogErrorFuture<F>
436where
437 F: Future<Output = Result<T, E>>,
438 E: std::fmt::Display,
439{
440 type Output = Option<T>;
441
442 fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
443 let level = self.1;
444 let location = self.2;
445 let inner = unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().0) };
446 match inner.poll(cx) {
447 Poll::Ready(output) => Poll::Ready(match output {
448 Ok(output) => Some(output),
449 Err(error) => {
450 log_error_with_caller(location, error, level);
451 None
452 }
453 }),
454 Poll::Pending => Poll::Pending,
455 }
456 }
457}
458
459#[must_use]
460pub struct LogErrorWithBacktraceFuture<F>(F, log::Level, core::panic::Location<'static>);
461
462impl<F, T, E> Future for LogErrorWithBacktraceFuture<F>
463where
464 F: Future<Output = Result<T, E>>,
465 E: std::fmt::Debug,
466{
467 type Output = Option<T>;
468
469 fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
470 let level = self.1;
471 let location = self.2;
472 let inner = unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().0) };
473 match inner.poll(cx) {
474 Poll::Ready(output) => Poll::Ready(match output {
475 Ok(output) => Some(output),
476 Err(error) => {
477 log_error_with_caller(location, DebugAsDisplay(&error), level);
478 None
479 }
480 }),
481 Poll::Pending => Poll::Pending,
482 }
483 }
484}
485
486pub struct UnwrapFuture<F>(F);
487
488impl<F, T, E> Future for UnwrapFuture<F>
489where
490 F: Future<Output = Result<T, E>>,
491 E: std::fmt::Debug,
492{
493 type Output = T;
494
495 fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
496 let inner = unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().0) };
497 match inner.poll(cx) {
498 Poll::Ready(result) => Poll::Ready(result.unwrap()),
499 Poll::Pending => Poll::Pending,
500 }
501 }
502}
503
504pub struct Deferred<F: FnOnce()>(Option<F>);
505
506impl<F: FnOnce()> Deferred<F> {
507 /// Drop without running the deferred function.
508 pub fn abort(mut self) {
509 self.0.take();
510 }
511}
512
513impl<F: FnOnce()> Drop for Deferred<F> {
514 fn drop(&mut self) {
515 if let Some(f) = self.0.take() {
516 f()
517 }
518 }
519}
520
521/// Run the given function when the returned value is dropped (unless it's cancelled).
522#[must_use]
523pub fn defer<F: FnOnce()>(f: F) -> Deferred<F> {
524 Deferred(Some(f))
525}
526
527#[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
528pub struct TypeIdHashBuilder;
529
530impl std::hash::BuildHasher for TypeIdHashBuilder {
531 type Hasher = TypeIdHasher;
532
533 fn build_hasher(&self) -> Self::Hasher {
534 TypeIdHasher::default()
535 }
536}
537
538#[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
539pub struct TypeIdHasher {
540 value: u64,
541}
542
543impl std::hash::Hasher for TypeIdHasher {
544 #[inline]
545 fn write(&mut self, bytes: &[u8]) {
546 // TypeId should only hash its first 8 bytes
547 if let Some(bytes) = bytes.get(..8) {
548 bytes
549 .as_array()
550 .map(|&array| self.value = u64::from_ne_bytes(array))
551 .unwrap_or_else(|| unreachable!("slice was sliced to 8 bytes"));
552 } else {
553 debug_panic!(
554 "expected a 64-bit value, did you use this hasher with something other than a TypeId?"
555 );
556 }
557 }
558
559 #[inline]
560 fn finish(&self) -> u64 {
561 self.value
562 }
563}
564
565#[test]
566fn type_id_hasher() {
567 use core::any::TypeId;
568 use core::hash::{Hash, Hasher};
569 fn verify_hashing_with(type_id: TypeId) {
570 let mut hasher = TypeIdHasher::default();
571 type_id.hash(&mut hasher);
572 assert_ne!(hasher.finish(), 0);
573 }
574 // Pick a variety of types, just to demonstrate it’s all sane. Normal, zero-sized, unsized, &c.
575 verify_hashing_with(TypeId::of::<usize>());
576 verify_hashing_with(TypeId::of::<()>());
577 verify_hashing_with(TypeId::of::<str>());
578 verify_hashing_with(TypeId::of::<&str>());
579 verify_hashing_with(TypeId::of::<Vec<u8>>());
580}
581