@@ -11,6 +11,7 @@ import (
1111 "sync"
1212 "syscall"
1313
14+ "github.com/alecthomas/bit/engine/internal/eventsource"
1415 "github.com/alecthomas/bit/engine/logging/csi"
1516 "github.com/creack/pty"
1617 "github.com/kballard/go-shellquote"
@@ -20,8 +21,8 @@ import (
2021
2122type LogConfig struct {
2223 Level LogLevel `help:"Log level (${enum})." enum:"trace,debug,info,notice,warn,error" default:"info"`
23- Debug bool `help:"Enable debug mode ." xor:"trace "`
24- Trace bool `help:"Enable trace mode ." xor:"trace "`
24+ Debug bool `help:"Force debug logging ." xor:"level "`
25+ Trace bool `help:"Force trace logging ." xor:"level "`
2526}
2627
2728type LogLevel int
@@ -74,9 +75,14 @@ func (l *LogLevel) UnmarshalText(text []byte) error {
7475 return nil
7576}
7677
78+ type terminalSize struct {
79+ margin , width , height uint16
80+ }
81+
7782type Logger struct {
7883 level LogLevel
7984 scope string
85+ size * eventsource.EventSource [terminalSize ]
8086}
8187
8288func NewLogger (config LogConfig ) * Logger {
@@ -86,15 +92,24 @@ func NewLogger(config LogConfig) *Logger {
8692 } else if config .Debug {
8793 level = LogLevelDebug
8894 }
89- return & Logger {level : level }
95+ logger := & Logger {
96+ level : level ,
97+ size : eventsource .New [terminalSize ](),
98+ }
99+ logger .syncTermSize ()
100+ return logger
90101}
91102
92103// Scope returns a new logger with the given scope.
93104func (l * Logger ) Scope (scope string ) * Logger {
94- if len (scope ) > 16 {
95- scope = "…" + scope [len (scope )- 15 :]
105+ // Margin is 20% of terminal.
106+ size := l .size .Load ()
107+ margin := int (size .margin )
108+ if len (scope ) > margin {
109+ scope = "…" + scope [len (scope )- margin + 1 :]
110+ } else {
111+ scope += strings .Repeat (" " , margin - len (scope ))
96112 }
97- scope = fmt .Sprintf ("%-16s" , scope )
98113 scope = strings .ReplaceAll (scope , "%" , "%%" )
99114 return & Logger {scope : scope , level : l .level }
100115}
@@ -184,20 +199,19 @@ func (l *Logger) Exec(dir, command string) error {
184199 return err
185200 }
186201
187- winch := make (chan os.Signal , 1 )
188- signal .Notify (winch , syscall .SIGWINCH )
189- defer signal .Stop (winch )
190- go func () {
191- for range winch {
192- if w , h , err := term .GetSize (int (os .Stdin .Fd ())); err == nil {
193- _ = pty .Setsize (p , & pty.Winsize {Rows : uint16 (h ), Cols : uint16 (w ) - 17 })
194- }
195- }
196- }()
202+ changes := l .size .Subscribe (nil )
203+ defer l .size .Unsubscribe (changes )
204+
197205 // Resize the PTY to exclude the margin.
198206 if w , h , err := term .GetSize (int (os .Stdin .Fd ())); err == nil {
199- _ = pty .Setsize (p , & pty.Winsize {Rows : uint16 (h ), Cols : uint16 (w ) - 17 })
207+ _ = pty .Setsize (p , & pty.Winsize {Rows : uint16 (h ), Cols : uint16 (w ) - ( l . size . Load (). margin + 1 ) })
200208 }
209+
210+ go func () {
211+ for size := range changes {
212+ _ = pty .Setsize (p , & pty.Winsize {Rows : size .height , Cols : size .width - (size .margin + 1 )})
213+ }
214+ }()
201215 defer t .Close ()
202216 defer p .Close ()
203217 lw := l .WriterAt (LogLevelInfo )
@@ -318,3 +332,26 @@ func (l *Logger) writerScanner(wg *sync.WaitGroup, r *io.PipeReader, level LogLe
318332 }
319333 }
320334}
335+
336+ func (l * Logger ) syncTermSize () {
337+ // Initialise terminal size.
338+ size := terminalSize {margin : 16 , width : 80 , height : 25 }
339+ if w , h , err := term .GetSize (int (os .Stdin .Fd ())); err == nil {
340+ margin := uint16 (max (16 , w / 5 ))
341+ size = terminalSize {margin : margin , width : uint16 (w ), height : uint16 (h )}
342+ }
343+ l .size .Store (size )
344+
345+ // Watch WINCH for changes.
346+ winch := make (chan os.Signal , 1 )
347+ signal .Notify (winch , syscall .SIGWINCH )
348+ defer signal .Stop (winch )
349+ go func () {
350+ for range winch {
351+ if w , h , err := term .GetSize (int (os .Stdin .Fd ())); err == nil {
352+ margin := uint16 (max (16 , w / 5 ))
353+ l .size .Store (terminalSize {margin : margin , width : uint16 (w ), height : uint16 (h )})
354+ }
355+ }
356+ }()
357+ }
0 commit comments