wordwrap.go 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. package wordwrap
  2. import (
  3. "bytes"
  4. "unicode"
  5. )
  6. const nbsp = 0xA0
  7. // WrapString wraps the given string within lim width in characters.
  8. //
  9. // Wrapping is currently naive and only happens at white-space. A future
  10. // version of the library will implement smarter wrapping. This means that
  11. // pathological cases can dramatically reach past the limit, such as a very
  12. // long word.
  13. func WrapString(s string, lim uint) string {
  14. // Initialize a buffer with a slightly larger size to account for breaks
  15. init := make([]byte, 0, len(s))
  16. buf := bytes.NewBuffer(init)
  17. var current uint
  18. var wordBuf, spaceBuf bytes.Buffer
  19. var wordBufLen, spaceBufLen uint
  20. for _, char := range s {
  21. if char == '\n' {
  22. if wordBuf.Len() == 0 {
  23. if current+spaceBufLen > lim {
  24. current = 0
  25. } else {
  26. current += spaceBufLen
  27. spaceBuf.WriteTo(buf)
  28. }
  29. spaceBuf.Reset()
  30. spaceBufLen = 0
  31. } else {
  32. current += spaceBufLen + wordBufLen
  33. spaceBuf.WriteTo(buf)
  34. spaceBuf.Reset()
  35. spaceBufLen = 0
  36. wordBuf.WriteTo(buf)
  37. wordBuf.Reset()
  38. wordBufLen = 0
  39. }
  40. buf.WriteRune(char)
  41. current = 0
  42. } else if unicode.IsSpace(char) && char != nbsp {
  43. if spaceBuf.Len() == 0 || wordBuf.Len() > 0 {
  44. current += spaceBufLen + wordBufLen
  45. spaceBuf.WriteTo(buf)
  46. spaceBuf.Reset()
  47. spaceBufLen = 0
  48. wordBuf.WriteTo(buf)
  49. wordBuf.Reset()
  50. wordBufLen = 0
  51. }
  52. spaceBuf.WriteRune(char)
  53. spaceBufLen++
  54. } else {
  55. wordBuf.WriteRune(char)
  56. wordBufLen++
  57. if current+wordBufLen+spaceBufLen > lim && wordBufLen < lim {
  58. buf.WriteRune('\n')
  59. current = 0
  60. spaceBuf.Reset()
  61. spaceBufLen = 0
  62. }
  63. }
  64. }
  65. if wordBuf.Len() == 0 {
  66. if current+spaceBufLen <= lim {
  67. spaceBuf.WriteTo(buf)
  68. }
  69. } else {
  70. spaceBuf.WriteTo(buf)
  71. wordBuf.WriteTo(buf)
  72. }
  73. return buf.String()
  74. }