diff options
author | Colin Cross <ccross@android.com> | 2019-06-11 23:01:36 -0700 |
---|---|---|
committer | Luca Stefani <luca.stefani.ge1@gmail.com> | 2019-09-04 15:14:54 +0200 |
commit | 119e0ac022a83e014fd6044fcf0fa5a4008f4a6d (patch) | |
tree | 4ab2d67fb166089dee4dbbdd5c23973a92ec9aac /ui | |
parent | 24d53f97fb768e33b3165d3b62e35babc786589c (diff) | |
download | build_soong-119e0ac022a83e014fd6044fcf0fa5a4008f4a6d.tar.gz build_soong-119e0ac022a83e014fd6044fcf0fa5a4008f4a6d.tar.bz2 build_soong-119e0ac022a83e014fd6044fcf0fa5a4008f4a6d.zip |
Use SIGWINCH to update terminal size
Instead of reading the terminal size on every status update, register
for SIGWINCH to read and store the size when it changes.
Test: status_test.go
Change-Id: I555ad21a31a2c924ab0ca681e0c8f00df42a370a
Diffstat (limited to 'ui')
-rw-r--r-- | ui/terminal/smart_status.go | 62 | ||||
-rw-r--r-- | ui/terminal/status_test.go | 3 |
2 files changed, 54 insertions, 11 deletions
diff --git a/ui/terminal/smart_status.go b/ui/terminal/smart_status.go index 8fa9effc..999a2d0f 100644 --- a/ui/terminal/smart_status.go +++ b/ui/terminal/smart_status.go @@ -17,8 +17,11 @@ package terminal import ( "fmt" "io" + "os" + "os/signal" "strings" "sync" + "syscall" "android/soong/ui/status" ) @@ -30,18 +33,29 @@ type smartStatusOutput struct { lock sync.Mutex haveBlankLine bool + + termWidth int + sigwinch chan os.Signal } // NewSmartStatusOutput returns a StatusOutput that represents the // current build status similarly to Ninja's built-in terminal // output. func NewSmartStatusOutput(w io.Writer, formatter formatter) status.StatusOutput { - return &smartStatusOutput{ + s := &smartStatusOutput{ writer: w, formatter: formatter, haveBlankLine: true, + + sigwinch: make(chan os.Signal), } + + s.updateTermSize() + + s.startSigwinch() + + return s } func (s *smartStatusOutput) Message(level status.MsgLevel, message string) { @@ -101,6 +115,8 @@ func (s *smartStatusOutput) Flush() { s.lock.Lock() defer s.lock.Unlock() + s.stopSigwinch() + s.requestLine() } @@ -137,16 +153,8 @@ func (s *smartStatusOutput) statusLine(str string) { // Limit line width to the terminal width, otherwise we'll wrap onto // another line and we won't delete the previous line. - // - // Run this on every line in case the window has been resized while - // we're printing. This could be optimized to only re-run when we get - // SIGWINCH if it ever becomes too time consuming. - if max, ok := termWidth(s.writer); ok { - if len(str) > max { - // TODO: Just do a max. Ninja elides the middle, but that's - // more complicated and these lines aren't that important. - str = str[:max] - } + if s.termWidth > 0 { + str = s.elide(str) } // Move to the beginning on the line, turn on bold, print the output, @@ -156,3 +164,35 @@ func (s *smartStatusOutput) statusLine(str string) { fmt.Fprint(s.writer, start, str, end) s.haveBlankLine = false } + +func (s *smartStatusOutput) elide(str string) string { + if len(str) > s.termWidth { + // TODO: Just do a max. Ninja elides the middle, but that's + // more complicated and these lines aren't that important. + str = str[:s.termWidth] + } + + return str +} + +func (s *smartStatusOutput) startSigwinch() { + signal.Notify(s.sigwinch, syscall.SIGWINCH) + go func() { + for _ = range s.sigwinch { + s.lock.Lock() + s.updateTermSize() + s.lock.Unlock() + } + }() +} + +func (s *smartStatusOutput) stopSigwinch() { + signal.Stop(s.sigwinch) + close(s.sigwinch) +} + +func (s *smartStatusOutput) updateTermSize() { + if w, ok := termWidth(s.writer); ok { + s.termWidth = w + } +} diff --git a/ui/terminal/status_test.go b/ui/terminal/status_test.go index a87a7f07..fc9315b9 100644 --- a/ui/terminal/status_test.go +++ b/ui/terminal/status_test.go @@ -17,6 +17,7 @@ package terminal import ( "bytes" "fmt" + "syscall" "testing" "android/soong/ui/status" @@ -260,6 +261,8 @@ func TestSmartStatusOutputWidthChange(t *testing.T) { runner.startAction(action) smart.termWidth = 30 + // Fake a SIGWINCH + stat.(*smartStatusOutput).sigwinch <- syscall.SIGWINCH runner.finishAction(result) stat.Flush() |