prettytable-rs-0.10.0/.cargo_vcs_info.json 0000644 00000000136 00000000001 0014073 0 ustar {
"git": {
"sha1": "4d66e6ebddcd52b641369042b68959ad323d9ad0"
},
"path_in_vcs": ""
} prettytable-rs-0.10.0/.github/dependabot.yml 0000644 0000000 0000000 00000000277 10461020230 0017061 0 ustar 0000000 0000000 version: 2
updates:
- package-ecosystem: cargo
directory: "/"
schedule:
interval: daily
time: "04:00"
open-pull-requests-limit: 10
reviewers:
- phsym
assignees:
- phsym
prettytable-rs-0.10.0/.gitignore 0000644 0000000 0000000 00000000040 10461020230 0014645 0 ustar 0000000 0000000 /target/
/Cargo.lock
\.vscode/
prettytable-rs-0.10.0/.travis.yml 0000644 0000000 0000000 00000004756 10461020230 0015010 0 ustar 0000000 0000000 language: rust
rust:
- 1.32.0
- 1.33.0
- 1.34.0
- 1.35.0
- 1.36.0
- 1.37.0
- stable
- beta
- nightly
script:
- cargo build --verbose --no-default-features
- cargo test --verbose --no-default-features
- cargo build --verbose
- cargo test --verbose
- cargo build --verbose --all-features
- cargo test --verbose --all-features
env:
global:
- RUSTFLAGS="-C link-dead-code"
- secure: k+5s8j7arJSoqS/7BnX7vBEXb1csFsn/cr+WCxRQtlV7bK8JkQ/3t3E1MCUpCSHJLb6K+GlRSkN6tWkhPVUpYA57J7+bSADJ2cAWBq2ArMubXMkMl/t7ibuOArGggDRLulYZ83kDZEkVcMs3QyAv7cGvSMnj6VehTeUrZsIreHmNGJnpsxuXqsfaHhiToWkO/KTRGHOuro7xQczCKzV54g7NAfIgWvcy3T5zVpkaNZWGd/BaRvkBRP8fZpqNBQSlG3Unq3q6wWIeLIJd3QWAQCrzDDMNIbiwsU/KHOJfVvvDFDJF/rzn1EwVvkWRQmT+GtPmLDCRV5OD4hmjVyEtdFU1aLaxxeQBNdSUb3SsDbnUkfyX+WgHEAYRxRAOGW8vhA7+9gaMI2fStkc5JwAcfrZxKkDd9YsUX4iYNk207zsRz/5M6gTWCw2e7jLj9kUGMiTy+008TRxAjSNbN9sl+FRMH5BPMDlgDM4Ohp1+JRq0Mfu1qT6hoYXb+AoRvHijw9HoqtaU2lTamuSN6+LFNJ0CDt2Qhy4jn+Dmp5ZlivcUVzpQpdZoPG00BnLK6YfYoCF9gFX194TM2T6ljhYGaL7ITZI9Cz4qMxD3r459aGz8sUAcTkSbTRMGpTb4fJVfvCgsP2IDfKO7WS/W4SbCzYMh7PfpQg03BAvld0y69O8=
- secure: sF8l0788UwTlEjw+ctKwiw+73zLErGuah6Oh/zYjogwms27HDR7JxrWVXc/dvogwP0nuKoj5m8g4sbtIRkQDZ80OjEr1kefoE71fNDskDYXe4+lTP/RVHF4myTjVZ0HbrHLhiNzpP7NzzCURuOsXa6RGN7A6tSnpX5MZ7euW1HxF9Vjjebsrpko86AJbDESaJaBrFf40P+BJ0xKEEaygtAtnoYMEmSXzAAmOb6SAyDRx8do7433P6At2AEOTuUAocl/nefb36X4aEVfPPd23PVR1wICZmn1LwYccXbGZmW7OvhgU82P9Lb4SgsQtcDJdzOsH0yjsTimf/EDESLQhcD35MDGMUvL0nZ/sOWuTigZw8ax1CLna2kbxYwhZ3lfA8hqt9dkjzi6lwRRSP1CZD0YmaBA0S6H9zcmBdv551wn4nCGu4+uCYcvhqHh6cSZZGTSgiCZ3zr59TeMvAV5Fy3up4IhSYwrQYuPeZ3Wzzm3UEvGaTfmcgIEyqxRfBobNxzQI0I5PcvfXleHxuuOlZiMDFNQEO/dw5pbMaUdABggc0AR6Ph8dmScX3iCfuhzlErUFwNWGEifoojNquuj3+4FOkoAJ3hwqw+hdK3DS7cI2EFjTO9f6bBD72bbeo8lIylrbJo5KDAeIPzs0q1PX2s4DlSoRV39LggSaeZt/xAA=
after_success: |
sudo apt-get update && sudo apt-get install libcurl4-openssl-dev libelf-dev libdw-dev cmake gcc binutils-dev libiberty-dev &&
wget https://github.com/SimonKagstrom/kcov/archive/master.tar.gz &&
tar xzf master.tar.gz && mkdir kcov-master/build && cd kcov-master/build && cmake .. && make &&
sudo make install && cd ../.. &&
for file in target/debug/prettytable-*[^\.d]; do mkdir -p "target/cov/$(basename $file)"; kcov --exclude-pattern=/.cargo,/usr/lib --verify "target/cov/$(basename $file)" "$file"; done &&
bash <(curl -s https://codecov.io/bash)
rm -Rf master.tar.gz kcov-master
git clone https://gist.github.com/deaf3815d2eecce72279.git ./publish_doc &&
sh ./publish_doc/publish_doc.sh prettytable yes
prettytable-rs-0.10.0/CHANGELOG.md 0000644 0000000 0000000 00000001710 10461020230 0014473 0 ustar 0000000 0000000 # Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
# 0.10.0 (2022-12-27)
## Fixed
- Fix panic due to incorrect ANSI escape handling ([#137])
- Fix display of empty tables ([#127])
## Changed
- Remove the unsafe code in `Table::as_ref` ([#146])
- Switch `atty` to `is-terminal` ([#151])
- Minimal Supported Rust Version bumped to 1.56
## Thanks
- @alexanderkjall and @5225225 fuzzer work and fixing panics
- @david0u0 fixing ([#145]) Undefined behavior (UB) on `Table::as_ref`
[#127]: https://github.com/phsym/prettytable-rs/pull/127
[#137]: https://github.com/phsym/prettytable-rs/pull/137
[#145]: https://github.com/phsym/prettytable-rs/issues/145
[#146]: https://github.com/phsym/prettytable-rs/pull/146
[#151]: https://github.com/phsym/prettytable-rs/pull/151
prettytable-rs-0.10.0/Cargo.lock 0000644 00000025060 00000000001 0012051 0 ustar # This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bstr"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223"
dependencies = [
"lazy_static",
"memchr",
"regex-automata",
"serde",
]
[[package]]
name = "cc"
version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "csv"
version = "1.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1"
dependencies = [
"bstr",
"csv-core",
"itoa",
"ryu",
"serde",
]
[[package]]
name = "csv-core"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90"
dependencies = [
"memchr",
]
[[package]]
name = "dirs-next"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1"
dependencies = [
"cfg-if",
"dirs-sys-next",
]
[[package]]
name = "dirs-sys-next"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
dependencies = [
"libc",
"redox_users",
"winapi",
]
[[package]]
name = "encode_unicode"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0"
[[package]]
name = "errno"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1"
dependencies = [
"errno-dragonfly",
"libc",
"winapi",
]
[[package]]
name = "errno-dragonfly"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
dependencies = [
"cc",
"libc",
]
[[package]]
name = "getrandom"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "hermit-abi"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
dependencies = [
"libc",
]
[[package]]
name = "io-lifetimes"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46112a93252b123d31a119a8d1a1ac19deac4fac6e0e8b0df58f0d4e5870e63c"
dependencies = [
"libc",
"windows-sys",
]
[[package]]
name = "is-terminal"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28dfb6c8100ccc63462345b67d1bbc3679177c75ee4bf59bf29c8b1d110b8189"
dependencies = [
"hermit-abi",
"io-lifetimes",
"rustix",
"windows-sys",
]
[[package]]
name = "itoa"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.139"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
[[package]]
name = "linux-raw-sys"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
[[package]]
name = "memchr"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "prettytable-rs"
version = "0.10.0"
dependencies = [
"csv",
"encode_unicode",
"is-terminal",
"lazy_static",
"term",
"unicode-width",
]
[[package]]
name = "proc-macro2"
version = "1.0.49"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
dependencies = [
"proc-macro2",
]
[[package]]
name = "redox_syscall"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
dependencies = [
"bitflags",
]
[[package]]
name = "redox_users"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
dependencies = [
"getrandom",
"redox_syscall",
"thiserror",
]
[[package]]
name = "regex-automata"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
[[package]]
name = "rustix"
version = "0.36.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4feacf7db682c6c329c4ede12649cd36ecab0f3be5b7d74e6a20304725db4549"
dependencies = [
"bitflags",
"errno",
"io-lifetimes",
"libc",
"linux-raw-sys",
"windows-sys",
]
[[package]]
name = "rustversion"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70"
[[package]]
name = "ryu"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"
[[package]]
name = "serde"
version = "1.0.152"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
[[package]]
name = "syn"
version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "term"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f"
dependencies = [
"dirs-next",
"rustversion",
"winapi",
]
[[package]]
name = "thiserror"
version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "unicode-ident"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
[[package]]
name = "unicode-width"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
[[package]]
name = "windows_i686_gnu"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
[[package]]
name = "windows_i686_msvc"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
[[package]]
name = "windows_x86_64_gnu"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
[[package]]
name = "windows_x86_64_msvc"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
prettytable-rs-0.10.0/Cargo.toml 0000644 00000003343 00000000001 0012074 0 ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies.
#
# If you are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.
[package]
edition = "2018"
name = "prettytable-rs"
version = "0.10.0"
authors = ["Pierre-Henri Symoneaux"]
exclude = ["prettytable-evcxr.png"]
description = "A library for printing pretty formatted tables in terminal"
homepage = "https://github.com/phsym/prettytable-rs"
documentation = "https://docs.rs/crate/prettytable-rs/"
readme = "README.md"
keywords = [
"tab",
"table",
"format",
"pretty",
"print",
]
categories = ["command-line-interface"]
license = "BSD-3-Clause"
repository = "https://github.com/phsym/prettytable-rs"
[lib]
name = "prettytable"
[[bin]]
name = "main"
path = "src/main.rs"
edition = "2018"
[dependencies.csv]
version = "1.1"
optional = true
[dependencies.encode_unicode]
version = "1.0"
[dependencies.is-terminal]
version = "0.4"
[dependencies.lazy_static]
version = "1.4"
[dependencies.term]
version = "0.7"
[dependencies.unicode-width]
version = "0.1"
[features]
default = [
"win_crlf",
"csv",
]
evcxr = []
win_crlf = []
[badges.appveyor]
branch = "master"
repository = "phsym/prettytable-rs"
service = "github"
[badges.codecov]
branch = "master"
repository = "phsym/prettytable-rs"
service = "github"
[badges.maintenance]
status = "passively-maintained"
[badges.travis-ci]
branch = "master"
repository = "phsym/prettytable-rs"
prettytable-rs-0.10.0/Cargo.toml.orig 0000644 0000000 0000000 00000002261 10461020230 0015553 0 ustar 0000000 0000000 [package]
name = "prettytable-rs"
version = "0.10.0"
description = "A library for printing pretty formatted tables in terminal"
homepage = "https://github.com/phsym/prettytable-rs"
repository = "https://github.com/phsym/prettytable-rs"
documentation = "https://docs.rs/crate/prettytable-rs/"
readme = "README.md"
authors = [ "Pierre-Henri Symoneaux" ]
keywords = ["tab", "table", "format", "pretty", "print"]
categories = ["command-line-interface"]
license = "BSD-3-Clause"
edition = "2018"
exclude = [
"prettytable-evcxr.png"
]
[badges]
appveyor = { repository = "phsym/prettytable-rs", branch = "master", service = "github" }
travis-ci = { repository = "phsym/prettytable-rs", branch = "master" }
codecov = { repository = "phsym/prettytable-rs", branch = "master", service = "github" }
maintenance = { status = "passively-maintained" }
[features]
default = ["win_crlf", "csv"]
evcxr = []
win_crlf = []
[[bin]]
name = "main"
edition = "2018"
path = "src/main.rs"
[lib]
name = "prettytable"
[dependencies]
unicode-width = "0.1"
term = "0.7"
lazy_static = "1.4"
is-terminal = "0.4"
encode_unicode = "1.0"
csv = { version = "1.1", optional = true }
prettytable-rs-0.10.0/LICENSE.txt 0000644 0000000 0000000 00000002757 10461020230 0014521 0 ustar 0000000 0000000 Copyright (c) 2022, Pierre-Henri Symoneaux
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of prettytable-rs nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. prettytable-rs-0.10.0/README.md 0000644 0000000 0000000 00000032043 10461020230 0014144 0 ustar 0000000 0000000 
[](https://travis-ci.org/phsym/prettytable-rs)
[](https://ci.appveyor.com/project/phsym/tabprint)
[](https://codecov.io/gh/phsym/prettytable-rs)
[](https://crates.io/crates/prettytable-rs)
[](https://docs.rs/crate/prettytable-rs/)
[](http://phsym.github.io/prettytable-rs/master)
# prettytable-rs
A formatted and aligned table printer library for [Rust](https://www.rust-lang.org).
*Copyright © 2022 Pierre-Henri Symoneaux*
> THIS SOFTWARE IS DISTRIBUTED WITHOUT ANY WARRANTY
> Check LICENSE.txt file for more information.
# How to use
* [Including](#user-content-including)
* [Basic usage](#user-content-basic-usage)
* [Using macros](#user-content-using-macros)
* [Do it with style](#user-content-do-it-with-style)
* [List of style specifiers](#user-content-list-of-style-specifiers)
* [List of color specifiers](#user-content-list-of-color-specifiers)
* [Slicing](#user-content-slicing)
* [Customize look and feel of a table](#customize-look-and-feel-of-a-table)
* [CSV import/export](#user-content-csv-importexport)
* [Importing](#user-content-importing)
* [Exporting](#user-content-exporting)
* [Note on line endings](#user-content-note-on-line-endings)
* [Evcxr Integration](#evcxr-integration)
## Including
Include the library as a dependency to your project by adding the following lines to your **Cargo.toml** file:
```toml
[dependencies]
prettytable-rs = "^0.10"
```
The library requires at least `rust v1.56`.
Any changes to the MSRV will be done with a minor version bump.
## SemVer Policy
* Pre-1.0.0 breaking changes will follow a minor version bump
* Post-1.0.0 All default features of this library are covered by SemVer
* MSRV is considered exempt from SemVer as noted above
## Basic usage
Start using it like this:
```rust
#[macro_use] extern crate prettytable;
use prettytable::{Table, Row, Cell};
fn main() {
// Create the table
let mut table = Table::new();
// Add a row per time
table.add_row(row!["ABC", "DEFG", "HIJKLMN"]);
table.add_row(row!["foobar", "bar", "foo"]);
// A more complicated way to add a row:
table.add_row(Row::new(vec![
Cell::new("foobar2"),
Cell::new("bar2"),
Cell::new("foo2")]));
// Print the table to stdout
table.printstd();
}
```
The code above will output
```text
+---------+------+---------+
| ABC | DEFG | HIJKLMN |
+---------+------+---------+
| foobar | bar | foo |
+---------+------+---------+
| foobar2 | bar2 | foo2 |
+---------+------+---------+
```
## Using macros
For everyday usage consider `table!` macro. This code will produce the same output as above:
```rust
#[macro_use] extern crate prettytable;
fn main() {
let table = table!(["ABC", "DEFG", "HIJKLMN"],
["foobar", "bar", "foo"],
["foobar2", "bar2", "foo2"]);
table.printstd();
}
```
The `ptable!` macro combines creating and printing a table:
```rust
#[macro_use] extern crate prettytable;
fn main() {
let table = ptable!(["ABC", "DEFG", "HIJKLMN"],
["foobar", "bar", "foo"],
["foobar2", "bar2", "foo2"]);
}
```
Tables also support multiline cells content. As a result, you can print a table into another table (yo dawg ;).
For example:
```rust
let table1 = table!(["ABC", "DEFG", "HIJKLMN"],
["foobar", "bar", "foo"],
["foobar2", "bar2", "foo2"]);
let table2 = table!(["Title 1", "Title 2"],
["This is\na multiline\ncell", "foo"],
["Yo dawg ;) You can even\nprint tables\ninto tables", table1]);
table2.printstd();
```
will print
```text
+-------------------------+------------------------------+
| Title 1 | Title 2 |
+-------------------------+------------------------------+
| This is | foo |
| a multiline | |
| cell | |
+-------------------------+------------------------------+
| Yo dawg ;) You can even | +---------+------+---------+ |
| print tables | | ABC | DEFG | HIJKLMN | |
| into tables | +---------+------+---------+ |
| | | foobar | bar | foo | |
| | +---------+------+---------+ |
| | | foobar2 | bar2 | foo2 | |
| | +---------+------+---------+ |
+-------------------------+------------------------------+
```
Rows may have different numbers of cells. The table will automatically adapt to the largest row by printing additional empty cells in smaller rows.
## Do it with style!
Tables can have a styled output with background and foreground colors, bold and italic as configurable settings, thanks to the `term` crate. Alignment in cells can also be set (Left, Right, Center), and a cell can span accross multiple columns.
`term` style attributes are reexported
- directly:
```rust
use prettytable::{Attr, color};
/* ... */
table.add_row(Row::new(vec![
Cell::new("foobar")
.with_style(Attr::Bold)
.with_style(Attr::ForegroundColor(color::GREEN)),
Cell::new("bar")
.with_style(Attr::BackgroundColor(color::RED))
.with_style(Attr::Italic(true))
.with_hspan(2),
Cell::new("foo")
]));
```
- through style strings:
```rust
table.add_row(Row::new(vec![
Cell::new("foobar").style_spec("bFg"),
Cell::new("bar").style_spec("BriH2"),
Cell::new("foo")]));
```
- using `row!` macro:
```rust
table.add_row(row![bFg->"foobar", BriH2->"bar", "foo"]);
```
- using `table!` macro (this one creates a new table, unlike previous examples):
```rust
table!([bFg->"foobar", BriH2->"bar", "foo"]);
```
Here
- **bFg** means **bold**, **F**oreground: **g**reen,
- **BriH2** means **B**ackground: **r**ed, **i**talic, **H**orizontal span of **2**.
Another example: **FrBybc** means **F**oreground: **r**ed, **B**ackground: **y**ellow, **b**old, **c**enter.
All cases of styling cells in macros:
- With `row!`, for each cell separately:
```rust
row![FrByb->"ABC", FrByb->"DEFG", "HIJKLMN"];
```
- With `row!`, for the whole row:
```rust
row![FY => "styled", "bar", "foo"];
```
- With `table!`, for each cell separately:
```rust
table!([FrBybl->"A", FrBybc->"B", FrBybr->"C"], [123, 234, 345, 456]);
```
- With `table!`, for whole rows:
```rust
table!([Frb => "A", "B", "C"], [Frb => 1, 2, 3, 4], [1, 2, 3]);
```
- With `table!`, mixed styling:
```rust
table!([Frb => "A", "B", "C"], [Frb->1, Fgi->2, 3, 4], [1, 2, 3]);
```
### List of style specifiers:
* **F** : **F**oreground (must be followed by a color specifier)
* **B** : **B**ackground (must be followed by a color specifier)
* **H** : **H**orizontal span (must be followed by a number)
* **b** : **b**old
* **i** : **i**talic
* **u** : **u**nderline
* **c** : Align **c**enter
* **l** : Align **l**eft
* **r** : Align **r**ight
* **d** : **d**efault style
### List of color specifiers:
Lowercase letters stand for **usual** colors:
* **r** : Red
* **b** : Blue
* **g** : Green
* **y** : Yellow
* **c** : Cyan
* **m** : Magenta
* **w** : White
* **d** : Black
Uppercase letters stand for **bright** counterparts of the above colors:
* **R** : Bright Red
* **B** : Bright Blue
* ... and so on ...
## Slicing
Tables can be sliced into immutable borrowed subtables.
Slices are of type `prettytable::TableSlice<'a>`.
For example,
```rust
use prettytable::Slice;
/* ... */
let slice = table.slice(2..5);
table.printstd();
```
will print a table with only lines 2, 3 and 4 from `table`.
Other `Range` syntaxes are supported. For example:
```rust
table.slice(..); // Returns a borrowed immutable table with all rows
table.slice(2..); // Returns a table with rows starting at index 2
table.slice(..3); // Returns a table with rows until the one at index 3
```
## Customize look and feel of a table
The look and feel of a table can be customized with `prettytable::format::TableFormat`.
Configurable settings include:
- Borders (left and right)
- Junctions
- Column separators
- Line separators
- Titles (using `table.set_titles()`)
To do this, either:
- create a new `TableFormat` object, then call setters until you get the desired configuration;
- or use the convenient `FormatBuilder` and Builder pattern, shown below
```rust
let mut table = Table::new();
let format = format::FormatBuilder::new()
.column_separator('|')
.borders('|')
.separators(&[format::LinePosition::Top,
format::LinePosition::Bottom],
format::LineSeparator::new('-', '+', '+', '+'))
.padding(1, 1)
.build();
table.set_format(format);
table.set_titles(row!["Title 1", "Title 2"]);
table.add_row(row!["Value 1", "Value 2"]);
table.add_row(row!["Value three", "Value four"]);
```
The code above will make the table look like
```
+-------------+------------+
| Title 1 | Title 2 |
| Value 1 | Value 2 |
| Value three | Value four |
+-------------+------------+
```
For convenience, several formats are predefined in `prettytable::format::consts` module.
Some formats and their respective outputs:
- ```rust
use prettytable::format;
table.set_format(*format::consts::FORMAT_NO_LINESEP_WITH_TITLE);
```
```
+-------------+------------+
| Title 1 | Title 2 |
+-------------+------------+
| Value 1 | Value 2 |
| Value three | Value four |
+-------------+------------+
```
- ```rust
use prettytable::format;
table.set_format(*format::consts::FORMAT_NO_BORDER_LINE_SEPARATOR);
```
```
Title 1 | Title 2
------------+------------
Value 1 | Value 2
Value three | Value four
```
Check API documentation for the full list of available predefined formats.
## CSV import/export
Tables can be imported from and exported to **CSV**. This is possible thanks to the default & optional feature `csv`.
> The `csv` feature may become deactivated by default on future major releases.
### Importing
A `Table` can be imported from a string:
```rust
let table = Table::from_csv_string("ABC,DEFG,HIJKLMN\n\
foobar,bar,foo\n\
foobar2,bar2,foo2")?;
```
or from CSV files:
```rust
let table = Table::from_csv_file("input_csv.txt")?;
```
> Those 2 ways of importing CSV assumes a CSV format with `no headers`, and delimited with `commas`
Import can also be done from a CSV reader which allows more customization around the CSV format:
```rust
let reader = /* create a reader */;
/* do something with the reader */
let table = Table::from_csv(reader);
```
### Exporting
Export to a generic `Write`:
```rust
let out = File::create("output_csv.txt")?;
table.to_csv(out)?;
```
or to a `csv::Writer`:
```rust
let writer = /* create a writer */;
/* do something with the writer */
table.to_csv_writer(writer)?;
```
## Note on line endings
By default, the library prints tables with platform specific line ending. This means on Windows,
newlines will be rendered with `\r\n` while on other platforms they will be rendered with `\n`.
Since `v0.6.3`, platform specific line endings are activated though the default feature `win_crlf`, which can be deactivated.
When this feature is deactivated (for instance with the `--no-default-features` flag in cargo), line endings will be rendered with `\n`
on any platform.
This customization capability will probably move to Formatting API in a future release.
Additional examples are provided in the documentation and in [examples](./examples/) directory.
## Evcxr Integration
[Evcxr][evcxr] is a Rust REPL and a [Jupyter notebook kernel][evcxr-jupyter].
This crate integrates into Evcxr and the Jupyter notebooks using the `evcxr` feature flag, which enables native displays of tables.
This includes support for displaying colors and various formattings.
You can include prettytable as a dependency using this line:
```
:dep prettytable = { git = "https://github.com/phsym/prettytable-rs", package = "prettytable-rs", features = ["evcxr"] }
```

[evcxr]: https://github.com/google/evcxr/
[evcxr-jupyter]: https://github.com/google/evcxr/blob/master/evcxr_jupyter/README.md
prettytable-rs-0.10.0/appveyor.yml 0000644 0000000 0000000 00000001310 10461020230 0015246 0 ustar 0000000 0000000 environment:
matrix:
- TARGET: i686-pc-windows-gnu
- TARGET: i686-pc-windows-msvc
- TARGET: x86_64-pc-windows-gnu
- TARGET: x86_64-pc-windows-msvc
install:
- ps: Start-FileDownload "https://static.rust-lang.org/rustup/dist/x86_64-pc-windows-msvc/rustup-init.exe"
- rustup-init.exe -y --default-host %TARGET% --default-toolchain stable
- set PATH=%PATH%;C:\Users\appveyor\.cargo\bin
- rustc -V
- cargo -V
build_script:
- cargo build --verbose
- cargo build --verbose --no-default-features
- cargo build --verbose --all-features
test_script:
- cargo test --verbose
- cargo test --verbose --no-default-features
- cargo test --verbose --all-features
prettytable-rs-0.10.0/examples/basic.rs 0000644 0000000 0000000 00000002506 10461020230 0016133 0 ustar 0000000 0000000 use prettytable::{ptable, row, table, Cell, Row, Table};
/*
Following main function will print :
+---------+------+---------+
| ABC | DEFG | HIJKLMN |
+---------+------+---------+
| foobar | bar | foo |
+---------+------+---------+
| foobar2 | bar2 | foo2 |
+---------+------+---------+
Modified :
+---------+------+---------+
| ABC | DEFG | HIJKLMN |
+---------+------+---------+
| foobar | bar | foo |
+---------+------+---------+
| foobar2 | bar2 | new_foo |
+---------+------+---------+
*/
fn main() {
let mut table = Table::new();
table.add_row(row!["ABC", "DEFG", "HIJKLMN"]);
table.add_row(row!["foobar", "bar", "foo"]);
table.add_row(Row::new(vec![
Cell::new("foobar2"),
Cell::new("bar2"),
Cell::new("foo2"),
]));
table.printstd();
println!("Modified : ");
table.set_element("new_foo", 2, 1).unwrap();
table.printstd();
// The same table can be built the following way :
let _table = table!(
["ABC", "DEFG", "HIJKLMN"],
["foobar", "bar", "foo"],
["foobar2", "bar2", "foo2"]
);
// Or directly print it like this
let _table = ptable!(
["ABC", "DEFG", "HIJKLMN"],
["foobar", "bar", "foo"],
["foobar2", "bar2", "foo2"]
);
}
prettytable-rs-0.10.0/examples/csv.rs 0000644 0000000 0000000 00000001473 10461020230 0015647 0 ustar 0000000 0000000 /*
Following main function will print :
+---------+------+---------+
| ABC | DEFG | HIJKLMN |
+---------+------+---------+
| foobar | bar | foo |
+---------+------+---------+
| foobar2 | bar2 | foo2 |
+---------+------+---------+
ABC,DEFG,HIJKLMN
foobar,bar,foo
foobar2,bar2,foo2
*/
#[cfg(feature = "csv")]
fn main() {
use prettytable::Table;
let table = Table::from_csv_string(
"ABC,DEFG,HIJKLMN\n\
foobar,bar,foo\n\
foobar2,bar2,foo2",
)
.unwrap();
table.printstd();
println!("");
println!(
"{}",
String::from_utf8(table.to_csv(Vec::new()).unwrap().into_inner().unwrap()).unwrap()
);
}
#[cfg(not(feature = "csv"))]
fn main() {}
prettytable-rs-0.10.0/examples/formatting.rs 0000644 0000000 0000000 00000007717 10461020230 0017235 0 ustar 0000000 0000000 use prettytable::{format, row, table};
fn main() {
let mut table = table!(["Value 1", "Value 2"], ["Value three", "Value four"]);
table.set_titles(row!["Title 1", "Title 2"]);
// Print
// +-------------+------------+
// | Title 1 | Title 2 |
// +-------------+------------+
// | Value 1 | Value 2 |
// | Value three | Value four |
// +-------------+------------+
println!("FORMAT_NO_LINESEP_WITH_TITLE :");
table.set_format(*format::consts::FORMAT_NO_LINESEP_WITH_TITLE);
table.printstd();
println!("");
// Print
// -------------------------
// Title 1 Title 2
// =========================
// Value 1 Value 2
// -------------------------
// Value three Value four
// -------------------------
println!("FORMAT_NO_COLSEP :");
table.set_format(*format::consts::FORMAT_NO_COLSEP);
table.printstd();
println!("");
// Print
// +-------------------------+
// | Title 1 Title 2 |
// +=========================+
// | Value 1 Value 2 |
// | Value three Value four |
// +-------------------------+
println!("FORMAT_BORDERS_ONLY :");
table.set_format(*format::consts::FORMAT_BORDERS_ONLY);
table.printstd();
println!("");
// Custom format can be implemented using `prettytable::format::FormatBuilder`
// Example to print
// +-------------+------------+
// | Title 1 | Title 2 |
// | Value 1 | Value 2 |
// | Value three | Value four |
// +-------------+------------+
println!("Custom :");
table.set_format(
format::FormatBuilder::new()
.column_separator('|')
.borders('|')
.separators(
&[format::LinePosition::Top, format::LinePosition::Bottom],
format::LineSeparator::new('-', '+', '+', '+'),
)
.padding(1, 1)
.build(),
);
table.printstd();
// Customized format with unicode
// Example to print
// ┌─────────────┬────────────┐
// │ Title 1 │ Title 2 │
// ├─────────────┼────────────┤
// │ Value 1 │ Value 2 │
// ├─────────────┼────────────┤
// │ Value three │ Value four │
// └─────────────┴────────────┘
println!("With unicode:");
table.set_format(
format::FormatBuilder::new()
.column_separator('│')
.borders('│')
.separators(
&[format::LinePosition::Top],
format::LineSeparator::new('─', '┬', '┌', '┐'),
)
.separators(
&[format::LinePosition::Intern],
format::LineSeparator::new('─', '┼', '├', '┤'),
)
.separators(
&[format::LinePosition::Bottom],
format::LineSeparator::new('─', '┴', '└', '┘'),
)
.padding(1, 1)
.build(),
);
table.printstd();
// Customized format with unicode and different padding
// Example to print
// ┌───────────────┬──────────────┐
// │ Title 1 │ Title 2 │
// ├───────────────┼──────────────┤
// │ Value 1 │ Value 2 │
// ├───────────────┼──────────────┤
// │ Value three │ Value four │
// └───────────────┴──────────────┘
// Change individual format settings
println!("With unicode and padding:");
table.get_format().padding(2, 2);
table.printstd();
}
prettytable-rs-0.10.0/examples/multiline.rs 0000644 0000000 0000000 00000002535 10461020230 0017056 0 ustar 0000000 0000000 use prettytable::table;
/*
Following main function will print :
+-------------------------+------------------------------+
| Title 1 | Title 2 |
+-------------------------+------------------------------+
| This is | foo |
| a multiline | |
| cell | |
+-------------------------+------------------------------+
| Yo dawg ;) You can even | +---------+------+---------+ |
| print tables | | ABC | DEFG | HIJKLMN | |
| into tables | +---------+------+---------+ |
| | | foobar | bar | foo | |
| | +---------+------+---------+ |
| | | foobar2 | bar2 | foo2 | |
| | +---------+------+---------+ |
+-------------------------+------------------------------+
*/
fn main() {
let table1 = table!(
["ABC", "DEFG", "HIJKLMN"],
["foobar", "bar", "foo"],
["foobar2", "bar2", "foo2"]
);
let table2 = table!(
["Title 1", "Title 2"],
["This is\na multiline\ncell", "foo"],
["Yo dawg ;) You can even\nprint tables\ninto tables", table1]
);
table2.printstd();
}
prettytable-rs-0.10.0/examples/slices.rs 0000644 0000000 0000000 00000001315 10461020230 0016331 0 ustar 0000000 0000000 use prettytable::{row, table, Slice};
fn main() {
let mut table = table![
[0, 0, 0],
[1, 1, 1],
[2, 2, 2],
[3, 3, 3],
[4, 4, 4],
[5, 5, 5]
];
table.set_titles(row!["t1", "t2", "t3"]);
let slice = table.slice(..);
let slice = slice.slice(2..);
let slice = slice.slice(..3);
/*
Will print
+----+----+----+
| t1 | t2 | t3 |
+====+====+====+
| 2 | 2 | 2 |
+----+----+----+
| 3 | 3 | 3 |
+----+----+----+
| 4 | 4 | 4 |
+----+----+----+
*/
slice.printstd();
// This is equivalent to
let slice = table.slice(2..5);
slice.printstd();
}
prettytable-rs-0.10.0/examples/span.rs 0000644 0000000 0000000 00000001776 10461020230 0016023 0 ustar 0000000 0000000 use prettytable::{format::Alignment, table, Cell, Row};
fn main() {
/*
The following code will output
+---------------+---------------+--------------+
| A table with horizontal span |
+===============+===============+==============+
| This is a cell with span of 2 | span of 1 |
+---------------+---------------+--------------+
| span of 1 | span of 1 | span of 1 |
+---------------+---------------+--------------+
| This cell with a span of 3 is centered |
+---------------+---------------+--------------+
*/
let mut table: prettytable::Table = table![
[H2 -> "This is a cell with span of 2", "span of 1"],
["span of 1", "span of 1", "span of 1"],
[H03c -> "This cell with a span of 3 is centered"]
];
table.set_titles(Row::new(vec![Cell::new_align(
"A table with horizontal span",
Alignment::CENTER,
)
.with_hspan(3)]));
table.printstd();
}
prettytable-rs-0.10.0/examples/style.rs 0000644 0000000 0000000 00000002407 10461020230 0016212 0 ustar 0000000 0000000 use prettytable::{cell, ptable, row, table};
use prettytable::{color, Attr};
use prettytable::{Cell, Row, Table};
#[allow(dead_code)]
fn main() {
let _ = table!();
let mut table = Table::new();
// Add style to a cell
table.add_row(row![FrByb->"ABC", "DEFG", "HIJKLMN"]);
// Add style to a full row
table.add_row(row![FY => "styled", "bar", "foo"]);
table.add_row(Row::new(vec![
Cell::new("foobar2"),
// Create a cell with a red foreground color
Cell::new("bar2").with_style(Attr::ForegroundColor(color::RED)),
// Create a cell with red foreground color, yellow background color, with bold characters
Cell::new("foo2").style_spec("FrByb"),
// Using the cell! macro
cell!(Fr->"red"),
]));
table.printstd();
// Print a table with some styles on it :
// FrBybl means : Foregound red, Background yellow, bold, left align
ptable!([FrBybl->"A", "B", FrBybr->"C"], [123, 234, 345, 456], [Fg => 1, 2, 3]);
// You can also apply style to full rows :
let mut table = table!([Frb => "A", "B", "C"], [1, 2, 3, 4], ["A\nBCCZZZ\nDDD", 2, table]);
// Set a title line, with all text centered in the cell
table.set_titles(row![c => "Title 1", "Title 2"]);
table.printstd();
}
prettytable-rs-0.10.0/examples/tictactoe.rs 0000644 0000000 0000000 00000005657 10461020230 0017043 0 ustar 0000000 0000000 use prettytable::{cell, table, Table};
use std::io;
use std::io::Write;
use std::str::FromStr;
const CROSS: &'static str = "X";
const EMPTY: &'static str = " ";
const ROUND: &'static str = "O";
fn main() {
let mut table = table![
[EMPTY, EMPTY, EMPTY],
[EMPTY, EMPTY, EMPTY],
[EMPTY, EMPTY, EMPTY]
];
let mut height = table.print_tty(false).unwrap();
let stdin = io::stdin();
let mut stdout = io::stdout();
let mut current = CROSS;
let mut terminal = term::stdout().unwrap();
loop {
let mut line = String::new();
print!("{} plays > ", current);
height += 1;
stdout.flush().unwrap();
stdin.read_line(&mut line).expect("Cannot read input");
let i = match usize::from_str(line.trim()) {
Ok(i) => i,
_ => {
println!("Bad input");
height += 1;
continue;
}
};
if i < 1 || i > 9 {
println!("Bad input, should be between 1 and 9");
height += 1;
continue;
}
let x = (i - 1) % 3;
let y = (i - 1) / 3;
{
let row = table.get_mut_row(y).unwrap();
if row.get_cell(x).unwrap().to_string() != EMPTY {
println!("There's already someone there");
height += 1;
continue;
}
row.set_cell(cell!(current), x).unwrap();
}
for _ in 0..height {
terminal.cursor_up().unwrap();
terminal.delete_line().unwrap();
}
height = table.print_tty(false).unwrap();
if check(&table) {
return;
}
if current == CROSS {
current = ROUND;
} else {
current = CROSS;
}
}
}
fn get(table: &Table, x: usize, y: usize) -> String {
match table.get_row(y) {
Some(r) => match r.get_cell(x) {
Some(c) => c.to_string(),
_ => EMPTY.to_string(),
},
_ => EMPTY.to_string(),
}
}
fn is(table: &Table, s: &str, x: usize, y: usize) -> bool {
get(table, x, y).as_str() == s
}
fn check(table: &Table) -> bool {
let mut full = true;
for y in 0..3 {
for x in 0..3 {
if is(table, EMPTY, x, y) {
full = false;
continue;
}
let current = get(table, x, y);
let c = current.as_str();
if is(table, c, x + 1, y) && is(table, c, x + 2, y)
|| is(table, c, x + 1, y + 1) && is(table, c, x + 2, y + 2)
|| x >= 2 && is(table, c, x - 1, y + 1) && is(table, c, x - 2, y + 2)
|| is(table, c, x, y + 1) && is(table, c, x, y + 2)
{
println!("Game is over. {} is the winner", current);
return true;
}
}
}
if full {
println!("Game is over. It's a draw");
}
full
}
prettytable-rs-0.10.0/src/cell.rs 0000644 0000000 0000000 00000042567 10461020230 0014755 0 ustar 0000000 0000000 //! This module contains definition of table/row cells stuff
use super::format::Alignment;
use super::utils::{display_width, print_align, HtmlEscape};
use super::{color, Attr, Terminal};
use std::io::{Error, Write};
use std::str::FromStr;
use std::string::ToString;
/// Represent a table cell containing a string.
///
/// Once created, a cell's content cannot be modified.
/// The cell would have to be replaced by another one
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct Cell {
content: Vec,
width: usize,
align: Alignment,
style: Vec,
hspan: usize,
}
impl Cell {
/// Create a new `Cell` initialized with content from `string`.
/// Text alignment in cell is configurable with the `align` argument
pub fn new_align(string: &str, align: Alignment) -> Cell {
let content: Vec = string.lines().map(|x| x.to_string()).collect();
let mut width = 0;
for cont in &content {
let l = display_width(&cont[..]);
if l > width {
width = l;
}
}
Cell {
content,
width,
align,
style: Vec::new(),
hspan: 1,
}
}
/// Create a new `Cell` initialized with content from `string`.
/// By default, content is align to `LEFT`
pub fn new(string: &str) -> Cell {
Cell::new_align(string, Alignment::LEFT)
}
/// Set text alignment in the cell
pub fn align(&mut self, align: Alignment) {
self.align = align;
}
/// Add a style attribute to the cell
pub fn style(&mut self, attr: Attr) {
self.style.push(attr);
}
/// Add a style attribute to the cell. Can be chained
pub fn with_style(mut self, attr: Attr) -> Cell {
self.style(attr);
self
}
/// Add horizontal spanning to the cell
pub fn with_hspan(mut self, hspan: usize) -> Cell {
self.set_hspan(hspan);
self
}
/// Remove all style attributes and reset alignment to default (LEFT)
pub fn reset_style(&mut self) {
self.style.clear();
self.align(Alignment::LEFT);
}
/// Set the cell's style by applying the given specifier string
///
/// # Style spec syntax
///
/// The syntax for the style specifier looks like this :
/// **FrBybl** which means **F**oreground **r**ed **B**ackground **y**ellow **b**old **l**eft
///
/// ### List of supported specifiers :
///
/// * **F** : **F**oreground (must be followed by a color specifier)
/// * **B** : **B**ackground (must be followed by a color specifier)
/// * **H** : **H**orizontal span (must be followed by a number)
/// * **b** : **b**old
/// * **i** : **i**talic
/// * **u** : **u**nderline
/// * **c** : Align **c**enter
/// * **l** : Align **l**eft
/// * **r** : Align **r**ight
/// * **d** : **d**efault style
///
/// ### List of color specifiers :
///
/// * **r** : Red
/// * **b** : Blue
/// * **g** : Green
/// * **y** : Yellow
/// * **c** : Cyan
/// * **m** : Magenta
/// * **w** : White
/// * **d** : Black
///
/// And capital letters are for **bright** colors.
/// Eg :
///
/// * **R** : Bright Red
/// * **B** : Bright Blue
/// * ... and so on ...
pub fn style_spec(mut self, spec: &str) -> Cell {
self.reset_style();
let mut foreground = false;
let mut background = false;
let mut it = spec.chars().peekable();
while let Some(c) = it.next() {
if foreground || background {
let color = match c {
'r' => color::RED,
'R' => color::BRIGHT_RED,
'b' => color::BLUE,
'B' => color::BRIGHT_BLUE,
'g' => color::GREEN,
'G' => color::BRIGHT_GREEN,
'y' => color::YELLOW,
'Y' => color::BRIGHT_YELLOW,
'c' => color::CYAN,
'C' => color::BRIGHT_CYAN,
'm' => color::MAGENTA,
'M' => color::BRIGHT_MAGENTA,
'w' => color::WHITE,
'W' => color::BRIGHT_WHITE,
'd' => color::BLACK,
'D' => color::BRIGHT_BLACK,
_ => {
// Silently ignore unknown tags
foreground = false;
background = false;
continue;
}
};
if foreground {
self.style(Attr::ForegroundColor(color));
} else if background {
self.style(Attr::BackgroundColor(color));
}
foreground = false;
background = false;
} else {
match c {
'F' => foreground = true,
'B' => background = true,
'b' => self.style(Attr::Bold),
'i' => self.style(Attr::Italic(true)),
'u' => self.style(Attr::Underline(true)),
'c' => self.align(Alignment::CENTER),
'l' => self.align(Alignment::LEFT),
'r' => self.align(Alignment::RIGHT),
'H' => {
let mut span_s = String::new();
while let Some('0'..='9') = it.peek() {
span_s.push(it.next().unwrap());
}
let span = usize::from_str(&span_s).unwrap();
self.set_hspan(span);
}
_ => { /* Silently ignore unknown tags */ }
}
}
}
self
}
/// Return the height of the cell
// #[deprecated(since="0.8.0", note="Will become private in future release. See [issue #87](https://github.com/phsym/prettytable-rs/issues/87)")]
pub(crate) fn get_height(&self) -> usize {
self.content.len()
}
/// Return the width of the cell
// #[deprecated(since="0.8.0", note="Will become private in future release. See [issue #87](https://github.com/phsym/prettytable-rs/issues/87)")]
pub(crate) fn get_width(&self) -> usize {
self.width
}
/// Set horizontal span for this cell (must be > 0)
pub fn set_hspan(&mut self, hspan: usize) {
self.hspan = if hspan == 0 { 1 } else { hspan };
}
/// Get horizontal span of this cell (> 0)
pub fn get_hspan(&self) -> usize {
self.hspan
}
/// Return a copy of the full string contained in the cell
pub fn get_content(&self) -> String {
self.content.join("\n")
}
/// Print a partial cell to `out`. Since the cell may be multi-lined,
/// `idx` is the line index to print. `col_width` is the column width used to
/// fill the cells with blanks so it fits in the table.
/// If `ìdx` is higher than this cell's height, it will print empty content
// #[deprecated(since="0.8.0", note="Will become private in future release. See [issue #87](https://github.com/phsym/prettytable-rs/issues/87)")]
pub(crate) fn print(
&self,
out: &mut T,
idx: usize,
col_width: usize,
skip_right_fill: bool,
) -> Result<(), Error> {
let c = self.content.get(idx).map(|s| s.as_ref()).unwrap_or("");
print_align(out, self.align, c, ' ', col_width, skip_right_fill)
}
/// Apply style then call `print` to print the cell into a terminal
// #[deprecated(since="0.8.0", note="Will become private in future release. See [issue #87](https://github.com/phsym/prettytable-rs/issues/87)")]
pub(crate) fn print_term(
&self,
out: &mut T,
idx: usize,
col_width: usize,
skip_right_fill: bool,
) -> Result<(), Error> {
for a in &self.style {
match out.attr(*a) {
Ok(..) | Err(::term::Error::NotSupported) | Err(::term::Error::ColorOutOfRange) => {
} // Ignore unsupported attributes
Err(e) => return Err(term_error_to_io_error(e)),
};
}
self.print(out, idx, col_width, skip_right_fill)?;
match out.reset() {
Ok(..) | Err(::term::Error::NotSupported) | Err(::term::Error::ColorOutOfRange) => {
Ok(())
}
Err(e) => Err(term_error_to_io_error(e)),
}
}
/// Print the cell in HTML format to `out`.
pub fn print_html(&self, out: &mut T) -> Result {
/// Convert the color to a hex value useful in CSS
fn color2hex(color: color::Color) -> &'static str {
match color {
color::BLACK => "#000000",
color::RED => "#aa0000",
color::GREEN => "#00aa00",
color::YELLOW => "#aa5500",
color::BLUE => "#0000aa",
color::MAGENTA => "#aa00aa",
color::CYAN => "#00aaaa",
color::WHITE => "#aaaaaa",
color::BRIGHT_BLACK => "#555555",
color::BRIGHT_RED => "#ff5555",
color::BRIGHT_GREEN => "#55ff55",
color::BRIGHT_YELLOW => "#ffff55",
color::BRIGHT_BLUE => "#5555ff",
color::BRIGHT_MAGENTA => "#ff55ff",
color::BRIGHT_CYAN => "#55ffff",
color::BRIGHT_WHITE => "#ffffff",
// Unknown colors, fallback to blakc
_ => "#000000",
}
}
let colspan = if self.hspan > 1 {
format!(" colspan=\"{}\"", self.hspan)
} else {
String::new()
};
// Process style properties like color
let mut styles = String::new();
for style in &self.style {
match style {
Attr::Bold => styles += "font-weight: bold;",
Attr::Italic(true) => styles += "font-style: italic;",
Attr::Underline(true) => styles += "text-decoration: underline;",
Attr::ForegroundColor(c) => {
styles += "color: ";
styles += color2hex(*c);
styles += ";";
}
Attr::BackgroundColor(c) => {
styles += "background-color: ";
styles += color2hex(*c);
styles += ";";
}
_ => {}
}
}
// Process alignment
match self.align {
Alignment::LEFT => styles += "text-align: left;",
Alignment::CENTER => styles += "text-align: center;",
Alignment::RIGHT => styles += "text-align: right;",
}
let content = self.content.join("
");
out.write_all(
format!(
"{0} | ",
HtmlEscape(&content),
colspan,
styles
)
.as_bytes(),
)?;
Ok(self.hspan)
}
}
fn term_error_to_io_error(te: ::term::Error) -> Error {
match te {
::term::Error::Io(why) => why,
_ => Error::new(::std::io::ErrorKind::Other, te),
}
}
impl<'a, T: ToString> From<&'a T> for Cell {
fn from(f: &T) -> Cell {
Cell::new(&f.to_string())
}
}
impl ToString for Cell {
fn to_string(&self) -> String {
self.get_content()
}
}
impl Default for Cell {
/// Return a cell initialized with a single empty `String`, with LEFT alignment
fn default() -> Cell {
Cell {
content: vec!["".to_string(); 1],
width: 0,
align: Alignment::LEFT,
style: Vec::new(),
hspan: 1,
}
}
}
/// This macro simplifies `Cell` creation
///
/// Support 2 syntax : With and without style specification.
/// # Syntax
/// ```text
/// cell!(value);
/// ```
/// or
///
/// ```text
/// cell!(spec->value);
/// ```
/// Value must implement the `std::string::ToString` trait
///
/// For details about style specifier syntax, check doc for [`Cell::style_spec`](cell/struct.Cell.html#method.style_spec) method
/// # Example
/// ```
/// # #[macro_use] extern crate prettytable;
/// # fn main() {
/// let cell = cell!("value");
/// // Do something with the cell
/// # drop(cell);
/// // Create a cell with style (Red foreground, Bold, aligned to left);
/// let styled = cell!(Frbl->"value");
/// # drop(styled);
/// # }
/// ```
#[macro_export]
macro_rules! cell {
() => {
$crate::Cell::default()
};
($value:expr) => {
$crate::Cell::new(&$value.to_string())
};
($style:ident -> $value:expr) => {
$crate::cell!($value).style_spec(stringify!($style))
};
}
#[cfg(test)]
mod tests {
use super::Cell;
use crate::format::Alignment;
use crate::utils::StringWriter;
use term::{color, Attr};
#[test]
fn get_content() {
let cell = Cell::new("test");
assert_eq!(cell.get_content(), "test");
}
#[test]
fn print_ascii() {
let ascii_cell = Cell::new("hello");
assert_eq!(ascii_cell.get_width(), 5);
let mut out = StringWriter::new();
let _ = ascii_cell.print(&mut out, 0, 10, false);
assert_eq!(out.as_string(), "hello ");
}
#[test]
fn print_unicode() {
let unicode_cell = Cell::new("привет");
assert_eq!(unicode_cell.get_width(), 6);
let mut out = StringWriter::new();
let _ = unicode_cell.print(&mut out, 0, 10, false);
assert_eq!(out.as_string(), "привет ");
}
#[test]
fn print_cjk() {
let unicode_cell = Cell::new("由系统自动更新");
assert_eq!(unicode_cell.get_width(), 14);
let mut out = StringWriter::new();
let _ = unicode_cell.print(&mut out, 0, 20, false);
assert_eq!(out.as_string(), "由系统自动更新 ");
}
#[test]
fn print_ascii_html() {
let ascii_cell = Cell::new("hello");
assert_eq!(ascii_cell.get_width(), 5);
let mut out = StringWriter::new();
let _ = ascii_cell.print_html(&mut out);
assert_eq!(
out.as_string(),
r#"hello | "#
);
}
#[test]
fn print_html_special_chars() {
let ascii_cell = Cell::new("&'");
let mut out = StringWriter::new();
let _ = ascii_cell.print_html(&mut out);
assert_eq!(
out.as_string(),
r#"<abc">&' | "#
);
}
#[test]
fn align_left() {
let cell = Cell::new_align("test", Alignment::LEFT);
let mut out = StringWriter::new();
let _ = cell.print(&mut out, 0, 10, false);
assert_eq!(out.as_string(), "test ");
}
#[test]
fn align_center() {
let cell = Cell::new_align("test", Alignment::CENTER);
let mut out = StringWriter::new();
let _ = cell.print(&mut out, 0, 10, false);
assert_eq!(out.as_string(), " test ");
}
#[test]
fn align_right() {
let cell = Cell::new_align("test", Alignment::RIGHT);
let mut out = StringWriter::new();
let _ = cell.print(&mut out, 0, 10, false);
assert_eq!(out.as_string(), " test");
}
#[test]
fn style_spec() {
let mut cell = Cell::new("test").style_spec("FrBBbuic");
assert_eq!(cell.style.len(), 5);
assert!(cell.style.contains(&Attr::Underline(true)));
assert!(cell.style.contains(&Attr::Italic(true)));
assert!(cell.style.contains(&Attr::Bold));
assert!(cell.style.contains(&Attr::ForegroundColor(color::RED)));
assert!(cell
.style
.contains(&Attr::BackgroundColor(color::BRIGHT_BLUE)));
assert_eq!(cell.align, Alignment::CENTER);
cell = cell.style_spec("FDBwr");
assert_eq!(cell.style.len(), 2);
assert!(cell
.style
.contains(&Attr::ForegroundColor(color::BRIGHT_BLACK)));
assert!(cell.style.contains(&Attr::BackgroundColor(color::WHITE)));
assert_eq!(cell.align, Alignment::RIGHT);
// Test with invalid sepcifier chars
cell = cell.clone();
cell = cell.style_spec("FzBr");
assert!(cell.style.contains(&Attr::BackgroundColor(color::RED)));
assert_eq!(cell.style.len(), 1);
cell = cell.style_spec("zzz");
assert!(cell.style.is_empty());
assert_eq!(cell.get_hspan(), 1);
cell = cell.style_spec("FDBwH03r");
assert_eq!(cell.get_hspan(), 3);
}
#[test]
fn reset_style() {
let mut cell = Cell::new("test")
.with_style(Attr::ForegroundColor(color::BRIGHT_BLACK))
.with_style(Attr::BackgroundColor(color::WHITE));
cell.align(Alignment::RIGHT);
//style_spec("FDBwr");
assert_eq!(cell.style.len(), 2);
assert_eq!(cell.align, Alignment::RIGHT);
cell.reset_style();
assert_eq!(cell.style.len(), 0);
assert_eq!(cell.align, Alignment::LEFT);
}
#[test]
fn default_empty_cell() {
let cell = Cell::default();
assert_eq!(cell.align, Alignment::LEFT);
assert!(cell.style.is_empty());
assert_eq!(cell.get_content(), "");
assert_eq!(cell.to_string(), "");
assert_eq!(cell.get_height(), 1);
assert_eq!(cell.get_width(), 0);
}
}
prettytable-rs-0.10.0/src/csv.rs 0000644 0000000 0000000 00000011252 10461020230 0014614 0 ustar 0000000 0000000 //! CSV impl and reexported types
use csv;
pub use self::csv::{Reader, ReaderBuilder, Result, Writer};
use crate::AsTableSlice;
use std::io::{Read, Write};
use std::path::Path;
impl<'a> super::TableSlice<'a> {
/// Write the table to the specified writer.
pub fn to_csv(&self, w: W) -> Result> {
self.to_csv_writer(Writer::from_writer(w))
}
/// Write the table to the specified writer.
///
/// This allows for format customisation.
pub fn to_csv_writer(&self, mut writer: Writer) -> Result> {
for title in self.titles {
writer.write_record(title.iter().map(|c| c.get_content()))?;
}
for row in self.rows {
writer.write_record(row.iter().map(|c| c.get_content()))?;
}
writer.flush()?;
Ok(writer)
}
}
impl super::Table {
/// Create a table from a CSV string
///
/// For more customisability use `from_csv()`
pub fn from_csv_string(csv_s: &str) -> Result {
Ok(Self::from_csv(
&mut ReaderBuilder::new()
.has_headers(false)
.from_reader(csv_s.as_bytes()),
))
}
/// Create a table from a CSV file
///
/// For more customisability use `from_csv()`
pub fn from_csv_file>(csv_p: P) -> Result {
Ok(Self::from_csv(
&mut ReaderBuilder::new().has_headers(false).from_path(csv_p)?,
))
}
/// Create a table from a CSV reader
pub fn from_csv(reader: &mut Reader) -> Self {
Self::init(
reader
.records()
.map(|row| {
super::Row::new(
row.unwrap()
.into_iter()
.map(super::Cell::new)
.collect(),
)
})
.collect(),
)
}
/// Write the table to the specified writer.
pub fn to_csv(&self, w: W) -> Result> {
self.as_slice().to_csv(w)
}
/// Write the table to the specified writer.
///
/// This allows for format customisation.
pub fn to_csv_writer(&self, writer: Writer) -> Result> {
self.as_slice().to_csv_writer(writer)
}
}
#[cfg(test)]
mod tests {
use crate::{Cell, Row, Table};
static CSV_S: &str = "ABC,DEFG,HIJKLMN\n\
foobar,bar,foo\n\
foobar2,bar2,foo2\n";
fn test_table() -> Table {
let mut table = Table::new();
table.add_row(Row::new(vec![
Cell::new("ABC"),
Cell::new("DEFG"),
Cell::new("HIJKLMN"),
]));
table.add_row(Row::new(vec![
Cell::new("foobar"),
Cell::new("bar"),
Cell::new("foo"),
]));
table.add_row(Row::new(vec![
Cell::new("foobar2"),
Cell::new("bar2"),
Cell::new("foo2"),
]));
table
}
#[test]
fn from() {
assert_eq!(
test_table().to_string().replace("\r\n", "\n"),
Table::from_csv_string(CSV_S)
.unwrap()
.to_string()
.replace("\r\n", "\n")
);
}
#[test]
fn to() {
assert_eq!(
String::from_utf8(
test_table()
.to_csv(Vec::new())
.unwrap()
.into_inner()
.unwrap()
)
.unwrap(),
CSV_S
);
}
#[test]
fn trans() {
assert_eq!(
Table::from_csv_string(
&String::from_utf8(
test_table()
.to_csv(Vec::new())
.unwrap()
.into_inner()
.unwrap()
)
.unwrap()
)
.unwrap()
.to_string()
.replace("\r\n", "\n"),
test_table().to_string().replace("\r\n", "\n")
);
}
#[test]
fn extend_table() {
let mut table = Table::new();
table.add_row(Row::new(vec![
Cell::new("ABC"),
Cell::new("DEFG"),
Cell::new("HIJKLMN"),
]));
table.extend(vec![vec!["A", "B", "C"]]);
let t2 = table.clone();
table.extend(t2.rows);
assert_eq!(
table.get_row(1).unwrap().get_cell(2).unwrap().get_content(),
"C"
);
assert_eq!(
table.get_row(2).unwrap().get_cell(1).unwrap().get_content(),
"DEFG"
);
}
}
prettytable-rs-0.10.0/src/evcxr.rs 0000644 0000000 0000000 00000001600 10461020230 0015144 0 ustar 0000000 0000000 //! This modules contains traits and implementations to work within Evcxr
use super::utils::StringWriter;
use super::AsTableSlice;
use std::io::Write;
/// Evcxr specific output trait
pub trait EvcxrDisplay {
/// Print self in one or multiple Evcxr compatile types.
fn evcxr_display(&self);
}
impl EvcxrDisplay for T
where
T: AsTableSlice,
{
fn evcxr_display(&self) {
let mut writer = StringWriter::new();
// Plain Text
let _ = writer.write_all(b"EVCXR_BEGIN_CONTENT text/plain\n");
let _ = self.as_slice().print(&mut writer);
let _ = writer.write_all(b"\nEVCXR_END_CONTENT\n");
// Html
let _ = writer.write_all(b"EVCXR_BEGIN_CONTENT text/html\n");
let _ = self.as_slice().print_html(&mut writer);
let _ = writer.write_all(b"\nEVCXR_END_CONTENT\n");
println!("{}", writer.as_string());
}
}
prettytable-rs-0.10.0/src/format.rs 0000644 0000000 0000000 00000050200 10461020230 0015305 0 ustar 0000000 0000000 //! Define table formatting utilities
use std::io::{Error, Write};
use encode_unicode::Utf8Char;
use super::utils::NEWLINE;
/// Alignment for cell's content
#[derive(Clone, Debug, PartialEq, Copy, Hash, Eq)]
pub enum Alignment {
/// Align left
LEFT,
/// Align in the center
CENTER,
/// Align right
RIGHT,
}
/// Position of a line separator in a table
#[derive(Clone, Debug, PartialEq, Copy, Hash, Eq)]
pub enum LinePosition {
/// Table's border on top
Top,
/// Line separator between the titles row,
/// and the first data row
Title,
/// Line separator between data rows
Intern,
/// Bottom table's border
Bottom,
}
/// Position of a column separator in a row
#[derive(Clone, Debug, PartialEq, Copy, Hash, Eq)]
pub enum ColumnPosition {
/// Left table's border
Left,
/// Internal column separators
Intern,
/// Rigth table's border
Right,
}
/// Contains the character used for printing a line separator
#[derive(Clone, Debug, Copy, Hash, PartialEq, Eq)]
pub struct LineSeparator {
/// Line separator
line: char,
/// Internal junction separator
junc: char,
/// Left junction separator
ljunc: char,
/// Right junction separator
rjunc: char,
}
impl LineSeparator {
/// Create a new line separator instance where `line` is the character used to separate 2 lines
/// and `junc` is the one used for junctions between columns and lines
pub fn new(line: char, junc: char, ljunc: char, rjunc: char) -> LineSeparator {
LineSeparator {
line,
junc,
ljunc,
rjunc,
}
}
/// Print a full line separator to `out`. `col_width` is a slice containing the width of each column.
/// Returns the number of printed lines
fn print(
&self,
out: &mut T,
col_width: &[usize],
padding: (usize, usize),
colsep: bool,
lborder: bool,
rborder: bool,
) -> Result {
if lborder {
out.write_all(Utf8Char::from(self.ljunc).as_bytes())?;
}
let mut iter = col_width.iter().peekable();
while let Some(width) = iter.next() {
for _ in 0..width + padding.0 + padding.1 {
out.write_all(Utf8Char::from(self.line).as_bytes())?;
}
if colsep && iter.peek().is_some() {
out.write_all(Utf8Char::from(self.junc).as_bytes())?;
}
}
if rborder {
out.write_all(Utf8Char::from(self.rjunc).as_bytes())?;
}
out.write_all(NEWLINE)?;
Ok(1)
}
}
impl Default for LineSeparator {
fn default() -> Self {
LineSeparator::new('-', '+', '+', '+')
}
}
/// Contains the table formatting rules
#[derive(Clone, Debug, Copy, Hash, PartialEq, Eq)]
pub struct TableFormat {
/// Optional column separator character
csep: Option,
/// Optional left border character
lborder: Option,
/// Optional right border character
rborder: Option,
/// Optional internal line separator
lsep: Option,
/// Optional title line separator
tsep: Option,
/// Optional top line separator
top_sep: Option,
/// Optional bottom line separator
bottom_sep: Option,
/// Left padding
pad_left: usize,
/// Right padding
pad_right: usize,
/// Global indentation when rendering the table
indent: usize,
}
impl TableFormat {
/// Create a new empty TableFormat.
pub fn new() -> TableFormat {
TableFormat {
csep: None,
lborder: None,
rborder: None,
lsep: None,
tsep: None,
top_sep: None,
bottom_sep: None,
pad_left: 0,
pad_right: 0,
indent: 0,
}
}
/// Return a tuple with left and right padding
pub fn get_padding(&self) -> (usize, usize) {
(self.pad_left, self.pad_right)
}
/// Set left and right padding
pub fn padding(&mut self, left: usize, right: usize) {
self.pad_left = left;
self.pad_right = right;
}
/// Set the character used for internal column separation
pub fn column_separator(&mut self, separator: char) {
self.csep = Some(separator);
}
/// Set the character used for table borders
pub fn borders(&mut self, border: char) {
self.lborder = Some(border);
self.rborder = Some(border);
}
/// Set the character used for left table border
pub fn left_border(&mut self, border: char) {
self.lborder = Some(border);
}
/// Set the character used for right table border
pub fn right_border(&mut self, border: char) {
self.rborder = Some(border);
}
/// Set a line separator
pub fn separator(&mut self, what: LinePosition, separator: LineSeparator) {
*match what {
LinePosition::Top => &mut self.top_sep,
LinePosition::Bottom => &mut self.bottom_sep,
LinePosition::Title => &mut self.tsep,
LinePosition::Intern => &mut self.lsep,
} = Some(separator);
}
/// Set format for multiple kind of line separator
pub fn separators(&mut self, what: &[LinePosition], separator: LineSeparator) {
for pos in what {
self.separator(*pos, separator);
}
}
fn get_sep_for_line(&self, pos: LinePosition) -> &Option {
match pos {
LinePosition::Intern => &self.lsep,
LinePosition::Top => &self.top_sep,
LinePosition::Bottom => &self.bottom_sep,
LinePosition::Title => match &self.tsep {
s @ &Some(_) => s,
&None => &self.lsep,
},
}
}
/// Set global indentation in spaces used when rendering a table
pub fn indent(&mut self, spaces: usize) {
self.indent = spaces;
}
/// Get global indentation in spaces used when rendering a table
pub fn get_indent(&self) -> usize {
self.indent
}
/// Print a full line separator to `out`. `col_width` is a slice containing the width of each column.
/// Returns the number of printed lines
// #[deprecated(since="0.8.0", note="Will become private in future release. See [issue #87](https://github.com/phsym/prettytable-rs/issues/87)")]
pub(crate) fn print_line_separator(
&self,
out: &mut T,
col_width: &[usize],
pos: LinePosition,
) -> Result {
match *self.get_sep_for_line(pos) {
Some(ref l) => {
//TODO: Wrap this into dedicated function one day
out.write_all(&vec![b' '; self.get_indent()])?;
l.print(
out,
col_width,
self.get_padding(),
self.csep.is_some(),
self.lborder.is_some(),
self.rborder.is_some(),
)
}
None => Ok(0),
}
}
/// Returns the character used to separate columns.
/// `pos` specify if the separator is left/right final or internal to the table
pub fn get_column_separator(&self, pos: ColumnPosition) -> Option {
match pos {
ColumnPosition::Left => self.lborder,
ColumnPosition::Intern => self.csep,
ColumnPosition::Right => self.rborder,
}
}
/// Print a column separator or a table border
// #[deprecated(since="0.8.0", note="Will become private in future release. See [issue #87](https://github.com/phsym/prettytable-rs/issues/87)")]
pub(crate) fn print_column_separator(
&self,
out: &mut T,
pos: ColumnPosition,
) -> Result<(), Error> {
match self.get_column_separator(pos) {
Some(s) => out.write_all(Utf8Char::from(s).as_bytes()),
None => Ok(()),
}
}
}
impl Default for TableFormat {
fn default() -> Self {
TableFormat::new()
}
}
/// A builder to create a `TableFormat`
#[derive(Default)]
pub struct FormatBuilder {
format: Box,
}
impl FormatBuilder {
/// Creates a new builder
pub fn new() -> FormatBuilder {
FormatBuilder {
format: Box::new(TableFormat::new()),
}
}
/// Set left and right padding
pub fn padding(mut self, left: usize, right: usize) -> Self {
self.format.padding(left, right);
self
}
/// Set the character used for internal column separation
pub fn column_separator(mut self, separator: char) -> Self {
self.format.column_separator(separator);
self
}
/// Set the character used for table borders
pub fn borders(mut self, border: char) -> Self {
self.format.borders(border);
self
}
/// Set the character used for left table border
pub fn left_border(mut self, border: char) -> Self {
self.format.left_border(border);
self
}
/// Set the character used for right table border
pub fn right_border(mut self, border: char) -> Self {
self.format.right_border(border);
self
}
/// Set a line separator format
pub fn separator(mut self, what: LinePosition, separator: LineSeparator) -> Self {
self.format.separator(what, separator);
self
}
/// Set separator format for multiple kind of line separators
pub fn separators(mut self, what: &[LinePosition], separator: LineSeparator) -> Self {
self.format.separators(what, separator);
self
}
/// Set global indentation in spaces used when rendering a table
pub fn indent(mut self, spaces: usize) -> Self {
self.format.indent(spaces);
self
}
/// Return the generated `TableFormat`
pub fn build(&self) -> TableFormat {
*self.format
}
}
impl From for FormatBuilder {
fn from(fmt: TableFormat) -> Self {
FormatBuilder {
format: Box::new(fmt),
}
}
}
/// Predifined formats. Those constants are lazily evaluated when
/// the corresponding struct is dereferenced
pub mod consts {
use super::{FormatBuilder, LinePosition, LineSeparator, TableFormat};
lazy_static! {
/// A line separator made of `-` and `+`
static ref MINUS_PLUS_SEP: LineSeparator = LineSeparator::new('-', '+', '+', '+');
/// A line separator made of `=` and `+`
static ref EQU_PLUS_SEP: LineSeparator = LineSeparator::new('=', '+', '+', '+');
/// Default table format
///
/// # Example
/// ```text
/// +----+----+
/// | T1 | T2 |
/// +====+====+
/// | a | b |
/// +----+----+
/// | d | c |
/// +----+----+
/// ```
pub static ref FORMAT_DEFAULT: TableFormat = FormatBuilder::new()
.column_separator('|')
.borders('|')
.separator(LinePosition::Intern, *MINUS_PLUS_SEP)
.separator(LinePosition::Title, *EQU_PLUS_SEP)
.separator(LinePosition::Bottom, *MINUS_PLUS_SEP)
.separator(LinePosition::Top, *MINUS_PLUS_SEP)
.padding(1, 1)
.build();
/// Similar to `FORMAT_DEFAULT` but without special separator after title line
///
/// # Example
/// ```text
/// +----+----+
/// | T1 | T2 |
/// +----+----+
/// | a | b |
/// +----+----+
/// | c | d |
/// +----+----+
/// ```
pub static ref FORMAT_NO_TITLE: TableFormat = FormatBuilder::new()
.column_separator('|')
.borders('|')
.separator(LinePosition::Intern, *MINUS_PLUS_SEP)
.separator(LinePosition::Title, *MINUS_PLUS_SEP)
.separator(LinePosition::Bottom, *MINUS_PLUS_SEP)
.separator(LinePosition::Top, *MINUS_PLUS_SEP)
.padding(1, 1)
.build();
/// With no line separator, but with title separator
///
/// # Example
/// ```text
/// +----+----+
/// | T1 | T2 |
/// +----+----+
/// | a | b |
/// | c | d |
/// +----+----+
/// ```
pub static ref FORMAT_NO_LINESEP_WITH_TITLE: TableFormat = FormatBuilder::new()
.column_separator('|')
.borders('|')
.separator(LinePosition::Title, *MINUS_PLUS_SEP)
.separator(LinePosition::Bottom, *MINUS_PLUS_SEP)
.separator(LinePosition::Top, *MINUS_PLUS_SEP)
.padding(1, 1)
.build();
/// With no line or title separator
///
/// # Example
/// ```text
/// +----+----+
/// | T1 | T2 |
/// | a | b |
/// | c | d |
/// +----+----+
/// ```
pub static ref FORMAT_NO_LINESEP: TableFormat = FormatBuilder::new()
.column_separator('|')
.borders('|')
.separator(LinePosition::Bottom, *MINUS_PLUS_SEP)
.separator(LinePosition::Top, *MINUS_PLUS_SEP)
.padding(1, 1)
.build();
/// No column separator
///
/// # Example
/// ```text
/// --------
/// T1 T2
/// ========
/// a b
/// --------
/// d c
/// --------
/// ```
pub static ref FORMAT_NO_COLSEP: TableFormat = FormatBuilder::new()
.separator(LinePosition::Intern, *MINUS_PLUS_SEP)
.separator(LinePosition::Title, *EQU_PLUS_SEP)
.separator(LinePosition::Bottom, *MINUS_PLUS_SEP)
.separator(LinePosition::Top, *MINUS_PLUS_SEP)
.padding(1, 1)
.build();
/// Format for printing a table without any separators (only alignment)
///
/// # Example
/// ```text
/// T1 T2
/// a b
/// d c
/// ```
pub static ref FORMAT_CLEAN: TableFormat = FormatBuilder::new()
.padding(1, 1)
.build();
/// Format for a table with only external borders and title separator
///
/// # Example
/// ```text
/// +--------+
/// | T1 T2 |
/// +========+
/// | a b |
/// | c d |
/// +--------+
/// ```
pub static ref FORMAT_BORDERS_ONLY: TableFormat = FormatBuilder::new()
.padding(1, 1)
.separator(LinePosition::Title, *EQU_PLUS_SEP)
.separator(LinePosition::Bottom, *MINUS_PLUS_SEP)
.separator(LinePosition::Top, *MINUS_PLUS_SEP)
.borders('|')
.build();
/// A table with no external border
///
/// # Example
/// ```text
/// T1 | T2
/// ====+====
/// a | b
/// ----+----
/// c | d
/// ```
pub static ref FORMAT_NO_BORDER: TableFormat = FormatBuilder::new()
.padding(1, 1)
.separator(LinePosition::Intern, *MINUS_PLUS_SEP)
.separator(LinePosition::Title, *EQU_PLUS_SEP)
.column_separator('|')
.build();
/// A table with no external border and no line separation
///
/// # Example
/// ```text
/// T1 | T2
/// ----+----
/// a | b
/// c | d
/// ```
pub static ref FORMAT_NO_BORDER_LINE_SEPARATOR: TableFormat = FormatBuilder::new()
.padding(1, 1)
.separator(LinePosition::Title, *MINUS_PLUS_SEP)
.column_separator('|')
.build();
/// A table with borders and delimiters made with box characters
///
/// # Example
/// ```text
/// ┌────┬────┬────┐
/// │ t1 │ t2 │ t3 │
/// ├────┼────┼────┤
/// │ 1 │ 1 │ 1 │
/// ├────┼────┼────┤
/// │ 2 │ 2 │ 2 │
/// └────┴────┴────┘
/// ```
pub static ref FORMAT_BOX_CHARS: TableFormat = FormatBuilder::new()
.column_separator('│')
.borders('│')
.separators(&[LinePosition::Top],
LineSeparator::new('─',
'┬',
'┌',
'┐'))
.separators(&[LinePosition::Intern],
LineSeparator::new('─',
'┼',
'├',
'┤'))
.separators(&[LinePosition::Bottom],
LineSeparator::new('─',
'┴',
'└',
'┘'))
.padding(1, 1)
.build();
}
}
prettytable-rs-0.10.0/src/lib.rs 0000644 0000000 0000000 00000117546 10461020230 0014604 0 ustar 0000000 0000000 #![warn(
missing_docs,
unused_extern_crates,
unused_import_braces,
unused_qualifications
)]
//! A formatted and aligned table printer written in rust
#[macro_use]
extern crate lazy_static;
use std::fmt;
use std::io::{self, Error, Write};
use std::iter::{FromIterator, IntoIterator};
use std::ops::{Index, IndexMut};
use std::slice::{Iter, IterMut};
pub use term::{color, Attr};
pub(crate) use term::{stdout, Terminal};
mod cell;
pub mod format;
mod row;
mod utils;
#[cfg(feature = "csv")]
pub mod csv;
#[cfg(feature = "evcxr")]
pub mod evcxr;
pub use cell::Cell;
use format::{consts, LinePosition, TableFormat};
pub use row::Row;
use utils::StringWriter;
/// An owned printable table
#[derive(Default, Clone, Debug, Hash, PartialEq, Eq)]
pub struct Table {
format: Box,
titles: Box