From a2c97a0d32b67739e89f524e91ed2ee8da95f948 Mon Sep 17 00:00:00 2001 From: kobtea Date: Mon, 20 Feb 2017 23:15:39 +0900 Subject: [PATCH] use self table renderer --- cmd/todoist/cmd/today.go | 20 +++++---------- cmd/util/format.go | 53 ++++++++++++++++++++++++++++++++++++++++ todoist/time.go | 14 ++++++++++- 3 files changed, 72 insertions(+), 15 deletions(-) create mode 100644 cmd/util/format.go diff --git a/cmd/todoist/cmd/today.go b/cmd/todoist/cmd/today.go index 4bd8b7e..bd0d42b 100644 --- a/cmd/todoist/cmd/today.go +++ b/cmd/todoist/cmd/today.go @@ -1,11 +1,10 @@ package cmd import ( - "github.com/fatih/color" + "fmt" + "github.com/kobtea/go-todoist/cmd/util" "github.com/kobtea/go-todoist/todoist" - "github.com/olekukonko/tablewriter" "github.com/spf13/cobra" - "os" "sort" "strconv" "strings" @@ -24,9 +23,7 @@ var todayCmd = &cobra.Command{ sort.Slice(items, func(i, j int) bool { return items[i].DueDateUtc.Before(items[j].DueDateUtc) }) - table := tablewriter.NewWriter(os.Stdout) - table.SetHeader([]string{"id", "date", "pri", "project", "labels", "content"}) - table.SetBorders(tablewriter.Border{Left: false, Top: false, Right: false, Bottom: false}) + var rows [][]string for _, i := range items { var project string if p := client.Project.Resolve(i.ProjectID); p != nil { @@ -38,21 +35,16 @@ var todayCmd = &cobra.Command{ labels = append(labels, j.String()) } } - date := i.DateString - if i.IsOverDueDate() { - date = color.New(color.BgRed).SprintFunc()(date) - } - table.Append([]string{ + rows = append(rows, []string{ i.ID.String(), - date, + i.DueDateUtc.Local().ColorShortString(), strconv.Itoa(i.Priority), project, strings.Join(labels, " "), i.Content, }) - } - table.Render() + fmt.Println(util.TableString(rows)) return nil }, } diff --git a/cmd/util/format.go b/cmd/util/format.go new file mode 100644 index 0000000..84cb549 --- /dev/null +++ b/cmd/util/format.go @@ -0,0 +1,53 @@ +package util + +import ( + "github.com/mattn/go-runewidth" + "regexp" + "strconv" +) + +func StringWidthWithoutColor(s string) int { + re := regexp.MustCompile("\x1b\\[[0-9;]*m") + return runewidth.StringWidth(re.ReplaceAllString(s, "")) +} + +func TableString(rows [][]string) string { + if len(rows) == 0 { + return "" + } + min := len(rows[0]) + for _, i := range rows { + if len(i) < min { + min = len(i) + } + } + // retrieve max width in each columns + lens := make([]int, min) + for _, ss := range rows { + for i := 0; i < len(lens); i++ { + // FIXME: regex may be slow + l := StringWidthWithoutColor(ss[i]) + if l > lens[i] { + lens[i] = l + } + } + } + // format rows into table + var res string + for i := 0; i < len(rows); i++ { + for j := 0; j < len(lens); j++ { + f := runewidth.FillRight + if _, err := strconv.Atoi(rows[i][j]); err == nil { + f = runewidth.FillLeft + } + res += f(rows[i][j], lens[j]) + if j < len(lens)-1 { + res += " " + } + } + if i < len(rows)-1 { + res += "\n" + } + } + return res +} diff --git a/todoist/time.go b/todoist/time.go index af9d992..3c4b867 100644 --- a/todoist/time.go +++ b/todoist/time.go @@ -1,6 +1,7 @@ package todoist import ( + "github.com/fatih/color" "strconv" "time" ) @@ -44,6 +45,10 @@ func (t Time) After(u Time) bool { return t.Time.After(u.Time) } +func (t Time) Local() Time { + return Time{t.Time.Local()} +} + func (t Time) MarshalJSON() ([]byte, error) { if t.IsZero() { return []byte("null"), nil @@ -64,9 +69,16 @@ func (t *Time) UnmarshalJSON(b []byte) (err error) { return nil } -func (t *Time) ShortString() string { +func (t Time) ShortString() string { if t.IsZero() { return "" } return t.Time.Local().Format(shortLayout) } + +func (t Time) ColorShortString() string { + if !t.IsZero() && t.Before(Time{time.Now()}) { + return color.New(color.BgRed).Sprint(t.ShortString()) + } + return t.ShortString() +}