//! The textwrap library provides functions for word wrapping and //! indenting text. //! //! # Wrapping Text //! //! Wrapping text can be very useful in command-line programs where //! you want to format dynamic output nicely so it looks good in a //! terminal. A quick example: //! //! ``` //! # #[cfg(feature = "smawk")] { //! let text = "textwrap: a small library for wrapping text."; //! assert_eq!(textwrap::wrap(text, 18), //! vec!["textwrap: a", //! "small library for", //! "wrapping text."]); //! # } //! ``` //! //! The [`wrap()`] function returns the individual lines, use //! [`fill()`] is you want the lines joined with `'\n'` to form a //! `String`. //! //! If you enable the `hyphenation` Cargo feature, you can get //! automatic hyphenation for a number of languages: //! //! ``` //! #[cfg(feature = "hyphenation")] { //! use hyphenation::{Language, Load, Standard}; //! use textwrap::{wrap, Options, WordSplitter}; //! //! let text = "textwrap: a small library for wrapping text."; //! let dictionary = Standard::from_embedded(Language::EnglishUS).unwrap(); //! let options = Options::new(18).word_splitter(WordSplitter::Hyphenation(dictionary)); //! assert_eq!(wrap(text, &options), //! vec!["textwrap: a small", //! "library for wrap-", //! "ping text."]); //! } //! ``` //! //! See also the [`unfill()`] and [`refill()`] functions which allow //! you to manipulate already wrapped text. //! //! ## Wrapping Strings at Compile Time //! //! If your strings are known at compile time, please take a look at //! the procedural macros from the [textwrap-macros] crate. //! //! ## Displayed Width vs Byte Size //! //! To word wrap text, one must know the width of each word so one can //! know when to break lines. This library will by default measure the //! width of text using the _displayed width_, not the size in bytes. //! The `unicode-width` Cargo feature controls this. //! //! This is important for non-ASCII text. ASCII characters such as `a` //! and `!` are simple and take up one column each. This means that //! the displayed width is equal to the string length in bytes. //! However, non-ASCII characters and symbols take up more than one //! byte when UTF-8 encoded: `é` is `0xc3 0xa9` (two bytes) and `⚙` is //! `0xe2 0x9a 0x99` (three bytes) in UTF-8, respectively. //! //! This is why we take care to use the displayed width instead of the //! byte count when computing line lengths. All functions in this //! library handle Unicode characters like this when the //! `unicode-width` Cargo feature is enabled (it is enabled by //! default). //! //! # Indentation and Dedentation //! //! The textwrap library also offers functions for adding a prefix to //! every line of a string and to remove leading whitespace. As an //! example, [`indent()`] allows you to turn lines of text into a //! bullet list: //! //! ``` //! let before = "\ //! foo //! bar //! baz //! "; //! let after = "\ //! * foo //! * bar //! * baz //! "; //! assert_eq!(textwrap::indent(before, "* "), after); //! ``` //! //! Removing leading whitespace is done with [`dedent()`]: //! //! ``` //! let before = " //! Some //! indented //! text //! "; //! let after = " //! Some //! indented //! text //! "; //! assert_eq!(textwrap::dedent(before), after); //! ``` //! //! # Cargo Features //! //! The textwrap library can be slimmed down as needed via a number of //! Cargo features. This means you only pay for the features you //! actually use. //! //! The full dependency graph, where dashed lines indicate optional //! dependencies, is shown below: //! //! //! //! ## Default Features //! //! These features are enabled by default: //! //! * `unicode-linebreak`: enables finding words using the //! [unicode-linebreak] crate, which implements the line breaking //! algorithm described in [Unicode Standard Annex //! #14](https://www.unicode.org/reports/tr14/). //! //! This feature can be disabled if you are happy to find words //! separated by ASCII space characters only. People wrapping text //! with emojis or East-Asian characters will want most likely want //! to enable this feature. See [`WordSeparator`] for details. //! //! * `unicode-width`: enables correct width computation of non-ASCII //! characters via the [unicode-width] crate. Without this feature, //! every [`char`] is 1 column wide, except for emojis which are 2 //! columns wide. See [`core::display_width()`] for details. //! //! This feature can be disabled if you only need to wrap ASCII //! text, or if the functions in [`core`] are used directly with //! [`core::Fragment`]s for which the widths have been computed in //! other ways. //! //! * `smawk`: enables linear-time wrapping of the whole paragraph via //! the [smawk] crate. See [`wrap_algorithms::wrap_optimal_fit()`] //! for details on the optimal-fit algorithm. //! //! This feature can be disabled if you only ever intend to use //! [`wrap_algorithms::wrap_first_fit()`]. //! //! //! //! With Rust 1.64.0, the size impact of the above features on your //! binary is as follows: //! //! | Configuration | Binary Size | Delta | //! | :--- | ---: | ---: | //! | quick-and-dirty implementation | 289 KB | — KB | //! | textwrap without default features | 305 KB | 16 KB | //! | textwrap with smawk | 317 KB | 28 KB | //! | textwrap with unicode-width | 309 KB | 20 KB | //! | textwrap with unicode-linebreak | 342 KB | 53 KB | //! //! //! //! The above sizes are the stripped sizes and the binary is compiled //! in release mode with this profile: //! //! ```toml //! [profile.release] //! lto = true //! codegen-units = 1 //! ``` //! //! See the [binary-sizes demo] if you want to reproduce these //! results. //! //! ## Optional Features //! //! These Cargo features enable new functionality: //! //! * `terminal_size`: enables automatic detection of the terminal //! width via the [terminal_size] crate. See //! [`Options::with_termwidth()`] for details. //! //! * `hyphenation`: enables language-sensitive hyphenation via the //! [hyphenation] crate. See the [`word_splitters::WordSplitter`] //! trait for details. //! //! [unicode-linebreak]: https://docs.rs/unicode-linebreak/ //! [unicode-width]: https://docs.rs/unicode-width/ //! [smawk]: https://docs.rs/smawk/ //! [binary-sizes demo]: https://github.com/mgeisler/textwrap/tree/master/examples/binary-sizes //! [textwrap-macros]: https://docs.rs/textwrap-macros/ //! [terminal_size]: https://docs.rs/terminal_size/ //! [hyphenation]: https://docs.rs/hyphenation/ #![doc(html_root_url = "https://docs.rs/textwrap/0.16.1")] #![forbid(unsafe_code)] // See https://github.com/mgeisler/textwrap/issues/210 #![deny(missing_docs)] #![deny(missing_debug_implementations)] #![allow(clippy::redundant_field_names)] // Make `cargo test` execute the README doctests. #[cfg(doctest)] #[doc = include_str!("../README.md")] mod readme_doctest {} pub mod core; #[cfg(fuzzing)] pub mod fuzzing; pub mod word_splitters; pub mod wrap_algorithms; mod columns; mod fill; mod indentation; mod line_ending; mod options; mod refill; #[cfg(feature = "terminal_size")] mod termwidth; mod word_separators; mod wrap; pub use columns::wrap_columns; pub use fill::{fill, fill_inplace}; pub use indentation::{dedent, indent}; pub use line_ending::LineEnding; pub use options::Options; pub use refill::{refill, unfill}; #[cfg(feature = "terminal_size")] pub use termwidth::termwidth; pub use word_separators::WordSeparator; pub use word_splitters::WordSplitter; pub use wrap::wrap; pub use wrap_algorithms::WrapAlgorithm;