From fb2130518c964f869b782cb298297e443034dc53 Mon Sep 17 00:00:00 2001 From: asdf Date: Wed, 4 Sep 2019 22:57:26 +1000 Subject: [PATCH 1/7] first attempt on line wrapping indents issue --- cui/cui.go | 16 ++++++++++++---- cui/cui_test.go | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 cui/cui_test.go diff --git a/cui/cui.go b/cui/cui.go index f02ba14..a784ce7 100644 --- a/cui/cui.go +++ b/cui/cui.go @@ -81,17 +81,25 @@ func Clear(dir string) { } -func wrapLines(s []string, length int) []string { +// takes the document content (as a slice) and modifies any lines that are longer +// than the specified console width, splitting them over two lines. returns the +// amended document content as a slice. +func wrapLines(s []string, consolewidth int) []string { + indent := " " //11 spaces out := []string{} for _, ln := range s { - if len(ln) <= length { + if len(ln) <= consolewidth { out = append(out, ln) } else { words := strings.Split(ln, " ") var subout bytes.Buffer for i, wd := range words { sublen := subout.Len() - if sublen+len(wd)+1 <= length { + if sublen+len(wd)+1 <= consolewidth { + //if line was indented, reinsert indent + if i == 11 && sublen == 0 { + subout.WriteString(indent) + } if sublen > 0 { subout.WriteString(" ") } @@ -102,7 +110,7 @@ func wrapLines(s []string, length int) []string { } else { out = append(out, subout.String()) subout.Reset() - subout.WriteString(wd) + subout.WriteString(indent + wd) if i == len(words)-1 { out = append(out, subout.String()) subout.Reset() diff --git a/cui/cui_test.go b/cui/cui_test.go new file mode 100644 index 0000000..755fa02 --- /dev/null +++ b/cui/cui_test.go @@ -0,0 +1,36 @@ +package cui + +import ( + "reflect" + "testing" +) + +func Test_wrapLines_doesnt_break_indents(t *testing.T) { + indent := " " + tables := []struct { + testinput []string + expectedoutput []string + linelength int + }{ + { + //20 character input - should not wrap + []string{indent + "012345678"}, + []string{indent + "012345678"}, + 20, + }, + { + //21 character input - should wrap + []string{indent + "0123456789"}, + []string{indent + "0123456789"}, + 20, + }, + } + + for _, table := range tables { + output := wrapLines(table.testinput, table.linelength) + + if !reflect.DeepEqual(output, table.expectedoutput) { + t.Errorf("Expected %v, got %v", table.expectedoutput, output) + } + } +} From 319138b189c084f226b5ce3b6359392fe44031c5 Mon Sep 17 00:00:00 2001 From: asdf Date: Thu, 5 Sep 2019 10:48:47 +1000 Subject: [PATCH 2/7] Addtional test for benchmarking the wrapLines() function --- cui/cui_test.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/cui/cui_test.go b/cui/cui_test.go index 755fa02..0c3f198 100644 --- a/cui/cui_test.go +++ b/cui/cui_test.go @@ -34,3 +34,16 @@ func Test_wrapLines_doesnt_break_indents(t *testing.T) { } } } + +func Benchmark_wrapLines(b *testing.B) { + indent := " " + teststring := []string{ + indent + "0123456789\n", + indent + "a really long line that will prolly be wrapped\n", + indent + "a l i n e w i t h a l o t o f w o r d s\n", + } + b.ResetTimer() + for n := 0; n < b.N; n++ { + wrapLines(teststring, 20) + } +} From be34a9a809042618cf06903de971b5fabcab365d Mon Sep 17 00:00:00 2001 From: asdf Date: Thu, 5 Sep 2019 21:52:12 +1000 Subject: [PATCH 3/7] identified more issues, added tests --- cui/cui_test.go | 73 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 70 insertions(+), 3 deletions(-) diff --git a/cui/cui_test.go b/cui/cui_test.go index 0c3f198..dc719ae 100644 --- a/cui/cui_test.go +++ b/cui/cui_test.go @@ -13,17 +13,84 @@ func Test_wrapLines_doesnt_break_indents(t *testing.T) { linelength int }{ { - //20 character input - should not wrap + //indented long word - 20 characters - should not wrap []string{indent + "012345678"}, []string{indent + "012345678"}, 20, }, { - //21 character input - should wrap - []string{indent + "0123456789"}, + //indented long word - 21 characters - should wrap []string{indent + "0123456789"}, + []string{indent + "012345678", indent + "9"}, 20, }, + { + //indented really long word - should wrap + []string{indent + "0123456789zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"}, + []string{ + indent + "012345678", + indent + "9zzzzzzzz", + indent + "zzzzzzzzz", + indent + "zzzzzzzzz", + indent + "zzzzz"}, + 20, + }, { + //non-indented long word - 20 characters - should not wrap + []string{"01234567890123456789"}, + []string{"01234567890123456789"}, + 20, + }, + { + //non-indented long word - 21 characters - should wrap + []string{"01234567890123456789a"}, + []string{"01234567890123456789", "a"}, + 20, + }, + { + //non-indented really long word - should wrap + []string{"01234567890123456789zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"}, + []string{ + "01234567890123456789", + "zzzzzzzzzzzzzzzzzzzz", + "zzzzzzzzzzzzzzzzzzzz", + "zzzzzzzzzzzzzzzzzzzz", + "zzzz"}, + 20, + }, + { + //indented normal sentence - 20 characters - should not wrap + []string{indent + "it is her"}, + []string{indent + "it is her"}, + 20, + }, + { + //indented normal sentence - more than 20 characters - should wrap + []string{indent + "it is her favourite thing in the world"}, + []string{ + indent + "it is her", + indent + "favourite", + indent + "thing in", + indent + "the world", + }, + 20, + }, + { + //non-indented normal sentence - 20 characters - should not wrap + []string{"it is her fav thingy"}, + []string{"it is her fav thingy"}, + 20, + }, + { + //non-indented normal sentence - more than 20 characters - should wrap + []string{"it is her favourite thing in the world"}, + []string{ + "it is her favourite", + "thing in the world", + }, + 20, + }, + //TODO further tests + //lines that are just spaces don't get misidentified as indents and then mangled } for _, table := range tables { From a9d5651e3c06187cbc8efa6f41fb2816b690683b Mon Sep 17 00:00:00 2001 From: asdf Date: Fri, 6 Sep 2019 20:18:03 +1000 Subject: [PATCH 4/7] added test for a specific line wrapping issue --- cui/cui_test.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/cui/cui_test.go b/cui/cui_test.go index dc719ae..f5c5294 100644 --- a/cui/cui_test.go +++ b/cui/cui_test.go @@ -89,6 +89,19 @@ func Test_wrapLines_doesnt_break_indents(t *testing.T) { }, 20, }, + { + //a specific test from cat's phlog that was wrapping and I'm not sure why + []string{ + " Suldusk – Really cool dark folk/black metal sort of deal. The lead singer", + "is a tiny fairy of a person and she's very charming. It's the bass players", + }, + []string{ + " Suldusk – Really cool dark folk/black metal sort of deal. The lead singer", + "is a tiny fairy of a person and she's very charming. It's the bass players", + }, + 80, + }, + //TODO further tests //lines that are just spaces don't get misidentified as indents and then mangled } From 3e8587f039ec5476799b36b20eb07b36c2f02117 Mon Sep 17 00:00:00 2001 From: asdf Date: Sat, 7 Sep 2019 23:04:20 +1000 Subject: [PATCH 5/7] using strings.SplitAfter in wrapLines --- cui/cui.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/cui/cui.go b/cui/cui.go index a784ce7..f357343 100644 --- a/cui/cui.go +++ b/cui/cui.go @@ -85,23 +85,23 @@ func Clear(dir string) { // than the specified console width, splitting them over two lines. returns the // amended document content as a slice. func wrapLines(s []string, consolewidth int) []string { - indent := " " //11 spaces + //indent := " " //11 spaces out := []string{} for _, ln := range s { if len(ln) <= consolewidth { out = append(out, ln) } else { - words := strings.Split(ln, " ") + words := strings.SplitAfter(ln, " ") var subout bytes.Buffer for i, wd := range words { sublen := subout.Len() if sublen+len(wd)+1 <= consolewidth { //if line was indented, reinsert indent if i == 11 && sublen == 0 { - subout.WriteString(indent) + //subout.WriteString(indent) } if sublen > 0 { - subout.WriteString(" ") + //subout.WriteString(" ") } subout.WriteString(wd) if i == len(words)-1 { @@ -110,7 +110,8 @@ func wrapLines(s []string, consolewidth int) []string { } else { out = append(out, subout.String()) subout.Reset() - subout.WriteString(indent + wd) + //subout.WriteString(indent) + subout.WriteString(wd) if i == len(words)-1 { out = append(out, subout.String()) subout.Reset() From ea096af5114314e0cdd7f6c5cdca63935a1b5b89 Mon Sep 17 00:00:00 2001 From: asdf Date: Tue, 10 Sep 2019 20:19:45 +1000 Subject: [PATCH 6/7] simple line wrapping that does not mangle spaces --- cui/cui.go | 13 ++------ cui/cui_test.go | 87 +++++++------------------------------------------ 2 files changed, 15 insertions(+), 85 deletions(-) diff --git a/cui/cui.go b/cui/cui.go index f357343..67d8b3a 100644 --- a/cui/cui.go +++ b/cui/cui.go @@ -84,8 +84,8 @@ func Clear(dir string) { // takes the document content (as a slice) and modifies any lines that are longer // than the specified console width, splitting them over two lines. returns the // amended document content as a slice. +// word wrapping uses a "greedy" algorithm func wrapLines(s []string, consolewidth int) []string { - //indent := " " //11 spaces out := []string{} for _, ln := range s { if len(ln) <= consolewidth { @@ -95,14 +95,8 @@ func wrapLines(s []string, consolewidth int) []string { var subout bytes.Buffer for i, wd := range words { sublen := subout.Len() - if sublen+len(wd)+1 <= consolewidth { - //if line was indented, reinsert indent - if i == 11 && sublen == 0 { - //subout.WriteString(indent) - } - if sublen > 0 { - //subout.WriteString(" ") - } + wdlen := len(wd) + if sublen+wdlen <= consolewidth { subout.WriteString(wd) if i == len(words)-1 { out = append(out, subout.String()) @@ -110,7 +104,6 @@ func wrapLines(s []string, consolewidth int) []string { } else { out = append(out, subout.String()) subout.Reset() - //subout.WriteString(indent) subout.WriteString(wd) if i == len(words)-1 { out = append(out, subout.String()) diff --git a/cui/cui_test.go b/cui/cui_test.go index f5c5294..5c30169 100644 --- a/cui/cui_test.go +++ b/cui/cui_test.go @@ -5,92 +5,32 @@ import ( "testing" ) -func Test_wrapLines_doesnt_break_indents(t *testing.T) { - indent := " " +// tests related to issue 31 +func Test_wrapLines_space_preservation(t *testing.T) { tables := []struct { testinput []string expectedoutput []string linelength int }{ { - //indented long word - 20 characters - should not wrap - []string{indent + "012345678"}, - []string{indent + "012345678"}, - 20, - }, - { - //indented long word - 21 characters - should wrap - []string{indent + "0123456789"}, - []string{indent + "012345678", indent + "9"}, - 20, - }, - { - //indented really long word - should wrap - []string{indent + "0123456789zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"}, - []string{ - indent + "012345678", - indent + "9zzzzzzzz", - indent + "zzzzzzzzz", - indent + "zzzzzzzzz", - indent + "zzzzz"}, - 20, - }, { - //non-indented long word - 20 characters - should not wrap - []string{"01234567890123456789"}, - []string{"01234567890123456789"}, - 20, - }, - { - //non-indented long word - 21 characters - should wrap - []string{"01234567890123456789a"}, - []string{"01234567890123456789", "a"}, - 20, - }, - { - //non-indented really long word - should wrap - []string{"01234567890123456789zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"}, - []string{ - "01234567890123456789", - "zzzzzzzzzzzzzzzzzzzz", - "zzzzzzzzzzzzzzzzzzzz", - "zzzzzzzzzzzzzzzzzzzz", - "zzzz"}, - 20, - }, - { - //indented normal sentence - 20 characters - should not wrap - []string{indent + "it is her"}, - []string{indent + "it is her"}, - 20, - }, - { - //indented normal sentence - more than 20 characters - should wrap - []string{indent + "it is her favourite thing in the world"}, - []string{ - indent + "it is her", - indent + "favourite", - indent + "thing in", - indent + "the world", - }, - 20, - }, - { - //non-indented normal sentence - 20 characters - should not wrap + //normal sentence - 20 characters - should not wrap []string{"it is her fav thingy"}, []string{"it is her fav thingy"}, 20, }, { - //non-indented normal sentence - more than 20 characters - should wrap + //normal sentence - more than 20 characters - should wrap with a space at the end of the first line []string{"it is her favourite thing in the world"}, []string{ - "it is her favourite", + "it is her favourite ", "thing in the world", }, 20, }, { - //a specific test from cat's phlog that was wrapping and I'm not sure why + // a specific test from cat's phlog (gopher://baud.baby:70/0/phlog/fs20190818.txt) + // I think the – character U+2013 : EN DASH characteris causing wrapping incorrectly + // but the test passes and i'm not sure why []string{ " Suldusk – Really cool dark folk/black metal sort of deal. The lead singer", "is a tiny fairy of a person and she's very charming. It's the bass players", @@ -101,9 +41,6 @@ func Test_wrapLines_doesnt_break_indents(t *testing.T) { }, 80, }, - - //TODO further tests - //lines that are just spaces don't get misidentified as indents and then mangled } for _, table := range tables { @@ -116,11 +53,11 @@ func Test_wrapLines_doesnt_break_indents(t *testing.T) { } func Benchmark_wrapLines(b *testing.B) { - indent := " " teststring := []string{ - indent + "0123456789\n", - indent + "a really long line that will prolly be wrapped\n", - indent + "a l i n e w i t h a l o t o f w o r d s\n", + "0123456789", + "a really long line that will prolly be wrapped", + "a l i n e w i t h a l o t o f w o r d s", + "onehugelongwordaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", } b.ResetTimer() for n := 0; n < b.N; n++ { From 089482756340f4639883c555b63b42c916b304fd Mon Sep 17 00:00:00 2001 From: asdf Date: Tue, 10 Sep 2019 20:24:16 +1000 Subject: [PATCH 7/7] simple line wrapping and associated unit tests --- cui/cui_test.go | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/cui/cui_test.go b/cui/cui_test.go index 5c30169..1a286d3 100644 --- a/cui/cui_test.go +++ b/cui/cui_test.go @@ -27,20 +27,6 @@ func Test_wrapLines_space_preservation(t *testing.T) { }, 20, }, - { - // a specific test from cat's phlog (gopher://baud.baby:70/0/phlog/fs20190818.txt) - // I think the – character U+2013 : EN DASH characteris causing wrapping incorrectly - // but the test passes and i'm not sure why - []string{ - " Suldusk – Really cool dark folk/black metal sort of deal. The lead singer", - "is a tiny fairy of a person and she's very charming. It's the bass players", - }, - []string{ - " Suldusk – Really cool dark folk/black metal sort of deal. The lead singer", - "is a tiny fairy of a person and she's very charming. It's the bass players", - }, - 80, - }, } for _, table := range tables {