pkg/cmd/util/term/terminal_writer.go
6366c25e
 package term
 
 import (
 	"io"
 	"os"
 
 	"github.com/docker/docker/pkg/term"
 	wordwrap "github.com/mitchellh/go-wordwrap"
 	kterm "k8s.io/kubernetes/pkg/util/term"
 )
 
 type wordWrapWriter struct {
 	limit  uint
 	writer io.Writer
 }
 
 // NewResponsiveWriter creates a Writer that detects the column width of the
 // terminal we are in, and adjusts every line width to fit and use recommended
 // terminal sizes for better readability. Does proper word wrapping automatically.
 //    if terminal width >= 120 columns		use 120 columns
 //    if terminal width >= 100 columns		use 100 columns
 //    if terminal width >=  80 columns		use  80 columns
 // In case we're not in a terminal or if it's smaller than 80 columns width,
 // doesn't do any wrapping.
 func NewResponsiveWriter(w io.Writer) io.Writer {
 	file, ok := w.(*os.File)
 	if !ok {
 		return w
 	}
 	fd := file.Fd()
 	if !term.IsTerminal(fd) {
 		return w
 	}
 
 	terminalSize := kterm.GetSize(fd)
 	if terminalSize == nil {
 		return w
 	}
 
 	var limit uint
 	switch {
 	case terminalSize.Width >= 120:
 		limit = 120
 	case terminalSize.Width >= 100:
 		limit = 100
 	case terminalSize.Width >= 80:
 		limit = 80
 	}
 
 	return NewWordWrapWriter(w, limit)
 }
 
 // NewWordWrapWriter is a Writer that supports a limit of characters on every line
 // and does auto word wrapping that respects that limit.
 func NewWordWrapWriter(w io.Writer, limit uint) io.Writer {
 	return &wordWrapWriter{
 		limit:  limit,
 		writer: w,
 	}
 }
 
 func (w wordWrapWriter) Write(p []byte) (nn int, err error) {
 	if w.limit == 0 {
 		return w.writer.Write(p)
 	}
 	original := string(p)
 	wrapped := wordwrap.WrapString(original, w.limit)
 	return w.writer.Write([]byte(wrapped))
 }
 
 // NewPunchCardWriter is a NewWordWrapWriter that limits the line width to 80 columns.
 func NewPunchCardWriter(w io.Writer) io.Writer {
 	return NewWordWrapWriter(w, 80)
 }
 
 type maxWidthWriter struct {
 	maxWidth     uint
 	currentWidth uint
 	written      uint
 	writer       io.Writer
 }
 
 // NewMaxWidthWriter is a Writer that supports a limit of characters on every
 // line, but doesn't do any word wrapping automatically.
 func NewMaxWidthWriter(w io.Writer, maxWidth uint) io.Writer {
 	return &maxWidthWriter{
 		maxWidth: maxWidth,
 		writer:   w,
 	}
 }
 
 func (m maxWidthWriter) Write(p []byte) (nn int, err error) {
 	for _, b := range p {
 		if m.currentWidth == m.maxWidth {
 			m.writer.Write([]byte{'\n'})
 			m.currentWidth = 0
 		}
 		if b == '\n' {
 			m.currentWidth = 0
 		}
 		_, err := m.writer.Write([]byte{b})
 		if err != nil {
 			return int(m.written), err
 		}
 		m.written++
 		m.currentWidth++
 	}
 	return len(p), nil
 }