Skip to main content

AppBuilder

Struct AppBuilder 

Source
pub struct AppBuilder { /* private fields */ }
Expand description

The fluent entry point for constructing an App.

Collects settings, database pools, and routes, then locks everything into place at build.

Implementations§

Source§

impl AppBuilder

Source

pub fn settings(self, settings: Settings) -> Self

Set the application settings.

Source

pub fn database(self, alias: &str, pool: impl Into<DbPool>) -> Self

Register a database pool under the given alias.

The "default" pool is the one returned by umbral::db::pool() and is required: build() fails with BuildError:: DefaultPoolMissing if it isn’t registered. The caller opens the pool via umbral::db::connect(&url).await and passes it here.

Accepts anything that converts into a DbPool: a typed sqlx::SqlitePool, a typed sqlx::PgPool, or an already- built DbPool. The From impls on DbPool make plain SqlitePool callers (every test, every plugin example) work unchanged.

Source

pub fn router<R: DatabaseRouter + 'static>(self, router: R) -> Self

Install a custom crate::db::DatabaseRouter. Omit to use DefaultRouter (today’s static per-model routing).

Source

pub fn route_context<F>(self, resolver: F) -> Self
where F: Fn(&Request) -> RouteContext + Send + Sync + 'static,

Install a per-request crate::db::RouteContext resolver.

The resolver runs once per request, builds a RouteContext (typically reading a tenant header or subdomain), and build() wraps the entire downstream future in crate::db::route_context::scope. Because the scope spans the whole handler — including every .await and every ORM call — the ambient umbral::db::route_context() accessor inside the handler, and the active crate::db::DatabaseRouter, see exactly the context this resolver returned. A request the resolver maps to a default RouteContext runs with no tenant (no silent inheritance from a prior request).

use umbral::prelude::*;
use umbral::db::{RouteContext, TenantKey};

App::builder()
    .route_context(|req| match req.headers().get("x-tenant") {
        Some(v) => RouteContext::new()
            .with_tenant(TenantKey::new(v.to_str().unwrap_or_default())),
        None => RouteContext::new(),
    })
    .build()?;
Source

pub fn model<T: Model>(self) -> Self

Register a model with the app’s migration engine.

Called once per model the user wants the M5 makemigrations / migrate commands to track. Captures the model’s NAME / TABLE / FIELDS constants into an owned ModelMeta so the migration code can iterate without naming concrete T at the call site. M7’s Plugin contract will replace this with Plugin::models() discovered through the plugin registry.

Source

pub fn plugin<P: Plugin>(self, plugin: P) -> Self

Register a plugin (M7).

Plugins contribute models, routes, system_checks, and an on_ready hook. App::build() topologically sorts the registered set by Plugin::dependencies() and walks every plugin’s contributions. The plugin name "app" is reserved for the implicit plugin that owns models registered via .model::<T>(); a plugin claiming that name causes BuildError::ReservedPluginName.

Source

pub fn routes(self, routes: Routes) -> Self

Attach a Routes bundle of hand-registered routes.

Each .get(...) / .post(...) / .put(...) / .patch(...) / .delete(...) / .head(...) / .options(...) call on Routes records the path and registers the handler, so the framework surfaces declared routes in the dev-mode 404 page without a parallel declaration list.

Multi-method routes go through [Routes::route] (explicit method list + axum::routing::MethodRouter). Routes that need axum features the per-method shorthands don’t expose (typed State, middleware layers, nest, fallback handlers, etc.) go through [Routes::with_router] — that escape hatch merges an external axum::Router and its paths stay opaque to the framework (won’t appear in the dev 404 page).

Calling this more than once merges the router and concatenates the specs.

use umbral::prelude::*;

App::builder()
    .routes(
        Routes::new()
            .get("/", home)
            .get("/articles", list_articles_html)
            .post("/api/articles", create_article),
    )
    .build()?;
Source

pub fn templates_dir<P: Into<PathBuf>>(self, path: P) -> Self

Set the project-level templates directory.

Defaults to ./templates (relative to the binary’s cwd) when the builder method isn’t called. If the resolved path doesn’t exist, the engine still publishes — calls to umbral::templates::render then return TemplateError::Missing with a clear diagnostic, which matches the “absence isn’t an error unless something tries to render” rule from the spec.

This directory is searched first (highest priority). Plugin directories contributed via Plugin::templates_dirs() are appended in topological order and searched afterwards. To override a plugin’s template, drop a same-named file here.

Source

pub fn slash_redirect(self, policy: SlashRedirect) -> Self

Set the trailing-slash redirect policy. See crate::slash::SlashRedirect.

Default is Off (axum’s strict matching). Most apps want Append (/foo 404 → 308 → /foo/) so that the same URL works with or without the trailing slash.

use umbral::prelude::*;
use umbral::web::SlashRedirect;

App::builder()
    .slash_redirect(SlashRedirect::Append)
    .build()?;
Source

pub fn not_found_template(self, name: impl Into<String>) -> Self

Set the template rendered on a 404. Follows the 404.html convention.

The template gets { path } in scope — the request path that missed — so you can render The page {{ path }} doesn't exist. without wiring extractors. When unset, 404s return plain-text “Not Found”. When set but the template fails to render (missing file, parse error), the framework falls back to the plain-text response and logs the render error.

Composes with Self::slash_redirect — if a slash-redirect probe finds the alternate, it 308s before the not-found template fires.

Source

pub fn server_error_template(self, name: impl Into<String>) -> Self

Set the template rendered on a panicking handler. Follows the 500.html convention.

Installs a tower-http CatchPanic layer around the router. A panic in any handler is caught, logged via tracing::error, and replaced with a 500 response carrying the rendered template. When unset, panics use tower-http’s default behaviour (log + empty 500 body).

In dev mode (settings.environment == Dev), the template receives dev_mode, error_display, error_chain, and request_path context variables. In prod those variables are empty.

See Self::on_server_error for a hook that fires before the template renders.

Source

pub fn error_template(self, status: StatusCode, name: impl Into<String>) -> Self

Register a custom template for error responses with status (e.g. 429, 403, 410). When a handler returns Err((status, message)) (or any non-HTML error response with this status), the template is rendered in its place — styled like the 404/500 pages — preserving the status code. The template receives { status, status_text, message, request_path, dev_mode }. Repeatable for multiple codes.

404 and 500 have dedicated methods (Self::not_found_template / Self::server_error_template); use this for everything else.

App::builder()
    .error_template(StatusCode::TOO_MANY_REQUESTS, "errors/429.html")
    .error_template(StatusCode::FORBIDDEN, "errors/403.html")
Source

pub fn on_server_error<F>(self, hook: F) -> Self
where F: Fn(&str, &str) + Send + Sync + 'static,

Register a hook that fires on every internal server error (500).

The closure receives:

  • error_display: &str — the Display form of the error or the stringified panic payload.
  • request_path: &str — the URI path of the failing request (empty for panic-path errors where path isn’t yet available).

The hook runs synchronously before the 500 template is rendered. It cannot change the response — use it to log to an external service (Sentry, Datadog, a file, etc.).

App::builder()
    .on_server_error(|err, path| {
        tracing::error!(err, path, "500 error");
    })
    .build()?
Source

pub fn disable_default_error_pages(self) -> Self

Disable the built-in default 404/500 templates.

By default, when the user hasn’t called .not_found_template(...) or .server_error_template(...), umbral renders its own embedded Tailwind error pages. Call this method to revert to axum’s built-in behaviour: a plain-text “Not Found” on 404 and an empty 500 body on panic.

App::builder()
    .disable_default_error_pages()
    .build()?
Source

pub fn cors(self, config: CorsConfig) -> Self

Install a CORS policy as the outermost middleware.

The framework doesn’t install a CorsLayer by default — same-origin requests need no policy, and CORS is too security-sensitive to enable implicitly. Pass a crate::cors::CorsConfig (start from CorsConfig::strict for production or CorsConfig::permissive for dev).

use umbral::prelude::*;
use umbral::cors::CorsConfig;

App::builder()
    .cors(CorsConfig::strict()
        .allow_origin("https://app.example.com")
        .allow_credentials(true))
    .build()
    .await?

The layer is applied LAST in the middleware chain so it becomes the outermost wrapper — preflight OPTIONS is answered before any plugin / handler sees the request, and the response headers are added on the way back out regardless of which downstream layer produced the body.

Source

pub fn cors_for(self, prefix: impl Into<String>, config: CorsConfig) -> Self

Apply a CORS policy scoped to requests whose path starts with prefix (e.g. "/api"), leaving every other route’s responses untouched. The path-scoped counterpart to cors — the shape you want for “CORS on the REST API, not the HTML pages.” Call repeatedly for several prefixes. Scoped policies are applied after (outside) the global one.

use umbral::cors::CorsConfig;

App::builder()
    .cors_for("/api", CorsConfig::strict()
        .allow_origins(vec!["https://app.example.com"])
        .allow_credentials(true))
    .build()
    .await?
Source

pub fn atomic_transactions(self, enabled: bool) -> Self

Default every ORM write to run inside its own transaction.

When enabled = true, terminals that opt into the contract (Manager::create, Manager::bulk_create, Manager::get_or_create, QuerySet::update_values, QuerySet::delete) wrap their work in a BEGIN / COMMIT pair unless the caller explicitly opts out with .non_atomic().

This is the safe-by-default posture: a framework that claims “secure by default” should also be “transaction-safe by default.” Opting out matters mostly for high-throughput seed scripts that already wrap an outer transaction themselves.

Without this flag the framework’s behaviour is unchanged — writes run with whatever transaction the caller arranges. The per-call .atomic() / .non_atomic() overrides still work.

Source

pub fn compression(self) -> Self

Compress responses with gzip / brotli (a tower-http CompressionLayer). The algorithm is chosen from the request’s Accept-Encoding; already-encoded or non-compressible content types are skipped automatically.

Off by default: in most deployments the reverse proxy (nginx, a CDN) already compresses, and doing it twice is wasted CPU. Enable this when you serve directly (a single binary with no proxy in front).

Source

pub fn middleware<M: Middleware>(self, mw: M) -> Self

Register a framework-level Middleware (feature #68) with before_request / after_response hooks.

App-level middleware is added to the stack before any plugin’s contribution, so its before_request runs first and its after_response runs last (it’s the outermost layer of the onion). Call this multiple times to register several, in order.

Use this for the common “look at every request / response” case. For a real tower Layer (timeouts, body limits) reach for the router directly via a plugin’s wrap_router.

Source

pub fn build(self) -> Result<App, BuildError>

Finalize the application.

Phases (see spec 01 §Mechanics and invariants and spec 02 §Dependency ordering):

  1. Collect. Gather settings, databases, and router from builder-local state. Settings must be set explicitly via .settings(...); the “default” database pool must be registered via .database("default", pool). The caller opens the pool first (with umbral::db::connect(...).await) and hands it to the builder. This matches the canonical pattern in spec 01-app-and-settings.md.
  2. Validate plugins. Reject the reserved "app" name, reject duplicate Plugin::name()s, verify every entry in a dependencies() list points at a registered plugin, and compute a stable topological order. Cycles surface as BuildError::PluginCycle.
  3. Detect backend. backend::detect(&settings.database_url) picks one of the shipped DatabaseBackend impls (M4 abstraction). An unknown URL scheme (mysql / oracle / etc.) fails here, before any system check runs.
  4. Publish ambient state. Write settings, pools, and the active backend into their OnceLocks. The model registry carries one entry per plugin (the implicit "app" plus every registered plugin’s Plugin::models()).
  5. System check. Run framework-built-in checks plus every plugin’s system_checks() (concatenated in topological order) against the just-published context. Errors block boot; warnings log and continue.
  6. Build router. Start from the hand-written router (or a fallback handler), then merge every plugin’s routes() in topological order. axum’s Router::merge panics on duplicate routes with a clear message.
  7. Fire on_ready. Call each plugin’s on_ready(&AppContext) in topological order. A failure here surfaces as BuildError::PluginOnReady.

build() is intentionally sync. Earlier iterations auto-opened the default pool from settings.database_url by spinning up a throwaway tokio runtime to drive db::connect. That panicked when called from inside any caller that was already in a tokio runtime (“Cannot start a runtime from within a runtime”), which is every realistic case. Requiring an explicit .database(...) is both spec-correct and avoids the trap.

Trait Implementations§

Source§

impl Default for AppBuilder

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<A, B, T> HttpServerConnExec<A, B> for T
where B: Body,

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Paint for T
where T: ?Sized,

Source§

fn fg(&self, value: Color) -> Painted<&T>

Returns a styled value derived from self with the foreground set to value.

This method should be used rarely. Instead, prefer to use color-specific builder methods like red() and green(), which have the same functionality but are pithier.

§Example

Set foreground color to white using fg():

use yansi::{Paint, Color};

painted.fg(Color::White);

Set foreground color to white using white().

use yansi::Paint;

painted.white();
Source§

fn primary(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Primary].

§Example
println!("{}", value.primary());
Source§

fn fixed(&self, color: u8) -> Painted<&T>

Returns self with the fg() set to [Color :: Fixed].

§Example
println!("{}", value.fixed(color));
Source§

fn rgb(&self, r: u8, g: u8, b: u8) -> Painted<&T>

Returns self with the fg() set to [Color :: Rgb].

§Example
println!("{}", value.rgb(r, g, b));
Source§

fn black(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Black].

§Example
println!("{}", value.black());
Source§

fn red(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Red].

§Example
println!("{}", value.red());
Source§

fn green(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Green].

§Example
println!("{}", value.green());
Source§

fn yellow(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Yellow].

§Example
println!("{}", value.yellow());
Source§

fn blue(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Blue].

§Example
println!("{}", value.blue());
Source§

fn magenta(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Magenta].

§Example
println!("{}", value.magenta());
Source§

fn cyan(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Cyan].

§Example
println!("{}", value.cyan());
Source§

fn white(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: White].

§Example
println!("{}", value.white());
Source§

fn bright_black(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightBlack].

§Example
println!("{}", value.bright_black());
Source§

fn bright_red(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightRed].

§Example
println!("{}", value.bright_red());
Source§

fn bright_green(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightGreen].

§Example
println!("{}", value.bright_green());
Source§

fn bright_yellow(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightYellow].

§Example
println!("{}", value.bright_yellow());
Source§

fn bright_blue(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightBlue].

§Example
println!("{}", value.bright_blue());
Source§

fn bright_magenta(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightMagenta].

§Example
println!("{}", value.bright_magenta());
Source§

fn bright_cyan(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightCyan].

§Example
println!("{}", value.bright_cyan());
Source§

fn bright_white(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightWhite].

§Example
println!("{}", value.bright_white());
Source§

fn bg(&self, value: Color) -> Painted<&T>

Returns a styled value derived from self with the background set to value.

This method should be used rarely. Instead, prefer to use color-specific builder methods like on_red() and on_green(), which have the same functionality but are pithier.

§Example

Set background color to red using fg():

use yansi::{Paint, Color};

painted.bg(Color::Red);

Set background color to red using on_red().

use yansi::Paint;

painted.on_red();
Source§

fn on_primary(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Primary].

§Example
println!("{}", value.on_primary());
Source§

fn on_fixed(&self, color: u8) -> Painted<&T>

Returns self with the bg() set to [Color :: Fixed].

§Example
println!("{}", value.on_fixed(color));
Source§

fn on_rgb(&self, r: u8, g: u8, b: u8) -> Painted<&T>

Returns self with the bg() set to [Color :: Rgb].

§Example
println!("{}", value.on_rgb(r, g, b));
Source§

fn on_black(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Black].

§Example
println!("{}", value.on_black());
Source§

fn on_red(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Red].

§Example
println!("{}", value.on_red());
Source§

fn on_green(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Green].

§Example
println!("{}", value.on_green());
Source§

fn on_yellow(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Yellow].

§Example
println!("{}", value.on_yellow());
Source§

fn on_blue(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Blue].

§Example
println!("{}", value.on_blue());
Source§

fn on_magenta(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Magenta].

§Example
println!("{}", value.on_magenta());
Source§

fn on_cyan(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Cyan].

§Example
println!("{}", value.on_cyan());
Source§

fn on_white(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: White].

§Example
println!("{}", value.on_white());
Source§

fn on_bright_black(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightBlack].

§Example
println!("{}", value.on_bright_black());
Source§

fn on_bright_red(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightRed].

§Example
println!("{}", value.on_bright_red());
Source§

fn on_bright_green(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightGreen].

§Example
println!("{}", value.on_bright_green());
Source§

fn on_bright_yellow(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightYellow].

§Example
println!("{}", value.on_bright_yellow());
Source§

fn on_bright_blue(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightBlue].

§Example
println!("{}", value.on_bright_blue());
Source§

fn on_bright_magenta(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightMagenta].

§Example
println!("{}", value.on_bright_magenta());
Source§

fn on_bright_cyan(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightCyan].

§Example
println!("{}", value.on_bright_cyan());
Source§

fn on_bright_white(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightWhite].

§Example
println!("{}", value.on_bright_white());
Source§

fn attr(&self, value: Attribute) -> Painted<&T>

Enables the styling Attribute value.

This method should be used rarely. Instead, prefer to use attribute-specific builder methods like bold() and underline(), which have the same functionality but are pithier.

§Example

Make text bold using attr():

use yansi::{Paint, Attribute};

painted.attr(Attribute::Bold);

Make text bold using using bold().

use yansi::Paint;

painted.bold();
Source§

fn bold(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Bold].

§Example
println!("{}", value.bold());
Source§

fn dim(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Dim].

§Example
println!("{}", value.dim());
Source§

fn italic(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Italic].

§Example
println!("{}", value.italic());
Source§

fn underline(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Underline].

§Example
println!("{}", value.underline());

Returns self with the attr() set to [Attribute :: Blink].

§Example
println!("{}", value.blink());

Returns self with the attr() set to [Attribute :: RapidBlink].

§Example
println!("{}", value.rapid_blink());
Source§

fn invert(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Invert].

§Example
println!("{}", value.invert());
Source§

fn conceal(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Conceal].

§Example
println!("{}", value.conceal());
Source§

fn strike(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Strike].

§Example
println!("{}", value.strike());
Source§

fn quirk(&self, value: Quirk) -> Painted<&T>

Enables the yansi Quirk value.

This method should be used rarely. Instead, prefer to use quirk-specific builder methods like mask() and wrap(), which have the same functionality but are pithier.

§Example

Enable wrapping using .quirk():

use yansi::{Paint, Quirk};

painted.quirk(Quirk::Wrap);

Enable wrapping using wrap().

use yansi::Paint;

painted.wrap();
Source§

fn mask(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: Mask].

§Example
println!("{}", value.mask());
Source§

fn wrap(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: Wrap].

§Example
println!("{}", value.wrap());
Source§

fn linger(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: Linger].

§Example
println!("{}", value.linger());
Source§

fn clear(&self) -> Painted<&T>

👎Deprecated since 1.0.1:

renamed to resetting() due to conflicts with Vec::clear(). The clear() method will be removed in a future release.

Returns self with the quirk() set to [Quirk :: Clear].

§Example
println!("{}", value.clear());
Source§

fn resetting(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: Resetting].

§Example
println!("{}", value.resetting());
Source§

fn bright(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: Bright].

§Example
println!("{}", value.bright());
Source§

fn on_bright(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: OnBright].

§Example
println!("{}", value.on_bright());
Source§

fn whenever(&self, value: Condition) -> Painted<&T>

Conditionally enable styling based on whether the Condition value applies. Replaces any previous condition.

See the crate level docs for more details.

§Example

Enable styling painted only when both stdout and stderr are TTYs:

use yansi::{Paint, Condition};

painted.red().on_yellow().whenever(Condition::STDOUTERR_ARE_TTY);
Source§

fn new(self) -> Painted<Self>
where Self: Sized,

Create a new Painted with a default Style. Read more
Source§

fn paint<S>(&self, style: S) -> Painted<&Self>
where S: Into<Style>,

Apply a style wholesale to self. Any previous style is replaced. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more