轻松地在 Swift 中打印文本表格。灵感来自 Python 的 tabulate 库。
此软件包是为以下 Swift 版本编写并测试的
Apple Swift 版本 5.0
使用 Swift Package Manager 安装 TextTable
作为项目的依赖项。
dependencies: [
.package(
url: "https://github.com/cfilipov/TextTable",
.branch("master"))
]
首先,导入 TextTable
import TextTable
在整个示例中,将使用以下数据结构
struct Person {
let name: String
let age: Int
let birhtday: Date
}
假设我们有一个 Person
集合,希望将其显示为表格。
let data = [
Person(name: "Alice", age: 42, birhtday: Date()),
Person(name: "Bob", age: 22, birhtday: Date()),
Person(name: "Eve", age: 142, birhtday: Date())
]
为您希望打印为表格的类型配置一个 TextTable
实例。 最低配置将需要一个值到列的映射。
let table = TextTable<Person> {
[Column("Name" <- $0.name),
Column("Age" <- $0.age),
Column("Birthday" <- $0.birhtday)]
}
<-
运算符只是语法糖。 如果您不想使用该运算符,则可以使用标记的参数。
let table = TextTable<Person> {
[Column(title: "Name", value: $0.name),
Column(title: "Age", value: $0.age),
Column(title: "Birthday", value: $0.birhtday)]
}
只需调用 print()
方法,传入一个 Person
集合。
table.print(data)
Name Age Birthday
----- --- -------------------------
Alice 42 2016-08-13 19:21:54 +0000
Bob 22 2016-08-13 19:21:54 +0000
Eve 142 2016-08-13 19:21:54 +0000
您也可以通过调用 string(for:)
方法来获取渲染的表格作为字符串。
let s = table.string(for: data)
您可以选择使用 style:
参数指定表格样式。
table.print(data, style: Style.psql)
+-------+-----+---------------------------+
| Name | Age | Birthday |
+-------+-----+---------------------------+
| Alice | 42 | 2016-08-13 08:12:58 +0000 |
| Bob | 22 | 2016-08-13 08:12:58 +0000 |
| Eve | 142 | 2016-08-13 08:12:58 +0000 |
+-------+-----+---------------------------+
在使用 string(for:)
方法时也可以指定样式。
let s = table.string(for: data, style: Style.psql)
有关支持的样式的完整列表,请参见下面的支持的样式。
您可以基于每列指定一个 格式化器。 在此示例中,使用 DateFormatter 自定义 Birthday
列的显示。
let df = DateFormatter()
dateFormatter.dateStyle = .medium
let table = TextTable<Person> {
[Column("Name" <- $0.name),
Column("Age" <- $0.age),
Column("Birthday" <- $0.birhtday, formatter: df)]
}
table.print(data, style: Style.psql)
+-------+-----+--------------+
| Name | Age | Birthday |
+-------+-----+--------------+
| Alice | 42 | Aug 13, 2016 |
| Bob | 22 | Aug 13, 2016 |
| Eve | 142 | Aug 13, 2016 |
+-------+-----+--------------+
默认情况下,TextTable 将计算每列所需的宽度。 您还可以使用 width:
参数显式设置宽度。
let table = TextTable<Person> {
[Column("Name" <- $0.name, width: 10),
Column("Age" <- $0.age, width: 10)]
}
table.print(data, style: Style.psql)
+------------+------------+
| Name | Age |
+------------+------------+
| Alice | 42 |
| Bob | 22 |
| Eve | 142 |
+------------+------------+
某些表格样式可能包括内容左侧和/或右侧的填充,width 参数不影响此填充。
默认情况下,如果指定了宽度并且列的内容比宽度更宽,则文本将在尾部被截断 (.tail
截断模式)。
let table = TextTable<Person> {
[Column("Name" <- $0.name, width: 4), // defaults to truncation: .tail
Column("Age" <- $0.age)]
}
table.print(data, style: testStyle)
+------+-----+
| Name | Age |
+------+-----+
| Ali… | 42 |
| Bob | 22 |
| Eve | 142 |
+------+-----+
您还可以通过为 truncation:
参数指定 .head
来在文本字符串的头部截断。 如果不存在 width
参数,则 truncation
参数无效。
let table = TextTable<Person> {
[Column("Name" <- $0.name, width: 4, truncate: .head),
Column("Age" <- $0.age)]
}
table.print(data, style: testStyle)
+------+-----+
| Name | Age |
+------+-----+
| …ice | 42 |
| Bob | 22 |
| Eve | 142 |
+------+-----+
如果您希望在列的内容不适合指定的宽度时触发致命错误,则可以指定 .error
截断模式。
let table = TextTable<Person> {
[Column("Name" <- $0.name, width: 4, truncate: .error),
Column("Age" <- $0.age)]
}
table.print(data, style: testStyle)
// fatal error: Truncation error
默认情况下,所有列都将左对齐。 您可以分别设置每列的对齐方式。
let table = TextTable<Person> {
[Column("Name" <- $0.name), // default: .left
Column("Age" <- $0.age, align: .right)]
}
table.print(data, style: Style.psql)
+-------+-----+
| Name | Age |
+-------+-----+
| Alice | 42 |
| Bob | 22 |
| Eve | 142 |
+-------+-----+
默认情况下,TextTable 将计算未使用 width:
列参数指定显式宽度的每一列所需的宽度。 通过遍历表格的每一行两次来完成此计算:第一次计算最大宽度,第二次实际渲染表格。 此计算的开销可能不适用于非常大的表格。 如果您希望避免此计算,则必须为每一列指定宽度。
在下面的示例中,table1
将产生宽度计算的开销,因为其中一列没有显式宽度。 另一方面,table2
不会产生开销,因为所有列都具有显式宽度。
// This will still result in extra calculations
let table1 = TextTable<Person> {
[Column("Name" <- $0.name),
Column("Age" <- $0.age, width: 10)]
}
// This will skip the width calculations
let table2 = TextTable<Person> {
[Column("Name" <- $0.name, width: 9),
Column("Age" <- $0.age, width: 10)]
}
TextTable 支持与 tabulate 大多数相同的样式。
table.print(data, style: Style.plain)
Name Age Birthday
Alice 42 8/13/16
Bob 22 8/13/16
Eve 142 8/13/16
simple
是默认样式。它对应于 Pandoc Markdown 扩展中的 simple_tables
。
table.print(data) // or:
table.print(data, style: Style.simple)
Name Age Birthday
----- --- --------
Alice 42 8/13/16
Bob 22 8/13/16
Eve 142 8/13/16
grid
遵循 Emacs 的 table.el package 的约定。 它对应于 Pandoc Markdown 扩展中的 grid_tables
。
table.print(data, style: Style.grid)
+-------+-----+----------+
| Name | Age | Birthday |
+=======+=====+==========+
| Alice | 42 | 8/13/16 |
+-------+-----+----------+
| Bob | 22 | 8/13/16 |
+-------+-----+----------+
| Eve | 142 | 8/13/16 |
+-------+-----+----------+
table.print(data, style: Style.fancyGrid)
╒═══════╤═════╤══════════╕
│ Name │ Age │ Birthday │
╞═══════╪═════╪══════════╡
│ Alice │ 42 │ 8/13/16 │
├───────┼─────┼──────────┤
│ Bob │ 22 │ 8/13/16 │
├───────┼─────┼──────────┤
│ Eve │ 142 │ 8/13/16 │
╘═══════╧═════╧══════════╛
table.print(data, style: Style.psql)
+-------+-----+----------+
| Name | Age | Birthday |
+-------+-----+----------+
| Alice | 42 | 8/13/16 |
| Bob | 22 | 8/13/16 |
| Eve | 142 | 8/13/16 |
+-------+-----+----------+
pipe
遵循 PHP Markdown Extra extension 的约定。 它对应于 Pandoc 中的 pipe_tables
。 此样式使用冒号来指示列对齐。
table.print(data, style: Style.pipe)
| Name | Age | Birthday |
|:------|----:|---------:|
| Alice | 42 | 8/13/16 |
| Bob | 22 | 8/13/16 |
| Eve | 142 | 8/13/16 |
org
遵循 Emacs org-mode 的约定。
table.print(data, style: Style.org)
| Name | Age | Birthday |
|-------+-----+----------|
| Alice | 42 | 8/13/16 |
| Bob | 22 | 8/13/16 |
| Eve | 142 | 8/13/16 |
rst
遵循 reStructuredText 样式的简单表格的约定。
table.print(data, style: Style.rst)
===== === ========
Name Age Birthday
===== === ========
Alice 42 8/13/16
Bob 22 8/13/16
Eve 142 8/13/16
===== === ========
html
生成 HTML 表格 标记。
table.print(data, style: Style.html)
<table>
<tr>
<th style="text-align:left;">Name</th>
<th style="text-align:center;">Age</th>
<th style="text-align:right;">Birthday</th>
</tr>
<tr>
<td>Alice</td>
<td>42</td>
<td>8/14/16</td>
</tr>
<tr>
<td>Bob</td>
<td>22</td>
<td>8/14/16</td>
</tr>
<tr>
<td>Eve</td>
<td>142</td>
<td>8/14/16</td>
</tr>
</table>
latex
为 Latex 生成一个 tabular 环境。
table.print(data, style: Style.latex)
\begin{tabular}{lll}
\hline
Name & Age & Birthday \\
\hline
Alice & 42 & 8/13/16 \\
Bob & 22 & 8/13/16 \\
Eve & 142 & 8/13/16 \\
\hline
\end{tabular}
您可以通过遵循 TextTableStyle
协议来创建自定义表格样式。
enum MyCustomStyle: TextTableStyle {
// implement methods from TextTableStyle...
}
extension Style {
static let custom = MyCustomStyle.self
}
table.print(data, style: Style.custom)
更改列表可以在 CHANGELOG 中找到。
其他 Swift 库具有类似的目的。
MIT 许可证
Copyright (c) 2016 Cristian Filipov
特此授予任何人免费获得本软件及其相关文档文件(“软件”)副本的许可,以便无限制地处理本软件,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或出售本软件副本的权利,并允许向其提供本软件的人员这样做,但须遵守以下条件:
上述版权声明和本许可声明应包含在本软件的所有副本或重要部分中。
本软件按“原样”提供,不附带任何形式的明示或暗示保证,包括但不限于适销性、适用于特定用途和不侵权的保证。 在任何情况下,作者或版权持有人均不对任何索赔、损害或其他责任负责,无论是在合同诉讼、侵权诉讼还是其他诉讼中,由于与本软件或本软件的使用或其他处理有关而引起或与之相关的任何索赔、损害或其他责任负责。