├── .gitignore ├── LICENSE ├── README.md ├── docs └── api │ └── terminaltables.html ├── src └── terminaltables.nim └── terminaltables.nimble /.gitignore: -------------------------------------------------------------------------------- 1 | nimcache/ 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2019, xmonader 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nim-terminaltables 2 | terminal tables for nim 3 | 4 | ## API 5 | 6 | API docs available [here](https://xmonader.github.io/nim-terminaltables/api/terminaltables.html) 7 | terminaltables has a very small API 8 | - `newUnicodeTable` uses `unicodeStyle` 9 | - `newAsciiTable` uses `asciiStyle` 10 | 11 | Table style is configurable using `Style` object. Here's an example of how `asciiStyle` and `unicodeStyle` are defined 12 | 13 | ```nim 14 | 15 | let asciiStyle = Style(rowSeparator:"-", colSeparator:"|", cellEdgeLeft:"+", cellEdgeRight:"+", topLeft:"+", topRight:"+", bottomLeft:"-", bottomRight:"-", topRowSeparator:"-", bottomRowSeparator:"-", dashLineLeft:"+", dashLineRight:"+", dashLineColSeparatorLastRow:"+", dashLineColSeparatorTopRow:"+", dashLineColSeparator:"+") 16 | let unicodeStyle = Style(rowSeparator:"─", colSeparator:"│", cellEdgeLeft:"├", cellEdgeRight:"┤", topLeft:"┌", topRight:"┐", bottomLeft:"└", bottomRight:"┘", topRowSeparator:"┬", bottomRowSeparator:"┴", dashLineLeft:"├", dashLineRight:"┤", dashLineColSeparatorLastRow:"┴", dashLineColSeparatorTopRow:"┬", dashLineColSeparator:"┼") 17 | 18 | ``` 19 | - newUnicodeTable to create Table with unicode table style 20 | - newAsciiTable to create Table with ascii table style 21 | - separateRows controls if you want to add dashline between rows. 22 | - addRow used to add a row to the table 23 | - setHeaders used to set headers of the table and it accepts strings or `cell objects` with padding information. 24 | - a 25 | ```nim 26 | 27 | 28 | let t2 = newUnicodeTable() 29 | t2.separateRows = false 30 | t2.setHeaders(@["ID", "Name", "Fav animal", "Date"]) 31 | # t2.setHeaders(@[newCell("ID", pad=5), newCell("Name", rightpad=10), newCell("Fav animal", pad=2), newCell("Date", 5)]) 32 | t2.addRow(@["1", "xmonader", "Cat, Dog", "2018-10-22"]) 33 | t2.addRow(@["2", "ahmed", "Shark", "2015-12-6"]) 34 | t2.addRow(@["3", "dr who", "Humans", "1018-5-2"]) 35 | printTable(t2) 36 | ``` 37 | 38 | 39 | ## Examples 40 | 41 | ```nim 42 | 43 | var t = newTerminalTable() 44 | var width = 150 45 | when not defined(js): 46 | width = termColumns() 47 | echo "termColumns: " & $termColumns() 48 | 49 | # width of the table is the terminal COLUMNS - the amount of separators (columns + 1) multiplied by length of the separator 50 | t.tableWidth = width - (t.columnsCount() * len($t.style.colSeparator)) - 10 51 | t.setHeaders(@["ID", "Name", "Fav animal", "Date", "OK"]) 52 | t.addRow(@["1", "xmonader", "Cat, Dog", "2018-10-2", "yes"]) 53 | t.addRow(@["2", "ahmed", "Shark", "2018-10-2", "yes"]) 54 | t.addRow(@["3", "dr who", "Humans", "1018-5-2", "no"]) 55 | printTable(t) 56 | 57 | t.tableWidth = 0 58 | printTable(t) 59 | 60 | t.tableWidth = 0 61 | t.separateRows = false 62 | printTable(t) 63 | 64 | t.reset() 65 | 66 | let t2 = newUnicodeTable() 67 | t2.separateRows = false 68 | t2.setHeaders(@[newCell("ID", pad=5), newCell("Name", rightpad=10), newCell("Fav animal", pad=2), newCell("Date", 5)]) 69 | t2.addRow(@["1", "xmonader", "Cat, Dog", "2018-10-22"]) 70 | t2.addRow(@["2", "ahmed", "Shark", "2015-12-6"]) 71 | t2.addRow(@["3", "dr who", "Humans", "1018-5-2"]) 72 | printTable(t2) 73 | ``` 74 | 75 | ``` 76 | +------------------------+------------------------+------------------------+------------------------+------------------------+ 77 | | ID | Name | Fav animal | Date | OK | 78 | +------------------------+------------------------+------------------------+------------------------+------------------------+ 79 | | 1 | xmonader | Cat, Dog | 2018-10-2 | yes | 80 | +------------------------+------------------------+------------------------+------------------------+------------------------+ 81 | | 2 | ahmed | Shark | 2018-10-2 | yes | 82 | +------------------------+------------------------+------------------------+------------------------+------------------------+ 83 | | 3 | dr who | Humans | 1018-5-2 | no | 84 | -------------------------+------------------------+------------------------+------------------------+------------------------- 85 | 86 | +----+----------+------------+-----------+-----+ 87 | | ID | Name | Fav animal | Date | OK | 88 | +----+----------+------------+-----------+-----+ 89 | | 1 | xmonader | Cat, Dog | 2018-10-2 | yes | 90 | +----+----------+------------+-----------+-----+ 91 | | 2 | ahmed | Shark | 2018-10-2 | yes | 92 | +----+----------+------------+-----------+-----+ 93 | | 3 | dr who | Humans | 1018-5-2 | no | 94 | -----+----------+------------+-----------+------ 95 | 96 | +----+----------+------------+-----------+-----+ 97 | | ID | Name | Fav animal | Date | OK | 98 | +----+----------+------------+-----------+-----+ 99 | | 1 | xmonader | Cat, Dog | 2018-10-2 | yes | 100 | | 2 | ahmed | Shark | 2018-10-2 | yes | 101 | | 3 | dr who | Humans | 1018-5-2 | no | 102 | -----+----------+------------+-----------+------ 103 | 104 | ┌────────────┬───────────────────┬──────────────┬────────────────┐ 105 | │ ID │ Name │ Fav animal │ Date │ 106 | ├────────────┼───────────────────┼──────────────┼────────────────┤ 107 | │ 1 │ xmonader │ Cat, Dog │ 2018-10-22 │ 108 | │ 2 │ ahmed │ Shark │ 2015-12-6 │ 109 | │ 3 │ dr who │ Humans │ 1018-5-2 │ 110 | └────────────┴───────────────────┴──────────────┴────────────────┘ 111 | ``` 112 | 113 | ## using custom styles 114 | Using custom styles is pretty easy 115 | 116 | ```nim 117 | 118 | 119 | var t2 = newUnicodeTable() 120 | t2.separateRows = false 121 | t2.setHeaders(@[newCell("ID", pad=5), newCell("Name", rightpad=10), newCell("Fav animal", pad=2), newCell("Date", 5)]) 122 | t2.addRow(@["1", "xmonader", "Cat, Dog", "2018-10-22"]) 123 | t2.addRow(@["2", "ahmed", "Shark", "2015-12-6"]) 124 | t2.addRow(@["3", "dr who", "Humans", "1018-5-2"]) 125 | t2.separateRows = true 126 | let testStyle = Style(rowSeparator:"┈", colSeparator:"┇", cellEdgeLeft:"├", cellEdgeRight:"┤", topLeft:"┏", topRight:"┓", bottomLeft:"└", bottomRight:"┘", topRowSeparator:"┬", bottomRowSeparator:"┴", dashLineLeft:"├", dashLineRight:"┤", dashLineColSeparatorLastRow:"┴", dashLineColSeparatorTopRow:"┬", dashLineColSeparator:"┼") 127 | 128 | t2.style = testStyle 129 | printTable(t2) 130 | ``` 131 | ``` 132 | ┏┈┈┈┈┈┈┈┈┈┈┈┈┬┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┬┈┈┈┈┈┈┈┈┈┈┈┈┈┈┬┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┓ 133 | ┇ ID ┇ Name ┇ Fav animal ┇ Date ┇ 134 | ├┈┈┈┈┈┈┈┈┈┈┈┈┼┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┼┈┈┈┈┈┈┈┈┈┈┈┈┈┈┼┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┤ 135 | ┇ 1 ┇ xmonader ┇ Cat, Dog ┇ 2018-10-22 ┇ 136 | ├┈┈┈┈┈┈┈┈┈┈┈┈┼┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┼┈┈┈┈┈┈┈┈┈┈┈┈┈┈┼┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┤ 137 | ┇ 2 ┇ ahmed ┇ Shark ┇ 2015-12-6 ┇ 138 | ├┈┈┈┈┈┈┈┈┈┈┈┈┼┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┼┈┈┈┈┈┈┈┈┈┈┈┈┈┈┼┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┤ 139 | ┇ 3 ┇ dr who ┇ Humans ┇ 1018-5-2 ┇ 140 | └┈┈┈┈┈┈┈┈┈┈┈┈┴┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┴┈┈┈┈┈┈┈┈┈┈┈┈┈┈┴┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┘ 141 | 142 | 143 | ``` -------------------------------------------------------------------------------- /docs/api/terminaltables.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | terminaltables 20 | 1201 | 1202 | 1203 | 1204 | 1217 | 1218 | 1219 | 1220 |
1221 |
1222 |

terminaltables

1223 |
1224 |
1225 | 1229 |
1230 | Search: 1232 |
1233 |
1234 | Group by: 1235 | 1239 |
1240 | 1302 | 1303 |
1304 |
1305 |
1306 |

1307 |
1308 |

Types

1309 |
1310 | 1311 |
Cell = object
1312 |   leftpad*: int
1313 |   rightpad: int
1314 |   pad*: int
1315 |   text*: string
1316 | 
1317 |
1318 | 1319 | 1320 |
1321 | 1322 |
TerminalTable = object
1323 |   rows: seq[seq[string]]
1324 |   headers: seq[ref Cell]
1325 |   style: Style
1326 |   widths: seq[int]
1327 |   suggestedWidths: seq[int]
1328 |   tableWidth*: int
1329 |   separateRows*: bool
1330 | 
1331 |
1332 | 1333 | 1334 |
1335 | 1336 |
1337 |
1338 |

Procs

1339 |
1340 | 1341 |
proc newCell(text: string; leftpad = 1; rightpad = 1; pad = 0): ref Cell {...}{.raises: [], tags: [].}
1342 |
1343 | 1344 | 1345 |
1346 | 1347 |
proc len(this: ref Cell): int {...}{.raises: [], tags: [].}
1348 |
1349 | 1350 | 1351 |
1352 | 1353 |
proc `$`(this: ref Cell): string {...}{.raises: [], tags: [].}
1354 |
1355 | 1356 | 1357 |
1358 | 1359 |
proc newTerminalTable(style: Style = asciiStyle): ref TerminalTable {...}{.raises: [],
1360 |     tags: [].}
1361 |
1362 | 1363 | 1364 |
1365 | 1366 |
proc newAsciiTable(style: Style = asciiStyle): ref TerminalTable {...}{.raises: [], tags: [].}
1367 |
1368 | 1369 | 1370 |
1371 | 1372 |
proc newUnicodeTable(style: Style = unicodeStyle): ref TerminalTable {...}{.raises: [],
1373 |     tags: [].}
1374 |
1375 | 1376 | 1377 |
1378 | 1379 |
proc columnsCount(this: ref TerminalTable): int {...}{.raises: [], tags: [].}
1380 |
1381 | 1382 | 1383 |
1384 | 1385 |
proc setHeaders(this: ref TerminalTable; headers: seq[string]) {...}{.raises: [], tags: [].}
1386 |
1387 | 1388 | 1389 |
1390 | 1391 |
proc setHeaders(this: ref TerminalTable; headers: seq[ref Cell]) {...}{.raises: [], tags: [].}
1392 |
1393 | 1394 | 1395 |
1396 | 1397 |
proc setRows(this: ref TerminalTable; rows: seq[seq[string]]) {...}{.raises: [], tags: [].}
1398 |
1399 | 1400 | 1401 |
1402 | 1403 |
proc addRows(this: ref TerminalTable; rows: seq[seq[string]]) {...}{.raises: [], tags: [].}
1404 |
1405 | 1406 | 1407 |
1408 | 1409 |
proc addRow(this: ref TerminalTable; row: seq[string]) {...}{.raises: [], tags: [].}
1410 |
1411 | 1412 | 1413 |
1414 | 1415 |
proc suggestWidths(this: ref TerminalTable; widths: seq[int]) {...}{.raises: [], tags: [].}
1416 |
1417 | 1418 | 1419 |
1420 | 1421 |
proc reset(this: ref TerminalTable) {...}{.raises: [], tags: [].}
1422 |
1423 | 1424 | 1425 |
1426 | 1427 |
proc render(this: ref TerminalTable): string {...}{.raises: [ValueError], tags: [].}
1428 |
1429 | 1430 | 1431 |
1432 | 1433 |
proc printTable(this: ref TerminalTable) {...}{.raises: [ValueError], tags: [].}
1434 |
1435 | 1436 | 1437 |
1438 | 1439 |
1440 | 1441 |
1442 |
1443 | 1444 |
1445 | 1450 |
1451 |
1452 |
1453 | 1454 | 1455 | 1456 | -------------------------------------------------------------------------------- /src/terminaltables.nim: -------------------------------------------------------------------------------- 1 | import strformat, strutils 2 | from unicode import runeLen 3 | 4 | type Cell* = ref object 5 | leftpad*: int 6 | rightpad: int 7 | pad*: int 8 | text*: string 9 | 10 | proc newCell*(text: string, leftpad = 1, rightpad = 1, pad = 0): Cell = 11 | result = Cell(pad: pad, text: text) 12 | if pad != 0: 13 | result.leftpad = pad 14 | result.rightpad = pad 15 | else: 16 | result.leftpad = leftpad 17 | result.rightpad = rightpad 18 | 19 | proc newCellFromAnother(another: Cell): Cell = 20 | result = newCell(another.text, another.leftpad, another.rightpad) 21 | 22 | proc len*(this: Cell): int = 23 | result = this.leftpad + this.text.runeLen + this.rightpad 24 | 25 | proc `$`*(this:Cell): string = 26 | result = " ".repeat(this.leftpad) & this.text & " ".repeat(this.rightpad) 27 | 28 | type Style* = object 29 | rowSeparator*: string 30 | colSeparator*: string 31 | cellEdgeLeft*: string 32 | cellEdgeRight*: string 33 | dashLineLeft*: string 34 | dashLineRight*: string 35 | dashLineColSeparatorTopRow*: string 36 | dashLineColSeparatorLastRow*: string 37 | dashLineColSeparator*: string 38 | topLeft*: string 39 | topRight*: string 40 | topRowSeparator*: string 41 | bottomRowSeparator*: string 42 | bottomLeft*: string 43 | bottomRight*: string 44 | 45 | const 46 | asciiStyle* = Style( 47 | rowSeparator: "-", colSeparator: "|", 48 | cellEdgeLeft: "+", cellEdgeRight: "+", 49 | topLeft: "+", topRight: "+", 50 | bottomLeft: "-", bottomRight: "-", 51 | topRowSeparator: "-", bottomRowSeparator: "-", 52 | dashLineLeft: "+", dashLineRight: "+", 53 | dashLineColSeparatorLastRow: "+", dashLineColSeparatorTopRow: "+", 54 | dashLineColSeparator: "+" 55 | ) 56 | 57 | unicodeStyle* = Style( 58 | rowSeparator: "─", colSeparator: "│", 59 | cellEdgeLeft: "├", cellEdgeRight: "┤", 60 | topLeft: "┌", topRight: "┐", 61 | bottomLeft: "└", bottomRight: "┘", 62 | topRowSeparator: "┬", bottomRowSeparator: "┴", 63 | dashLineLeft: "├", dashLineRight: "┤", 64 | dashLineColSeparatorLastRow: "┴", dashLineColSeparatorTopRow: "┬", 65 | dashLineColSeparator: "┼" 66 | ) 67 | 68 | noStyle* = Style() 69 | 70 | type TerminalTable* = ref object 71 | rows: seq[seq[string]] 72 | headers: seq[Cell] 73 | style*: Style 74 | widths: seq[int] 75 | suggestedWidths: seq[int] 76 | tableWidth*: int 77 | separateRows*: bool 78 | 79 | proc newTerminalTable*(style = asciiStyle): TerminalTable = 80 | TerminalTable( 81 | style: style, 82 | tableWidth: 0, 83 | separateRows: true 84 | ) 85 | 86 | proc newAsciiTable*(style = asciiStyle): TerminalTable = 87 | result = newTerminalTable() 88 | 89 | proc newUnicodeTable*(style = unicodeStyle): TerminalTable = 90 | result = newTerminalTable(style) 91 | 92 | proc columnsCount*(this: TerminalTable): int = 93 | result = this.headers.len 94 | 95 | proc setHeaders*(this: TerminalTable, headers: seq[string]) = 96 | for s in headers: 97 | var cell = newCell(s) 98 | this.headers.add(cell) 99 | 100 | proc setHeaders*(this: TerminalTable, headers: seq[Cell]) = 101 | this.headers = headers 102 | 103 | proc setRows*(this: TerminalTable, rows: seq[seq[string]]) = 104 | this.rows = rows 105 | 106 | proc addRows*(this: TerminalTable, rows: seq[seq[string]]) = 107 | this.rows.add(rows) 108 | 109 | proc addRow*(this: TerminalTable, row: seq[string]) = 110 | this.rows.add(row) 111 | 112 | proc suggestWidths*(this: TerminalTable, widths: seq[int]) = 113 | this.suggestedWidths = widths 114 | 115 | proc reset*(this: TerminalTable) = 116 | this[] = newTerminalTable()[] 117 | 118 | proc calculateWidths(this: TerminalTable) = 119 | var colsWidths = newSeq[int]() 120 | if this.suggestedWidths.len == 0: 121 | for h in this.headers: 122 | colsWidths.add(h.len) 123 | else: 124 | colsWidths = this.suggestedWidths 125 | 126 | for row in this.rows: 127 | for colpos, c in row: 128 | var acell = newCellFromAnother(this.headers[colpos]) 129 | acell.text = c 130 | if len(acell) > colsWidths[colpos]: 131 | colsWidths[colpos] = len(acell) 132 | 133 | let sizeForCol = (this.tablewidth/len(this.headers)).toInt() 134 | var lenHeaders = 0 135 | for w in colsWidths: 136 | lenHeaders += w 137 | 138 | if this.tablewidth > lenHeaders: 139 | if this.suggestedWidths.len == 0: 140 | for colpos, c in colsWidths: 141 | colsWidths[colpos] += sizeForCol - c 142 | 143 | if this.suggestedWidths.len != 0: 144 | var sumSuggestedWidths = 0 145 | for s in this.suggestedWidths: 146 | sumSuggestedWidths += s 147 | 148 | if lenHeaders > sumSuggestedWidths: 149 | raise newException(ValueError, fmt"sum of {this.suggestedWidths} = {sumSuggestedWidths} and it's less than required length {lenHeaders}") 150 | 151 | this.widths = colsWidths 152 | 153 | proc oneLine(this: TerminalTable): string = 154 | result &= this.style.cellEdgeLeft 155 | for w in this.widths[0..^2]: 156 | result &= this.style.rowSeparator.repeat(w) & this.style.dashLineColSeparator 157 | result &= this.style.rowSeparator.repeat(this.widths[^1]) & this.style.dashLineRight & "\n" 158 | 159 | 160 | proc oneLineTop(this: TerminalTable): string = 161 | result &= this.style.topLeft 162 | for w in this.widths[0..^2]: 163 | result &= this.style.rowSeparator.repeat(w) & this.style.dashLineColSeparatorTopRow 164 | 165 | result &= this.style.rowSeparator.repeat(this.widths[^1]) & this.style.topRight & "\n" 166 | 167 | proc oneLineBottom(this: TerminalTable): string = 168 | result &= this.style.bottomLeft 169 | for w in this.widths[0..^2]: 170 | result &= this.style.rowSeparator.repeat(w) & this.style.dashLineColSeparatorLastRow 171 | 172 | result &= this.style.rowSeparator.repeat(this.widths[^1]) & this.style.bottomRight & "\n" 173 | 174 | proc render*(this: TerminalTable): string = 175 | this.calculateWidths() 176 | # top border 177 | result &= this.oneLineTop() 178 | 179 | # headers 180 | for colidx, h in this.headers: 181 | result &= this.style.colSeparator & $h & " ".repeat(this.widths[colidx]-len(h) ) 182 | 183 | result &= this.style.colSeparator 184 | result &= "\n" 185 | # finish headers 186 | 187 | # line after headers 188 | result &= this.oneline() 189 | 190 | # start rows 191 | for ridx,r in this.rows: 192 | # start row 193 | for colidx, c in r: 194 | let cell = newCell(c, 195 | leftpad = this.headers[colidx].leftpad, 196 | rightpad = this.headers[colidx].rightpad 197 | ) 198 | result &= this.style.colSeparator & $cell & " ".repeat(this.widths[colidx]-len(cell)) 199 | result &= this.style.colSeparator 200 | result &= "\n" 201 | if this.separateRows and ridx < this.rows.len-1: 202 | result &= this.oneLine() 203 | 204 | result &= this.oneLineBottom() 205 | 206 | proc printTable*(this: TerminalTable) = 207 | ## print table. 208 | echo(this.render()) 209 | 210 | when not defined(js): 211 | import os, osproc 212 | proc termColumns(): int = 213 | if os.existsEnv("COLUMNS") and getEnv("COLUMNS")[0].isDigit(): 214 | return parseInt(getEnv("COLUMNS")) 215 | else: 216 | if findExe("tput") != "": 217 | let (cols, rc) = execCmdEx("tput cols") 218 | if rc == 0: 219 | return cols.strip().parseInt() 220 | if findExe("stty") != "": 221 | let (output, rc) = execCmdEx("stty size") 222 | if rc == 0: 223 | let parts = output.splitWhitespace() 224 | if len(parts) == 2: 225 | return parts[1].strip().parseInt() 226 | return 0 227 | 228 | 229 | when isMainModule: 230 | 231 | var t = newTerminalTable() 232 | var width = 150 233 | when not defined(js): 234 | width = termColumns() 235 | echo "termColumns: " & $termColumns() 236 | 237 | # width of the table is the terminal COLUMNS - the amount of separators (columns + 1) multiplied by length of the separator 238 | t.tableWidth = width - (t.columnsCount() * len($t.style.colSeparator)) - 10 239 | t.setHeaders(@["ID", "Name", "Fav animal", "Date", "OK"]) 240 | t.addRow(@["1", "xmonader", "Cat, Dog", "2018-10-2", "yes"]) 241 | t.addRow(@["2", "ahmed", "Shark", "2018-10-2", "yes"]) 242 | t.addRow(@["3", "dr who", "Humans", "1018-5-2", "no"]) 243 | printTable(t) 244 | 245 | t.tableWidth = 0 246 | printTable(t) 247 | 248 | t.tableWidth = 0 249 | t.separateRows = false 250 | printTable(t) 251 | 252 | t.reset() 253 | 254 | var t2 = newUnicodeTable() 255 | t2.separateRows = false 256 | t2.setHeaders(@[newCell("ID", pad=5), newCell("Name", rightpad=10), newCell("Fav animal", pad=2), newCell("Date", 5)]) 257 | t2.addRow(@["1", "xmonader", "Cat, Dog", "2018-10-22"]) 258 | t2.addRow(@["2", "ahmed", "Shark", "2015-12-6"]) 259 | t2.addRow(@["3", "dr who", "Humans", "1018-5-2"]) 260 | printTable(t2) 261 | t2.separateRows = false 262 | let testStyle = Style( 263 | rowSeparator:"┈", colSeparator:"┇", 264 | cellEdgeLeft:"├", cellEdgeRight:"┤", 265 | topLeft:"┏", topRight:"┓", 266 | bottomLeft:"└", bottomRight:"┘", 267 | topRowSeparator:"┬", bottomRowSeparator:"┴", 268 | dashLineLeft:"├", dashLineRight:"┤", 269 | dashLineColSeparatorLastRow:"┴", dashLineColSeparatorTopRow:"┬", 270 | dashLineColSeparator:"┼" 271 | ) 272 | 273 | t2.style = testStyle 274 | printTable(t2) 275 | 276 | t2.style = noStyle 277 | printTable(t2) 278 | 279 | t2.setHeaders(@[newCell("ID", pad=0), newCell("Name", pad=0), newCell("Fav animal", pad=0), newCell("Date", 0)]) 280 | 281 | printTable(t2) 282 | -------------------------------------------------------------------------------- /terminaltables.nimble: -------------------------------------------------------------------------------- 1 | # Package 2 | version = "0.1.1" 3 | author = "xmonader" 4 | description = "terminal tables" 5 | license = "BSD-3-Clause" 6 | srcDir = "src" 7 | 8 | 9 | # Dependencies 10 | 11 | requires "nim >= 0.19.4" 12 | task genDocs, "Create code documentation for terminaltables": 13 | exec "nim doc --threads:on --project src/terminaltables.nim && rm -rf docs/api; mkdir -p docs && mv src/htmldocs docs/api " 14 | 15 | 16 | task dmdm, "dmdm": 17 | echo paramCount() 18 | echo paramStr(2) 19 | exec "echo in dmdm" --------------------------------------------------------------------------------