Dogfood term package from go-gh
This commit is contained in:
parent
a493f6dbe8
commit
25a926d5cb
11 changed files with 38 additions and 381 deletions
|
|
@ -64,10 +64,6 @@ func mainRun() exitCode {
|
|||
|
||||
cmdFactory := factory.New(buildVersion)
|
||||
stderr := cmdFactory.IOStreams.ErrOut
|
||||
|
||||
if spec := os.Getenv("GH_FORCE_TTY"); spec != "" {
|
||||
cmdFactory.IOStreams.ForceTerminal(spec)
|
||||
}
|
||||
if !cmdFactory.IOStreams.ColorEnabled() {
|
||||
surveyCore.DisableColor = true
|
||||
} else {
|
||||
|
|
|
|||
4
go.mod
4
go.mod
|
|
@ -25,7 +25,6 @@ require (
|
|||
github.com/mattn/go-colorable v0.1.13
|
||||
github.com/mattn/go-isatty v0.0.16
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d
|
||||
github.com/muesli/termenv v0.12.0
|
||||
github.com/muhammadmuzzammil1998/jsonc v0.0.0-20201229145248-615b0916ca38
|
||||
github.com/opentracing/opentracing-go v1.1.0
|
||||
github.com/shurcooL/githubv4 v0.0.0-20220520033151-0b4e3294ff00
|
||||
|
|
@ -35,7 +34,6 @@ require (
|
|||
github.com/stretchr/testify v1.7.5
|
||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211
|
||||
golang.org/x/text v0.3.7
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
|
|
@ -59,6 +57,7 @@ require (
|
|||
github.com/mattn/go-runewidth v0.0.13 // indirect
|
||||
github.com/microcosm-cc/bluemonday v1.0.19 // indirect
|
||||
github.com/muesli/reflow v0.3.0 // indirect
|
||||
github.com/muesli/termenv v0.12.0 // indirect
|
||||
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
|
|
@ -70,6 +69,7 @@ require (
|
|||
github.com/yuin/goldmark-emoji v1.0.1 // indirect
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a // indirect
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ package iostreams
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
|
|
@ -25,30 +24,6 @@ var (
|
|||
}
|
||||
)
|
||||
|
||||
func EnvColorDisabled() bool {
|
||||
return os.Getenv("NO_COLOR") != "" || os.Getenv("CLICOLOR") == "0"
|
||||
}
|
||||
|
||||
func EnvColorForced() bool {
|
||||
return os.Getenv("CLICOLOR_FORCE") != "" && os.Getenv("CLICOLOR_FORCE") != "0"
|
||||
}
|
||||
|
||||
func Is256ColorSupported() bool {
|
||||
return IsTrueColorSupported() ||
|
||||
strings.Contains(os.Getenv("TERM"), "256") ||
|
||||
strings.Contains(os.Getenv("COLORTERM"), "256")
|
||||
}
|
||||
|
||||
func IsTrueColorSupported() bool {
|
||||
term := os.Getenv("TERM")
|
||||
colorterm := os.Getenv("COLORTERM")
|
||||
|
||||
return strings.Contains(term, "24bit") ||
|
||||
strings.Contains(term, "truecolor") ||
|
||||
strings.Contains(colorterm, "24bit") ||
|
||||
strings.Contains(colorterm, "truecolor")
|
||||
}
|
||||
|
||||
func NewColorScheme(enabled, is256enabled bool, trueColor bool) *ColorScheme {
|
||||
return &ColorScheme{
|
||||
enabled: enabled,
|
||||
|
|
|
|||
|
|
@ -6,127 +6,6 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestEnvColorDisabled(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
NO_COLOR string
|
||||
CLICOLOR string
|
||||
CLICOLOR_FORCE string
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
name: "pristine env",
|
||||
NO_COLOR: "",
|
||||
CLICOLOR: "",
|
||||
CLICOLOR_FORCE: "",
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "NO_COLOR enabled",
|
||||
NO_COLOR: "1",
|
||||
CLICOLOR: "",
|
||||
CLICOLOR_FORCE: "",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "CLICOLOR disabled",
|
||||
NO_COLOR: "",
|
||||
CLICOLOR: "0",
|
||||
CLICOLOR_FORCE: "",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "CLICOLOR enabled",
|
||||
NO_COLOR: "",
|
||||
CLICOLOR: "1",
|
||||
CLICOLOR_FORCE: "",
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "CLICOLOR_FORCE has no effect",
|
||||
NO_COLOR: "",
|
||||
CLICOLOR: "",
|
||||
CLICOLOR_FORCE: "1",
|
||||
want: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Setenv("NO_COLOR", tt.NO_COLOR)
|
||||
t.Setenv("CLICOLOR", tt.CLICOLOR)
|
||||
t.Setenv("CLICOLOR_FORCE", tt.CLICOLOR_FORCE)
|
||||
|
||||
if got := EnvColorDisabled(); got != tt.want {
|
||||
t.Errorf("EnvColorDisabled(): want %v, got %v", tt.want, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnvColorForced(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
NO_COLOR string
|
||||
CLICOLOR string
|
||||
CLICOLOR_FORCE string
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
name: "pristine env",
|
||||
NO_COLOR: "",
|
||||
CLICOLOR: "",
|
||||
CLICOLOR_FORCE: "",
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "NO_COLOR enabled",
|
||||
NO_COLOR: "1",
|
||||
CLICOLOR: "",
|
||||
CLICOLOR_FORCE: "",
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "CLICOLOR disabled",
|
||||
NO_COLOR: "",
|
||||
CLICOLOR: "0",
|
||||
CLICOLOR_FORCE: "",
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "CLICOLOR enabled",
|
||||
NO_COLOR: "",
|
||||
CLICOLOR: "1",
|
||||
CLICOLOR_FORCE: "",
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "CLICOLOR_FORCE enabled",
|
||||
NO_COLOR: "",
|
||||
CLICOLOR: "",
|
||||
CLICOLOR_FORCE: "1",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "CLICOLOR_FORCE disabled",
|
||||
NO_COLOR: "",
|
||||
CLICOLOR: "",
|
||||
CLICOLOR_FORCE: "0",
|
||||
want: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Setenv("NO_COLOR", tt.NO_COLOR)
|
||||
t.Setenv("CLICOLOR", tt.CLICOLOR)
|
||||
t.Setenv("CLICOLOR_FORCE", tt.CLICOLOR_FORCE)
|
||||
|
||||
if got := EnvColorForced(); got != tt.want {
|
||||
t.Errorf("EnvColorForced(): want %v, got %v", tt.want, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestColorFromRGB(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
|
|
|
|||
|
|
@ -3,8 +3,9 @@
|
|||
|
||||
package iostreams
|
||||
|
||||
import "errors"
|
||||
import "os"
|
||||
|
||||
func enableVirtualTerminalProcessing(fd uintptr) error {
|
||||
return errors.New("not implemented")
|
||||
func hasAlternateScreenBuffer(hasTrueColor bool) bool {
|
||||
// on non-Windows, we just assume that alternate screen buffer is supported in most cases
|
||||
return os.Getenv("TERM") != "dumb"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,14 +3,8 @@
|
|||
|
||||
package iostreams
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
func enableVirtualTerminalProcessing(fd uintptr) error {
|
||||
stdout := windows.Handle(fd)
|
||||
|
||||
var originalMode uint32
|
||||
windows.GetConsoleMode(stdout, &originalMode)
|
||||
return windows.SetConsoleMode(stdout, originalMode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING)
|
||||
func hasAlternateScreenBuffer(hasTrueColor bool) bool {
|
||||
// on Windows we just assume that alternate screen buffer is supported if we
|
||||
// enabled virtual terminal processing, which in turn enables truecolor
|
||||
return hasTrueColor
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,18 +8,16 @@ import (
|
|||
"os"
|
||||
"os/exec"
|
||||
"os/signal"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/briandowns/spinner"
|
||||
ghTerm "github.com/cli/go-gh/pkg/term"
|
||||
"github.com/cli/safeexec"
|
||||
"github.com/google/shlex"
|
||||
"github.com/mattn/go-colorable"
|
||||
"github.com/mattn/go-isatty"
|
||||
"github.com/muesli/termenv"
|
||||
"golang.org/x/term"
|
||||
)
|
||||
|
||||
const DefaultWidth = 80
|
||||
|
|
@ -40,13 +38,12 @@ type fileReader interface {
|
|||
}
|
||||
|
||||
type IOStreams struct {
|
||||
term ghTerm.Term
|
||||
|
||||
In fileReader
|
||||
Out fileWriter
|
||||
ErrOut io.Writer
|
||||
|
||||
colorEnabled bool
|
||||
is256enabled bool
|
||||
hasTrueColor bool
|
||||
terminalTheme string
|
||||
|
||||
progressIndicatorEnabled bool
|
||||
|
|
@ -63,8 +60,6 @@ type IOStreams struct {
|
|||
stdoutIsTTY bool
|
||||
stderrTTYOverride bool
|
||||
stderrIsTTY bool
|
||||
termWidthOverride int
|
||||
ttySize func() (int, int, error)
|
||||
|
||||
pagerCommand string
|
||||
pagerProcess *os.Process
|
||||
|
|
@ -75,42 +70,33 @@ type IOStreams struct {
|
|||
}
|
||||
|
||||
func (s *IOStreams) ColorEnabled() bool {
|
||||
return s.colorEnabled
|
||||
return s.term.IsColorEnabled()
|
||||
}
|
||||
|
||||
func (s *IOStreams) ColorSupport256() bool {
|
||||
return s.is256enabled
|
||||
return s.term.Is256ColorSupported()
|
||||
}
|
||||
|
||||
func (s *IOStreams) HasTrueColor() bool {
|
||||
return s.hasTrueColor
|
||||
return s.term.IsTrueColorSupported()
|
||||
}
|
||||
|
||||
// DetectTerminalTheme is a utility to call before starting the output pager so that the terminal background
|
||||
// can be reliably detected.
|
||||
func (s *IOStreams) DetectTerminalTheme() {
|
||||
if !s.ColorEnabled() {
|
||||
s.terminalTheme = "none"
|
||||
return
|
||||
}
|
||||
|
||||
if s.pagerProcess != nil {
|
||||
if !s.ColorEnabled() || s.pagerProcess != nil {
|
||||
s.terminalTheme = "none"
|
||||
return
|
||||
}
|
||||
|
||||
style := os.Getenv("GLAMOUR_STYLE")
|
||||
if style != "" && style != "auto" {
|
||||
// ensure GLAMOUR_STYLE takes precedence over "light" and "dark" themes
|
||||
s.terminalTheme = "none"
|
||||
return
|
||||
}
|
||||
|
||||
if termenv.HasDarkBackground() {
|
||||
s.terminalTheme = "dark"
|
||||
return
|
||||
}
|
||||
|
||||
s.terminalTheme = "light"
|
||||
s.terminalTheme = s.term.Theme()
|
||||
}
|
||||
|
||||
// TerminalTheme returns "light", "dark", or "none" depending on the background color of the terminal.
|
||||
|
|
@ -123,7 +109,7 @@ func (s *IOStreams) TerminalTheme() string {
|
|||
}
|
||||
|
||||
func (s *IOStreams) SetColorEnabled(colorEnabled bool) {
|
||||
s.colorEnabled = colorEnabled
|
||||
//s.colorEnabled = colorEnabled
|
||||
}
|
||||
|
||||
func (s *IOStreams) SetStdinTTY(isTTY bool) {
|
||||
|
|
@ -339,65 +325,13 @@ func (s *IOStreams) RefreshScreen() {
|
|||
}
|
||||
}
|
||||
|
||||
// TerminalWidth returns the width of the terminal that stdout is attached to.
|
||||
// TODO: investigate whether ProcessTerminalWidth could replace all this.
|
||||
// TerminalWidth returns the width of the terminal that controls the process
|
||||
func (s *IOStreams) TerminalWidth() int {
|
||||
if s.termWidthOverride > 0 {
|
||||
return s.termWidthOverride
|
||||
}
|
||||
|
||||
defaultWidth := DefaultWidth
|
||||
|
||||
if w, _, err := terminalSize(s.Out.Fd()); err == nil {
|
||||
w, _, err := s.term.Size()
|
||||
if err == nil && w > 0 {
|
||||
return w
|
||||
}
|
||||
|
||||
if isCygwinTerminal(s.Out.Fd()) {
|
||||
tputExe, err := safeexec.LookPath("tput")
|
||||
if err != nil {
|
||||
return defaultWidth
|
||||
}
|
||||
tputCmd := exec.Command(tputExe, "cols")
|
||||
tputCmd.Stdin = os.Stdin
|
||||
if out, err := tputCmd.Output(); err == nil {
|
||||
if w, err := strconv.Atoi(strings.TrimSpace(string(out))); err == nil {
|
||||
return w
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return defaultWidth
|
||||
}
|
||||
|
||||
// ProcessTerminalWidth returns the width of the terminal that the process is attached to.
|
||||
func (s *IOStreams) ProcessTerminalWidth() int {
|
||||
w, _, err := s.ttySize()
|
||||
if err != nil {
|
||||
return DefaultWidth
|
||||
}
|
||||
return w
|
||||
}
|
||||
|
||||
func (s *IOStreams) ForceTerminal(spec string) {
|
||||
s.colorEnabled = !EnvColorDisabled()
|
||||
s.SetStdoutTTY(true)
|
||||
|
||||
if w, err := strconv.Atoi(spec); err == nil {
|
||||
s.termWidthOverride = w
|
||||
return
|
||||
}
|
||||
|
||||
ttyWidth, _, err := s.ttySize()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
s.termWidthOverride = ttyWidth
|
||||
|
||||
if strings.HasSuffix(spec, "%") {
|
||||
if p, err := strconv.Atoi(spec[:len(spec)-1]); err == nil {
|
||||
s.termWidthOverride = int(float64(s.termWidthOverride) * (float64(p) / 100))
|
||||
}
|
||||
}
|
||||
return DefaultWidth
|
||||
}
|
||||
|
||||
func (s *IOStreams) ColorScheme() *ColorScheme {
|
||||
|
|
@ -427,25 +361,20 @@ func (s *IOStreams) TempFile(dir, pattern string) (*os.File, error) {
|
|||
}
|
||||
|
||||
func System() *IOStreams {
|
||||
terminal := ghTerm.FromEnv()
|
||||
|
||||
// we avoid using terminal.IsTerminalOutput() in order to additionally support cygwin
|
||||
stdoutIsTTY := isTerminal(os.Stdout)
|
||||
stderrIsTTY := isTerminal(os.Stderr)
|
||||
|
||||
var stdout fileWriter = os.Stdout
|
||||
isVirtualTerminal := false
|
||||
if stdoutIsTTY {
|
||||
// enables ANSI escape sequences on modern Windows
|
||||
if err := enableVirtualTerminalProcessing(os.Stdout.Fd()); err == nil {
|
||||
isVirtualTerminal = true
|
||||
} else {
|
||||
// as a fallback, translate ANSI escape sequences to Windows console syscalls
|
||||
colorableStdout := colorable.NewColorable(os.Stdout)
|
||||
if colorableStdout != os.Stdout {
|
||||
// ensure that the file descriptor of the original stdout is preserved
|
||||
stdout = &fdWriter{
|
||||
fd: os.Stdout.Fd(),
|
||||
Writer: colorableStdout,
|
||||
}
|
||||
}
|
||||
// On Windows with no virtual terminal processing support, translate ANSI escape
|
||||
// sequences to console syscalls
|
||||
if colorableStdout := colorable.NewColorable(os.Stdout); colorableStdout != os.Stdout {
|
||||
// ensure that the file descriptor of the original stdout is preserved
|
||||
stdout = &fdWriter{
|
||||
fd: os.Stdout.Fd(),
|
||||
Writer: colorableStdout,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -453,18 +382,15 @@ func System() *IOStreams {
|
|||
In: os.Stdin,
|
||||
Out: stdout,
|
||||
ErrOut: colorable.NewColorable(os.Stderr),
|
||||
colorEnabled: EnvColorForced() || (!EnvColorDisabled() && stdoutIsTTY),
|
||||
is256enabled: isVirtualTerminal || Is256ColorSupported(),
|
||||
hasTrueColor: isVirtualTerminal || IsTrueColorSupported(),
|
||||
pagerCommand: os.Getenv("PAGER"),
|
||||
ttySize: ttySize,
|
||||
term: terminal,
|
||||
}
|
||||
|
||||
if stdoutIsTTY && stderrIsTTY {
|
||||
io.progressIndicatorEnabled = true
|
||||
}
|
||||
|
||||
if stdoutIsTTY && isVirtualTerminal {
|
||||
if stdoutIsTTY && hasAlternateScreenBuffer(terminal.IsTrueColorSupported()) {
|
||||
io.alternateScreenBufferEnabled = true
|
||||
}
|
||||
|
||||
|
|
@ -485,9 +411,6 @@ func Test() (*IOStreams, *bytes.Buffer, *bytes.Buffer, *bytes.Buffer) {
|
|||
},
|
||||
Out: &fdWriter{fd: 1, Writer: out},
|
||||
ErrOut: errOut,
|
||||
ttySize: func() (int, int, error) {
|
||||
return -1, -1, errors.New("ttySize not implemented in tests")
|
||||
},
|
||||
}
|
||||
io.SetStdinTTY(false)
|
||||
io.SetStdoutTTY(false)
|
||||
|
|
@ -496,18 +419,13 @@ func Test() (*IOStreams, *bytes.Buffer, *bytes.Buffer, *bytes.Buffer) {
|
|||
}
|
||||
|
||||
func isTerminal(f *os.File) bool {
|
||||
return isatty.IsTerminal(f.Fd()) || isatty.IsCygwinTerminal(f.Fd())
|
||||
return ghTerm.IsTerminal(f) || isCygwinTerminal(f.Fd())
|
||||
}
|
||||
|
||||
func isCygwinTerminal(fd uintptr) bool {
|
||||
return isatty.IsCygwinTerminal(fd)
|
||||
}
|
||||
|
||||
// terminalSize measures the viewport of the terminal that the output stream is connected to
|
||||
func terminalSize(fd uintptr) (int, int, error) {
|
||||
return term.GetSize(int(fd))
|
||||
}
|
||||
|
||||
// pagerWriter implements a WriteCloser that wraps all EPIPE errors in an ErrClosedPagerPipe type.
|
||||
type pagerWriter struct {
|
||||
io.WriteCloser
|
||||
|
|
|
|||
|
|
@ -2,79 +2,11 @@ package iostreams
|
|||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestIOStreams_ForceTerminal(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
iostreams *IOStreams
|
||||
arg string
|
||||
wantTTY bool
|
||||
wantWidth int
|
||||
}{
|
||||
{
|
||||
name: "explicit width",
|
||||
iostreams: &IOStreams{},
|
||||
arg: "72",
|
||||
wantTTY: true,
|
||||
wantWidth: 72,
|
||||
},
|
||||
{
|
||||
name: "measure width",
|
||||
iostreams: &IOStreams{
|
||||
ttySize: func() (int, int, error) {
|
||||
return 72, 0, nil
|
||||
},
|
||||
},
|
||||
arg: "true",
|
||||
wantTTY: true,
|
||||
wantWidth: 72,
|
||||
},
|
||||
{
|
||||
name: "measure width fails",
|
||||
iostreams: &IOStreams{
|
||||
Out: &fdWriter{
|
||||
Writer: io.Discard,
|
||||
fd: 1,
|
||||
},
|
||||
ttySize: func() (int, int, error) {
|
||||
return -1, -1, errors.New("ttySize sabotage!")
|
||||
},
|
||||
},
|
||||
arg: "true",
|
||||
wantTTY: true,
|
||||
wantWidth: 80,
|
||||
},
|
||||
{
|
||||
name: "apply percentage",
|
||||
iostreams: &IOStreams{
|
||||
ttySize: func() (int, int, error) {
|
||||
return 72, 0, nil
|
||||
},
|
||||
},
|
||||
arg: "50%",
|
||||
wantTTY: true,
|
||||
wantWidth: 36,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tt.iostreams.ForceTerminal(tt.arg)
|
||||
if isTTY := tt.iostreams.IsStdoutTTY(); isTTY != tt.wantTTY {
|
||||
t.Errorf("IOStreams.IsStdoutTTY() = %v, want %v", isTTY, tt.wantTTY)
|
||||
}
|
||||
if tw := tt.iostreams.TerminalWidth(); tw != tt.wantWidth {
|
||||
t.Errorf("IOStreams.TerminalWidth() = %v, want %v", tw, tt.wantWidth)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestStopAlternateScreenBuffer(t *testing.T) {
|
||||
ios, _, stdout, _ := Test()
|
||||
ios.SetAlternateScreenBufferEnabled(true)
|
||||
|
|
|
|||
|
|
@ -1,20 +0,0 @@
|
|||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package iostreams
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"golang.org/x/term"
|
||||
)
|
||||
|
||||
// ttySize measures the size of the controlling terminal for the current process
|
||||
func ttySize() (int, int, error) {
|
||||
f, err := os.Open("/dev/tty")
|
||||
if err != nil {
|
||||
return -1, -1, err
|
||||
}
|
||||
defer f.Close()
|
||||
return term.GetSize(int(f.Fd()))
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
package iostreams
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"golang.org/x/term"
|
||||
)
|
||||
|
||||
func ttySize() (int, int, error) {
|
||||
f, err := os.Open("CONOUT$")
|
||||
if err != nil {
|
||||
return -1, -1, err
|
||||
}
|
||||
defer f.Close()
|
||||
return term.GetSize(int(f.Fd()))
|
||||
}
|
||||
|
|
@ -40,10 +40,8 @@ func NewTablePrinterWithOptions(ios *iostreams.IOStreams, opts TablePrinterOptio
|
|||
var maxWidth int
|
||||
if opts.MaxWidth > 0 {
|
||||
maxWidth = opts.MaxWidth
|
||||
} else if ios.IsStdoutTTY() {
|
||||
maxWidth = ios.TerminalWidth()
|
||||
} else {
|
||||
maxWidth = ios.ProcessTerminalWidth()
|
||||
maxWidth = ios.TerminalWidth()
|
||||
}
|
||||
return &ttyTablePrinter{
|
||||
out: out,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue