// FormatLines formats the StatLines as a table in the terminal ui
func (ilf *InteractiveLineFormatter) FormatLines(lines []*line.StatLine, headerKeys []string, keyNames map[string]string) string {
	// keep ordering consistent
	sort.Sort(line.StatLines(lines))

	if ilf.includeHeader {
		headerLine := &line.StatLine{
			Fields: keyNames,
		}
		lines = append([]*line.StatLine{headerLine}, lines...)
	}

	// add new rows and columns when new hosts and stats are shown
	for len(ilf.table) < len(headerKeys) {
		ilf.table = append(ilf.table, new(column))
	}
	for _, column := range ilf.table {
		for len(column.cells) < len(lines) {
			column.cells = append(column.cells, new(cell))
		}
	}

	for i, column := range ilf.table {
		key := headerKeys[i]
		for j, cell := range column.cells {
			// i, j <=> col, row
			l := lines[j]
			if l.Error != nil && i == 0 {
				cell.text = fmt.Sprintf("%s: %s", l.Fields["host"], l.Error)
				cell.feed = true
				continue
			}
			newText := l.Fields[key]
			cell.changed = cell.text != newText
			cell.text = newText
			cell.feed = false
			cell.header = j == 0 && ilf.includeHeader
			if w := len(cell.text); w > column.width {
				column.width = w
			}
		}
	}

	ilf.update()
	return ""
}
Example #2
0
// FormatLines formats the StatLines as a grid
func (glf *GridLineFormatter) FormatLines(lines []*line.StatLine, headerKeys []string, keyNames map[string]string) string {
	buf := &bytes.Buffer{}

	// Sort the stat lines by hostname, so that we see the output
	// in the same order for each snapshot
	sort.Sort(line.StatLines(lines))

	// Print the columns that are enabled
	for _, key := range headerKeys {
		header := keyNames[key]
		glf.WriteCell(header)
	}
	glf.EndRow()

	for _, l := range lines {
		if l.Printed && l.Error == nil {
			l.Error = fmt.Errorf("no data received")
		}
		l.Printed = true

		if l.Error != nil {
			glf.WriteCell(l.Fields["host"])
			glf.Feed(l.Error.Error())
			continue
		}

		for _, key := range headerKeys {
			glf.WriteCell(l.Fields[key])
		}
		glf.EndRow()
	}
	glf.Flush(buf)

	// clear the flushed data
	glf.Reset()

	gridLine := buf.String()

	if glf.prevLineCount != len(lines) {
		glf.index = 0
	}
	glf.prevLineCount = len(lines)

	if !glf.includeHeader || glf.index != 0 {
		// Strip out the first line of the formatted output,
		// which contains the headers. They've been left in up until this point
		// in order to force the formatting of the columns to be wide enough.
		firstNewLinePos := strings.Index(gridLine, "\n")
		if firstNewLinePos >= 0 {
			gridLine = gridLine[firstNewLinePos+1:]
		}
	}
	glf.index++
	if glf.index == headerInterval {
		glf.index = 0
	}

	if len(lines) > 1 {
		// For multi-node stats, add an extra newline to tell each block apart
		gridLine = fmt.Sprintf("\n%s", gridLine)
	}
	glf.increment()
	return gridLine
}