pub fn wrap_width(source: &str) -> usize {
let longest = source.lines().map(|l| l.chars().count()).max().unwrap_or(0);
longest.clamp(80, 100)
}
pub fn wrap_comment(text: &str, width: usize, indent: usize, delim_cols: usize) -> Vec<String> {
let budget = width.saturating_sub(indent + delim_cols).max(1);
let mut lines: Vec<String> = Vec::new();
let mut cur = String::new();
let mut cur_len = 0usize;
for word in text.split_whitespace() {
let w = word.chars().count();
if cur.is_empty() {
cur.push_str(word);
cur_len = w;
} else if cur_len + 1 + w <= budget {
cur.push(' ');
cur.push_str(word);
cur_len += 1 + w;
} else {
lines.push(std::mem::take(&mut cur));
cur.push_str(word);
cur_len = w;
}
}
lines.push(cur);
lines
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn width_clamps_to_the_band() {
assert_eq!(wrap_width("PORT=8080\n"), 80); assert_eq!(wrap_width(&format!("{}\n", "x".repeat(90))), 90); assert_eq!(wrap_width(&format!("{}\n", "x".repeat(200))), 100); assert_eq!(wrap_width(""), 80); }
#[test]
fn wraps_greedily_to_the_budget() {
let out = wrap_comment("the quick brown fox jumps", 20, 0, 2);
assert_eq!(out, vec!["the quick brown", "fox jumps"]);
}
#[test]
fn long_word_overflows_not_breaks() {
let out = wrap_comment("see https://example.com/a/very/long/path now", 30, 0, 2);
assert_eq!(
out,
vec!["see", "https://example.com/a/very/long/path", "now"]
);
}
#[test]
fn empty_text_is_one_empty_line() {
assert_eq!(wrap_comment("", 80, 0, 2), vec![String::new()]);
}
}