diff options
author | James Moger <james.moger@gitblit.com> | 2014-03-22 16:34:27 -0400 |
---|---|---|
committer | James Moger <james.moger@gitblit.com> | 2014-04-10 18:58:09 -0400 |
commit | 4a69998080bd01180c5e46e4f4fd2c50586fea80 (patch) | |
tree | ed5a3cd8e943bb1cba31d58a306546c1bc62b487 /src/main/java/com/gitblit/utils | |
parent | bcc8a015ae552726742b4f437b2cb9e809270f96 (diff) | |
download | gitblit-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.java | 211 |
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); + } +} |