/* * Copyright 2015 the original author or authors. * * 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 org.springframework.shell.table; /** * A SizeConstraints implementation that is tailored to rendering a series * of {@literal key = value} pairs. Computes extents so that equal signs (or any other * configurable delimiter) line up vertically. * * @author Eric Bottard */ public class KeyValueSizeConstraints implements SizeConstraints { private final String delimiter; public KeyValueSizeConstraints(String delimiter) { this.delimiter = delimiter; } private static String leftTrim(String raw) { int start = 0; int length = raw.length(); while (start < length && raw.charAt(start) == ' ') { start++; } return raw.substring(start); } private static String rightTrim(String raw) { int end = raw.length(); while (end > 0 && raw.charAt(end - 1) == ' ') { end--; } return raw.substring(0, end); } @Override public Extent width(String[] raw, int tableWidth, int nbColumns) { // We need to make sure we take care of the case where we have // k = long-value // long-key = v // as the real maximal extent is size(long-key) + size( = ) + size(long-value) // The minimal extent in the example above is size(long-value) int maxLeft = 0; int maxRight = 0; int min = 0; for (String line : raw) { String lineToConsider = line.trim(); int offset = lineToConsider.indexOf(delimiter); if (offset != -1) { // Compute minimal case (line can be split, decide where to put the delimiter) String minimalLeftPart = lineToConsider.substring(0, offset).trim(); String minimalRightPart = lineToConsider.substring(offset + delimiter.length()).trim(); int left = minimalLeftPart.length(); int right = minimalRightPart.length(); int case1 = Math.max(left, right + leftTrim(delimiter).length()); int case2 = Math.max(left + rightTrim(delimiter).length(), right); int bestMin = Math.min(case1, case2); min = Math.max(min, bestMin); // Compute maximal case (sum of worst case on left and right) maxLeft = Math.max(maxLeft, offset); int after = lineToConsider.length() - offset - delimiter.length(); maxRight = Math.max(maxRight, after); } else { min = Math.max(min, lineToConsider.length()); } } return new Extent(min, maxLeft + delimiter.length() + maxRight); } }