/// Fill a line of text at a given width. /// /// The result is a [`String`], complete with newlines between each /// line. Use [`wrap()`] if you need access to the individual lines. /// /// The easiest way to use this function is to pass an integer for /// `width_or_options`: /// /// ``` /// use textwrap::fill; /// /// assert_eq!( /// fill("Memory safety without garbage collection.", 15), /// "Memory safety\nwithout garbage\ncollection." /// ); /// ``` /// /// If you need to customize the wrapping, you can pass an [`Options`] /// instead of an `usize`: /// /// ``` /// use textwrap::{fill, Options}; /// /// let options = Options::new(15) /// .initial_indent("- ") /// .subsequent_indent(" "); /// assert_eq!( /// fill("Memory safety without garbage collection.", &options), /// "- Memory safety\n without\n garbage\n collection." /// ); /// ``` pubfn fill<'a, Opt>(text: &str, width_or_options: Opt) -> String where
Opt: Into<Options<'a>>,
{ let options = width_or_options.into();
/// Slow path for fill. /// /// This is taken when `text` is longer than `options.width`. pub(crate) fn fill_slow_path(text: &str, options: Options<'_>) -> String { // This will avoid reallocation in simple cases (no // indentation, no hyphenation). letmut result = String::with_capacity(text.len());
let line_ending_str = options.line_ending.as_str(); for (i, line) in wrap(text, options).iter().enumerate() { if i > 0 {
result.push_str(line_ending_str);
}
result.push_str(line);
}
result
}
/// Fill `text` in-place without reallocating the input string. /// /// This function works by modifying the input string: some `' '` /// characters will be replaced by `'\n'` characters. The rest of the /// text remains untouched. /// /// Since we can only replace existing whitespace in the input with /// `'\n'` (there is no space for `"\r\n"`), we cannot do hyphenation /// nor can we split words longer than the line width. We also need to /// use `AsciiSpace` as the word separator since we need `' '` /// characters between words in order to replace some of them with a /// `'\n'`. Indentation is also ruled out. In other words, /// `fill_inplace(width)` behaves as if you had called [`fill()`] with /// these options: /// /// ``` /// # use textwrap::{core, LineEnding, Options, WordSplitter, WordSeparator, WrapAlgorithm}; /// # let width = 80; /// Options::new(width) /// .break_words(false) /// .line_ending(LineEnding::LF) /// .word_separator(WordSeparator::AsciiSpace) /// .wrap_algorithm(WrapAlgorithm::FirstFit) /// .word_splitter(WordSplitter::NoHyphenation); /// ``` /// /// The wrap algorithm is /// [`WrapAlgorithm::FirstFit`](crate::WrapAlgorithm::FirstFit) since /// this is the fastest algorithm — and the main reason to use /// `fill_inplace` is to get the string broken into newlines as fast /// as possible. /// /// A last difference is that (unlike [`fill()`]) `fill_inplace` can /// leave trailing whitespace on lines. This is because we wrap by /// inserting a `'\n'` at the final whitespace in the input string: /// /// ``` /// let mut text = String::from("Hello World!"); /// textwrap::fill_inplace(&mut text, 10); /// assert_eq!(text, "Hello \nWorld!"); /// ``` /// /// If we didn't do this, the word `World!` would end up being /// indented. You can avoid this if you make sure that your input text /// has no double spaces. /// /// # Performance /// /// In benchmarks, `fill_inplace` is about twice as fast as /// [`fill()`]. Please see the [`linear` /// benchmark](https://github.com/mgeisler/textwrap/blob/master/benchmarks/linear.rs) /// for details. pubfn fill_inplace(text: &mut String, width: usize) { letmut indices = Vec::new();
letmut offset = 0; for line in text.split('\n') { let words = WordSeparator::AsciiSpace
.find_words(line)
.collect::<Vec<_>>(); let wrapped_words = wrap_algorithms::wrap_first_fit(&words, &[width as f64]);
letmut line_offset = offset; for words in &wrapped_words[..wrapped_words.len() - 1] { let line_len = words
.iter()
.map(|word| word.len() + word.whitespace.len())
.sum::<usize>();
line_offset += line_len; // We've advanced past all ' ' characters -- want to move // one ' ' backwards and insert our '\n' there.
indices.push(line_offset - 1);
}
// Advance past entire line, plus the '\n' which was removed // by the split call above.
offset += line.len() + 1;
}
letmut bytes = std::mem::take(text).into_bytes(); for idx in indices {
bytes[idx] = b'\n';
}
*text = String::from_utf8(bytes).unwrap();
}
#[cfg(test)] mod tests { usesuper::*; usecrate::WrapAlgorithm;
#[test] fn fill_inplace_simple() { letmut text = String::from("foo bar baz");
fill_inplace(&mut text, 10);
assert_eq!(text, "foo bar\nbaz");
}
#[test] fn fill_inplace_multiple_lines() { letmut text = String::from("Some text to wrap over multiple lines");
fill_inplace(&mut text, 12);
assert_eq!(text, "Some text to\nwrap over\nmultiple\nlines");
}
#[test] fn fill_inplace_long_word() { letmut text = String::from("Internationalization is hard");
fill_inplace(&mut text, 10);
assert_eq!(text, "Internationalization\nis hard");
}
#[test] fn fill_inplace_leading_whitespace() { letmut text = String::from(" foo bar baz");
fill_inplace(&mut text, 10);
assert_eq!(text, " foo bar\nbaz");
}
#[test] fn fill_inplace_trailing_whitespace() { letmut text = String::from("foo bar baz ");
fill_inplace(&mut text, 10);
assert_eq!(text, "foo bar\nbaz ");
}
#[test] fn fill_inplace_interior_whitespace() { // To avoid an unwanted indentation of "baz", it is important // to replace the final ' ' with '\n'. letmut text = String::from("foo bar baz");
fill_inplace(&mut text, 10);
assert_eq!(text, "foo bar \nbaz");
}
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet am 2026-06-19)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.