summaryrefslogtreecommitdiffstats
path: root/src/main/java/com/gitblit/utils
diff options
context:
space:
mode:
authorJames Moger <james.moger@gitblit.com>2014-03-22 16:34:27 -0400
committerJames Moger <james.moger@gitblit.com>2014-04-10 18:58:09 -0400
commit4a69998080bd01180c5e46e4f4fd2c50586fea80 (patch)
treeed5a3cd8e943bb1cba31d58a306546c1bc62b487 /src/main/java/com/gitblit/utils
parentbcc8a015ae552726742b4f437b2cb9e809270f96 (diff)
downloadgitblit-4a69998080bd01180c5e46e4f4fd2c50586fea80.tar.gz
gitblit-4a69998080bd01180c5e46e4f4fd2c50586fea80.zip
Integrate a patched version of FlipTables and improve ls output
Diffstat (limited to 'src/main/java/com/gitblit/utils')
-rw-r--r--src/main/java/com/gitblit/utils/FlipTable.java211
1 files changed, 211 insertions, 0 deletions
diff --git a/src/main/java/com/gitblit/utils/FlipTable.java b/src/main/java/com/gitblit/utils/FlipTable.java
new file mode 100644
index 00000000..1f788403
--- /dev/null
+++ b/src/main/java/com/gitblit/utils/FlipTable.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright 2014 Jake Wharton
+ * Copyright 2014 gitblit.com.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.gitblit.utils;
+
+
+/**
+ * This is a forked version of FlipTables which supports controlling the
+ * displayed borders.
+ *
+ * FULL = all borders
+ * BODY_COLS = header + perimeter + column separators
+ * COLS = header + column separators
+ * BODY = header + perimeter
+ * HEADER = header only
+ *
+ * <pre>
+ * ╔═════════════╤════════════════════════════╤══════════════╗
+ * ║ Name │ Function │ Author ║
+ * ╠═════════════╪════════════════════════════╪══════════════╣
+ * ║ Flip Tables │ Pretty-print a text table. │ Jake Wharton ║
+ * ╚═════════════╧════════════════════════════╧══════════════╝
+ * </pre>
+ */
+public final class FlipTable {
+ private static final String EMPTY = "(empty)";
+
+ public static enum Borders {
+ FULL(7), BODY_COLS(5), COLS(4), BODY(1), HEADER(0);
+
+ final int bitmask;
+
+ private Borders(int bitmask) {
+ this.bitmask = bitmask;
+ }
+
+ boolean body() {
+ return isset(0x1);
+ }
+
+ boolean rows() {
+ return isset(0x2);
+ }
+
+ boolean columns() {
+ return isset(0x4);
+ }
+
+ boolean isset(int v) {
+ return (bitmask & v) == v;
+ }
+ }
+
+ /** Create a new table with the specified headers and row data. */
+ public static String of(String[] headers, String[][] data) {
+ return of(headers, data, Borders.FULL);
+ }
+
+ /** Create a new table with the specified headers and row data. */
+ public static String of(String[] headers, String[][] data, Borders borders) {
+ if (headers == null)
+ throw new NullPointerException("headers == null");
+ if (headers.length == 0)
+ throw new IllegalArgumentException("Headers must not be empty.");
+ if (data == null)
+ throw new NullPointerException("data == null");
+ return new FlipTable(headers, data, borders).toString();
+ }
+
+ private final String[] headers;
+ private final String[][] data;
+ private final Borders borders;
+ private final int columns;
+ private final int[] columnWidths;
+ private final int emptyWidth;
+
+ private FlipTable(String[] headers, String[][] data, Borders borders) {
+ this.headers = headers;
+ this.data = data;
+ this.borders = borders;
+
+ columns = headers.length;
+ columnWidths = new int[columns];
+ for (int row = -1; row < data.length; row++) {
+ String[] rowData = (row == -1) ? headers : data[row];
+ if (rowData.length != columns) {
+ throw new IllegalArgumentException(String.format("Row %s's %s columns != %s columns", row + 1,
+ rowData.length, columns));
+ }
+ for (int column = 0; column < columns; column++) {
+ for (String rowDataLine : rowData[column].split("\\n")) {
+ columnWidths[column] = Math.max(columnWidths[column], rowDataLine.length());
+ }
+ }
+ }
+
+ // Account for column dividers and their spacing.
+ int emptyWidth = 3 * (columns - 1);
+ for (int columnWidth : columnWidths) {
+ emptyWidth += columnWidth;
+ }
+ this.emptyWidth = emptyWidth;
+
+ if (emptyWidth < EMPTY.length()) {
+ // Make sure we're wide enough for the empty text.
+ columnWidths[columns - 1] += EMPTY.length() - emptyWidth;
+ }
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ printDivider(builder, "╔═╤═╗");
+ printData(builder, headers, true);
+ if (data.length == 0) {
+ if (borders.body()) {
+ printDivider(builder, "╠═╧═╣");
+ builder.append('║').append(pad(emptyWidth, EMPTY)).append("║\n");
+ printDivider(builder, "╚═══╝");
+ } else {
+ printDivider(builder, "╚═╧═╝");
+ builder.append(' ').append(pad(emptyWidth, EMPTY)).append(" \n");
+ }
+ } else {
+ for (int row = 0; row < data.length; row++) {
+ if (row == 0) {
+ if (borders.body()) {
+ if (borders.columns()) {
+ printDivider(builder, "╠═╪═╣");
+ } else {
+ printDivider(builder, "╠═╧═╣");
+ }
+ } else {
+ if (borders.columns()) {
+ printDivider(builder, "╚═╪═╝");
+ } else {
+ printDivider(builder, "╚═╧═╝");
+ }
+ }
+ } else if (borders.rows()) {
+ if (borders.columns()) {
+ printDivider(builder, "╟─┼─╢");
+ } else {
+ printDivider(builder, "╟─┼─╢");
+ }
+ }
+ printData(builder, data[row], false);
+ }
+ if (borders.body()) {
+ if (borders.columns()) {
+ printDivider(builder, "╚═╧═╝");
+ } else {
+ printDivider(builder, "╚═══╝");
+ }
+ }
+ }
+ return builder.toString();
+ }
+
+ private void printDivider(StringBuilder out, String format) {
+ for (int column = 0; column < columns; column++) {
+ out.append(column == 0 ? format.charAt(0) : format.charAt(2));
+ out.append(pad(columnWidths[column], "").replace(' ', format.charAt(1)));
+ }
+ out.append(format.charAt(4)).append('\n');
+ }
+
+ private void printData(StringBuilder out, String[] data, boolean isHeader) {
+ for (int line = 0, lines = 1; line < lines; line++) {
+ for (int column = 0; column < columns; column++) {
+ if (column == 0) {
+ if (isHeader || borders.body()) {
+ out.append('║');
+ } else {
+ out.append(' ');
+ }
+ } else if (isHeader || borders.columns()) {
+ out.append('│');
+ } else {
+ out.append(' ');
+ }
+ String[] cellLines = data[column].split("\\n");
+ lines = Math.max(lines, cellLines.length);
+ String cellLine = line < cellLines.length ? cellLines[line] : "";
+ out.append(pad(columnWidths[column], cellLine));
+ }
+ if (isHeader || borders.body()) {
+ out.append("║\n");
+ } else {
+ out.append('\n');
+ }
+ }
+ }
+
+ private static String pad(int width, String data) {
+ return String.format(" %1$-" + width + "s ", data);
+ }
+}