Skip to content

Commit 999ddad

Browse files
authored
fix: Improve support for pager (#503)
1 parent 2224ab2 commit 999ddad

File tree

4 files changed

+95
-16
lines changed

4 files changed

+95
-16
lines changed

internal/view/issues.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ type IssueList struct {
3636

3737
// Render renders the view.
3838
func (l *IssueList) Render() error {
39-
if l.Display.Plain {
39+
if tui.IsDumbTerminal() || l.Display.Plain {
4040
w := tabwriter.NewWriter(os.Stdout, 0, tabWidth, 1, '\t', 0)
4141
return l.renderPlain(w)
4242
}
@@ -147,7 +147,7 @@ func (l *IssueList) data() tui.TableData {
147147
return data
148148
}
149149

150-
func (IssueList) assignColumns(columns []string, issue *jira.Issue) []string {
150+
func (*IssueList) assignColumns(columns []string, issue *jira.Issue) []string {
151151
var bucket []string
152152

153153
for _, column := range columns {

internal/view/sprint.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ func (sl *SprintList) Render() error {
7676

7777
// RenderInTable renders the list in table view.
7878
func (sl *SprintList) RenderInTable() error {
79-
if sl.Display.Plain {
79+
if tui.IsDumbTerminal() || sl.Display.Plain {
8080
w := tabwriter.NewWriter(os.Stdout, 0, tabWidth, 1, '\t', 0)
8181
return sl.renderPlain(w)
8282
}

pkg/tui/helper.go

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"runtime"
99
"strings"
1010

11+
"github.com/cli/safeexec"
1112
"github.com/gdamore/tcell/v2"
1213

1314
"github.com/ankitpokhrel/jira-cli/pkg/tui/primitive"
@@ -55,35 +56,66 @@ func getInfoModal() *primitive.Modal {
5556
SetBorderColor(tcell.ColorDefault)
5657
}
5758

59+
// IsDumbTerminal checks TERM environment variable and returns true if it is set to dumb.
60+
//
61+
// Dumb terminal indicates terminal with limited capability. It may not provide support
62+
// for special character sequences, e.g., no handling of ANSI escape sequences.
63+
func IsDumbTerminal() bool {
64+
term := strings.ToLower(os.Getenv("TERM"))
65+
return term == "" || term == "dumb"
66+
}
67+
5868
// GetPager returns configured pager.
5969
func GetPager() string {
6070
if runtime.GOOS == "windows" {
6171
return ""
6272
}
73+
if IsDumbTerminal() {
74+
return "cat"
75+
}
6376
pager := os.Getenv("PAGER")
64-
if pager == "" && cmdExists("less") {
65-
pager = "less -r"
77+
if pager == "" {
78+
pager = "less"
6679
}
6780
return pager
6881
}
6982

7083
// PagerOut outputs to configured pager if possible.
7184
func PagerOut(out string) error {
72-
pager := GetPager()
73-
if pager == "" {
85+
pagerCmd := GetPager()
86+
if pagerCmd == "" {
7487
_, err := fmt.Print(out)
7588
return err
7689
}
77-
pa := strings.Split(pager, " ")
78-
cmd := exec.Command(pa[0], pa[1:]...)
90+
91+
pa := strings.Split(pagerCmd, " ")
92+
pager, pagerArgs := pa[0], pa[1:]
93+
if err := cmdExists(pager); err != nil {
94+
return err
95+
}
96+
97+
pagerEnv := os.Environ()
98+
for i := len(pagerEnv) - 1; i >= 0; i-- {
99+
if strings.HasPrefix(pagerEnv[i], "PAGER=") {
100+
pagerEnv = append(pagerEnv[0:i], pagerEnv[i+1:]...)
101+
}
102+
}
103+
if _, ok := os.LookupEnv("LESS"); !ok {
104+
pagerEnv = append(pagerEnv, "LESS=R")
105+
}
106+
107+
cmd := exec.Command(pager, pagerArgs...)
108+
cmd.Env = pagerEnv
79109
cmd.Stdin = strings.NewReader(out)
80110
cmd.Stdout = os.Stdout
111+
cmd.Stderr = os.Stderr
112+
81113
return cmd.Run()
82114
}
83115

84-
func cmdExists(cmd string) bool {
85-
_, err := exec.LookPath(cmd)
86-
return err == nil
116+
func cmdExists(cmd string) error {
117+
_, err := safeexec.LookPath(cmd)
118+
return err
87119
}
88120

89121
func customTUIStyle(style TableStyle) tcell.Style {

pkg/tui/helper_test.go

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,13 +89,60 @@ func TestSplitText(t *testing.T) {
8989
func TestGetPager(t *testing.T) {
9090
t.Parallel()
9191

92+
term := os.Getenv("TERM")
9293
pager := os.Getenv("PAGER")
9394

94-
_ = os.Setenv("PAGER", "")
95-
assert.Equal(t, "less -r", GetPager())
95+
// TERM is xterm, PAGER is set.
96+
{
97+
_ = os.Setenv("TERM", "xterm")
9698

97-
_ = os.Setenv("PAGER", "more")
98-
assert.Equal(t, "more", GetPager())
99+
_ = os.Setenv("PAGER", "")
100+
assert.Equal(t, "less", GetPager())
99101

102+
_ = os.Setenv("PAGER", "more")
103+
assert.Equal(t, "more", GetPager())
104+
105+
_ = os.Setenv("PAGER", pager)
106+
}
107+
108+
// TERM is set, PAGER is unset.
109+
{
110+
_ = os.Unsetenv("PAGER")
111+
112+
_ = os.Setenv("TERM", "dumb")
113+
assert.Equal(t, "cat", GetPager())
114+
115+
_ = os.Setenv("TERM", "")
116+
assert.Equal(t, "cat", GetPager())
117+
118+
_ = os.Setenv("TERM", "xterm")
119+
assert.Equal(t, "less", GetPager())
120+
121+
_ = os.Setenv("TERM", term)
122+
}
123+
124+
// TERM gets precendence if both PAGER and TERM are set.
125+
{
126+
_ = os.Setenv("PAGER", "")
127+
_ = os.Setenv("TERM", "")
128+
assert.Equal(t, "cat", GetPager())
129+
130+
_ = os.Setenv("PAGER", "more")
131+
_ = os.Setenv("TERM", "dumb")
132+
assert.Equal(t, "cat", GetPager())
133+
134+
_ = os.Setenv("PAGER", "more")
135+
_ = os.Setenv("TERM", "xterm")
136+
assert.Equal(t, "more", GetPager())
137+
}
138+
139+
// TERM and PAGER are not set.
140+
{
141+
_ = os.Unsetenv("PAGER")
142+
_ = os.Unsetenv("TERM")
143+
assert.Equal(t, "cat", GetPager())
144+
}
145+
146+
_ = os.Setenv("TERM", term)
100147
_ = os.Setenv("PAGER", pager)
101148
}

0 commit comments

Comments
 (0)