![JAR search and dependency download from the Maven repository](/logo.png)
io.hyperfoil.cli.Table Maven / Gradle / Ivy
package io.hyperfoil.cli;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function;
import java.util.stream.Stream;
import org.aesh.utils.ANSI;
import io.hyperfoil.core.util.Util;
public class Table {
private boolean boldHeader = true;
private Function rowPrefix;
private Function rowSuffix;
private final List titles = new ArrayList<>();
private final List> functions = new ArrayList<>();
private final List aligns = new ArrayList<>();
public Table boldHeader(boolean boldHeader) {
this.boldHeader = boldHeader;
return this;
}
public Table rowPrefix(Function rowPrefix) {
if (this.rowPrefix != null) {
throw new IllegalStateException("Row prefix already set.");
}
this.rowPrefix = rowPrefix;
return this;
}
public Table rowSuffix(Function rowSuffix) {
if (this.rowSuffix != null) {
throw new IllegalStateException("Row suffix already set.");
}
this.rowSuffix = rowSuffix;
return this;
}
public Table column(String title, Function func) {
return column(title, func, Align.LEFT);
}
public Table columnInt(String title, Function func) {
return column(title, value -> String.valueOf(func.apply(value)), Align.RIGHT);
}
public Table columnLong(String title, Function func) {
return column(title, value -> String.valueOf(func.apply(value)), Align.RIGHT);
}
public Table columnNanos(String title, Function func) {
return column(title, value -> Util.prettyPrintNanos(func.apply(value)), Align.RIGHT);
}
public Table column(String title, Function func, Align align) {
titles.add(title);
functions.add(func);
aligns.add(align);
return this;
}
public String print(String keyTitle, Map> map) {
ArrayList titles = new ArrayList<>();
titles.add(keyTitle);
titles.addAll(this.titles);
ArrayList aligns = new ArrayList<>();
aligns.add(Align.LEFT);
aligns.addAll(this.aligns);
ArrayList prefixes = rowPrefix == null ? null : new ArrayList<>();
ArrayList suffixes = rowSuffix == null ? null : new ArrayList<>();
ArrayList values = new ArrayList<>();
int[] width = titles.stream().mapToInt(Table::width).toArray();
map.forEach((key, value) -> {
AtomicBoolean first = new AtomicBoolean(true);
value.forEach(item -> {
if (rowPrefix != null) {
prefixes.add(rowPrefix.apply(item));
}
if (rowSuffix != null) {
suffixes.add(rowSuffix.apply(item));
}
String[] row = new String[functions.size() + 1];
row[0] = first.compareAndSet(true, false) ? key : "";
width[0] = Math.max(width[0], width(key));
for (int i = 1; i < row.length; ++i) {
row[i] = functions.get(i - 1).apply(item);
if (row[i] == null) {
row[i] = "";
}
width[i] = Math.max(width[i], width(row[i]));
}
values.add(row);
});
});
return print(titles, prefixes, values, suffixes, aligns, width);
}
public String print(Stream stream) {
ArrayList values = new ArrayList<>();
ArrayList prefixes = rowPrefix == null ? null : new ArrayList<>();
ArrayList suffixes = rowSuffix == null ? null : new ArrayList<>();
int[] width = titles.stream().mapToInt(Table::width).toArray();
stream.forEach(item -> {
if (rowPrefix != null) {
prefixes.add(rowPrefix.apply(item));
}
if (rowSuffix != null) {
suffixes.add(rowSuffix.apply(item));
}
String[] row = new String[functions.size()];
for (int i = 0; i < row.length; ++i) {
row[i] = functions.get(i).apply(item);
if (row[i] == null) {
row[i] = "";
}
width[i] = Math.max(width[i], width(row[i]));
}
values.add(row);
});
return print(titles, prefixes, values, suffixes, aligns, width);
}
private static int width(String str) {
int width = 0;
for (int i = 0; i < str.length(); ++i) {
if (str.charAt(i) == '\u001b') {
++i;
while (i < str.length()) {
char c = str.charAt(i);
if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z') break;
++i;
}
} else {
++width;
}
}
return width;
}
private String print(List titles, List prefixes, List values, List suffixes, List aligns, int[] width) {
StringBuilder sb = new StringBuilder();
if (boldHeader) {
sb.append(ANSI.BOLD);
}
for (int i = 0; i < titles.size() - 1; ++i) {
String title = titles.get(i);
sb.append(title);
pad(sb, width[i] - width(title) + 2);
}
sb.append(titles.get(titles.size() - 1));
if (boldHeader) {
sb.append(ANSI.RESET);
}
sb.append('\n');
int prefixLength = prefixes == null ? 0 : prefixes.stream().filter(Objects::nonNull).mapToInt(Table::width).max().orElse(0);
int suffixLength = prefixes == null ? 0 : prefixes.stream().filter(Objects::nonNull).mapToInt(Table::width).max().orElse(0);
int rowNumber = 0;
for (String[] row : values) {
String prefix = prefixes == null ? null : prefixes.get(rowNumber);
if (prefix != null) {
sb.append(prefix);
pad(sb, prefixLength - width(prefix));
}
for (int i = 0; i < row.length; ++i) {
Align align = aligns.get(i);
if (align == Align.RIGHT) {
pad(sb, width[i] - width(row[i]));
}
sb.append(row[i]);
if (align == Align.LEFT) {
pad(sb, width[i] - width(row[i]));
}
sb.append(" ");
}
String suffix = suffixes == null ? null : suffixes.get(rowNumber);
if (suffix != null) {
sb.append(suffix);
pad(sb, suffixLength - width(suffix));
}
sb.append('\n');
++rowNumber;
}
return sb.toString();
}
private static void pad(StringBuilder sb, int n) {
for (int i = 0; i < n; ++i) {
sb.append(' ');
}
}
public enum Align {
LEFT,
RIGHT
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy