From be428e899707fcdcf2a5311b93dfd203d982bee8 Mon Sep 17 00:00:00 2001 From: Yanjun Shi Date: Mon, 26 Aug 2019 15:24:02 +0800 Subject: [PATCH] WIP: Fix mess up the table output when words are not English (#120) * Fix mess up the table output when words are not English * Fix mess up the table when words are other language and add util testing * remove surplus commit file * Restore test file pluginManager_test.go * add util testing and update some function * Fix the test cases * Fix util test question --- util/padding.go | 75 +++++++++++++++++++++++++++-- util/padding_test.go | 93 ++++++++++++++++++++++++++++++++++++ util/table.go | 2 +- util/table_test.go | 109 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 275 insertions(+), 4 deletions(-) create mode 100644 util/padding_test.go create mode 100644 util/table_test.go diff --git a/util/padding.go b/util/padding.go index 3043a73..0421985 100644 --- a/util/padding.go +++ b/util/padding.go @@ -3,6 +3,7 @@ package util import ( "math" "strings" + "unicode" "unicode/utf8" ) @@ -24,7 +25,7 @@ func Pad(s, pad string, width int, align int) string { } func PadRight(s, pad string, width int) string { - gap := width - utf8.RuneCountInString(s) + gap := widthValue(s, width) if gap > 0 { return s + strings.Repeat(string(pad), gap) } @@ -32,7 +33,7 @@ func PadRight(s, pad string, width int) string { } func PadLeft(s, pad string, width int) string { - gap := width - utf8.RuneCountInString(s) + gap := widthValue(s, width) if gap > 0 { return strings.Repeat(string(pad), gap) + s } @@ -40,7 +41,7 @@ func PadLeft(s, pad string, width int) string { } func PadCenter(s, pad string, width int) string { - gap := width - utf8.RuneCountInString(s) + gap := widthValue(s, width) if gap > 0 { gapLeft := int(math.Ceil(float64(gap / 2))) gapRight := gap - gapLeft @@ -48,3 +49,71 @@ func PadCenter(s, pad string, width int) string { } return s } + +func isHan(s string) (isHan bool) { + wh := []rune(s) + for _, r := range wh { + if unicode.Is(unicode.Han, r) { + isHan = true + } else if unicode.Is(unicode.Hiragana, r) { + isHan = true + } else if unicode.Is(unicode.Katakana, r) { + isHan = true + } else if unicode.Is(unicode.Common, r) { + isHan = true + } else { + isHan = false + break + } + } + return +} + +func countCN(s string) (count int) { + wh := []rune(s) + for _, r := range wh { + if unicode.Is(unicode.Han, r) { + count++ + } else if unicode.Is(unicode.Hiragana, r) { + count++ + } else if unicode.Is(unicode.Katakana, r) { + count++ + } else if unicode.Is(unicode.Common, r) && len(string(r)) != 1 { + count++ + } + } + return +} + +func widthValue(s string, width int) (gap int) { + l := utf8.RuneCountInString(s) + ln := len(s) + isHan := isHan(s) + count := countCN(s) + if ln != l { + if isHan { + gap = width - (ln - l) + } else { + gap = width - (ln - count) + } + } else { + gap = width - l + } + return +} + +func Lenf(han string) (l int) { + ln := len(han) + l = utf8.RuneCountInString(han) + isHan := isHan(han) + count := countCN(han) + if ln != l { + if isHan { + l = ln - l + } else { + l = ln - count + } + + } + return +} diff --git a/util/padding_test.go b/util/padding_test.go new file mode 100644 index 0000000..fed1822 --- /dev/null +++ b/util/padding_test.go @@ -0,0 +1,93 @@ +package util + +import ( + "github.com/golang/mock/gomock" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = Describe("Padding util test", func() { + var ( + ctrl *gomock.Controller + ) + + BeforeEach(func() { + ctrl = gomock.NewController(GinkgoT()) + }) + + AfterEach(func() { + ctrl.Finish() + }) + + Context("isHan test", func() { + var han string + It("english test", func() { + han = "ZSOMZAYNHG" + Expect(isHan(han)).To(Equal(false)) + }) + It("chinese test", func() { + han = "构建一个自由风格的软件项目" + Expect(isHan(han)).To(Equal(true)) + }) + It("hk test", func() { + han = "建置 Free-Style 軟體專案" + Expect(isHan(han)).To(Equal(false)) + }) + It("japanese test", func() { + han = "フリースタイル・プロジェクトのビルド" + Expect(isHan(han)).To(Equal(true)) + }) + It("japanese and chinese and english test", func() { + han = "フリースタイル・プ中ロジasdェクトのビルド" + Expect(isHan(han)).To(Equal(false)) + }) + }) + + Context("countCN test", func() { + var han string + It("english test", func() { + han = "ZSOMZAYNHG" + Expect(countCN(han)).To(Equal(0)) + }) + It("chinese test", func() { + han = "构建一个自由风格的软件项目" + Expect(countCN(han)).To(Equal(13)) + }) + It("hk test", func() { + han = "建置 Free-Style 軟體專案" + Expect(countCN(han)).To(Equal(6)) + }) + It("japanese test", func() { + han = "フリースタイル・プロジェクトのビルド" + Expect(countCN(han)).To(Equal(18)) + }) + It("japanese and chinese and english test", func() { + han = "フリースタイル・プ中ロジasdェクトのビルド" + Expect(countCN(han)).To(Equal(19)) + }) + }) + + Context("Lenf test", func() { + var han string + It("english test", func() { + han = "ZSOMZAYNHG" + Expect(Lenf(han) == len(han)).To(Equal(true)) + }) + It("chinese test", func() { + han = "构建一个自由风格的软件项目" + Expect(Lenf(han) == len(han)).To(Equal(false)) + }) + It("hk test", func() { + han = "建置 Free-Style 軟體專案" + Expect(Lenf(han) == len(han)).To(Equal(false)) + }) + It("japanese test", func() { + han = "フリースタイル・プロジェクトのビルド" + Expect(Lenf(han) == len(han)).To(Equal(false)) + }) + It("japanese and chinese and english test", func() { + han = "フリースタイル・プ中ロジasdェクトのビルド" + Expect(Lenf(han) == len(han)).To(Equal(false)) + }) + }) +}) diff --git a/util/table.go b/util/table.go index 1f6c97f..e120adf 100644 --- a/util/table.go +++ b/util/table.go @@ -38,7 +38,7 @@ func (t *Table) Render() { l := utf8.RuneCountInString(col) t.ColumnWidths = ensureArrayCanContain(t.ColumnWidths, ci) if l > t.ColumnWidths[ci] { - t.ColumnWidths[ci] = l + t.ColumnWidths[ci] = Lenf(col) } } } diff --git a/util/table_test.go b/util/table_test.go new file mode 100644 index 0000000..1e89f2e --- /dev/null +++ b/util/table_test.go @@ -0,0 +1,109 @@ +package util + +import ( + "bytes" + + "github.com/golang/mock/gomock" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = Describe("Table util test", func() { + var ( + ctrl *gomock.Controller + ) + + BeforeEach(func() { + ctrl = gomock.NewController(GinkgoT()) + }) + + AfterEach(func() { + ctrl.Finish() + }) + + Context("basic test", func() { + It("english test", func() { + var buffer bytes.Buffer + table := CreateTable(&buffer) + table.AddRow("number", "name", "type") + table.AddRow("0", "Freestyle project", "Standalone Projects") + table.AddRow("1", "Maven project", "Standalone Projects") + table.AddRow("2", "Pipeline", "Standalone Projects") + table.AddRow("3", "External Job", "Standalone Projects") + table.AddRow("4", "Multi-configuration project", "Standalone Projects") + table.AddRow("0", "Bitbucket Team/Project", "Nested Projects") + table.AddRow("1", "Folder", "Nested Projects") + table.AddRow("2", "GitHub Organization", "Nested Projects") + table.AddRow("3", "Multibranch Pipeline", "Nested Projects") + table.Render() + comp := string(`number name type +0 Freestyle project Standalone Projects +1 Maven project Standalone Projects +2 Pipeline Standalone Projects +3 External Job Standalone Projects +4 Multi-configuration project Standalone Projects +0 Bitbucket Team/Project Nested Projects +1 Folder Nested Projects +2 GitHub Organization Nested Projects +3 Multibranch Pipeline Nested Projects`) + comp = comp + "\n" + Expect(buffer.String()).To(Equal(comp)) + }) + + It("chinese test", func() { + var buffer bytes.Buffer + table := CreateTable(&buffer) + table.AddRow("number", "name", "type") + table.AddRow("0", "构建一个自由风格的软件项目", "Standalone Projects") + table.AddRow("1", "构建一个maven项目", "Standalone Projects") + table.AddRow("2", "流水线", "Standalone Projects") + table.AddRow("3", "External Job", "Standalone Projects") + table.AddRow("4", "构建一个多配置项目", "Standalone Projects") + table.AddRow("0", "Bitbucket Team/Project", "Nested Projects") + table.AddRow("1", "文件夹", "Nested Projects") + table.AddRow("2", "GitHub 组织", "Nested Projects") + table.AddRow("3", "多分支流水线", "Nested Projects") + table.Render() + comp := string(`number name type +0 构建一个自由风格的软件项目 Standalone Projects +1 构建一个maven项目 Standalone Projects +2 流水线 Standalone Projects +3 External Job Standalone Projects +4 构建一个多配置项目 Standalone Projects +0 Bitbucket Team/Project Nested Projects +1 文件夹 Nested Projects +2 GitHub 组织 Nested Projects +3 多分支流水线 Nested Projects`) + comp = comp + "\n" + Expect(buffer.String()).To(Equal(comp)) + }) + + It("japanese test", func() { + var buffer bytes.Buffer + table := CreateTable(&buffer) + table.AddRow("number", "name", "type") + table.AddRow("0", "フリースタイル・プロジェクトのビルド", "Standalone Projects") + table.AddRow("1", "Mavenプロジェクトのビルド", "Standalone Projects") + table.AddRow("2", "パイプライン", "Standalone Projects") + table.AddRow("3", "外部ジョブ", "Standalone Projects") + table.AddRow("4", "マルチ構成プロジェクトのビルド", "Standalone Projects") + table.AddRow("0", "Bitbucket Team/Project", "Nested Projects") + table.AddRow("1", "フォルダ", "Nested Projects") + table.AddRow("2", "GitHub Organization", "Nested Projects") + table.AddRow("3", "Multibranch Pipeline", "Nested Projects") + table.Render() + comp := string(`number name type +0 フリースタイル・プロジェクトのビルド Standalone Projects +1 Mavenプロジェクトのビルド Standalone Projects +2 パイプライン Standalone Projects +3 外部ジョブ Standalone Projects +4 マルチ構成プロジェクトのビルド Standalone Projects +0 Bitbucket Team/Project Nested Projects +1 フォルダ Nested Projects +2 GitHub Organization Nested Projects +3 Multibranch Pipeline Nested Projects`) + comp = comp + "\n" + Expect(buffer.String()).To(Equal(comp)) + }) + }) +}) -- GitLab