pax_global_header00006660000000000000000000000064137334310010014505gustar00rootroot0000000000000052 comment=ecf0936a077a4bd73a1cc2ac5c370f2b55618d62 go-wordwrap-1.0.1/000077500000000000000000000000001373343100100137545ustar00rootroot00000000000000go-wordwrap-1.0.1/LICENSE.md000066400000000000000000000020751373343100100153640ustar00rootroot00000000000000The MIT License (MIT) Copyright (c) 2014 Mitchell Hashimoto Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. go-wordwrap-1.0.1/README.md000066400000000000000000000020471373343100100152360ustar00rootroot00000000000000# go-wordwrap `go-wordwrap` (Golang package: `wordwrap`) is a package for Go that automatically wraps words into multiple lines. The primary use case for this is in formatting CLI output, but of course word wrapping is a generally useful thing to do. ## Installation and Usage Install using `go get github.com/mitchellh/go-wordwrap`. Full documentation is available at http://godoc.org/github.com/mitchellh/go-wordwrap Below is an example of its usage ignoring errors: ```go wrapped := wordwrap.WrapString("foo bar baz", 3) fmt.Println(wrapped) ``` Would output: ``` foo bar baz ``` ## Word Wrap Algorithm This library doesn't use any clever algorithm for word wrapping. The wrapping is actually very naive: whenever there is whitespace or an explicit linebreak. The goal of this library is for word wrapping CLI output, so the input is typically pretty well controlled human language. Because of this, the naive approach typically works just fine. In the future, we'd like to make the algorithm more advanced. We would do so without breaking the API. go-wordwrap-1.0.1/go.mod000066400000000000000000000000611373343100100150570ustar00rootroot00000000000000module github.com/mitchellh/go-wordwrap go 1.14 go-wordwrap-1.0.1/wordwrap.go000066400000000000000000000034421373343100100161530ustar00rootroot00000000000000package wordwrap import ( "bytes" "unicode" ) const nbsp = 0xA0 // 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 var wordBufLen, spaceBufLen uint for _, char := range s { if char == '\n' { if wordBuf.Len() == 0 { if current+spaceBufLen > lim { current = 0 } else { current += spaceBufLen spaceBuf.WriteTo(buf) } spaceBuf.Reset() spaceBufLen = 0 } else { current += spaceBufLen + wordBufLen spaceBuf.WriteTo(buf) spaceBuf.Reset() spaceBufLen = 0 wordBuf.WriteTo(buf) wordBuf.Reset() wordBufLen = 0 } buf.WriteRune(char) current = 0 } else if unicode.IsSpace(char) && char != nbsp { if spaceBuf.Len() == 0 || wordBuf.Len() > 0 { current += spaceBufLen + wordBufLen spaceBuf.WriteTo(buf) spaceBuf.Reset() spaceBufLen = 0 wordBuf.WriteTo(buf) wordBuf.Reset() wordBufLen = 0 } spaceBuf.WriteRune(char) spaceBufLen++ } else { wordBuf.WriteRune(char) wordBufLen++ if current+wordBufLen+spaceBufLen > lim && wordBufLen < lim { buf.WriteRune('\n') current = 0 spaceBuf.Reset() spaceBufLen = 0 } } } if wordBuf.Len() == 0 { if current+spaceBufLen <= lim { spaceBuf.WriteTo(buf) } } else { spaceBuf.WriteTo(buf) wordBuf.WriteTo(buf) } return buf.String() } go-wordwrap-1.0.1/wordwrap_test.go000066400000000000000000000037011373343100100172100ustar00rootroot00000000000000package wordwrap import ( "strings" "testing" ) func TestWrapString(t *testing.T) { cases := []struct { Input, Output string Lim uint }{ // A simple word passes through. { "foo", "foo", 4, }, // A single word that is too long passes through. // We do not break words. { "foobarbaz", "foobarbaz", 4, }, // Lines are broken at whitespace. { "foo bar baz", "foo\nbar\nbaz", 4, }, // Lines are broken at whitespace, even if words // are too long. We do not break words. { "foo bars bazzes", "foo\nbars\nbazzes", 4, }, // A word that would run beyond the width is wrapped. { "fo sop", "fo\nsop", 4, }, // Do not break on non-breaking space. { "foo bar\u00A0baz", "foo\nbar\u00A0baz", 10, }, // Whitespace that trails a line and fits the width // passes through, as does whitespace prefixing an // explicit line break. A tab counts as one character. { "foo\nb\t r\n baz", "foo\nb\t r\n baz", 4, }, // Trailing whitespace is removed if it doesn't fit the width. // Runs of whitespace on which a line is broken are removed. { "foo \nb ar ", "foo\nb\nar", 4, }, // An explicit line break at the end of the input is preserved. { "foo bar baz\n", "foo\nbar\nbaz\n", 4, }, // Explicit break are always preserved. { "\nfoo bar\n\n\nbaz\n", "\nfoo\nbar\n\n\nbaz\n", 4, }, // Complete example: { " This is a list: \n\n\t* foo\n\t* bar\n\n\n\t* baz \nBAM ", " This\nis a\nlist: \n\n\t* foo\n\t* bar\n\n\n\t* baz\nBAM", 6, }, // Multi-byte characters { strings.Repeat("\u2584 ", 4), "\u2584 \u2584" + "\n" + strings.Repeat("\u2584 ", 2), 4, }, } for i, tc := range cases { actual := WrapString(tc.Input, tc.Lim) if actual != tc.Output { t.Fatalf("Case %d Input:\n\n`%s`\n\nExpected Output:\n\n`%s`\n\nActual Output:\n\n`%s`", i, tc.Input, tc.Output, actual) } } }