diff --git a/README.md b/README.md
index dee03fa..62b935d 100644
--- a/README.md
+++ b/README.md
@@ -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
```
@@ -36,7 +113,7 @@ allprojects {
}
dependencies {
- compile 'com.github.ivanfrolovmd:asciitable:0.0.6'
+ compile 'com.github.ivanfrolovmd:asciitable:0.0.7'
}
```
@@ -52,12 +129,12 @@ dependencies {
AsciiTable should be used as a builder by chaining building instructions and calling terminal toString()
+ * or write()
functions in the end.
+ *
+ *
Usage example: + * + *
+ * 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() + *+ * + *
renders: + * + *
+ * <------------ 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 -> + *+ */ +final class AsciiTable { private var header: Option[Seq[String]] = None private val streamBuilder = new StreamBuilder[Seq[String]] private var width: Option[Int] = None @@ -16,23 +54,24 @@ class AsciiTable { 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() @@ -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 = "