Code Monkey home page Code Monkey logo

ascii-table's Introduction

ASCII Tables for Java

Easily create and customize simple ASCII tables in Java. Based off nedtwigg/asciitable and klaus31/ascii-art-table.

How to get it?

Maven:

<dependency>
  <groupId>com.github.freva</groupId>
  <artifactId>ascii-table</artifactId>
  <version>1.8.0</version>
</dependency>

Gradle:

compile 'com.github.freva:ascii-table:1.8.0'

Basic case

String[] headers = {"", "Name", "Diameter", "Mass", "Atmosphere"};
String[][] data = {
        {"1", "Mercury", "0.382", "0.06", "minimal"},
        {"2", "Venus", "0.949", "0.82", "Carbon dioxide, Nitrogen"},
        {"3", "Earth", "1.000", "1.00", "Nitrogen, Oxygen, Argon"},
        {"4", "Mars", "0.532", "0.11", "Carbon dioxide, Nitrogen, Argon"}};

System.out.println(AsciiTable.getTable(headers, data));

Will print

+---+---------+----------+------+---------------------------------+
|   | Name    | Diameter | Mass | Atmosphere                      |
+---+---------+----------+------+---------------------------------+
| 1 | Mercury |    0.382 | 0.06 |                         minimal |
+---+---------+----------+------+---------------------------------+
| 2 |   Venus |    0.949 | 0.82 |        Carbon dioxide, Nitrogen |
+---+---------+----------+------+---------------------------------+
| 3 |   Earth |    1.000 | 1.00 |         Nitrogen, Oxygen, Argon |
+---+---------+----------+------+---------------------------------+
| 4 |    Mars |    0.532 | 0.11 | Carbon dioxide, Nitrogen, Argon |
+---+---------+----------+------+---------------------------------+

Table from Collections

List<Planet> planets = Arrays.asList(
        new Planet(1, "Mercury", 0.382, 0.06, "minimal"),
        new Planet(2, "Venus", 0.949, 0.82, "Carbon dioxide, Nitrogen"),
        new Planet(3, "Earth", 1.0, 1.0, "Nitrogen, Oxygen, Argon"),
        new Planet(4, "Mars", 0.532, 0.11, "Carbon dioxide, Nitrogen, Argon"));

System.out.println(AsciiTable.getTable(planets, Arrays.asList(
        new Column().with(planet -> Integer.toString(planet.num)),
        new Column().header("Name").with(planet -> planet.name),
        new Column().header("Diameter").with(planet -> String.format("%.03f", planet.diameter)),
        new Column().header("Mass").with(planet -> String.format("%.02f", planet.mass)),
        new Column().header("Atmosphere").with(planet -> planet.atmosphere))));

Prints the same table as above.

Column alignments

Horizontally align header and data columns independently to left, right and center:

System.out.println(AsciiTable.getTable(planets, Arrays.asList(
        new Column().with(planet -> Integer.toString(planet.num)),
        new Column().header("Name").headerAlign(HorizontalAlign.CENTER).dataAlign(HorizontalAlign.LEFT).with(planet -> planet.name),
        new Column().header("Diameter").with(planet -> String.format("%.03f", planet.diameter)),
        new Column().header("Mass").with(planet -> String.format("%.02f", planet.mass)),
        new Column().header("Atmosphere").headerAlign(HorizontalAlign.RIGHT).dataAlign(HorizontalAlign.CENTER).with(planet -> planet.atmosphere))));

Prints

+---+---------+----------+------+---------------------------------+
|   |  Name   | Diameter | Mass |                      Atmosphere |
+---+---------+----------+------+---------------------------------+
| 1 | Mercury |    0.382 | 0.06 |             minimal             |
+---+---------+----------+------+---------------------------------+
| 2 | Venus   |    0.949 | 0.82 |    Carbon dioxide, Nitrogen     |
+---+---------+----------+------+---------------------------------+
| 3 | Earth   |    1.000 | 1.00 |     Nitrogen, Oxygen, Argon     |
+---+---------+----------+------+---------------------------------+
| 4 | Mars    |    0.532 | 0.11 | Carbon dioxide, Nitrogen, Argon |
+---+---------+----------+------+---------------------------------+

Min/max column width

Limit any column to certain width:

System.out.println(AsciiTable.getTable(planets, Arrays.asList(
        new Column().minWidth(5).with(planet -> Integer.toString(planet.num)),
        new Column().header("Name").with(planet -> planet.name),
        new Column().header("Diameter").with(planet -> String.format("%.03f", planet.diameter)),
        new Column().header("Mass").with(planet -> String.format("%.02f", planet.mass)),
        new Column().header("Atmosphere Composition").maxWidth(12).with(planet -> planet.atmosphere))));

Prints

+-----+---------+----------+------+--------+
|     | Name    | Diameter | Mass | Atmosp |
|     |         |          |      | here   |
+-----+---------+----------+------+--------+
|   1 | Mercury |    0.382 | 0.06 | minima |
|     |         |          |      |      l |
+-----+---------+----------+------+--------+
|   2 |   Venus |    0.949 | 0.82 | Carbon |
|     |         |          |      | dioxid |
|     |         |          |      |     e, |
|     |         |          |      | Nitrog |
|     |         |          |      |     en |
+-----+---------+----------+------+--------+
|   3 |   Earth |    1.000 | 1.00 | Nitrog |
|     |         |          |      |    en, |
|     |         |          |      | Oxygen |
|     |         |          |      |      , |
|     |         |          |      |  Argon |
+-----+---------+----------+------+--------+
|   4 |    Mars |    0.532 | 0.11 | Carbon |
|     |         |          |      | dioxid |
|     |         |          |      |     e, |
|     |         |          |      | Nitrog |
|     |         |          |      |    en, |
|     |         |          |      |  Argon |
+-----+---------+----------+------+--------+

Controlling overflow behaviour

By default when a cell reaches max column width, a newline is inserted before remainder of the text. Other possible behaviours are clipping and ellipsis:

System.out.println(AsciiTable.getTable(planets, Arrays.asList(
        new Column().header("Atmosphere Composition").maxWidth(12, OverflowBehaviour.NEWLINE).with(planet -> planet.atmosphere),
        new Column().header("Atmosphere Composition").maxWidth(12, OverflowBehaviour.CLIP_LEFT).with(planet -> planet.atmosphere),
        new Column().header("Atmosphere Composition").maxWidth(12, OverflowBehaviour.CLIP_RIGHT).with(planet -> planet.atmosphere),
        new Column().header("Atmosphere Composition").maxWidth(12, OverflowBehaviour.ELLIPSIS_LEFT).with(planet -> planet.atmosphere),
        new Column().header("Atmosphere Composition").maxWidth(12, OverflowBehaviour.ELLIPSIS_RIGHT).with(planet -> planet.atmosphere))));

Prints

+------------+------------+------------+------------+------------+
| Atmosphere | omposition | Atmosphere | …mposition | Atmospher… |
| Compositio |            |            |            |            |
| n          |            |            |            |            |
+------------+------------+------------+------------+------------+
|    minimal |    minimal |    minimal |    minimal |    minimal |
+------------+------------+------------+------------+------------+
|     Carbon | , Nitrogen | Carbon dio | … Nitrogen | Carbon di… |
|   dioxide, |            |            |            |            |
|   Nitrogen |            |            |            |            |
+------------+------------+------------+------------+------------+
|  Nitrogen, | gen, Argon | Nitrogen,  | …en, Argon | Nitrogen,… |
|    Oxygen, |            |            |            |            |
|      Argon |            |            |            |            |
+------------+------------+------------+------------+------------+
|     Carbon | gen, Argon | Carbon dio | …en, Argon | Carbon di… |
|   dioxide, |            |            |            |            |
|  Nitrogen, |            |            |            |            |
|      Argon |            |            |            |            |
+------------+------------+------------+------------+------------+

Bonus: The original line breaks are always preserved, so you can split your text however you want before making the table.

Footer

Special row at the end of the table that can be used to for example repeat the header if the table is really long, or display some summary information such as average or totals.

System.out.println(AsciiTable.getTable(planets, Arrays.asList(
        new Column().with(planet -> Integer.toString(planet.num)),
        new Column().header("Name").footer("Average").headerAlign(CENTER).dataAlign(RIGHT).with(planet -> planet.name),
        new Column().header("Diameter").headerAlign(RIGHT).dataAlign(CENTER).footerAlign(CENTER)
                .footer(String.format("%.03f", planets.stream().mapToDouble(planet -> planet.diameter).average().orElse(0)))
                .with(planet -> String.format("%.03f", planet.diameter)),
        new Column().header("Mass").headerAlign(RIGHT).dataAlign(LEFT)
                .footer(String.format("%.02f", planets.stream().mapToDouble(planet -> planet.mass).average().orElse(0)))
                .with(planet -> String.format("%.02f", planet.mass)),
        new Column().header("Atmosphere").headerAlign(LEFT).dataAlign(CENTER).with(planet -> planet.atmosphere))));

Prints

+---+---------+----------+------+---------------------------------+
|   |  Name   | Diameter | Mass | Atmosphere                      |
+---+---------+----------+------+---------------------------------+
| 1 | Mercury |  0.382   | 0.06 |             minimal             |
+---+---------+----------+------+---------------------------------+
| 2 |   Venus |  0.949   | 0.82 |    Carbon dioxide, Nitrogen     |
+---+---------+----------+------+---------------------------------+
| 3 |   Earth |  1.000   | 1.00 |     Nitrogen, Oxygen, Argon     |
+---+---------+----------+------+---------------------------------+
| 4 |    Mars |  0.532   | 0.11 | Carbon dioxide, Nitrogen, Argon |
+---+---------+----------+------+---------------------------------+
|   | Average |  0.716   | 0.50 |                                 |
+---+---------+----------+------+---------------------------------+

Builder

Using the builder from AsciiTable.builder() you can customize the table further, e.g. setting the line separator or outputting the table to an OutputStream:

try (OutputStream fos = Files.newOutputStream(Paths.get("table.txt"))) {
    AsciiTable.builder()
            .lineSeparator("\r\n")
            .border(AsciiTable.BASIC_ASCII_NO_OUTSIDE_BORDER)
            .data(planets, Arrays.asList(
                    new Column().with(planet -> Integer.toString(planet.num)),
                    new Column().header("Name").footer("Average").headerAlign(CENTER).dataAlign(RIGHT).with(planet -> planet.name),
                    new Column().header("Diameter").headerAlign(RIGHT).dataAlign(CENTER).footerAlign(CENTER)
                            .footer(String.format("%.03f", planets.stream().mapToDouble(planet -> planet.diameter).average().orElse(0)))
                            .with(planet -> String.format("%.03f", planet.diameter)),
                    new Column().header("Mass").headerAlign(RIGHT).dataAlign(LEFT)
                            .footer(String.format("%.02f", planets.stream().mapToDouble(planet -> planet.mass).average().orElse(0)))
                            .with(planet -> String.format("%.02f", planet.mass)),
                    new Column().header("Atmosphere").headerAlign(LEFT).dataAlign(CENTER).with(planet -> planet.atmosphere)))
            .writeTo(fos);
}

Border styles

Character[] borderStyle = ...;
System.out.println(AsciiTable.getTable(borderStyles, planets, Arrays.asList(
        new Column().with(planet -> Integer.toString(planet.num)),
        new Column().header("Name").footer("Average").headerAlign(CENTER).dataAlign(RIGHT).with(planet -> planet.name),
        new Column().header("Diameter").headerAlign(RIGHT).dataAlign(CENTER).footerAlign(CENTER)
                .footer(String.format("%.03f", planets.stream().mapToDouble(planet -> planet.diameter).average().orElse(0)))
                .with(planet -> String.format("%.03f", planet.diameter)),
        new Column().header("Mass").headerAlign(RIGHT).dataAlign(LEFT)
                .footer(String.format("%.02f", planets.stream().mapToDouble(planet -> planet.mass).average().orElse(0)))
                .with(planet -> String.format("%.02f", planet.mass)),
        new Column().header("Atmosphere").headerAlign(LEFT).dataAlign(CENTER).with(planet -> planet.atmosphere))));

Default style is AsciiTable.BASIC_ASCII


With borderStyle = AsciiTable.BASIC_ASCII_NO_OUTSIDE_BORDER, it prints

   |  Name   | Diameter | Mass | Atmosphere                      
---+---------+----------+------+---------------------------------
 1 | Mercury |  0.382   | 0.06 |             minimal             
---+---------+----------+------+---------------------------------
 2 |   Venus |  0.949   | 0.82 |    Carbon dioxide, Nitrogen     
---+---------+----------+------+---------------------------------
 3 |   Earth |  1.000   | 1.00 |     Nitrogen, Oxygen, Argon     
---+---------+----------+------+---------------------------------
 4 |    Mars |  0.532   | 0.11 | Carbon dioxide, Nitrogen, Argon 
---+---------+----------+------+---------------------------------
   | Average |  0.716   | 0.50 |                                 

With borderStyle = AsciiTable.BASIC_ASCII_NO_DATA_SEPARATORS, it prints

+---+---------+----------+------+---------------------------------+
|   |  Name   | Diameter | Mass | Atmosphere                      |
+---+---------+----------+------+---------------------------------+
| 1 | Mercury |  0.382   | 0.06 |             minimal             |
| 2 |   Venus |  0.949   | 0.82 |    Carbon dioxide, Nitrogen     |
| 3 |   Earth |  1.000   | 1.00 |     Nitrogen, Oxygen, Argon     |
| 4 |    Mars |  0.532   | 0.11 | Carbon dioxide, Nitrogen, Argon |
+---+---------+----------+------+---------------------------------+
|   | Average |  0.716   | 0.50 |                                 |
+---+---------+----------+------+---------------------------------+

With borderStyle = AsciiTable.BASIC_ASCII_NO_DATA_SEPARATORS_NO_OUTSIDE_BORDER, it prints

   |  Name   | Diameter | Mass | Atmosphere                      
---+---------+----------+------+---------------------------------
 1 | Mercury |  0.382   | 0.06 |             minimal             
 2 |   Venus |  0.949   | 0.82 |    Carbon dioxide, Nitrogen     
 3 |   Earth |  1.000   | 1.00 |     Nitrogen, Oxygen, Argon     
 4 |    Mars |  0.532   | 0.11 | Carbon dioxide, Nitrogen, Argon 
---+---------+----------+------+---------------------------------
   | Average |  0.716   | 0.50 |                                 

With borderStyle = AsciiTable.NO_BORDERS, it prints

     Name    Diameter  Mass  Atmosphere                      
 1  Mercury   0.382    0.06              minimal             
 2    Venus   0.949    0.82     Carbon dioxide, Nitrogen     
 3    Earth   1.000    1.00      Nitrogen, Oxygen, Argon     
 4     Mars   0.532    0.11  Carbon dioxide, Nitrogen, Argon 
    Average   0.716    0.50                                  

With borderStyle = AsciiTable.FANCY_ASCII, it prints

╔═══╤═════════╤══════════╤══════╤═════════════════════════════════╗
║   │  Name   │ Diameter │ Mass │ Atmosphere                      ║
╠═══╪═════════╪══════════╪══════╪═════════════════════════════════╣
║ 1 │ Mercury │  0.382   │ 0.06 │             minimal             ║
╟───┼─────────┼──────────┼──────┼─────────────────────────────────╢
║ 2 │   Venus │  0.949   │ 0.82 │    Carbon dioxide, Nitrogen     ║
╟───┼─────────┼──────────┼──────┼─────────────────────────────────╢
║ 3 │   Earth │  1.000   │ 1.00 │     Nitrogen, Oxygen, Argon     ║
╟───┼─────────┼──────────┼──────┼─────────────────────────────────╢
║ 4 │    Mars │  0.532   │ 0.11 │ Carbon dioxide, Nitrogen, Argon ║
╠═══╪═════════╪══════════╪══════╪═════════════════════════════════╣
║   │ Average │  0.716   │ 0.50 │                                 ║
╚═══╧═════════╧══════════╧══════╧═════════════════════════════════╝

Border styles is a Character array of length 29 and you can configure your own styles by passing in different array. To see which element in Character array corresponds to which element in the table:

Character[] borderStyles = "ABCDEFGHIJKLMNOPQRSTUVWXYZ123".chars().mapToObj(c -> (char)c).toArray(Character[]::new);

Prints

ABBBCBBBBBBBBBCBBBBBBBBBBCBBBBBBCBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBD
E   F  Name   F Diameter F Mass F Atmosphere                      G
HIIIJIIIIIIIIIJIIIIIIIIIIJIIIIIIJIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIK
L 1 M Mercury M  0.382   M 0.06 M             minimal             N
OPPPQPPPPPPPPPQPPPPPPPPPPQPPPPPPQPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPR
L 2 M   Venus M  0.949   M 0.82 M    Carbon dioxide, Nitrogen     N
OPPPQPPPPPPPPPQPPPPPPPPPPQPPPPPPQPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPR
L 3 M   Earth M  1.000   M 1.00 M     Nitrogen, Oxygen, Argon     N
OPPPQPPPPPPPPPQPPPPPPPPPPQPPPPPPQPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPR
L 4 M    Mars M  0.532   M 0.11 M Carbon dioxide, Nitrogen, Argon N
STTTUTTTTTTTTTUTTTTTTTTTTUTTTTTTUTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTV
W   X Average X  0.716   X 0.50 X                                 Y
Z111211111111121111111111211111121111111111111111111111111111111113

ascii-table's People

Contributors

freva avatar rosiecki avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

ascii-table's Issues

Make it possible to cut column data instead of word wrapping when using maxColumnWidth

Great utility, we started using this with Apache Camel

We print a table with Camel route status, and instead of word wrapping then I would like to make it automatic cut the excess length

new Column().header("Name").dataAlign(HorizontalAlign.LEFT).maxColumnWidth(30).with(r -> r.name),
new Column().header("Route ID").dataAlign(HorizontalAlign.LEFT).maxColumnWidth(30).with(r -> r.routeId),
new Column().header("From").dataAlign(HorizontalAlign.LEFT).maxColumnWidth(30).with(r -> r.from),

See screenshot for an example of what it does today with word wrap.

Cut column in start instead of end

I would like to be able to cut the column value in the start, so the visible text is the suffix text, eg

I have this class name sample.camel.MyCamelApplication which are shown in full in the PS command below

~/workspace ❯ camel ps
  PID   NAME                             AGE
 61818  sample.camel.MyCamelApplication   5s

However in the next command with more details I want to cut the class name in the beginning, eg:

~/workspace ❯ camel get
  PID   NAME                          CAMEL            PLATFORM            READY   STATE   AGE  TOTAL  FAILED  INFLIGHT  SINCE-LAST
 61818  sample.camel.MyCamelApplica…  3.19.0-SNAPSHOT  Spring Boot v2.7.3   1/1   Started   9s      3       0         0          0s

Should be `....camel.MyCamelApplication`

PS: Thanks for implementing the other features so quickly, we use this table library with joy at Apache Camel for our new CLI.

Using colour output leads to table miss alignment

I am experimenting with adding colour output via
https://github.com/fusesource/jansi

This is what for example Apache Maven, Spring Boot, etc uses to log in colour.

I wanted to mark Camel components that are in preview mode with a yellow colour, that are in a middle column. When doing this then the column width gets larger ... I just wanted to let you know and we can maybe work on having better color support over time.

See the screenshot below

Ansi color glitch in adjacent cell

Hi

Many thanks for this great table printer.

Just in case you want to see what we have been up to of late with Apache Camel, then we have a panel in the middle with 2 columns. When using ansi color then the 2nd panel will start out of position.

I think you have been aware of this and its tricky to solve. But just wanted to show you a real world use of this great util.

Screenshot 2023-11-03 at 13 11 28

Adding a column that spans entire table as child to each row

At Apache Camel we have a new for a master/child row that is something ala

Column A | Column B | Column C | Column D
Column E that spans the entire line
Column A | Column B | Column C | Column D
Column E that spans the entire line
Column A | Column B | Column C | Column D
Column E that spans the entire line

I only need one special column. Maybe something you can add as the last column in a table, and specify that is a child column or something.

Custom line/row separator

This is my table format

id   column1        column2                    column3          
---- --------------- ------------------------------ ------------------ 
 1   data11       data12                           data13
 2   data21       data22                           data23
 3   data31       data32                           data33
 4   data41       data42                           data43

I need to have empty line between each record to view the data clearly.

Add a utility method to get table rows as Collection

It would be flexible if you provide a utility method that simply returns collection of rows in the table.
To say exactly the result of below method.
private static List<String> getTableRows(int[] colWidths, HorizontalAlign[] headerAligns, HorizontalAlign[] dataAligns, HorizontalAlign[] footerAligns, Character[] borderChars, String[] header, String[][] data, String[] footer) {

using AsciiTable as email body

Hi, I hope it's ok to ask this here. I am using AsciiTable to create an email body and it seems to work fine on thunderbird, but its a bit broken on windows outlook.

i get this nice table in thunderbird:
image

this is what it displays on outlook

image

does anyone know anything i can do to get this working on outlook better? or any suggestions will be appreciated

Make it easier to define table structure and afterwards to select which columns to print

At Apache Camel we have a CLI that allows to output data in tables, and we want to allow the table to output only specific columns depending on CLI arguments. (for example a --wide mode to list more etc.)

However it is a bit too difficult to make it possible to define the table once with all the columns, alignment, min/max width etc, and then afterwards be able to select which columns to include when printing the table.

So what we have done is to copy the table and have "ugly" if ... elseif ... code in Camel.

Here is a little example whether GAV is enabled or not
https://github.com/apache/camel/blob/main/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/catalog/CatalogBaseCommand.java#L77

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.