1# Textwrap 2 3[![](https://img.shields.io/crates/v/textwrap.svg)][crates-io] 4[![](https://docs.rs/textwrap/badge.svg)][api-docs] 5[![](https://travis-ci.org/mgeisler/textwrap.svg?branch=master)][travis-ci] 6[![](https://ci.appveyor.com/api/projects/status/yo6iak55nraupjw3/branch/master?svg=true)][appveyor] 7 8Textwrap is a small Rust crate for word wrapping text. You can use it 9to format strings for display in commandline applications. The crate 10name and interface is inspired by 11the [Python textwrap module][py-textwrap]. 12 13## Usage 14 15Add this to your `Cargo.toml`: 16```toml 17[dependencies] 18textwrap = "0.9" 19``` 20 21and this to your crate root: 22```rust 23extern crate textwrap; 24``` 25 26If you would like to have automatic hyphenation, specify the 27dependency as: 28```toml 29[dependencies] 30textwrap = { version = "0.9", features = ["hyphenation"] } 31``` 32 33To conveniently wrap text at the current terminal width, enable the 34`term_size` feature: 35 36```toml 37[dependencies] 38textwrap = { version = "0.9", features = ["term_size"] } 39``` 40 41## Documentation 42 43**[API documentation][api-docs]** 44 45## Getting Started 46 47Word wrapping single strings is easy using the `fill` function: 48```rust 49extern crate textwrap; 50use textwrap::fill; 51 52fn main() { 53 let text = "textwrap: a small library for wrapping text."; 54 println!("{}", fill(text, 18)); 55} 56``` 57The output is 58``` 59textwrap: a small 60library for 61wrapping text. 62``` 63 64With the `hyphenation` feature, you can get automatic hyphenation 65for [about 70 languages][patterns]. Your program must load and 66configure the hyphenation patterns to use: 67```rust 68extern crate hyphenation; 69extern crate textwrap; 70 71use hyphenation::Language; 72use textwrap::Wrapper; 73 74fn main() { 75 let corpus = hyphenation::load(Language::English_US).unwrap(); 76 let wrapper = Wrapper::with_splitter(18, corpus); 77 let text = "textwrap: a small library for wrapping text."; 78 println!("{}", wrapper.fill(text)) 79} 80``` 81 82The output now looks like this: 83``` 84textwrap: a small 85library for wrap- 86ping text. 87``` 88 89The hyphenation uses high-quality TeX hyphenation patterns. 90 91## Examples 92 93The library comes with some small example programs that shows various 94features. 95 96### Layout Example 97 98The `layout` example shows how a fixed example string is wrapped at 99different widths. Run the example with: 100 101```shell 102$ cargo run --features hyphenation --example layout 103``` 104 105The program will use the following string: 106 107> Memory safety without garbage collection. Concurrency without data 108> races. Zero-cost abstractions. 109 110The string is wrapped at all widths between 15 and 60 columns. With 111narrow columns the output looks like this: 112 113``` 114.--- Width: 15 ---. 115| Memory safety | 116| without garbage | 117| collection. | 118| Concurrency | 119| without data | 120| races. Zero- | 121| cost abstrac- | 122| tions. | 123.--- Width: 16 ----. 124| Memory safety | 125| without garbage | 126| collection. Con- | 127| currency without | 128| data races. Ze- | 129| ro-cost abstrac- | 130| tions. | 131``` 132 133Later, longer lines are used and the output now looks like this: 134 135``` 136.-------------------- Width: 49 --------------------. 137| Memory safety without garbage collection. Concur- | 138| rency without data races. Zero-cost abstractions. | 139.---------------------- Width: 53 ----------------------. 140| Memory safety without garbage collection. Concurrency | 141| without data races. Zero-cost abstractions. | 142.------------------------- Width: 59 -------------------------. 143| Memory safety without garbage collection. Concurrency with- | 144| out data races. Zero-cost abstractions. | 145``` 146 147Notice how words are split at hyphens (such as "zero-cost") but also 148how words are hyphenated using automatic/machine hyphenation. 149 150### Terminal Width Example 151 152The `termwidth` example simply shows how the width can be set 153automatically to the current terminal width. Run it with this command: 154 155``` 156$ cargo run --example termwidth 157``` 158 159If you run it in a narrow terminal, you'll see output like this: 160``` 161Formatted in within 60 columns: 162---- 163Memory safety without garbage collection. Concurrency 164without data races. Zero-cost abstractions. 165---- 166``` 167 168If `stdout` is not connected to the terminal, the program will use a 169default of 80 columns for the width: 170 171``` 172$ cargo run --example termwidth | cat 173Formatted in within 80 columns: 174---- 175Memory safety without garbage collection. Concurrency without data races. Zero- 176cost abstractions. 177---- 178``` 179 180## Release History 181 182This section lists the largest changes per release. 183 184### Version 0.9.0 — October 5th, 2017 185 186The dependency on `term_size` is now optional, and by default this 187feature is not enabled. This is a *breaking change* for users of 188`Wrapper::with_termwidth`. Enable the `term_size` feature to restore 189the old functionality. 190 191Added a regression test for case where width is set to usize::MAX. 192Thanks @Fraser999! All public structs now implement `Debug`. 193 194Issues closed: 195 196* Fixed [#101][issue-101]: Remove `term_size` as a (hard required) 197 dependency. 198 199### Version 0.8.0 — September 4th, 2017 200 201The `Wrapper` stuct is now generic over the type of word splitter 202being used. This means less boxing and a nicer API. The 203`Wrapper::word_splitter` method has been removed. This is a *breaking 204API change* if you used the method to change the word splitter. 205 206The `Wrapper` struct has two new methods that will wrap the input text 207lazily: `Wrapper::wrap_iter` and `Wrapper::into_wrap_iter`. Use those 208if you will be iterating over the wrapped lines one by one. 209 210Issues closed: 211 212* Fixed [#59][issue-59]: `wrap` could return an iterator. Thanks 213 @hcpl! 214 215* Fixed [#81][issue-81]: Set `html_root_url` 216 217### Version 0.7.0 — July 20th, 2017 218 219Version 0.7.0 changes the return type of `Wrapper::wrap` from 220`Vec<String>` to `Vec<Cow<'a, str>>`. This means that the output lines 221borrow data from the input string. This is a *breaking API change* if 222you relied on the exact return type of `Wrapper::wrap`. Callers of the 223`textwrap::fill` convenience function will see no breakage. 224 225The above change and other optimizations makes version 0.7.0 roughly 22615-30% faster than version 0.6.0. 227 228The `squeeze_whitespace` option has been removed since it was 229complicating the above optimization. Let us know if this option is 230important for you so we can provide a work around. 231 232Issues closed: 233 234* Fixed [#58][issue-58]: Add a "fast_wrap" function that reuses the 235 input string 236 237* Fixed [#61][issue-61]: Documentation errors 238 239### Version 0.6.0 — May 22nd, 2017 240 241Version 0.6.0 adds builder methods to `Wrapper` for easy one-line 242initialization and configuration: 243 244```rust 245let wrapper = Wrapper::new(60).break_words(false); 246``` 247 248It also add a new `NoHyphenation` word splitter that will never split 249words, not even at existing hyphens. 250 251Issues closed: 252 253* Fixed [#28][issue-28]: Support not squeezing whitespace 254 255### Version 0.5.0 — May 15th, 2017 256 257Version 0.5.0 has *breaking API changes*. However, this only affects 258code using the hyphenation feature. The feature is now optional, so 259you will first need to enable the `hyphenation` feature as described 260above. Afterwards, please change your code from 261```rust 262wrapper.corpus = Some(&corpus); 263``` 264to 265```rust 266wrapper.splitter = Box::new(corpus); 267``` 268 269Other changes include optimizations, so version 0.5.0 is roughly 27010-15% faster than version 0.4.0. 271 272Issues closed: 273 274* Fixed [#19][issue-19]: Add support for finding terminal size 275* Fixed [#25][issue-25]: Handle words longer than `self.width` 276* Fixed [#26][issue-26]: Support custom indentation 277* Fixed [#36][issue-36]: Support building without `hyphenation` 278* Fixed [#39][issue-39]: Respect non-breaking spaces 279 280### Version 0.4.0 — January 24th, 2017 281 282Documented complexities and tested these via `cargo bench`. 283 284* Fixed [#13][issue-13]: Immediatedly add word if it fits 285* Fixed [#14][issue-14]: Avoid splitting on initial hyphens in `--foo-bar` 286 287### Version 0.3.0 — January 7th, 2017 288 289Added support for automatic hyphenation. 290 291### Version 0.2.0 — December 28th, 2016 292 293Introduced `Wrapper` struct. Added support for wrapping on hyphens. 294 295### Version 0.1.0 — December 17th, 2016 296 297First public release with support for wrapping strings on whitespace. 298 299## License 300 301Textwrap can be distributed according to the [MIT license][mit]. 302Contributions will be accepted under the same license. 303 304[crates-io]: https://crates.io/crates/textwrap 305[travis-ci]: https://travis-ci.org/mgeisler/textwrap 306[appveyor]: https://ci.appveyor.com/project/mgeisler/textwrap 307[py-textwrap]: https://docs.python.org/library/textwrap 308[patterns]: https://github.com/tapeinosyne/hyphenation/tree/master/patterns-tex 309[api-docs]: https://docs.rs/textwrap/ 310[issue-13]: https://github.com/mgeisler/textwrap/issues/13 311[issue-14]: https://github.com/mgeisler/textwrap/issues/14 312[issue-19]: https://github.com/mgeisler/textwrap/issues/19 313[issue-25]: https://github.com/mgeisler/textwrap/issues/25 314[issue-26]: https://github.com/mgeisler/textwrap/issues/26 315[issue-28]: https://github.com/mgeisler/textwrap/issues/28 316[issue-36]: https://github.com/mgeisler/textwrap/issues/36 317[issue-39]: https://github.com/mgeisler/textwrap/issues/39 318[issue-58]: https://github.com/mgeisler/textwrap/issues/58 319[issue-59]: https://github.com/mgeisler/textwrap/issues/59 320[issue-61]: https://github.com/mgeisler/textwrap/issues/61 321[issue-81]: https://github.com/mgeisler/textwrap/issues/81 322[issue-101]: https://github.com/mgeisler/textwrap/issues/101 323[mit]: LICENSE 324