diff --git a/internal/view/helper.go b/internal/view/helper.go index 3bb8138b..2240463c 100644 --- a/internal/view/helper.go +++ b/internal/view/helper.go @@ -35,6 +35,68 @@ const ( Press 'q' / ESC / CTRL+C to quit.` ) +// ValidIssueColumns returns valid columns for issue list. +func ValidIssueColumns() []string { + return []string{ + fieldType, + fieldKey, + fieldSummary, + fieldStatus, + fieldAssignee, + fieldReporter, + fieldPriority, + fieldResolution, + fieldCreated, + fieldUpdated, + } +} + +// ValidSprintColumns returns valid columns for sprint list. +func ValidSprintColumns() []string { + return []string{ + fieldID, + fieldName, + fieldStartDate, + fieldEndDate, + fieldCompleteDate, + fieldState, + } +} + +// GetPager returns configured pager. +func GetPager() string { + if runtime.GOOS == "windows" { + return "" + } + pager := os.Getenv("PAGER") + if pager == "" { + pager = "less -r" + } + return pager +} + +// PagerOut outputs to configured pager if possible. +func PagerOut(out string) error { + pager := GetPager() + if pager == "" { + _, err := fmt.Print(out) + return err + } + pa := strings.Split(pager, " ") + cmd := exec.Command(pa[0], pa[1:]...) + cmd.Stdin = strings.NewReader(out) + cmd.Stdout = os.Stdout + return cmd.Run() +} + +// MDRenderer constructs markdown renderer. +func MDRenderer() (*glamour.TermRenderer, error) { + return glamour.NewTermRenderer( + glamour.WithAutoStyle(), + glamour.WithWordWrap(wordWrap), + ) +} + func formatDateTime(dt, format string) string { t, err := time.Parse(format, dt) if err != nil { @@ -90,12 +152,12 @@ func renderPlain(w io.Writer, data tui.TableData) error { for _, items := range data { n := len(items) for j, v := range items { - _, _ = fmt.Fprintf(w, "%s", v) + fmt.Fprintf(w, "%s", v) if j != n-1 { - _, _ = fmt.Fprintf(w, "\t") + fmt.Fprintf(w, "\t") } } - _, _ = fmt.Fprintln(w) + fmt.Fprintln(w) } if _, ok := w.(*tabwriter.Writer); ok { @@ -104,65 +166,3 @@ func renderPlain(w io.Writer, data tui.TableData) error { return nil } - -// ValidIssueColumns returns valid columns for issue list. -func ValidIssueColumns() []string { - return []string{ - fieldType, - fieldKey, - fieldSummary, - fieldStatus, - fieldAssignee, - fieldReporter, - fieldPriority, - fieldResolution, - fieldCreated, - fieldUpdated, - } -} - -// ValidSprintColumns returns valid columns for sprint list. -func ValidSprintColumns() []string { - return []string{ - fieldID, - fieldName, - fieldStartDate, - fieldEndDate, - fieldCompleteDate, - fieldState, - } -} - -// GetPager returns configured pager. -func GetPager() string { - if runtime.GOOS == "windows" { - return "" - } - pager := os.Getenv("PAGER") - if pager == "" { - pager = "less -r" - } - return pager -} - -// PagerOut outputs to configured pager if possible. -func PagerOut(out string) error { - pager := GetPager() - if pager == "" { - _, err := fmt.Print(out) - return err - } - pa := strings.Split(pager, " ") - cmd := exec.Command(pa[0], pa[1:]...) - cmd.Stdin = strings.NewReader(out) - cmd.Stdout = os.Stdout - return cmd.Run() -} - -// MDRenderer constructs markdown renderer. -func MDRenderer() (*glamour.TermRenderer, error) { - return glamour.NewTermRenderer( - glamour.WithAutoStyle(), - glamour.WithWordWrap(wordWrap), - ) -} diff --git a/pkg/tui/preview.go b/pkg/tui/preview.go index a9d50861..05ecfe88 100644 --- a/pkg/tui/preview.go +++ b/pkg/tui/preview.go @@ -41,7 +41,9 @@ func NewPreview(opts ...PreviewOption) *Preview { pv := Preview{ screen: NewScreen(), + sidebar: tview.NewTable(), contents: NewTable(), + footer: tview.NewTextView(), contentsCache: make(map[string]interface{}), } for _, opt := range opts { @@ -153,9 +155,9 @@ func (pv *Preview) renderContents(pd PreviewData) { } func (pv *Preview) init() { - pv.initSidebarView() - pv.initContentsView() - pv.initFooterView() + pv.initSidebar() + pv.initContents() + pv.initFooter() pv.painter = tview.NewGrid(). SetRows(0, 1, 2). @@ -170,9 +172,7 @@ func (pv *Preview) init() { pv.initLayout(pv.contents.view) } -func (pv *Preview) initSidebarView() { - pv.sidebar = tview.NewTable() - +func (pv *Preview) initSidebar() { pv.sidebar.SetInputCapture(func(ev *tcell.EventKey) *tcell.EventKey { if ev.Key() == tcell.KeyRune { switch ev.Rune() { @@ -187,51 +187,47 @@ func (pv *Preview) initSidebarView() { }) } -func (pv *Preview) initContentsView() { +func (pv *Preview) initContents() { pv.contents.view. SetBorder(true). - SetBorderColor(tcell.ColorDarkGray) - - pv.contents.view.SetInputCapture(func(ev *tcell.EventKey) *tcell.EventKey { - if ev.Key() == tcell.KeyRune { - switch ev.Rune() { - case 'q': - pv.screen.Stop() - os.Exit(0) - case 'w': - pv.screen.SetFocus(pv.sidebar) - case 'v': - if pv.contents.viewModeFunc != nil { - sr, _ := pv.sidebar.GetSelection() - r, c := pv.contents.view.GetSelection() - contents := pv.contentsCache[pv.data[sr].Key] - - pv.screen.Suspend(func() { _ = pv.contents.viewModeFunc(r, c, contents) }) + SetBorderColor(tcell.ColorDarkGray). + SetInputCapture(func(ev *tcell.EventKey) *tcell.EventKey { + if ev.Key() == tcell.KeyRune { + switch ev.Rune() { + case 'q': + pv.screen.Stop() + os.Exit(0) + case 'w': + pv.screen.SetFocus(pv.sidebar) + case 'v': + if pv.contents.viewModeFunc != nil { + sr, _ := pv.sidebar.GetSelection() + r, c := pv.contents.view.GetSelection() + contents := pv.contentsCache[pv.data[sr].Key] + + pv.screen.Suspend(func() { _ = pv.contents.viewModeFunc(r, c, contents) }) + } } } - } - return ev - }) + return ev + }) } -func (pv *Preview) initFooterView() { - view := tview.NewTextView(). +func (pv *Preview) initFooter() { + pv.footer. SetWordWrap(true). SetText(pad(pv.footerText, 1)). SetTextColor(tcell.ColorDefault) - - pv.footer = view } func (pv *Preview) initLayout(view *tview.Table) { view.SetSelectable(true, false). - SetSelectedStyle(tcell.StyleDefault.Bold(true).Dim(true)) - - view.SetDoneFunc(func(key tcell.Key) { - if key == tcell.KeyEsc { - pv.screen.Stop() - } - }) + SetSelectedStyle(tcell.StyleDefault.Bold(true).Dim(true)). + SetDoneFunc(func(key tcell.Key) { + if key == tcell.KeyEsc { + pv.screen.Stop() + } + }) view.SetFixed(1, 1) } diff --git a/pkg/tui/table.go b/pkg/tui/table.go index c6064e47..a801a04e 100644 --- a/pkg/tui/table.go +++ b/pkg/tui/table.go @@ -47,16 +47,17 @@ func NewTable(opts ...TableOption) *Table { tbl := Table{ screen: NewScreen(), + view: tview.NewTable(), + footer: tview.NewTextView(), colPad: defaultColPad, maxColWidth: defaultColWidth, } - for _, opt := range opts { opt(&tbl) } - tbl.initTableView() - tbl.initFooterView() + tbl.initTable() + tbl.initFooter() tbl.painter = tview.NewGrid(). SetRows(0, 1, 2). @@ -95,7 +96,7 @@ func WithSelectedFunc(fn SelectedFunc) TableOption { } } -// WithViewModeFunc sets a func that is triggered when user a press 'v'. +// WithViewModeFunc sets a func that is triggered when a user press 'v'. func WithViewModeFunc(fn ViewModeFunc) TableOption { return func(t *Table) { t.viewModeFunc = fn @@ -122,42 +123,36 @@ func (t *Table) render(data TableData) { renderTableCell(t, data) } -func (t *Table) initFooterView() { - view := tview.NewTextView(). +func (t *Table) initFooter() { + t.footer. SetWordWrap(true). SetText(pad(t.footerText, 1)). SetTextColor(tcell.ColorDefault) - - t.footer = view } -func (t *Table) initTableView() { - view := tview.NewTable() - - view.SetSelectable(true, false). - SetSelectedStyle(tcell.StyleDefault.Bold(true).Dim(true)) - - view.SetDoneFunc(func(key tcell.Key) { - if key == tcell.KeyEsc { - t.screen.Stop() - } - }).SetInputCapture(func(ev *tcell.EventKey) *tcell.EventKey { - if ev.Key() == tcell.KeyRune { - switch ev.Rune() { - case 'q': +func (t *Table) initTable() { + t.view.SetSelectable(true, false). + SetSelectedStyle(tcell.StyleDefault.Bold(true).Dim(true)). + SetDoneFunc(func(key tcell.Key) { + if key == tcell.KeyEsc { t.screen.Stop() - os.Exit(0) - case 'v': - r, c := t.view.GetSelection() - t.screen.Suspend(func() { _ = t.viewModeFunc(r, c, t.data) }) } - } - return ev - }) - - view.SetFixed(1, 1) + }). + SetInputCapture(func(ev *tcell.EventKey) *tcell.EventKey { + if ev.Key() == tcell.KeyRune { + switch ev.Rune() { + case 'q': + t.screen.Stop() + os.Exit(0) + case 'v': + r, c := t.view.GetSelection() + t.screen.Suspend(func() { _ = t.viewModeFunc(r, c, t.data) }) + } + } + return ev + }) - t.view = view + t.view.SetFixed(1, 1) } func renderTableHeader(t *Table, data []string) {