1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
//! Utilities for formatting, bordering, aligning and printing text content
//!
//! This module provides functions for formatting content with borders and colors, printing them to the console.
//! The functions in this module are designed to simplify the process of creating visually appealing
//! output for CLI applications.
//!
//! Note that most of the utilities in this module are focused on communication with humans, not
//! with machines. Consider evaluating [`std::io::IsTerminal`] before using colorful, dynamic and bordered
//! printing. If you are talking to a machine, it might be useful to not add extra space, add a
//! newline per output or even output JSON. An example that does this well is `ls`:
//!
//! ```bash
//! $ ls
//! Cargo.lock Cargo.toml data LICENSE members README.md scripts src target
//! ```
//!
//! ```bash
//! $ ls | cat
//! Cargo.lock
//! Cargo.toml
//! data
//! LICENSE
//! members
//! README.md
//! scripts
//! src
//! target
//! ```
//!
//! See the [CLI Rustbook](https://rust-cli.github.io/book/in-depth/machine-communication.html) for
//! more information on the topic.
use comfy_table::presets;
use comfy_table::{CellAlignment, ContentArrangement, Table};
use console::{style, Color};
/// Prints content with a simple border around it
///
/// This function is a convenience wrapper around [blockfmt] and [println]. It automatically
/// formats the content with a border using the specified color and then prints it to the console.
///
/// # Example
///
/// ```
/// use libpt_cli::console::Color;
/// use libpt_cli::printing::blockprint;
/// # fn main() {
/// blockprint("Hello world!", Color::Blue);
/// # }
/// ```
#[inline]
#[allow(clippy::needless_pass_by_value)] // we just take an impl, using a &impl is much less ergonomic
pub fn blockprint(content: impl ToString, color: Color) {
println!("{}", blockfmt(content, color));
}
/// Formats content with a simple border around it
///
/// This function is a convenience wrapper around [`blockfmt_advanced`] with preset values for
/// border style, content arrangement, and cell alignment. It automatically formats the content
/// with a border as large as possible and centers the content. The resulting cell is colored in
/// the specified color.
///
/// # Example
///
/// ```
/// use libpt_cli::console::Color;
/// use libpt_cli::printing::blockfmt;
/// # fn main() {
/// let formatted_content = blockfmt("Hello world!", Color::Blue);
/// println!("{}", formatted_content);
/// # }
/// ```
#[inline]
#[allow(clippy::needless_pass_by_value)] // we just take an impl, using a &impl is much less ergonomic
pub fn blockfmt(content: impl ToString, color: Color) -> String {
blockfmt_advanced(
content,
Some(color),
presets::UTF8_BORDERS_ONLY,
ContentArrangement::DynamicFullWidth,
CellAlignment::Center,
)
}
/// Formats content with a border around it
///
/// Unless you are looking for something specific, use [blockfmt] or [blockprint].
///
/// The border can be created using box-drawing characters, and the content is formatted
/// within the border. The function allows customization of the border's color, preset,
/// content arrangement, and cell alignment.
///
/// # Example
/// ```
/// use libpt_cli::comfy_table::{presets, CellAlignment, ContentArrangement};
/// use libpt_cli::console::Color;
/// use libpt_cli::printing::blockfmt_advanced;
/// # fn main() {
/// println!(
/// "{}",
/// blockfmt_advanced(
/// "Hello world!",
/// Some(Color::Blue),
/// presets::UTF8_FULL,
/// ContentArrangement::DynamicFullWidth,
/// CellAlignment::Center
/// )
/// );
/// # }
/// ```
/// ```text
/// ┌────────────────────────────────────────────────────────────────────────────────────────┐
/// │ Hello world! │
/// └────────────────────────────────────────────────────────────────────────────────────────┘
/// ```
///
/// # Parameters
///
/// - `content`: The content to be formatted within the border
/// - `color`: The color of the border and text
/// - `preset`: The preset style for the border
/// - `arrangement`: The arrangement of the the border (e.g., stretch to sides, wrap around )
/// - `alignment`: The alignment of the content within the cells (e.g., left, center, right)
#[allow(clippy::missing_panics_doc)] // we add a row then unwrap it, no panic should be possible
#[allow(clippy::needless_pass_by_value)] // we just take an impl, using a &impl is much less ergonomic
pub fn blockfmt_advanced(
content: impl ToString,
color: Option<Color>,
preset: &str,
arrangement: ContentArrangement,
alignment: CellAlignment,
) -> String {
let mut table = Table::new();
table
.load_preset(preset)
.set_content_arrangement(arrangement)
.add_row(vec![content.to_string()]);
table.column_mut(0).unwrap().set_cell_alignment(alignment);
match color {
Some(c) => format!("{}", style(table).fg(c)),
None => table.to_string(),
}
}