diff options
| author | Dave Henderson <dhenderson@gmail.com> | 2019-02-17 14:54:28 -0500 |
|---|---|---|
| committer | Dave Henderson <dhenderson@gmail.com> | 2019-02-17 16:20:41 -0500 |
| commit | 2065fe0d4818515300dadd63bf70ee7629f8e91b (patch) | |
| tree | 09d55085da86d2e535662c3746b55c31985a4f2f /strings | |
| parent | a9b3f9390642d3f361f64528073e3199a116222a (diff) | |
New strings.WordWrap function
Signed-off-by: Dave Henderson <dhenderson@gmail.com>
Diffstat (limited to 'strings')
| -rw-r--r-- | strings/strings.go | 29 | ||||
| -rw-r--r-- | strings/strings_test.go | 61 |
2 files changed, 90 insertions, 0 deletions
diff --git a/strings/strings.go b/strings/strings.go index 8c10865a..c9b029fc 100644 --- a/strings/strings.go +++ b/strings/strings.go @@ -4,6 +4,8 @@ import ( "regexp" "sort" "strings" + + "github.com/Masterminds/goutils" ) // Indent - indent each line of the string with the given indent string @@ -81,3 +83,30 @@ func CamelCase(in string) string { s = strings.Replace(s, string(s[0]), string(in[0]), 1) return nonAlphaNum.ReplaceAllString(s, "") } + +// WordWrapOpts defines the options to apply to the WordWrap function +type WordWrapOpts struct { + // The desired maximum line length in characters (defaults to 80) + Width uint + + // Line-break sequence to insert (defaults to "\n") + LBSeq string +} + +// applies default options +func wwDefaults(opts WordWrapOpts) WordWrapOpts { + if opts.Width == 0 { + opts.Width = 80 + } + if opts.LBSeq == "" { + opts.LBSeq = "\n" + } + return opts +} + +// WordWrap - insert line-breaks into the string, before it reaches the given +// width. +func WordWrap(in string, opts WordWrapOpts) string { + opts = wwDefaults(opts) + return goutils.WrapCustom(in, int(opts.Width), opts.LBSeq, false) +} diff --git a/strings/strings_test.go b/strings/strings_test.go index dfcee552..d0c6ed62 100644 --- a/strings/strings_test.go +++ b/strings/strings_test.go @@ -1,6 +1,7 @@ package strings import ( + "strings" "testing" "github.com/stretchr/testify/assert" @@ -54,3 +55,63 @@ func TestCaseFuncs(t *testing.T) { assert.Equal(t, d.c, CamelCase(d.in)) } } + +func TestWordWrap(t *testing.T) { + in := "a short line that needs no wrapping" + assert.Equal(t, in, WordWrap(in, WordWrapOpts{Width: 40})) + + in = "a short line that needs wrapping" + out := `a short +line that +needs +wrapping` + + assert.Equal(t, out, WordWrap(in, WordWrapOpts{Width: 9})) + in = "a short line that needs wrapping" + out = `a short \ +line that \ +needs \ +wrapping` + assert.Equal(t, out, WordWrap(in, WordWrapOpts{Width: 9, LBSeq: " \\\n"})) + + out = `There shouldn't be any wrapping of long words or URLs because that would break +things very badly. To wit: +https://example.com/a/super-long/url/that-shouldnt-be?wrapped=for+fear+of#the-breaking-of-functionality +should appear on its own line, regardless of the desired word-wrapping width +that has been set.` + in = strings.Replace(out, "\n", " ", -1) + assert.Equal(t, out, WordWrap(in, WordWrapOpts{})) + + // TODO: get these working - need to switch to a word-wrapping package that + // can handle multi-byte characters! + // + // out = `ΤΟΙΣ πᾶσι χρόνος καὶ καιρὸς τῷ παντὶ πράγματι ὑπὸ τὸν οὐρανόν. καιρὸς τοῦ + // τεκεῖν καὶ καιρὸς τοῦ ἀποθανεῖν, καιρὸς τοῦ φυτεῦσαι καὶ καιρὸς τοῦ ἐκτῖλαι τὸ + // πεφυτευμένον, καιρὸς τοῦ ἀποκτεῖναι καὶ καιρὸς τοῦ ἰάσασθαι, καιρὸς τοῦ + // καθελεῖν καὶ καιρὸς τοῦ οἰκοδομεῖν, καιρὸς τοῦ κλαῦσαι καὶ καιρὸς τοῦ γελάσαι, + // καιρὸς τοῦ κόψασθαι καὶ καιρὸς τοῦ ὀρχήσασθαι, καιρὸς τοῦ βαλεῖν λίθους καὶ + // καιρὸς τοῦ συναγαγεῖν λίθους, καιρὸς τοῦ περιλαβεῖν καὶ καιρὸς τοῦ μακρυνθῆναι + // ἀπὸ περιλήψεως, καιρὸς τοῦ ζητῆσαι καὶ καιρὸς τοῦ ἀπολέσαι, καιρὸς τοῦ φυλάξαι + // καὶ καιρὸς τοῦ ἐκβαλεῖν, καιρὸς τοῦ ρῆξαι καὶ καιρὸς τοῦ ράψαι, καιρὸς τοῦ + // σιγᾶν καὶ καιρὸς τοῦ λαλεῖν, καιρὸς τοῦ φιλῆσαι καὶ καιρὸς τοῦ μισῆσαι, καιρὸς + // πολέμου καὶ καιρὸς εἰρήνης.` + // in = strings.Replace(out, "\n", " ", -1) + // assert.Equal(t, out, WordWrap(in, WordWrapOpts{})) + + // TODO: get these working - need to switch to a word-wrapping package that + // understands multi-byte and correctly identifies line-breaking opportunities + // for non-latin languages. + // + // out = `何事にも定まった時があります。 + // 生まれる時、死ぬ時、植える時、収穫の時、 + // 殺す時、病気が治る時、壊す時、やり直す時、 + // 泣く時、笑う時、悲しむ時、踊る時、 + // 石をばらまく時、石をかき集める時、 + // 抱きしめる時、抱きしめない時、 + // 何かを見つける時、物を失う時、 + // 大切にしまっておく時、遠くに投げ捨てる時、 + // 引き裂く時、修理する時、黙っている時、口を開く時、 + // 愛する時、憎む時、戦う時、和解する時。` + // in = strings.Replace(out, "\n", " ", -1) + // assert.Equal(t, out, WordWrap(in, WordWrapOpts{Width: 100})) +} |
