Merge changes I0b78ceeb,Ic57e1efd
* changes: Add environment variable to force keeping ANSI codes Disable table mode in smart status if window size is not available
This commit is contained in:
@@ -218,10 +218,16 @@ func distDir(outDir string) string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func forceAnsiOutput() bool {
|
||||||
|
value := os.Getenv("SOONG_UI_ANSI_OUTPUT")
|
||||||
|
return value == "1" || value == "y" || value == "yes" || value == "on" || value == "true"
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
stdio := terminal.StdioImpl{}
|
stdio := terminal.StdioImpl{}
|
||||||
|
|
||||||
output := terminal.NewStatusOutput(stdio.Stdout(), "", false, false)
|
output := terminal.NewStatusOutput(stdio.Stdout(), "", false, false,
|
||||||
|
forceAnsiOutput())
|
||||||
log := logger.New(output)
|
log := logger.New(output)
|
||||||
defer log.Cleanup()
|
defer log.Cleanup()
|
||||||
|
|
||||||
|
@@ -164,7 +164,8 @@ func main() {
|
|||||||
|
|
||||||
// Create a terminal output that mimics Ninja's.
|
// Create a terminal output that mimics Ninja's.
|
||||||
output := terminal.NewStatusOutput(c.stdio().Stdout(), os.Getenv("NINJA_STATUS"), c.simpleOutput,
|
output := terminal.NewStatusOutput(c.stdio().Stdout(), os.Getenv("NINJA_STATUS"), c.simpleOutput,
|
||||||
build.OsEnvironment().IsEnvTrue("ANDROID_QUIET_BUILD"))
|
build.OsEnvironment().IsEnvTrue("ANDROID_QUIET_BUILD"),
|
||||||
|
build.OsEnvironment().IsEnvTrue("SOONG_UI_ANSI_OUTPUT"))
|
||||||
|
|
||||||
// Attach a new logger instance to the terminal output.
|
// Attach a new logger instance to the terminal output.
|
||||||
log := logger.New(output)
|
log := logger.New(output)
|
||||||
|
@@ -48,7 +48,7 @@ type TestResults struct {
|
|||||||
|
|
||||||
// Run runs a single build command. It emulates the "m" command line by calling into Soong UI directly.
|
// Run runs a single build command. It emulates the "m" command line by calling into Soong UI directly.
|
||||||
func (t *Test) Run(logsDir string) {
|
func (t *Test) Run(logsDir string) {
|
||||||
output := terminal.NewStatusOutput(os.Stdout, "", false, false)
|
output := terminal.NewStatusOutput(os.Stdout, "", false, false, false)
|
||||||
|
|
||||||
log := logger.New(output)
|
log := logger.New(output)
|
||||||
defer log.Cleanup()
|
defer log.Cleanup()
|
||||||
|
@@ -24,15 +24,17 @@ import (
|
|||||||
type simpleStatusOutput struct {
|
type simpleStatusOutput struct {
|
||||||
writer io.Writer
|
writer io.Writer
|
||||||
formatter formatter
|
formatter formatter
|
||||||
|
keepANSI bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewSimpleStatusOutput returns a StatusOutput that represents the
|
// NewSimpleStatusOutput returns a StatusOutput that represents the
|
||||||
// current build status similarly to Ninja's built-in terminal
|
// current build status similarly to Ninja's built-in terminal
|
||||||
// output.
|
// output.
|
||||||
func NewSimpleStatusOutput(w io.Writer, formatter formatter) status.StatusOutput {
|
func NewSimpleStatusOutput(w io.Writer, formatter formatter, keepANSI bool) status.StatusOutput {
|
||||||
return &simpleStatusOutput{
|
return &simpleStatusOutput{
|
||||||
writer: w,
|
writer: w,
|
||||||
formatter: formatter,
|
formatter: formatter,
|
||||||
|
keepANSI: keepANSI,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,7 +56,9 @@ func (s *simpleStatusOutput) FinishAction(result status.ActionResult, counts sta
|
|||||||
progress := s.formatter.progress(counts) + str
|
progress := s.formatter.progress(counts) + str
|
||||||
|
|
||||||
output := s.formatter.result(result)
|
output := s.formatter.result(result)
|
||||||
output = string(stripAnsiEscapes([]byte(output)))
|
if !s.keepANSI {
|
||||||
|
output = string(stripAnsiEscapes([]byte(output)))
|
||||||
|
}
|
||||||
|
|
||||||
if output != "" {
|
if output != "" {
|
||||||
fmt.Fprint(s.writer, progress, "\n", output)
|
fmt.Fprint(s.writer, progress, "\n", output)
|
||||||
|
@@ -77,7 +77,12 @@ func NewSmartStatusOutput(w io.Writer, formatter formatter) status.StatusOutput
|
|||||||
s.requestedTableHeight = h
|
s.requestedTableHeight = h
|
||||||
}
|
}
|
||||||
|
|
||||||
s.updateTermSize()
|
if w, h, ok := termSize(s.writer); ok {
|
||||||
|
s.termWidth, s.termHeight = w, h
|
||||||
|
s.computeTableHeight()
|
||||||
|
} else {
|
||||||
|
s.tableMode = false
|
||||||
|
}
|
||||||
|
|
||||||
if s.tableMode {
|
if s.tableMode {
|
||||||
// Add empty lines at the bottom of the screen to scroll back the existing history
|
// Add empty lines at the bottom of the screen to scroll back the existing history
|
||||||
@@ -296,40 +301,44 @@ func (s *smartStatusOutput) stopSigwinch() {
|
|||||||
close(s.sigwinch)
|
close(s.sigwinch)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// computeTableHeight recomputes s.tableHeight based on s.termHeight and s.requestedTableHeight.
|
||||||
|
func (s *smartStatusOutput) computeTableHeight() {
|
||||||
|
tableHeight := s.requestedTableHeight
|
||||||
|
if tableHeight == 0 {
|
||||||
|
tableHeight = s.termHeight / 4
|
||||||
|
if tableHeight < 1 {
|
||||||
|
tableHeight = 1
|
||||||
|
} else if tableHeight > 10 {
|
||||||
|
tableHeight = 10
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if tableHeight > s.termHeight-1 {
|
||||||
|
tableHeight = s.termHeight - 1
|
||||||
|
}
|
||||||
|
s.tableHeight = tableHeight
|
||||||
|
}
|
||||||
|
|
||||||
|
// updateTermSize recomputes the table height after a SIGWINCH and pans any existing text if
|
||||||
|
// necessary.
|
||||||
func (s *smartStatusOutput) updateTermSize() {
|
func (s *smartStatusOutput) updateTermSize() {
|
||||||
if w, h, ok := termSize(s.writer); ok {
|
if w, h, ok := termSize(s.writer); ok {
|
||||||
firstUpdate := s.termHeight == 0 && s.termWidth == 0
|
|
||||||
oldScrollingHeight := s.termHeight - s.tableHeight
|
oldScrollingHeight := s.termHeight - s.tableHeight
|
||||||
|
|
||||||
s.termWidth, s.termHeight = w, h
|
s.termWidth, s.termHeight = w, h
|
||||||
|
|
||||||
if s.tableMode {
|
if s.tableMode {
|
||||||
tableHeight := s.requestedTableHeight
|
s.computeTableHeight()
|
||||||
if tableHeight == 0 {
|
|
||||||
tableHeight = s.termHeight / 4
|
|
||||||
if tableHeight < 1 {
|
|
||||||
tableHeight = 1
|
|
||||||
} else if tableHeight > 10 {
|
|
||||||
tableHeight = 10
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if tableHeight > s.termHeight-1 {
|
|
||||||
tableHeight = s.termHeight - 1
|
|
||||||
}
|
|
||||||
s.tableHeight = tableHeight
|
|
||||||
|
|
||||||
scrollingHeight := s.termHeight - s.tableHeight
|
scrollingHeight := s.termHeight - s.tableHeight
|
||||||
|
|
||||||
if !firstUpdate {
|
// If the scrolling region has changed, attempt to pan the existing text so that it is
|
||||||
// If the scrolling region has changed, attempt to pan the existing text so that it is
|
// not overwritten by the table.
|
||||||
// not overwritten by the table.
|
if scrollingHeight < oldScrollingHeight {
|
||||||
if scrollingHeight < oldScrollingHeight {
|
pan := oldScrollingHeight - scrollingHeight
|
||||||
pan := oldScrollingHeight - scrollingHeight
|
if pan > s.tableHeight {
|
||||||
if pan > s.tableHeight {
|
pan = s.tableHeight
|
||||||
pan = s.tableHeight
|
|
||||||
}
|
|
||||||
fmt.Fprint(s.writer, ansi.panDown(pan))
|
|
||||||
}
|
}
|
||||||
|
fmt.Fprint(s.writer, ansi.panDown(pan))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -26,12 +26,12 @@ import (
|
|||||||
//
|
//
|
||||||
// statusFormat takes nearly all the same options as NINJA_STATUS.
|
// statusFormat takes nearly all the same options as NINJA_STATUS.
|
||||||
// %c is currently unsupported.
|
// %c is currently unsupported.
|
||||||
func NewStatusOutput(w io.Writer, statusFormat string, forceSimpleOutput, quietBuild bool) status.StatusOutput {
|
func NewStatusOutput(w io.Writer, statusFormat string, forceSimpleOutput, quietBuild, forceKeepANSI bool) status.StatusOutput {
|
||||||
formatter := newFormatter(statusFormat, quietBuild)
|
formatter := newFormatter(statusFormat, quietBuild)
|
||||||
|
|
||||||
if !forceSimpleOutput && isSmartTerminal(w) {
|
if !forceSimpleOutput && isSmartTerminal(w) {
|
||||||
return NewSmartStatusOutput(w, formatter)
|
return NewSmartStatusOutput(w, formatter)
|
||||||
} else {
|
} else {
|
||||||
return NewSimpleStatusOutput(w, formatter)
|
return NewSimpleStatusOutput(w, formatter, forceKeepANSI)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -94,7 +94,7 @@ func TestStatusOutput(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("smart", func(t *testing.T) {
|
t.Run("smart", func(t *testing.T) {
|
||||||
smart := &fakeSmartTerminal{termWidth: 40}
|
smart := &fakeSmartTerminal{termWidth: 40}
|
||||||
stat := NewStatusOutput(smart, "", false, false)
|
stat := NewStatusOutput(smart, "", false, false, false)
|
||||||
tt.calls(stat)
|
tt.calls(stat)
|
||||||
stat.Flush()
|
stat.Flush()
|
||||||
|
|
||||||
@@ -105,7 +105,7 @@ func TestStatusOutput(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("simple", func(t *testing.T) {
|
t.Run("simple", func(t *testing.T) {
|
||||||
simple := &bytes.Buffer{}
|
simple := &bytes.Buffer{}
|
||||||
stat := NewStatusOutput(simple, "", false, false)
|
stat := NewStatusOutput(simple, "", false, false, false)
|
||||||
tt.calls(stat)
|
tt.calls(stat)
|
||||||
stat.Flush()
|
stat.Flush()
|
||||||
|
|
||||||
@@ -116,7 +116,7 @@ func TestStatusOutput(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("force simple", func(t *testing.T) {
|
t.Run("force simple", func(t *testing.T) {
|
||||||
smart := &fakeSmartTerminal{termWidth: 40}
|
smart := &fakeSmartTerminal{termWidth: 40}
|
||||||
stat := NewStatusOutput(smart, "", true, false)
|
stat := NewStatusOutput(smart, "", true, false, false)
|
||||||
tt.calls(stat)
|
tt.calls(stat)
|
||||||
stat.Flush()
|
stat.Flush()
|
||||||
|
|
||||||
@@ -269,7 +269,7 @@ func TestSmartStatusOutputWidthChange(t *testing.T) {
|
|||||||
os.Setenv(tableHeightEnVar, "")
|
os.Setenv(tableHeightEnVar, "")
|
||||||
|
|
||||||
smart := &fakeSmartTerminal{termWidth: 40}
|
smart := &fakeSmartTerminal{termWidth: 40}
|
||||||
stat := NewStatusOutput(smart, "", false, false)
|
stat := NewStatusOutput(smart, "", false, false, false)
|
||||||
smartStat := stat.(*smartStatusOutput)
|
smartStat := stat.(*smartStatusOutput)
|
||||||
smartStat.sigwinchHandled = make(chan bool)
|
smartStat.sigwinchHandled = make(chan bool)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user