| package wordwrap |
| |
| import ( |
| "bytes" |
| "unicode" |
| ) |
| |
| // WrapString wraps the given string within lim width in characters. |
| // |
| // Wrapping is currently naive and only happens at white-space. A future |
| // version of the library will implement smarter wrapping. This means that |
| // pathological cases can dramatically reach past the limit, such as a very |
| // long word. |
| func WrapString(s string, lim uint) string { |
| // Initialize a buffer with a slightly larger size to account for breaks |
| init := make([]byte, 0, len(s)) |
| buf := bytes.NewBuffer(init) |
| |
| var current uint |
| var wordBuf, spaceBuf bytes.Buffer |
| |
| for _, char := range s { |
| if char == '\n' { |
| if wordBuf.Len() == 0 { |
| if current+uint(spaceBuf.Len()) > lim { |
| current = 0 |
| } else { |
| current += uint(spaceBuf.Len()) |
| spaceBuf.WriteTo(buf) |
| } |
| spaceBuf.Reset() |
| } else { |
| current += uint(spaceBuf.Len() + wordBuf.Len()) |
| spaceBuf.WriteTo(buf) |
| spaceBuf.Reset() |
| wordBuf.WriteTo(buf) |
| wordBuf.Reset() |
| } |
| buf.WriteRune(char) |
| current = 0 |
| } else if unicode.IsSpace(char) { |
| if spaceBuf.Len() == 0 || wordBuf.Len() > 0 { |
| current += uint(spaceBuf.Len() + wordBuf.Len()) |
| spaceBuf.WriteTo(buf) |
| spaceBuf.Reset() |
| wordBuf.WriteTo(buf) |
| wordBuf.Reset() |
| } |
| |
| spaceBuf.WriteRune(char) |
| } else { |
| |
| wordBuf.WriteRune(char) |
| |
| if current+uint(spaceBuf.Len()+wordBuf.Len()) > lim && uint(wordBuf.Len()) < lim { |
| buf.WriteRune('\n') |
| current = 0 |
| spaceBuf.Reset() |
| } |
| } |
| } |
| |
| if wordBuf.Len() == 0 { |
| if current+uint(spaceBuf.Len()) <= lim { |
| spaceBuf.WriteTo(buf) |
| } |
| } else { |
| spaceBuf.WriteTo(buf) |
| wordBuf.WriteTo(buf) |
| } |
| |
| return buf.String() |
| } |