A lightweight library for generating text tables.

Overview

SwiftyTextTable

A lightweight Swift library for generating text tables.

Build Status codecov.io Carthage compatible Swift Package Manager compatible CocoaPods Platform OS X + Linux Language Swift 4.0

Example

Swift Language Support

SwiftyTextTable is now Swift 4.0 compatible! The last release to support Swift 3.1 was 0.7.1. The last release to support Swift 2.3 was 0.3.1.

Installation

Carthage (OS X)

You can use Carthage to install SwiftyTextTable by adding it to your Cartfile:

github "scottrhoyt/SwiftyTextTable"

Swift Package Manager (OS X + Linux)

You can use The Swift Package Manager to install SwiftyTextTable by adding the proper description to your Package.swift file:

import PackageDescription

let package = Package(
    name: "<YOUR_PROJECT_NAME>",
    dependencies: [
        .package(url: "https://github.com/scottrhoyt/SwiftyTextTable.git", from: "0.5.0")
    ]
)

CocoaPods (OS X)

You can use CocoaPods to install SwiftyTextTable by adding it to your Podfile:

pod 'SwiftyTextTable'

Manual

Simply copy the *.swift files from the Source/SwiftyTextTable directory into your project.

Usage

import SwiftyTextTable

// First create some columns
let foo = TextTableColumn(header: "foo")
let bar = TextTableColumn(header: "bar")
let baz = TextTableColumn(header: "baz")

// Then create a table with the columns
var table = TextTable(columns: [foo, bar, baz])

// Then add some rows
table.addRow([1, 2, 3])
table.addRow([11, 22, 33])

// Then render the table and use
let tableString = table.render()
print(tableString)

/*
+-----+-----+-----+
| foo | bar | baz |
+-----+-----+-----+
| 1   | 2   | 3   |
| 11  | 22  | 33  |
+-----+-----+-----+
*/

// Put a header on the table if you'd like
table.header = "my foo table"
print(table.render())

/*
+-----------------+
| my foo table    |
+-----------------+
| foo | bar | baz |
+-----+-----+-----+
| 1   | 2   | 3   |
| 11  | 22  | 33  |
+-----+-----+-----+
*/

Any CustomStringConvertible can be used for row values.

Creating Tables from Arrays of Objects with TextTableRepresentable

Let's say you have an array of objects that looks this:

enum AnimalType: String, CustomStringConvertible {
    case dog = "Dog"
    case cat = "Cat"
    case gorilla = "Gorilla"

    var description: String {
        return self.rawValue
    }
}

struct Pet {
    let type: AnimalType
    let name: String
    let canHazPizza: Bool
}

let furball = Pet(type: .cat, name: "Furball", canHazPizza: false)
let bestFriend = Pet(type: .dog, name: "Best Friend", canHazPizza: true)
let scary = Pet(type: .gorilla, name: "Scary", canHazPizza: true)
let pets = [furball, bestFriend, scary]

Now you want to print a table containing your pets. You can accomplish this by having Pet conform to TextTableRepresentable:

extension Pet: TextTableRepresentable {
    static var columnHeaders: [String] {
        return ["Name", "Animal", "Can Haz Pizza?"]
    }

    var tableValues: [CustomStringConvertible] {
        return [name, type, canHazPizza ? "yes" : "no"]
    }

    // Optional
    static var tableHeader: String? {
      return "My Pets"
    }
}

You can now print a table of your pets simply:

print(pets.renderTextTable())

/*
+----------------------------------------+
| My Pets                                |
+----------------------------------------+
| Name        | Animal  | Can Haz Pizza? |
+-------------+---------+----------------+
| Furball     | Cat     | no             |
| Best Friend | Dog     | yes            |
| Scary       | Gorilla | yes            |
+-------------+---------+----------------+
*/

Fence Custimization

You can also customize the output of TextTable.render() by using different values for columnFence, rowFence, and cornerFence.

table.columnFence = ":"
table.rowFence = "."
table.cornerFence = "."

print(table.render())

/*
...................
: foo : bar : baz :
...................
: 1   : 2   :     :
: 11  : 22  : 33  :
...................
*/

Row Padding/Truncation

When adding rows, TextTable will automatically pad the rows with empty strings when there are fewer values than columns. TextTable will also disregard all values over the column count.

let foo = TextTableColumn(header: "foo")
let bar = TextTableColumn(header: "bar")
let baz = TextTableColumn(header: "baz")

var table = TextTable(columns: [foo, bar, baz])

table.addRow([1, 2])
table.addRow([11, 22, 33])
table.addRow([111, 222, 333, 444])

let tableString = table.render()
print(tableString)

/*
+-----+-----+-----+
| foo | bar | baz |
+-----+-----+-----+
| 1   | 2   |     |
| 11  | 22  | 33  |
| 111 | 222 | 333 |
+-----+-----+-----+
*/

Console Formatting Support

SwiftyTextTable will recognize many console escape sequences used to format output (e.g. Rainbow) and account for them in constructing the table.

API Reference

Check out the full API reference here.

License

SwiftyTextTable is released under the MIT License.

Comments
  • Improve support for escape sequences to support Rainbow.

    Improve support for escape sequences to support Rainbow.

    Hi, just stumbled across SwiftyTextTable and wanted to use it for a project. Thanks for building it!

    Unfortunately it seems SwiftTextTable is unable to calculate the correct size for a column when trying to apply additional information to the strings via something like onevcat/Rainbow.

    I'm getting this for example when applying the color red to the string foo:

    +--------------+-----+-----+
    | foo | bar | baz |
    +--------------+-----+-----+
    | 1            | 2   | 3   |
    | 11           |     | 33  |
    | 111          | 222 | 333 |
    +--------------+-----+-----+
    

    I'm guessing it's because of this, seeing how color information in the terminal is represented through escape sequences that are counted as additional length in this case. Is there any way one could work around this?

    bug help wanted 
    opened by kiliankoe 26
  • Improved support for escape sequences

    Improved support for escape sequences

    This should resolve #5. I have changed the stripping pattern to account for additional escape sequence. However, I am not aware of all escape sequences, so I might have missed something.

    All test passes and I have tested it with the example provided by @kiliankoe in the issue thread. I have also added two additional stripping test that fail on master.

    I would advise some testing before merging.

    opened by Roslund 4
  • Swift 2.2 and 3.0 compatibility

    Swift 2.2 and 3.0 compatibility

    • Uses Xcode 7.3 for version checking on #if
    • Runs swift test using swift-DEVELOPMENT-SNAPSHOT-2016-03-24-a on OS X
    • ~~Does not add test on Linux because swift-corelibs-foundation is still in Swift 2.2~~
    opened by norio-nomura 3
  • Move tests

    Move tests

    Addresses #3 and should help with realm/SwiftLint#555.

    Note that you'll need to make a new tag in order for these changes to be available to other SPM Packages. :pray:

    opened by jpsim 3
  • Proposed change for Travis CI

    Proposed change for Travis CI

    The following updates have been done to improve readability and convenience of CI builds Travis CI:

    • Use jobs instead of matrix
    • Use stages
    • Give proper names to each job, instead of relying on environment variables
    • Ensure release deploys are only run on master branch
    opened by eneko 2
  •  Pre-compute column width to increase rendering performance

    Pre-compute column width to increase rendering performance

    Summary

    Currently, TextTableColumn.width() method is able to return the column width with complexity O(n). This is, when called, it loops through each value (row) in the column, to compute the width.

    Linear complexity O(n) is not bad per se. However, this method width() is called multiple times per column in the TextTable.render() method.

    Moving the computation of column widths before render() is called improves 2x speed by itself (computation time is reduced in half). However, it imposes a penalty in addRow(), which can still slow down populating large tables.

    To further improve performance removing this bottleneck, a new addRows() method has been introduced, which allows adding all rows to the table as a single operation. This ensures column widths are only computed once, after all values have been added.

    To complement the add row methods, a new method clearRows() has been added. This method will remove all values from the table, which is useful for performance tests and may be also useful for consumers of the package.

    Some statistics

    Given a dataset with 3 columns and 1100+ rows, it took over a minute (72s) to render the table:

    $ swift build
    ...
    $ time swift run
    real	1m12.296s
    user	1m10.930s
    sys	0m1.226s
    

    After the update, it took barely 4 seconds to generate and render the same table:

    $ swift build
    ...
    $ time swift run
    real	0m4.029s
    user	0m3.288s
    sys	0m0.728s
    

    Performance Tests

    Together with additional unit tests for the new addRows() and clearRows() methods, new performance tests have been added with baselines for addRow() and addRows().

    opened by eneko 2
  • Multi-Byte Unicode Characters not counted correctly

    Multi-Byte Unicode Characters not counted correctly

    I found that multi-byte unicode characters are counted incorrectly resulting in wrong column widths:

    +----------------------------------------+-------------+-----------------+
    | FILENAME                               | STATUS      | TIMESTAMP       |
    +----------------------------------------+-------------+-----------------+
    | 234212640FW20_0716_C_FRONT_WHL_096.jpg | ❇️ DELIVERED | 17.06.20, 01:57 |
    | 230257732FW20_0013_C_FRONT_BLL_019.jpg | ❇️ DELIVERED | 22.06.20, 19:54 |
    | 230306780BLAA_038.jpg                  | ❇️ DELIVERED | 16.06.20, 12:00 |
    | 230306780FW20_0290_C_FRONT_BKER.jpg    | ❇️ DELIVERED | 17.06.20, 01:58 |
    +----------------------------------------+-------------+-----------------+
    
    opened by odrobnik 1
  • Swift 4.2 Carthage

    Swift 4.2 Carthage

    I'm trying to use SwiftyTextTable using Carthage on macOS Mojave, with Xcode 10 that uses Swift 4.2, and I'm getting the following error:

    *** Cloning SwiftyTextTable
    *** Checking out SwiftyTextTable at "0.8.2"
    *** xcodebuild output can be found in /var/folders/9t/kjmwgng518vcjnczl_0j9h780000gn/T/carthage-xcodebuild.R3VNUw.log
    *** Downloading SwiftyTextTable.framework binary at "0.8.2"
    ***  Skipped installing SwiftyTextTable.framework binary due to the error:
    	"Incompatible Swift version - framework was built with 4.1.2 (swiftlang-902.0.54 clang-902.0.39.2) and the local version is 4.2.1 (swiftlang-1000.11.42 clang-1000.11.45.1)."
    
        Falling back to building from the source
    *** Building scheme "SwiftyTextTable" in SwiftyTextTable.xcodeproj
    
    opened by arguiot 1
  • Carthage failing on CI builds (Xcode 9.4 required)

    Carthage failing on CI builds (Xcode 9.4 required)

    Just noticed CI builds failing on Travis CI because of Carthage now requiring Xcode 9.4.

    Carthage installed. Upgrading if neccessary.
    carthage (0.25.0) < 0.31.1
    ==> Upgrading 1 outdated package:
    carthage 0.25.0 -> 0.31.1
    carthage: A full installation of Xcode.app 9.4 is required to compile this software.
    Installing just the Command Line Tools is not sufficient.
    Xcode 9.4 cannot be installed on macOS 10.12.
    You must upgrade your version of macOS.
    Error: carthage: An unsatisfied requirement failed this build.
    The command "./scripts/upstall-carthage.sh" failed and exited with 1 during .
    

    I believe this would be fixed by requiring Xcode 9.4 on the .travis.yml file. @scottrhoyt let me know your thoughts, I can submit a PR for that.

    opened by eneko 0
  • Pre-compute column width to increase rendering performance

    Pre-compute column width to increase rendering performance

    Summary

    Currently, TextTableColumn.width() method is able to return the column width with complexity O(n). This is, when called, it loops through each value (row) in the column, to compute the width.

    Linear complexity O(n) is not bad per se. However, this method width() is called multiple times per column in the TextTable.render() method.

    Moving the computation of column widths before render() is called improves 2x speed by itself (computation time is reduced in half). However, it imposes a penalty in addRow(), which can still slow down populating large tables.

    To further improve performance removing this bottleneck, a new addRows() method has been introduced, which allows adding all rows to the table as a single operation. This ensures column widths are only computed once, after all values have been added.

    To complement the add row methods, a new method clearRows() has been added. This method will remove all values from the table, which is useful for performance tests and may be also useful for consumers of the package.

    Some statistics

    Given a dataset with 3 columns and 1100+ rows, it took over a minute (72s) to render the table:

    $ swift build
    ...
    $ time swift run
    real	1m12.296s
    user	1m10.930s
    sys	0m1.226s
    

    After the update, it took barely 4 seconds to generate and render the same table:

    $ swift build
    ...
    $ time swift run
    real	0m4.029s
    user	0m3.288s
    sys	0m0.728s
    

    Performance Tests

    Together with additional unit tests for the new addRows() and clearRows() methods, new performance tests have been added with baselines for addRow() and addRows().

    opened by eneko 0
  • Published CVE's in Swift text table

    Published CVE's in Swift text table

    Our OWASP third party scan tool reported 4 published CVE's in SwiftyTextTable library version 0.9.0 which were listed below. CVE-2015-9251 CVE-2019-11358 CVE-2020-11022 CVE-2020-11023 Is there a plan to resolve this and If there is a plan when we can expect the new version of library.

    opened by Divya-Somasundaram 2
  • Changed accessibility of TextTable.columns to public private(set)

    Changed accessibility of TextTable.columns to public private(set)

    I'm writing an extension that allows JSON output for interaction with other scripts – it required me to open up access to the columns property. I thought I'd send it upstream for those in a similar boat.

    I don't think write access is appropriate, as that is what the addRow/addRows functions are for.

    opened by EricRabil 1
  • Further improve support for escape sequences

    Further improve support for escape sequences

    To address the issues in #5 that @travispaul had, I've updated the striping pattern to be shorter (possibly faster?) and catch bold and underline escape sequences. I've also added three aditional cases for the stripping test

    opened by Roslund 0
Releases(0.9.0)
Owner
Scott Hoyt
Software Engineer @facebook
Scott Hoyt
Log messages to text files and share them by email or other way.

LogToFiles How to log messages to text files and share them by email or share center. 1 - Add the Log.swift file to your App 2 - Just log the messages

Miguel Chaves 0 Jan 9, 2022
CleanroomLogger provides an extensible Swift-based logging API that is simple, lightweight and performant

CleanroomLogger CleanroomLogger provides an extensible Swift-based logging API that is simple, lightweight and performant. The API provided by Cleanro

null 1.3k Dec 8, 2022
A lightweight logging framework for Swift

HeliumLogger Provides a lightweight logging implementation for Swift which logs to standard output. Features Logs output to stdout by default. You can

Kitura 174 Nov 30, 2022
A lightweight logging framework for Swift

HeliumLogger Provides a lightweight logging implementation for Swift which logs to standard output. Features Logs output to stdout by default. You can

Kitura 174 Nov 30, 2022
A fancy logger yet lightweight, and configurable. 🖨

?? ?? Important: Printer can only print console logs if you're running an app in the Simulator. If you're running in a real device it will not print a

Hemang 66 Dec 7, 2022
Simple, lightweight and flexible debug logging framework written in Swift

AELog Simple, lightweight and flexible debug logging minion written in Swift If you find yourself in upcoming statements, then you probably want to us

Marko Tadić 28 Jul 6, 2022
A lightweight Swift logger, uses `print` in development and `NSLog` in production. Support colourful and formatted output.

Loggerithm A lightweight Swift logger, uses print in Debug and NSLog in Production with colourful output. Why In Swift, we usually use print to log in

HongHao Zhang 270 Oct 8, 2022
Easy to use and lightweight logger for iOS, macOS, tvOS, watchOS and Linux in Swift.

Lighty Easy to use and lightweight logger for iOS, macOS, tvOS, watchOS and Linux in Swift. Screenshots Requirements Lighty Version Minimum iOS Target

Abdullah Selek 51 Dec 21, 2022
Spy is a flexible, lightweight, multiplatform logging utility written in pure Swift.

Spy is a flexible, lightweight, multiplatform logging utility written in pure Swift. It allows to log with different levels and on different channels. You can define what levels and channels actually are.

AppUnite Sp. z o.o. Spk. 12 Jul 28, 2021
A flexible logging library written in Swift

Puppy Puppy is a flexible logging library written in Swift ?? It supports multiple transports(console, file, syslog, and oslog) as loggers. It not onl

Koichi Yokota 92 Dec 29, 2022
A pure Swift library for using ANSI codes. Basically makes command-line coloring and styling very easy!

Colors A pure Swift library for using ANSI codes. Basically makes command-line coloring and styling very easy! Note: Colors master requires Xcode 7.3

Chad Scira 27 Jun 3, 2021
Swift library for working with Debug Adapter Protocol (DAP)

DebugAdapterProtocol This is a Swift library for interacting with Debug Adapter Protocol. It contains type definitions and utilities useful for both s

Chime 2 Apr 12, 2022
A lightweight library for generating text tables.

SwiftyTextTable A lightweight Swift library for generating text tables. Swift Language Support SwiftyTextTable is now Swift 4.0 compatible! The last r

Scott Hoyt 283 Dec 23, 2022
Swift package for easily rendering text tables. Inspired by the Python tabulate library.

TextTable Easily print textual tables in Swift. Inspired by the Python tabulate library. Upcoming Changes See details on an upcoming change.

Cristian Filipov 102 Jan 5, 2023
Microtonal Tuning Tables for AudioKit

Microtonal Tuning Tables for AudioKit These tuning tables were developed by Marcus Hobbs and used in the AudioKit Synth One iOS app. Installation via

AudioKit 11 Nov 23, 2022
The repository for a command line / build pipeline tool for generating colors from a human-readable text file that designers can also use.

ColorPaletteGenerator ColorPaletteGenerator is a tool that takes a human-readable input file describing a color palette, and generates the associated

horseshoe7 0 Dec 7, 2021
SwiftUI-Text-Animation-Library - Text animation library for SwiftUI

⚠️ This repository is under construction. SwiftUI Text Animation Library Make yo

null 28 Jan 8, 2023
A Swift client library for generating URLs with imgix

imgix-swift is a client library for generating image URLs with imgix. Written in Swift, but can be used with Objective-C codebases as well. Installati

imgix 24 Sep 28, 2022
A Swift micro library for generating Sunrise and Sunset times.

Solar A Swift helper for generating Sunrise and Sunset times. Solar performs its calculations locally using an algorithm from the United States Naval

Chris Howell 493 Dec 25, 2022
A Swift micro library for generating Sunrise and Sunset times.

Solar A Swift helper for generating Sunrise and Sunset times. Solar performs its calculations locally using an algorithm from the United States Naval

Chris Howell 493 Dec 25, 2022