Skip to content

Instantly share code, notes, and snippets.

@jmini
Last active August 10, 2022 14:47
Show Gist options
  • Save jmini/80a813a483c2f1f54c278d19362031e6 to your computer and use it in GitHub Desktop.
Save jmini/80a813a483c2f1f54c278d19362031e6 to your computer and use it in GitHub Desktop.
Display ASCII Art tree
import java.util.ArrayList;
import java.util.List;
public class DisplayTree {
private static final boolean USE_UNICODE = false;
public static void main(final String[] args) {
final DisplayTree.Node node = new DisplayTree.Node("example")
.addChild(new Node("a"))
.addChild(new Node("b")
.addChild(new Node("b1")
.addChild(new Node("b11")
.addChild(new Node("b111")))
.addChild(new Node("b12")
.addChild(new Node("b121"))
.addChild(new Node("b122")
.addChild(new Node("b1221"))))))
.addChild(new Node("c"));
final StringBuilder sb = renderFolder(node);
System.out.println(sb.toString());
}
private static class Node {
private final String name;
private final List<Node> children;
public Node(final String name) {
this.name = name;
this.children = new ArrayList<>();
}
public String getName() {
return name;
}
public DisplayTree.Node addChild(final Node n) {
children.add(n);
return this;
}
}
private static StringBuilder renderFolder(final Node folder) {
return renderFolder(folder, new StringBuilder(), false, new ArrayList<>());
}
private static StringBuilder renderFolder(final Node folder, final StringBuilder sb, final boolean isLast, final List<Boolean> hierarchyTree) {
indent(sb, isLast, hierarchyTree).append(folder.getName()).append("\n");
for (int i = 0; i < folder.children.size(); i++) {
final boolean last = ((i + 1) == folder.children.size());
// this means if the current folder will still need to print subfolders at this level, if yes, then we need to continue print |
hierarchyTree.add(i != folder.children.size() - 1);
renderFolder(folder.children.get(i), sb, last, hierarchyTree);
// pop the last value as we return from a lower level to a higher level
hierarchyTree.remove(hierarchyTree.size() - 1);
}
return sb;
}
private static StringBuilder indent(final StringBuilder sb, final boolean isLast, final List<Boolean> hierarchyTree) {
final String indentContent = USE_UNICODE ? "\u2502 " : "| ";
for (int i = 0; i < hierarchyTree.size() - 1; ++i) {
// determines if we need to print | at this level to show the tree structure
// i.e. if this folder has a sibling foler that is going to be printed later
if (hierarchyTree.get(i).booleanValue()) {
sb.append(indentContent);
} else {
sb.append(" "); // otherwise print empty space
}
}
if (!hierarchyTree.isEmpty()) {
if (USE_UNICODE) {
sb.append(isLast ? "\u2514\u2500\u2500" : "\u251c\u2500\u2500").append(" ");
} else {
sb.append(isLast ? "\\---" : "+---").append(" ");
}
}
return sb;
}
}
@jmini
Copy link
Author

jmini commented Aug 10, 2022

Based on this StackOverflow response without having to have an existing folder structure.

See this also Representing a tree with ASCII or Unicode characters.

Output
With USE_UNICODE = true:

example
├── a
├── b
│   └── b1
│       ├── b11
│       │   └── b111
│       └── b12
│           ├── b121
│           └── b122
│               └── b1221
└── c

With USE_UNICODE = false:

example
+--- a
+--- b
|    \--- b1
|        +--- b11
|        |    \--- b111
|        \--- b12
|            +--- b121
|            \--- b122
|                \--- b1221
\--- c

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment