-
Notifications
You must be signed in to change notification settings - Fork 0
/
FormattableCommand.swift
62 lines (51 loc) · 1.86 KB
/
FormattableCommand.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import ArgumentParser
import Rainbow
import SwiftyTextTable
enum Format: String, ExpressibleByArgument, CaseIterable {
case text
case table
case csv
}
struct FormattableResult {
let title: String
let columns: [String]
let values: [[String]]
let footer: String?
}
protocol FormattableCommand: ColorizedCommand {
var format: Format { get }
func getResult() throws -> FormattableResult
}
extension FormattableCommand {
static func supportedFormats() -> String {
"Supported formats: \(Format.allCases.map { $0.rawValue }.joined(separator: ", "))"
}
func run() throws {
adjustColorization()
print(formatted(try getResult()))
}
func formatted(_ value: FormattableResult) -> String {
var result: String
switch format {
case .text:
var table = TextTable(columns: value.columns.map { TextTableColumn(header: $0.bold) })
table.addRows(values: value.values)
table.columnFence = ""
table.rowFence = ""
table.cornerFence = ""
result = value.title.bold.underline + "\n\n"
result += table.render().split(whereSeparator: \.isNewline).map { $0.trimmingCharacters(in: .whitespaces) }.joined(separator: "\n")
case .table:
var table = TextTable(columns: value.columns.map { TextTableColumn(header: $0) }, header: value.title.bold)
table.addRows(values: value.values)
result = table.render()
case .csv:
result = value.columns.map { "\"\($0)\"" }.joined(separator: ", ") + "\n"
result += value.values.map { $0.map { "\"\($0)\"" }.joined(separator: ", ") }.joined(separator: "\n")
}
if let footer = value.footer, !footer.isEmpty, format != .csv {
result += "\n\n\(footer.lightBlack)"
}
return result
}
}