diff --git a/columnize.go b/columnize.go index 4925ddf..915716a 100644 --- a/columnize.go +++ b/columnize.go @@ -97,6 +97,15 @@ func elementsFromLine(config *Config, line string) []interface{} { return elements } +// runeLen calculates the number of visible "characters" in a string +func runeLen(s string) int { + l := 0 + for _ = range s { + l++ + } + return l +} + // widthsFromLines examines a list of strings and determines how wide each // column should be considering all of the elements that need to be printed // within it. @@ -106,7 +115,7 @@ func widthsFromLines(config *Config, lines []string) []int { for _, line := range lines { elems := elementsFromLine(config, line) for i := 0; i < len(elems); i++ { - l := len(elems[i].(string)) + l := runeLen(elems[i].(string)) if len(widths) <= i { widths = append(widths, l) } else if widths[i] < l { diff --git a/columnize_test.go b/columnize_test.go index 493e61e..89dabaa 100644 --- a/columnize_test.go +++ b/columnize_test.go @@ -75,7 +75,30 @@ func TestColumnWidthCalculator(t *testing.T) { expected += "short short short" if output != expected { - t.Fatalf("\nexpected:\n%s\n\ngot:\n%s", expected, output) + printableProof := fmt.Sprintf("\nGot: %+q", output) + printableProof += fmt.Sprintf("\nExpected: %+q", expected) + t.Fatalf("\n%s", printableProof) + } +} + +func TestColumnWidthCalculatorNonASCII(t *testing.T) { + input := []string{ + "Column A | Column B | Column C", + "⌘⌘⌘⌘⌘⌘⌘⌘ | Longer than B | Longer than C", + "short | short | short", + } + + config := DefaultConfig() + output := Format(input, config) + + expected := "Column A Column B Column C\n" + expected += "⌘⌘⌘⌘⌘⌘⌘⌘ Longer than B Longer than C\n" + expected += "short short short" + + if output != expected { + printableProof := fmt.Sprintf("\nGot: %+q", output) + printableProof += fmt.Sprintf("\nExpected: %+q", expected) + t.Fatalf("\n%s", printableProof) } }