Line-Wrapping Summaries

So our program is working well and it's printing everything to the terminal in a readable manner. However, are there ways that we can improve the output to be easier on the eyes? Indeed, there is.

The Problem

One of the issues with the output of our program is that article summaries are printed as a single line and aren't being properly wrapped around a specific character limit. You may notice that words are being broken as they are forcefully wrapped around your terminal without a care. Your terminal doesn't care about keeping words together.

Challenge

This is a good mental exercise if you'd like to solve this problem yourself. Try to get your summaries to print by wrapping them around an 80 char limit. Make it even better by making your output like so:

Summary:
 - This is a sentence that our
 - program is outputting and
 - is keeping our words together.

Solution

This is one such solution to the problem:

Create a file named linesplit.rs and import it into your main.rs file by adding mod linesplit; with the rest of the mods. Then, inside the phoronix.rs file, add use linesplit; so that you can use it in that file.

The following function will take the summary as the first input and the character length to wrap words around as the second.

pub fn split_by_chars(input: &str, length: usize) -> Vec<String> {
    let words: Vec<&str> = input.split_whitespace().collect();
    let mut lines: Vec<String> = Vec::new();
    let mut current_line = String::with_capacity(length);
    let mut chars: usize = 0;
    let mut initialized = false;
    for word in words {
        if chars + word.len() >= length {
            lines.push(current_line.clone());
            current_line.clear();
            current_line.reserve(length);
            current_line = String::from(word);
            chars = word.len();
        } else if !initialized {
            current_line = String::from(word);
            chars = word.len();
            initialized = true;
        } else {
            current_line = current_line + " " + &word;
            chars += word.len() + 1;
        }
    }
    if !current_line.is_empty() { lines.push(current_line); }
    return lines;
}

Inside your printing function, change it so that it makes use of this function:

pub fn print() {
    let phoronix_articles = Article::get_articles(homepage::offline());
    for article in phoronix_articles.iter().rev() {
        println!("Title:   {}", article.title);
        println!("Link:    https://www.phoronix.com/{}", article.link);
        println!("Details: {}", article.details);
        println!("Summary:");
        for line in linesplit::split_by_chars(&article.summary, 77) {
            println!(" - {}", line);
        }
        print!("\n");
    }
}