spannify/
lib.rs

1//! # Spannify
2//!
3//! This crate provides functionality to produce nice-looking graphs that represent your
4//! callstack. It is designed to help developers trace and understand the execution flow of their
5//! programs, making it easier to debug and optimize their code.
6//!
7//! ## Overview
8//!
9//! The core functionality of this crate revolves around creating spans that represent different
10//! sections of your code. These spans are organized hierarchically, and the crate generates
11//! messages to visualize when you enter and exit each span. The generated messages can be
12//! customized to suit your preferences using a variety of configuration options.
13//!
14//! ## Modules
15//!
16//! - [`config`]: Contains the configuration structures and options for customizing the appearance
17//!   and behavior of the callstack visualization.
18//! - [`core`]: Contains the core functionality for managing spans, generating messages, and
19//!   handling the callstack visualization logic.
20//! - [`level`]: Contains the levels of spans, which determines if the span should be outputted or not
21//!
22//! ## Example
23//!
24//! ```rust
25//! use spannify::{config::Config, core::StdoutSpanner, spf};
26//! use std::sync::LazyLock;
27//!
28//! static SPANNER: LazyLock<StdoutSpanner> =
29//!     LazyLock::new(|| StdoutSpanner::new().with_config(Config::new().with_skip(1)));
30//!
31//! fn fib(n: usize) -> usize {
32//!     let _span = spf!(SPANNER, "fib({n})");
33//!     match n {
34//!         0 => 0,
35//!         1 | 2 => 1,
36//!         _ => fib(n - 1) + fib(n - 2),
37//!     }
38//! }
39//!
40//! fn main() {
41//!     fib(5);
42//! }
43//!
44//!  ```
45//! ### Output
46//!
47//!  ```text
48//!┌fib(5)
49//!|  fib(4)
50//!|   ┌fib(3)
51//!|   ┆  fib(2)
52//!|   ┆  fib(2)
53//!|   ┆  fib(1)
54//!|   ┆  fib(1)
55//!|   └fib(3)
56//!|   ┌fib(2)
57//!|   └fib(2)
58//!|  fib(4)
59//!|  fib(3)
60//!|   ┌fib(2)
61//!|   └fib(2)
62//!|   ┌fib(1)
63//!|   └fib(1)
64//!|  fib(3)
65//!└fib(5)
66//! ```
67//!
68//! ## Usage
69//!
70//! To use this crate, you typically start by creating a `spannify` instance with a desired writer
71//! and configuration. Then, you create spans by calling the `Span::enter` method, which tracks the
72//! entry and exit points of different sections of your code.
73//!
74//! ```rust
75//! use spannify::{config::Config, core::{StdoutSpanner}};
76//! use std::io::stdout;
77//!
78//! // Create a configuration
79//! let config = Config::default();
80//!
81//! // Create a spannify
82//! let spanner = StdoutSpanner::new().with_config(config);
83//!
84//! // Create a span
85//! {
86//!     let _span = spanner.enter_span("main");
87//!     // Your code here...
88//! }
89//! // The span is automatically dropped here, and the exit message is generated
90//! ```
91//!
92//! ## Configuration
93//!
94//! The [`config`] module provides various options to customize the appearance and behavior of the
95//! callstack visualization. This includes settings for indentation, depth display, and message
96//! formatting. You can create a custom configuration by modifying the default values.
97//!
98//! ```rust
99//! use spannify::config::Config;
100//!
101//! let mut config = Config::default();
102//! config.tabwidth = 4;
103//! config.skip = 2;
104//! config.depthmap = |depth| if depth % 2 == 0 { '|' } else { '^' };
105//!
106//! // Use this configuration when creating a spannify
107//! ```
108//!
109//! ## License
110//!
111//! This crate is licensed under the MIT License. See the LICENSE file for more details.
112//!
113//! ## Contributing
114//!
115//! Contributions are welcome! Please open an issue or submit a pull request
116
117#![doc(html_root_url = "https://docs.rs/spannify/latest")]
118#![deny(unsafe_code)]
119#![warn(
120    clippy::cognitive_complexity,
121    clippy::dbg_macro,
122    clippy::debug_assert_with_mut_call,
123    clippy::doc_link_with_quotes,
124    clippy::doc_markdown,
125    clippy::empty_line_after_outer_attr,
126    clippy::empty_structs_with_brackets,
127    clippy::float_cmp,
128    clippy::float_cmp_const,
129    clippy::float_equality_without_abs,
130    keyword_idents,
131    clippy::missing_const_for_fn,
132    missing_copy_implementations,
133    missing_debug_implementations,
134    clippy::missing_errors_doc,
135    clippy::missing_panics_doc,
136    clippy::mod_module_files,
137    non_ascii_idents,
138    noop_method_call,
139    clippy::option_if_let_else,
140    clippy::print_stderr,
141    clippy::print_stdout,
142    clippy::semicolon_if_nothing_returned,
143    clippy::unseparated_literal_suffix,
144    clippy::similar_names,
145    clippy::suspicious_operation_groupings,
146    unused_crate_dependencies,
147    unused_extern_crates,
148    unused_import_braces,
149    clippy::unused_self,
150    clippy::use_debug,
151    clippy::used_underscore_binding,
152    clippy::useless_let_if_seq,
153    clippy::wildcard_dependencies,
154    clippy::wildcard_imports
155)]
156
157pub mod config;
158pub mod core;
159pub mod level;