CLI app for developers prototyping atproto functionality
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add common::diagnostics scaffold

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>

+55
+3
src/common.rs
··· 1 + //! Cross-feature primitives shared by every `atproto-devtool` subcommand. 2 + 3 + pub mod diagnostics;
+52
src/common/diagnostics.rs
··· 1 + //! Shared miette configuration and `NamedSource` helpers. 2 + 3 + use std::sync::Arc; 4 + 5 + use miette::{GraphicalTheme, MietteHandlerOpts, NamedSource}; 6 + 7 + // Re-exports so Phase 3 onwards can import `LabeledSpan` / `SourceSpan` from a 8 + // single path. Unused in Phase 1 itself; declared here to keep the diagnostics 9 + // surface area in one file. 10 + pub use miette::{LabeledSpan, SourceSpan}; 11 + 12 + /// Install the miette panic hook and graphical report handler. 13 + /// 14 + /// Honours `NO_COLOR=1` by dropping to an unstyled theme. Call this exactly once 15 + /// from `main` before any `miette::Result`-returning code runs. 16 + pub fn install_miette_handler(no_color: bool) -> miette::Result<()> { 17 + // `NO_COLOR` is also respected automatically by miette when set in the 18 + // environment; passing an explicit theme here covers the `--no-color` flag 19 + // path without having to touch process-wide env vars (which is `unsafe` in 20 + // Rust 2024). 21 + miette::set_hook(Box::new(move |_| { 22 + let theme = if no_color { 23 + GraphicalTheme::unicode_nocolor() 24 + } else { 25 + GraphicalTheme::unicode() 26 + }; 27 + Box::new( 28 + MietteHandlerOpts::new() 29 + .graphical_theme(theme) 30 + .context_lines(3) 31 + .build(), 32 + ) 33 + }))?; 34 + 35 + // Install miette's panic hook so panics render through the same handler. 36 + miette::set_panic_hook(); 37 + 38 + Ok(()) 39 + } 40 + 41 + /// Build a `NamedSource` from a name and raw bytes. 42 + /// 43 + /// The bytes are cloned into an `Arc<str>`/`Arc<[u8]>` via miette's constructor, 44 + /// so callers may drop the original slice after this returns. 45 + pub fn named_source_from_bytes(name: impl Into<String>, bytes: &[u8]) -> NamedSource<Arc<[u8]>> { 46 + NamedSource::new(name, Arc::<[u8]>::from(bytes)) 47 + } 48 + 49 + /// Build a `NamedSource` from a name and a UTF-8 string slice. 50 + pub fn named_source_from_str(name: impl Into<String>, text: &str) -> NamedSource<String> { 51 + NamedSource::new(name, text.to_string()) 52 + }