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