Repository: mgeisler/textwrap (language: rust)

Issue:
Immediatedly add word if it fits
When a word fits on the current line, we don't need to compute all the possible splits. We can simply push it onto the line and continue with next word.


Discussion / hints:

Fix patch:
diff --git a/src/lib.rs b/src/lib.rs
index 8b75368a..b07e18cc 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -101,6 +101,12 @@ impl<'a> Wrapper<'a> {
         let mut remaining = self.width;
 
         for mut word in s.split_whitespace() {
+            // Attempt to fit the word without any splitting.
+            if self.fit_part(word, "", &mut remaining, &mut line) {
+                continue;
+            }
+
+            // If that failed, loop until nothing remains to be added.
             while !word.is_empty() {
                 let splits = self.split_word(&word);
                 let (smallest, hyphen, longest) = splits[0];
@@ -114,17 +120,9 @@ impl<'a> Wrapper<'a> {
                     remaining = self.width;
                 }
 
-                let space = if line.is_empty() { 0 } else { 1 };
-
                 // Find a split that fits on the current line.
                 for &(head, hyphen, tail) in splits.iter().rev() {
-                    if space + head.width() + hyphen.len() <= remaining {
-                        if !line.is_empty() {
-                            line.push(' ');
-                        }
-                        line.push_str(head);
-                        line.push_str(hyphen);
-                        remaining -= space + head.width() + hyphen.len();
+                    if self.fit_part(head, hyphen, &mut remaining, &mut line) {
                         word = tail;
                         break;
                     }
@@ -185,6 +183,28 @@ impl<'a> Wrapper<'a> {
 
         return result;
     }
+
+    /// Try to fit a word (or part of a word) onto a line. The line
+    /// and the remaining width is updated as appropriate if the word
+    /// or part fits.
+    fn fit_part<'b>(&self,
+                    part: &'b str,
+                    hyphen: &'b str,
+                    remaining: &mut usize,
+                    line: &mut String)
+                    -> bool {
+        let space = if line.is_empty() { 0 } else { 1 };
+        if space + part.width() + hyphen.len() <= *remaining {
+            if !line.is_empty() {
+                line.push(' ');
+            }
+            line.push_str(part);
+            line.push_str(hyphen);
+            *remaining -= space + part.width() + hyphen.len();
+            return true;
+        }
+        return false;
+    }
 }
 
 /// Fill a line of text at `width` characters. Strings are wrapped


Test patch: