code: public static void printColumns(final Terminal terminal, final PrintWriter out, final Stream<String> values, final boolean horizontal) {
      int width = terminal.getWidth();
      List<AttributedString> strings = values.map(AttributedString::fromAnsi).collect(Collectors.toList());
  
      if (!strings.isEmpty()) {
        int max = strings.stream().mapToInt(AttributedString::columnLength).max().orElse(0);
        int c = Math.max(1, width / max);
        while (c > 1 && c * max + (c - 1) >= width) {
          c--;
        }
  
        int columns = c;
        int lines = (strings.size() + columns - 1) / columns;
        IntBinaryOperator index;
  
        if (horizontal) {
          index = (i, j) -> i * columns + j;
        }
        else {
          index = (i, j) -> j * lines + i;
        }
  
        AttributedStringBuilder buff = new AttributedStringBuilder();
        for (int i = 0; i < lines; i++) {
          for (int j = 0; j < columns; j++) {
            int idx = index.applyAsInt(i, j);
            if (idx < strings.size()) {
              AttributedString str = strings.get(idx);
              boolean hasRightItem = j < columns - 1 && index.applyAsInt(i, j + 1) < strings.size();
              buff.append(str);
              if (hasRightItem) {
                for (int k = 0; k <= max - str.length(); k++) {
                  buff.append(' ');
                }
              }
            }
          }
          buff.append('\n');
        }
  
        out.print(buff.toAnsi(terminal));
      }
    }
docs: Adapted from: https://github.com/apache/felix/blob/trunk/gogo/jline/src/main/java/org/apache/felix/gogo/jline/Posix.java