franta-hg@123: /** franta-hg@123: * SQL-DK franta-hg@123: * Copyright © 2014 František Kučera (frantovo.cz) franta-hg@123: * franta-hg@123: * This program is free software: you can redistribute it and/or modify franta-hg@123: * it under the terms of the GNU General Public License as published by franta-hg@123: * the Free Software Foundation, either version 3 of the License, or franta-hg@123: * (at your option) any later version. franta-hg@123: * franta-hg@123: * This program is distributed in the hope that it will be useful, franta-hg@123: * but WITHOUT ANY WARRANTY; without even the implied warranty of franta-hg@123: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the franta-hg@123: * GNU General Public License for more details. franta-hg@123: * franta-hg@123: * You should have received a copy of the GNU General Public License franta-hg@123: * along with this program. If not, see . franta-hg@123: */ franta-hg@123: package info.globalcode.sql.dk.formatting; franta-hg@123: franta-hg@123: import info.globalcode.sql.dk.ColorfulPrintWriter.TerminalColor; franta-hg@123: import java.util.ArrayList; franta-hg@123: import java.util.List; franta-hg@123: import static info.globalcode.sql.dk.Functions.lpad; franta-hg@123: import static info.globalcode.sql.dk.Functions.rpad; franta-hg@123: import static info.globalcode.sql.dk.Functions.repeat; franta-hg@123: franta-hg@123: /** franta-hg@155: * Longer values are line-wrapped – the cell then contains multiple lines. Marks are added to franta-hg@155: * signalize forced line ends (not present in original data). franta-hg@123: * franta-hg@123: * @author Ing. František Kučera (frantovo.cz) franta-hg@123: */ franta-hg@123: public class TabularWrappingFormatter extends TabularFormatter { franta-hg@123: franta-hg@123: public static final String NAME = "tabular-wrapping"; // bash-completion:formatter franta-hg@123: private List currentRow; franta-hg@123: franta-hg@123: public TabularWrappingFormatter(FormatterContext formatterContext) { franta-hg@123: super(formatterContext); franta-hg@123: } franta-hg@123: franta-hg@123: @Override franta-hg@142: public void writeStartResultSet(ColumnsHeader header) { franta-hg@142: super.writeStartResultSet(header); franta-hg@123: currentRow = new ArrayList<>(header.getColumnCount()); franta-hg@123: } franta-hg@123: franta-hg@123: @Override franta-hg@123: protected void writeColumnValueInternal(Object value) { franta-hg@123: boolean rightAlign = value instanceof Number || value instanceof Boolean; franta-hg@123: String valueString = String.valueOf(value); franta-hg@123: int columnWidth = getColumnWidth(getCurrentColumnsCount()) - 1; // -1 = space for new line symbol franta-hg@142: currentRow.add(wrapLines(valueString, columnWidth, rightAlign)); franta-hg@123: } franta-hg@123: franta-hg@123: @Override franta-hg@123: public void writeEndRow() { franta-hg@123: super.writeEndRow(); franta-hg@123: franta-hg@123: int wrappedLine = 0; franta-hg@123: boolean hasMoreWrappedLines; franta-hg@123: franta-hg@123: do { franta-hg@123: hasMoreWrappedLines = false; franta-hg@123: for (int i = 0; i < currentRow.size(); i++) { franta-hg@123: if (i == 0) { franta-hg@123: printTableIndent(); franta-hg@123: printTableBorder("│ "); franta-hg@123: } else { franta-hg@123: printTableBorder(" │ "); franta-hg@123: } franta-hg@123: String[] columnArray = currentRow.get(i); franta-hg@123: if (wrappedLine < columnArray.length) { franta-hg@169: printValueWithWhitespaceReplaced(columnArray[wrappedLine]); franta-hg@123: franta-hg@123: if (wrappedLine < columnArray.length - 1) { franta-hg@123: out.print(TerminalColor.Red, "↩"); franta-hg@123: hasMoreWrappedLines = true; franta-hg@123: } else { franta-hg@123: out.print(" "); franta-hg@123: } franta-hg@123: franta-hg@123: } else { franta-hg@123: out.print(repeat(' ', getColumnWidth(i + 1))); franta-hg@123: } franta-hg@123: franta-hg@123: if (i == (currentRow.size() - 1)) { franta-hg@123: printTableBorder(" │"); franta-hg@123: } franta-hg@123: } franta-hg@123: out.println(); franta-hg@123: out.flush(); franta-hg@123: wrappedLine++; franta-hg@123: } while (hasMoreWrappedLines); franta-hg@123: franta-hg@123: currentRow.clear(); franta-hg@123: } franta-hg@123: franta-hg@123: @Override franta-hg@123: public void writeEndRowInternal() { franta-hg@123: // already done – wrapped row ends franta-hg@123: } franta-hg@123: franta-hg@142: private static String[] wrapLines(String s, int width, boolean rightAlign) { franta-hg@123: String[] array = new String[(s.length() - 1) / width + 1]; franta-hg@123: for (int i = 0; i < array.length; i++) { franta-hg@123: if (i == array.length - 1) { franta-hg@123: String part = s.substring(i * width, s.length()); franta-hg@123: array[i] = rightAlign ? lpad(part, width) : rpad(part, width); franta-hg@123: } else { franta-hg@123: array[i] = s.substring(i * width, (i + 1) * width); franta-hg@123: } franta-hg@123: } franta-hg@123: return array; franta-hg@123: } franta-hg@123: }