Skip to content

Commit

Permalink
prnt command: improved heterogeneous object list printing
Browse files Browse the repository at this point in the history
  • Loading branch information
mattirn committed Mar 16, 2020
1 parent c41e2df commit 1feab62
Showing 1 changed file with 137 additions and 111 deletions.
248 changes: 137 additions & 111 deletions builtins/src/main/java/org/jline/builtins/ConsoleEngineImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ public void setObjectToString(Map<Class<?>, Function<Object, String>> objectToSt

/**
* Highlight column value
* @param highlightValue key: regex for column name, value: highlight function
* @param highlightValue key: regex for column name, value: highlight function
*/
public void setHighlightValue(Map<String, Function<Object, AttributedString>> highlightValue) {
this.highlightValue = highlightValue;
Expand Down Expand Up @@ -757,7 +757,7 @@ public boolean executeWidget(Object function) {

@SuppressWarnings("unchecked")
private Map<String,Object> consoleOptions() {
return engine.hasVariable(VAR_CONSOLE_OPTIONS) ? (Map<String, Object>) engine.get(VAR_CONSOLE_OPTIONS)
return engine.hasVariable(VAR_CONSOLE_OPTIONS) ? (Map<String, Object>) engine.get(VAR_CONSOLE_OPTIONS)
: new HashMap<>();
}

Expand Down Expand Up @@ -1142,7 +1142,7 @@ private AttributedString highlightValue(Map<String, Object> options, String colu
}
return out;
}

@SuppressWarnings("unchecked")
private List<Object> objectToList(Object obj) {
List<Object> out = new ArrayList<>();
Expand Down Expand Up @@ -1184,130 +1184,138 @@ private List<AttributedString> highlight(Map<String, Object> options, Object obj
out.add(highlightValue(options, null, objectToString(options, obj)));
}
} else {
Object elem = collection.iterator().next();
boolean convert = canConvert(elem);
if ((elem instanceof Map || convert) && !options.containsKey("toString")) {
Map<String, Object> map = convert ? objectToMap(options, elem) : keysToString((Map<Object, Object>)elem);
List<String> _header = null;
List<String> columnsIn = optionList("columnsIn", options);
List<String> columnsOut = !options.containsKey("all") ? optionList("columnsOut", options)
: new ArrayList<>();
if (options.containsKey("columns")) {
_header = (List<String>)options.get("columns");
} else {
_header = columnsIn;
_header.addAll(map.keySet().stream().filter(k -> !columnsIn.contains(k) && !hasMatch(columnsOut, k))
.collect(Collectors.toList()));
}
List<String> header = new ArrayList<>();
List<Integer> columns = new ArrayList<>();
int headerWidth = 0;
for (int i = 0; i < _header.size(); i++) {
if (!map.containsKey(_header.get(i).split("\\.")[0])) {
continue;
}
try {
Object elem = collection.iterator().next();
boolean convert = canConvert(elem);
if ((elem instanceof Map || convert) && !options.containsKey("toString")) {
Map<String, Object> map = convert ? objectToMap(options, elem)
: keysToString((Map<Object, Object>) elem);
List<String> _header = null;
List<String> columnsIn = optionList("columnsIn", options);
List<String> columnsOut = !options.containsKey("all") ? optionList("columnsOut", options)
: new ArrayList<>();
if (options.containsKey("columns")) {
// do nothing
} else if (!options.containsKey("structsOnTable")) {
Object val = mapValue(options, _header.get(i), map);
if (val == null || !simpleObject(val)) {
_header = (List<String>) options.get("columns");
} else {
_header = columnsIn;
_header.addAll(map.keySet().stream()
.filter(k -> !columnsIn.contains(k) && !hasMatch(columnsOut, k))
.collect(Collectors.toList()));
}
List<String> header = new ArrayList<>();
List<Integer> columns = new ArrayList<>();
int headerWidth = 0;
for (int i = 0; i < _header.size(); i++) {
if (!map.containsKey(_header.get(i).split("\\.")[0])) {
continue;
}
}
header.add(_header.get(i));
columns.add(_header.get(i).length() + 1);
headerWidth += _header.get(i).length() + 1;
if (headerWidth > width) {
break;
}
}
for (Object o : collection) {
for (int i = 0; i < header.size(); i++) {
Map<String, Object> m = convert ? objectToMap(options, o) : keysToString((Map<Object, Object>)o);
if (engine.toString(m.get(header.get(i))).length() > columns.get(i) - 1) {
columns.set(i, highlightMapValue(options, header.get(i), m).columnLength() + 1);
if (options.containsKey("columns")) {
// do nothing
} else if (!options.containsKey("structsOnTable")) {
Object val = mapValue(options, _header.get(i), map);
if (val == null || !simpleObject(val)) {
continue;
}
}
}
}
columns.add(0, 0);
toTabStops(columns, rownum);
AttributedStringBuilder asb = new AttributedStringBuilder().tabs(columns);
int firstColumn = 0;
if (rownum) {
asb.append("\t");
firstColumn = 1;
}
for (int i = 0; i < header.size(); i++) {
asb.append(header.get(i), AttributedStyle.DEFAULT.foreground(AttributedStyle.BLUE + AttributedStyle.BRIGHT));
asb.append("\t");
}
out.add(truncate(asb, width));
Integer row = 0;
for (Object o : collection) {
AttributedStringBuilder asb2 = new AttributedStringBuilder().tabs(columns);
if (rownum) {
asb2.append(addPadding(row.toString(), columns.get(1) - 1), AttributedStyle.DEFAULT.foreground(AttributedStyle.BLUE + AttributedStyle.BRIGHT));
asb2.append("\t");
row++;
}
for (int i = 0; i < header.size(); i++) {
Map<String, Object> m = convert ? objectToMap(options, o) : keysToString((Map<Object, Object>)o);
AttributedString v = highlightMapValue(options, header.get(i), m);
if (isNumber(v.toString())) {
v = addPadding(v, columns.get(firstColumn + i + 1) - columns.get(firstColumn + i) - 1);
header.add(_header.get(i));
columns.add(_header.get(i).length() + 1);
headerWidth += _header.get(i).length() + 1;
if (headerWidth > width) {
break;
}
asb2.append(v);
asb2.append("\t");
}
out.add(asb2.subSequence(0, width));
}
} else if (collectionObject(elem) && !options.containsKey("toString")) {
List<Integer> columns = new ArrayList<>();
for (Object o : collection) {
List<Object> inner = objectToList(o);
for (int i = 0; i < inner.size(); i++) {
int len1 = engine.toString(inner.get(i)).length() + 1;
if (columns.size() <= i) {
columns.add(len1);
} else if (len1 > columns.get(i)) {
columns.set(i, len1);
for (Object o : collection) {
if (o.getClass() != elem.getClass()) {
throw new Exception();
}
for (int i = 0; i < header.size(); i++) {
Map<String, Object> m = convert ? objectToMap(options, o)
: keysToString((Map<Object, Object>) o);
if (engine.toString(m.get(header.get(i))).length() > columns.get(i) - 1) {
columns.set(i, highlightMapValue(options, header.get(i), m).columnLength() + 1);
}
}
}
}
toTabStops(columns, rownum);
Integer row = 0;
int firstColumn = rownum ? 1 : 0;
for (Object o : collection) {
columns.add(0, 0);
toTabStops(columns, rownum);
AttributedStringBuilder asb = new AttributedStringBuilder().tabs(columns);
int firstColumn = 0;
if (rownum) {
asb.append(addPadding(row.toString(), columns.get(1) - 1), AttributedStyle.DEFAULT.foreground(AttributedStyle.BLUE + AttributedStyle.BRIGHT));
asb.append("\t");
row++;
firstColumn = 1;
}
List<Object> inner = objectToList(o);
for (int i = 0; i < inner.size(); i++) {
AttributedString v = highlightValue(options, null, inner.get(i));
if (isNumber(v.toString())) {
v = addPadding(v, columns.get(firstColumn + i + 1) - columns.get(firstColumn + i) - 1);
}
asb.append(v);
for (int i = 0; i < header.size(); i++) {
asb.append(header.get(i), AttributedStyle.DEFAULT
.foreground(AttributedStyle.BLUE + AttributedStyle.BRIGHT));
asb.append("\t");
}
out.add(truncate(asb, width));
}
} else {
Integer row = 0;
Integer tabsize = ((Integer)collection.size()).toString().length() + 1;
for (Object o: collection) {
AttributedStringBuilder asb = new AttributedStringBuilder().tabs(tabsize);
if (rownum) {
asb.append(addPadding(row.toString(), tabsize - 1), AttributedStyle.DEFAULT.foreground(AttributedStyle.BLUE + AttributedStyle.BRIGHT));
asb.append("\t");
row++;
Integer row = 0;
for (Object o : collection) {
AttributedStringBuilder asb2 = new AttributedStringBuilder().tabs(columns);
if (rownum) {
asb2.append(addPadding(row.toString(), columns.get(1) - 1), AttributedStyle.DEFAULT
.foreground(AttributedStyle.BLUE + AttributedStyle.BRIGHT));
asb2.append("\t");
row++;
}
for (int i = 0; i < header.size(); i++) {
Map<String, Object> m = convert ? objectToMap(options, o)
: keysToString((Map<Object, Object>) o);
AttributedString v = highlightMapValue(options, header.get(i), m);
if (isNumber(v.toString())) {
v = addPadding(v,
columns.get(firstColumn + i + 1) - columns.get(firstColumn + i) - 1);
}
asb2.append(v);
asb2.append("\t");
}
out.add(asb2.subSequence(0, width));
}
asb.append(highlightValue(options, null, objectToString(options, o)));
out.add(truncate(asb, width));
} else if (collectionObject(elem) && !options.containsKey("toString")) {
List<Integer> columns = new ArrayList<>();
for (Object o : collection) {
List<Object> inner = objectToList(o);
for (int i = 0; i < inner.size(); i++) {
int len1 = engine.toString(inner.get(i)).length() + 1;
if (columns.size() <= i) {
columns.add(len1);
} else if (len1 > columns.get(i)) {
columns.set(i, len1);
}
}
}
toTabStops(columns, rownum);
Integer row = 0;
int firstColumn = rownum ? 1 : 0;
for (Object o : collection) {
AttributedStringBuilder asb = new AttributedStringBuilder().tabs(columns);
if (rownum) {
asb.append(addPadding(row.toString(), columns.get(1) - 1), AttributedStyle.DEFAULT
.foreground(AttributedStyle.BLUE + AttributedStyle.BRIGHT));
asb.append("\t");
row++;
}
List<Object> inner = objectToList(o);
for (int i = 0; i < inner.size(); i++) {
AttributedString v = highlightValue(options, null, inner.get(i));
if (isNumber(v.toString())) {
v = addPadding(v,
columns.get(firstColumn + i + 1) - columns.get(firstColumn + i) - 1);
}
asb.append(v);
asb.append("\t");
}
out.add(truncate(asb, width));
}
} else {
out = highlightList(options, collection, width);
}
} catch (Exception e) {
if(consoleOption("trace", 0) > 0) {
trace(e);
}
out = highlightList(options, collection, width);
}
}
}
Expand All @@ -1319,6 +1327,24 @@ private List<AttributedString> highlight(Map<String, Object> options, Object obj
return out;
}

public List<AttributedString> highlightList(Map<String, Object> options, List<Object> collection, int width) {
List<AttributedString> out = new ArrayList<>();
Integer row = 0;
Integer tabsize = ((Integer) collection.size()).toString().length() + 1;
for (Object o : collection) {
AttributedStringBuilder asb = new AttributedStringBuilder().tabs(tabsize);
if (options.containsKey("rownum")) {
asb.append(addPadding(row.toString(), tabsize - 1), AttributedStyle.DEFAULT
.foreground(AttributedStyle.BLUE + AttributedStyle.BRIGHT));
asb.append("\t");
row++;
}
asb.append(highlightValue(options, null, objectToString(options, o)));
out.add(truncate(asb, width));
}
return out;
}

private boolean collectionObject(Object obj) {
return obj instanceof Iterator || obj instanceof Iterable || obj instanceof Object[] || obj instanceof Collection;
}
Expand Down Expand Up @@ -1369,7 +1395,7 @@ private List<AttributedString> highlightMap(Map<String, Object> options, Map<Str
}
} else {
asb.append(val);
out.add(truncate(asb, width));
out.add(truncate(asb, width));
}
} else {
if (val.contains('\n')) {
Expand Down

0 comments on commit 1feab62

Please sign in to comment.