Skip to content

Commit cdeeb69

Browse files
committed
Add example showing how one can use owned options
The `textwrap::Options<'a>` type is a little annoying: it insists on borrowing all its fields from somewhere else. In particular, the indentation fields are of type `&'a str`. This means that it’s not really possible for a program to store an `Options<'a>` and use it later if the fields are anything but string literals (of type `&str`). However, what does work is to create the `Options<'a>` on demand. Since all functions that need the options take an argument of type `impl Options<'a>`, you can easily convert your own type as needed. This can be as cheap as possible, i.e., converting `String` fields to `&str`. From the discussion in #592.
1 parent 77a634f commit cdeeb69

File tree

1 file changed

+58
-0
lines changed

1 file changed

+58
-0
lines changed

examples/owned-options.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
//! Example showing how to deal with an owned options type.
2+
3+
/// Your owned options. You can put anything here which you need to
4+
/// produce a `textwrap::Options<'a>` later. Here we specify a subset
5+
/// of the fields in `Options`.
6+
#[derive(Debug, Default)]
7+
struct OwnedOptions {
8+
width: u16, // Smaller integer type.
9+
initial_indent: String, // Owned string type.
10+
}
11+
12+
impl OwnedOptions {
13+
fn new(width: u16) -> Self {
14+
Self {
15+
width,
16+
..OwnedOptions::default()
17+
}
18+
}
19+
}
20+
21+
/// All `textwrap` functions take an `impl Into<Options<'a>>`
22+
/// argument, so with this implementation, we can transparently use
23+
/// our own type in calls to `textwrap::wrap` and related functions.
24+
impl<'a> From<&'a OwnedOptions> for textwrap::Options<'a> {
25+
fn from(owned_options: &'a OwnedOptions) -> textwrap::Options<'a> {
26+
textwrap::Options::new(owned_options.width.into()) // converted
27+
.initial_indent(&owned_options.initial_indent) // borrowed
28+
.break_words(true) // hard-coded
29+
.wrap_algorithm(textwrap::WrapAlgorithm::FirstFit)
30+
}
31+
}
32+
33+
/// Update `options`.
34+
///
35+
/// We can only do this because we own the string field.
36+
fn update_indent(n: usize, options: &mut OwnedOptions) {
37+
options.initial_indent = "-".repeat(n);
38+
options.initial_indent.push('>');
39+
options.initial_indent.push(' ');
40+
}
41+
42+
fn main() {
43+
let mut owned_options = OwnedOptions::new(28);
44+
let text = "This text is wrapped using OwnedOptions, not the standard Options from Textwrap.";
45+
46+
println!("Initial options: {owned_options:?}");
47+
println!("{}", textwrap::fill(text, &owned_options));
48+
println!();
49+
50+
update_indent(5, &mut owned_options);
51+
println!("First update: {owned_options:?}");
52+
println!("{}", textwrap::fill(text, &owned_options));
53+
println!();
54+
55+
update_indent(8, &mut owned_options);
56+
println!("Second update: {owned_options:?}");
57+
println!("{}", textwrap::fill(text, &owned_options));
58+
}

0 commit comments

Comments
 (0)