// 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 "" }
// 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 }