Skip to content

Commit

Permalink
Merge pull request #9 from ivanfrolovmd/readme-enhancements
Browse files Browse the repository at this point in the history
Update readme and javadoc
  • Loading branch information
ivanfrolovmd committed Jul 29, 2018
2 parents ea833eb + 251daf8 commit 1f3a69a
Show file tree
Hide file tree
Showing 2 changed files with 142 additions and 27 deletions.
109 changes: 93 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,106 @@

# ASCII Table

This is a small library to display tables using ascii art.
This is a small library to render tables using ascii art. The column widths are calculated automatically by sampling the
first 50 rows (configurable) to fit the table in desired screen width.

### Multi-line mode

When used in multi-line mode, cells overflowing the column width are rendered using several lines, for example:

```scala
AsciiTable()
.header("first column", "2")
.row("1", "second value")
.row("", "")
.width(40) // screen width to fit table in
.multiline(true) // render rows across multiple lines
.columnMinWidth(7) // column width will be 7 characters or more
.rowMaxHeight(3) // clip cells at 3 lines
.header("N", "column", "column with long values")
.row("1", "value 1", "Lorem ipsum dolor sit amet, consectetur")
.row("2", "value 2", "Lorem ipsum dolor sit amet, consectetur" * 3)
.row("3", "foo", "bar")
.write()
```

will render
produces:

```text
<------------ 40 characters ----------->
╔═╤═══════╤════════════════════════════╗
║N│column │column with long values ║
╠═╪═══════╪════════════════════════════╣
║1│value 1│Lorem ipsum dolor sit amet, ║
║ │ │consectetur ║
╟─┼───────┼────────────────────────────╢ ↑
║2│value 2│Lorem ipsum dolor sit amet, ║ |
║ │ │consecteturLorem ipsum dolor║ 3 lines max
║ │ │ sit amet, consecteturLorem…║ |
╟─┼───────┼────────────────────────────╢ ↓
║3│foo │bar ║
╚═╧═══════╧════════════════════════════╝
<- 7 ->
```

### One-line mode

In one-line mode cells are clipped at column width:

```scala
AsciiTable()
.width(40) // screen width to fit table in
.multiline(false) // one line per row
.columnMinWidth(7) // column width is be 7 characters or more
.header("N", "column", "column with long values")
.row("1", "value 1", "Lorem ipsum dolor sit amet, consectetur")
.row("2", "value 2", "Lorem ipsum dolor sit amet, consectetur" * 3)
.row("3", "foo", "bar")
```

```text
<------------ 40 characters ----------->
╔═╤═══════╤════════════════════════════╗
║N│column │column with long values ║
╠═╪═══════╪════════════════════════════╣
║1│value 1│Lorem ipsum dolor sit amet,…║
║2│value 2│Lorem ipsum dolor sit amet,…║
║3│foo │bar ║
╚═╧═══════╧════════════════════════════╝
```

### ASCII-only mode

Previous sections used [box drawing characters](https://en.wikipedia.org/wiki/Box-drawing_character), which contain
unicode symbols. If ASCII-only set is required, it is possible to switch to legacy mode:

```scala
AsciiTable()
.useAscii(true) // use ASCII-only characters
.width(40)
.multiline(true)
.columnMinWidth(7)
.rowMaxHeight(3)
.header("N", "column", "column with long values")
.row("1", "value 1", "Lorem ipsum dolor sit amet, consectetur")
.row("2", "value 2", "Lorem ipsum dolor sit amet, consectetur" * 3)
.row("3", "foo", "bar")
.write()
```
┌────────────┬────────────┐
│first column│2 │
├────────────┼────────────┤
│1 │second value│
├────────────┼────────────┤
│ │ │
└────────────┴────────────┘

```text
+-+-------+----------------------------+
|N|column |column with long values |
+-+-------+----------------------------+
|1|value 1|Lorem ipsum dolor sit amet, |
| | |consectetur |
+-+-------+----------------------------+
|2|value 2|Lorem ipsum dolor sit amet, |
| | |consecteturLorem ipsum dolor|
| | | sit amet, consecteturLorem_|
+-+-------+----------------------------+
|3|foo |bar |
+-+-------+----------------------------+
```

## Usage
## Installation

### Gradle
```
Expand All @@ -36,7 +113,7 @@ allprojects {
}
dependencies {
compile 'com.github.ivanfrolovmd:asciitable:0.0.6'
compile 'com.github.ivanfrolovmd:asciitable:0.0.7'
}
```

Expand All @@ -52,12 +129,12 @@ dependencies {
<dependency>
<groupId>com.github.ivanfrolovmd</groupId>
<artifactId>asciitable</artifactId>
<version>0.0.6</version>
<version>0.0.7</version>
</dependency>
```

### SBT
```
resolvers += "jitpack" at "https://jitpack.io"
libraryDependencies += "com.github.ivanfrolovmd" % "asciitable" % "0.0.6"
libraryDependencies += "com.github.ivanfrolovmd" % "asciitable" % "0.0.7"
```
60 changes: 49 additions & 11 deletions src/main/scala/io/github/asciitable/AsciiTable.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,70 @@ import io.github.asciitable.Maths._
import scala.collection.immutable.Stream.StreamBuilder
import scala.language.postfixOps

class AsciiTable {
/**
* <p>AsciiTable should be used as a builder by chaining building instructions and calling terminal <code>toString()</code>
* or <code>write()</code> functions in the end.
*
* <p>Usage example:
*
* <pre>
* AsciiTable()
* .width(40) // screen width to fit table in
* .multiline(true) // render rows across multiple lines
* .columnMinWidth(7) // column width will be 7 characters or more
* .rowMaxHeight(3) // clip cells at 3 lines
* .header("N", "column", "column with long values")
* .row("1", "value 1", "Lorem ipsum dolor sit amet, consectetur")
* .row("2", "value 2", "Lorem ipsum dolor sit amet, consectetur" * 3)
* .row("3", "foo", "bar")
* .write()
* </pre>
*
* <p>renders:
*
* <pre>
* &lt;------------ 40 characters ----------->
* ╔═╤═══════╤════════════════════════════╗
* ║N│column │column with long values ║
* ╠═╪═══════╪════════════════════════════╣
* ║1│value 1│Lorem ipsum dolor sit amet, ║
* ║ │ │consectetur ║
* ╟─┼───────┼────────────────────────────╢ ↑
* ║2│value 2│Lorem ipsum dolor sit amet, ║ |
* ║ │ │consecteturLorem ipsum dolor║ 3 lines max
* ║ │ │ sit amet, consecteturLorem…║ |
* ╟─┼───────┼────────────────────────────╢ ↓
* ║3│foo │bar ║
* ╚═╧═══════╧════════════════════════════╝
* &lt;- 7 ->
* </pre>
*/
final class AsciiTable {
private var header: Option[Seq[String]] = None
private val streamBuilder = new StreamBuilder[Seq[String]]
private var width: Option[Int] = None
private var multiline: Boolean = true
private var emptyMessage = DefaultEmptyMessage
private var rowMaxHeight = DefaultRowMaxHeight
private var columnMinWidth = DefaultColumnMinWidth
private var columnMaxWidth = DefaultColumnMaxWidth
private var sampleRows = DefaultSampleRows
private var chars: CharacterSet = Unicode

// data builders
def header(columnNames: String*): AsciiTable = { header = Some(columnNames); this }
def header(columnNames: TraversableOnce[String]): AsciiTable = { header = Some(columnNames.toSeq); this }
def row(values: String*): AsciiTable = { streamBuilder += values; this }
def row(values: TraversableOnce[String]): AsciiTable = { streamBuilder += values.toSeq; this }
def rows(rows: TraversableOnce[TraversableOnce[String]]): AsciiTable = { streamBuilder ++= rows.map(_.toSeq); this }
def width(value: Int): AsciiTable = { width = Some(value); this }
def multiline(value: Boolean): AsciiTable = { multiline = value; this }
def emptyMessage(value: String): AsciiTable = { emptyMessage = value; this }
def rowMaxHeight(value: Int): AsciiTable = { rowMaxHeight = value; this }
def columnMinWidth(value: Int): AsciiTable = { columnMinWidth = value; this }
def columnMaxWidth(value: Int): AsciiTable = { columnMaxWidth = value; this }
def sampleAtMostRows(value: Int): AsciiTable = { sampleRows = value; this }
def useAscii(value: Boolean): AsciiTable = { chars = if (value) Ascii else Unicode; this }

// configuration
def width(value: Int): AsciiTable = { width = Some(value); this }
def multiline(value: Boolean): AsciiTable = { multiline = value; this }
def emptyMessage(value: String): AsciiTable = { emptyMessage = value; this }
def rowMaxHeight(value: Int): AsciiTable = { rowMaxHeight = value; this }
def columnMinWidth(value: Int): AsciiTable = { columnMinWidth = value; this }
def sampleAtMostRows(value: Int): AsciiTable = { sampleRows = value; this }
def useAscii(value: Boolean): AsciiTable = { chars = if (value) Ascii else Unicode; this }

private lazy val rows = streamBuilder.result()

Expand Down Expand Up @@ -229,7 +268,6 @@ object AsciiTable {
private val DefaultWidth = 80
private val DefaultRowMaxHeight = 7
private val DefaultColumnMinWidth = 1
private val DefaultColumnMaxWidth = 5
private val DefaultWidthPercentile = .75
private val DefaultEmptyMessage = "<Empty>"
private val DefaultSampleRows = 50
Expand Down

0 comments on commit 1f3a69a

Please sign in to comment.