From 3caeb21c31e595e50bd884c817543f2986e8226e Mon Sep 17 00:00:00 2001 From: Lucas Pickering Date: Wed, 27 Apr 2022 12:50:19 -0400 Subject: [PATCH] Replace prettytable with comfy-table --- .github/workflows/test.yml | 6 +- Cargo.lock | 269 +++++++++++++++++++++++++++++-------- Cargo.toml | 11 +- rust-toolchain.toml | 2 +- src/commands/calc/stew.rs | 115 +++++++++------- src/commands/hiscore.rs | 49 ++++--- src/commands/price.rs | 22 ++- src/utils/context.rs | 4 +- src/utils/mod.rs | 1 + src/utils/skill.rs | 2 +- src/utils/table.rs | 28 ++++ 11 files changed, 358 insertions(+), 151 deletions(-) create mode 100644 src/utils/table.rs diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 81413cf..37f5d21 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -52,16 +52,16 @@ jobs: matrix: rust: # If you update stable, make sure to update Cargo.toml - - "1.56" + - "1.58" # If you update nightly, make sure to update rust-toolchain.toml - - nightly-2021-12-10 + - nightly-2022-04-25 target: # Don't bother testing all targets because linting should only be # different for wasm vs non-wasm - x86_64-unknown-linux-gnu - wasm32-unknown-unknown exclude: - - rust: "1.56" + - rust: "1.58" target: wasm32-unknown-unknown env: # This overrides rust-toolchain.toml diff --git a/Cargo.lock b/Cargo.lock index 2c4860f..3448791 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -74,9 +74,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "base64" @@ -120,12 +120,6 @@ version = "1.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - [[package]] name = "cfg-if" version = "1.0.0" @@ -158,13 +152,25 @@ dependencies = [ "winapi", ] +[[package]] +name = "comfy-table" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b103d85ca6e209388771bfb7aa6b68a7aeec4afbf6f0a0264bfbf50360e5212e" +dependencies = [ + "crossterm", + "strum", + "strum_macros", + "unicode-width", +] + [[package]] name = "console_error_panic_hook" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "wasm-bindgen", ] @@ -174,6 +180,31 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" +[[package]] +name = "crossterm" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2102ea4f781910f8a5b98dd061f4c2023f479ce7bb1236330099ceb5a93cf17" +dependencies = [ + "bitflags", + "crossterm_winapi", + "libc", + "mio 0.8.2", + "parking_lot", + "signal-hook", + "signal-hook-mio", + "winapi", +] + +[[package]] +name = "crossterm_winapi" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ae1b35a484aa10e07fe0638d02301c5ad24de82d310ccbd2f3693da5f09bf1c" +dependencies = [ + "winapi", +] + [[package]] name = "csv" version = "1.1.6" @@ -209,16 +240,6 @@ dependencies = [ "syn", ] -[[package]] -name = "dirs" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3" -dependencies = [ - "cfg-if 0.1.10", - "dirs-sys", -] - [[package]] name = "dirs" version = "4.0.0" @@ -239,19 +260,13 @@ dependencies = [ "winapi", ] -[[package]] -name = "encode_unicode" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" - [[package]] name = "encoding_rs" version = "0.8.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7896dc8abb250ffdda33912550faa54c88ec8b998dec0b2c55ab224921ce11df" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] @@ -378,9 +393,9 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", - "wasi", + "wasi 0.10.2+wasi-snapshot-preview1", ] [[package]] @@ -557,13 +572,23 @@ version = "0.2.112" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" +[[package]] +name = "lock_api" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" +dependencies = [ + "autocfg", + "scopeguard", +] + [[package]] name = "log" version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] @@ -597,6 +622,20 @@ dependencies = [ "winapi", ] +[[package]] +name = "mio" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52da4364ffb0e4fe33a9841a98a3f3014fb964045ce4f7a45a398243c8d6b0c9" +dependencies = [ + "libc", + "log", + "miow", + "ntapi", + "wasi 0.11.0+wasi-snapshot-preview1", + "winapi", +] + [[package]] name = "miow" version = "0.3.7" @@ -655,17 +694,17 @@ dependencies = [ "assert_approx_eq", "async-trait", "colored", + "comfy-table", "console_error_panic_hook", "csv", "derive_more", - "dirs 4.0.0", + "dirs", "figment", "futures", "js-sys", "lazy_static", "num-format", "open", - "prettytable-rs", "regex", "reqwest", "serde", @@ -679,6 +718,29 @@ dependencies = [ "web-sys", ] +[[package]] +name = "parking_lot" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "995f667a6c822200b0433ac218e05582f0e2efa1b922a3fd2fbaadc5f87bab37" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-sys", +] + [[package]] name = "pathdiff" version = "0.2.1" @@ -703,19 +765,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" -[[package]] -name = "prettytable-rs" -version = "0.8.0" -source = "git+https://github.com/phsym/prettytable-rs?branch=master#cf7dca33e2e2131c20e4bbc34ad222c5e6edc29a" -dependencies = [ - "atty", - "csv", - "encode_unicode", - "lazy_static", - "term", - "unicode-width", -] - [[package]] name = "proc-macro-error" version = "1.0.4" @@ -882,12 +931,24 @@ dependencies = [ "base64", ] +[[package]] +name = "rustversion" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f" + [[package]] name = "ryu" version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + [[package]] name = "sct" version = "0.7.0" @@ -947,12 +1008,48 @@ dependencies = [ "serde", ] +[[package]] +name = "signal-hook" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "647c97df271007dcea485bb74ffdb57f2e683f1306c854f468a0c244badabf2d" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-mio" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" +dependencies = [ + "libc", + "mio 0.8.2", + "signal-hook", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +dependencies = [ + "libc", +] + [[package]] name = "slab" version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" +[[package]] +name = "smallvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" + [[package]] name = "socket2" version = "0.4.2" @@ -1000,24 +1097,33 @@ dependencies = [ ] [[package]] -name = "syn" -version = "1.0.82" +name = "strum" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59" +checksum = "cae14b91c7d11c9a851d3fbc80a963198998c2a64eec840477fa92d8ce9b70bb" + +[[package]] +name = "strum_macros" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bb0dc7ee9c15cea6199cde9a127fa16a4c5819af85395457ad72d68edc85a38" dependencies = [ + "heck", "proc-macro2", "quote", - "unicode-xid", + "rustversion", + "syn", ] [[package]] -name = "term" -version = "0.6.1" +name = "syn" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0863a3345e70f61d613eab32ee046ccd1bcc5f9105fe402c61fcd0c13eeb8b5" +checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59" dependencies = [ - "dirs 2.0.2", - "winapi", + "proc-macro2", + "quote", + "unicode-xid", ] [[package]] @@ -1073,7 +1179,7 @@ dependencies = [ "bytes", "libc", "memchr", - "mio", + "mio 0.7.14", "pin-project-lite", "tokio-macros", "winapi", @@ -1127,7 +1233,7 @@ version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "pin-project-lite", "tracing-core", ] @@ -1241,13 +1347,19 @@ version = "0.10.2+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + [[package]] name = "wasm-bindgen" version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "wasm-bindgen-macro", ] @@ -1272,7 +1384,7 @@ version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e8d7523cb1f2a4c96c1317ca690031b714a51cc14e05f712446691f413f5d39" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "js-sys", "wasm-bindgen", "web-sys", @@ -1358,6 +1470,49 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-sys" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5acdd78cb4ba54c0045ac14f62d8f94a03d10047904ae2a40afa1e99d8f70825" +dependencies = [ + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17cffbe740121affb56fad0fc0e421804adf0ae00891205213b5cecd30db881d" + +[[package]] +name = "windows_i686_gnu" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2564fde759adb79129d9b4f54be42b32c89970c18ebf93124ca8870a498688ed" + +[[package]] +name = "windows_i686_msvc" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cd9d32ba70453522332c14d38814bceeb747d80b3958676007acadd7e166956" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfce6deae227ee8d356d19effc141a509cc503dfd1f850622ec4b0f84428e1f4" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d19538ccc21819d01deaf88d6a17eae6596a12e9aafdbb97916fb49896d89de9" + [[package]] name = "winreg" version = "0.7.0" diff --git a/Cargo.toml b/Cargo.toml index 2ef0e34..0978da4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT" name = "osrs-cli" repository = "https://github.com/LucasPickering/osrs-cli" # If you update this, make sure to update the version used in ci.yml -rust-version = "1.56" +rust-version = "1.58" version = "1.1.0" [lib] @@ -35,7 +35,6 @@ figment = {version = "^0.10.6", features = ["json"]} futures = "^0.3.19" lazy_static = "^1.4.0" num-format = "^0.4.0" -prettytable-rs = {version = "^0.8.0", git = "https://github.com/phsym/prettytable-rs", branch = "master"}# Latest version needed to be compatible with wasm regex = "^1.3.9" reqwest = {version = "^0.11.8", default-features = false, features = ["rustls-tls"]} serde = {version = "^1.0.114", features = ["derive"]} @@ -49,12 +48,14 @@ assert_approx_eq = "^1.1.0" # Non-wasm dependencies (stuff that can't run in the browser) [target.'cfg(not(target_family = "wasm"))'.dependencies] -dirs = "4.0" -open = "^2.0.1" -tokio = {version = "^1.15.0", default-features = false, features = ["macros", "rt"]} +comfy-table = "^5.0.1" # tty feature not supported in wasm +dirs = "4.0" +open = "^2.0.1" +tokio = {version = "^1.15.0", default-features = false, features = ["macros", "rt"]} # Wasm-only dependencies [target.'cfg(target_family = "wasm")'.dependencies] +comfy-table = {version = "^5.0.1", default-features = false} console_error_panic_hook = "^0.1.7" js-sys = "^0.3.55" wasm-bindgen = "^0.2.78" diff --git a/rust-toolchain.toml b/rust-toolchain.toml index c39e593..8d41ff6 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] # If you update this, make sure to update the version used in ci.yml -channel = "nightly-2021-12-10" +channel = "nightly-2022-04-25" components = ["cargo", "clippy", "rustfmt"] diff --git a/src/commands/calc/stew.rs b/src/commands/calc/stew.rs index f61d357..d628582 100644 --- a/src/commands/calc/stew.rs +++ b/src/commands/calc/stew.rs @@ -3,10 +3,10 @@ use std::{io::Write, iter}; use crate::{ commands::Command, error::OsrsError, - utils::{context::CommandContext, fmt, math}, + utils::{context::CommandContext, fmt, math, table::TableExt}, }; use async_trait::async_trait; -use prettytable::{color, format::Alignment, Attr, Cell, Row, Table}; +use comfy_table::{presets, Cell, CellAlignment, Row, Table}; use structopt::StructOpt; /// Maximum number of doses per stew @@ -58,60 +58,51 @@ impl Command for CalcStewCommand { probabilities.optimal_doses(Boost(self.boost)); let mut table = Table::new(); - table.set_format( - *prettytable::format::consts::FORMAT_NO_LINESEP_WITH_TITLE, - ); - - table.set_titles(Row::new( - iter::once(Cell::new_align("Doses/Stew", Alignment::RIGHT)) - // Add one col for each boost number (1-5) - .chain((1..=MAX_BOOST).map(|boost| { - let mut cell = Cell::new_align( - &format!("≥+{}", boost), - Alignment::RIGHT, - ); - if boost == self.boost { - cell.style(Attr::Bold); - } - cell - })) - .collect(), - )); + table + .load_preset(presets::ASCII_BORDERS_ONLY_CONDENSED) + .set_aligned_header( + iter::once((Cell::new("Doses/Stew"), CellAlignment::Right)) + // Add one col for each boost number (1-5) + .chain((1..=MAX_BOOST).map(|boost| { + let cell = style_cell( + Cell::new(&format!("≥+{}", boost)) + .set_alignment(CellAlignment::Right), + boost == self.boost, + false, + ); + (cell, CellAlignment::Right) + })), + ); for (doses_per_stew, dose_probabilities) in probabilities.doses_iter() { - table.add_row(Row::new( - iter::once(Cell::new_align( - &fmt::fmt_int(&doses_per_stew.0), - Alignment::RIGHT, - )) - // Calculate prob for hitting each boost value (1-5) - .chain(dose_probabilities.into_iter().map(|(boost, prob)| { - let mut cell = Cell::new_align( - &fmt::fmt_probability(prob), - Alignment::RIGHT, - ); - - // Bold the column for the requested boost level - if boost == Boost(self.boost) { - cell.style(Attr::Bold); - // Highlight the cell with the highest probability - if doses_per_stew == optimal_doses_per_stew { - cell.style(Attr::ForegroundColor(color::GREEN)); - } - } - - cell - })) - .collect(), + table.add_row(Row::from( + iter::once(Cell::new(&fmt::fmt_int(&doses_per_stew.0))) + // Calculate prob for hitting each boost value (1-5) + .chain(dose_probabilities.into_iter().map( + |(boost, prob)| { + let boost_matches = boost == Boost(self.boost); + style_cell( + Cell::new(&fmt::fmt_probability(prob)), + // Bold the column of the requested boost level + boost_matches, + // Highlight cell with highest probability + boost_matches + && doses_per_stew == optimal_doses_per_stew, + ) + }, + )), )); } - context.println( - "The bolded column indicates the requested boost. \ - The green cell is the optimal number of doses to use per stew, to \ - maximize your odds of hitting the boost. - ", - )?; + // Styling doesn 't work on wasm so this caption is pointless + if cfg!(not(wasm)) { + context.println( + "The bolded column indicates the requested boost. \ + The green cell is the optimal number of doses to use per stew, to \ + maximize your odds of hitting the boost. + ", + )?; + } context.print_table(&table)?; Ok(()) @@ -231,3 +222,25 @@ impl Probabilities { ) } } + +/// Apply ANSI styling to a cell. This needs to be a separate function so +/// its functionality can vary for wasm vs native (since ANSI terminal +/// stuff isn't supported in wasm) +#[cfg(not(wasm))] +fn style_cell(mut cell: Cell, bold: bool, color: bool) -> Cell { + use comfy_table::{Attribute, Color}; + + if bold { + cell = cell.add_attribute(Attribute::Bold); + } + if color { + cell = cell.fg(Color::Green); + } + cell +} + +/// Placehold to match the native call signature +#[cfg(wasm)] +fn style_cell(cell: Cell, _bold: bool, _color: bool) -> Cell { + cell +} diff --git a/src/commands/hiscore.rs b/src/commands/hiscore.rs index 1348ab8..0a962db 100644 --- a/src/commands/hiscore.rs +++ b/src/commands/hiscore.rs @@ -1,9 +1,11 @@ use crate::{ commands::Command, - utils::{context::CommandContext, fmt, hiscore::HiscorePlayer}, + utils::{ + context::CommandContext, fmt, hiscore::HiscorePlayer, table::TableExt, + }, }; use async_trait::async_trait; -use prettytable::{row, Table}; +use comfy_table::{presets, CellAlignment, Table}; use std::io::Write; use structopt::StructOpt; @@ -31,16 +33,24 @@ impl Command for HiscoreCommand { // Print a table for skills context.println("Skills")?; let mut table = Table::new(); - table.set_format( - *prettytable::format::consts::FORMAT_NO_LINESEP_WITH_TITLE, - ); - table.set_titles(row!["Skill", r->"Rank", r->"Level", r->"XP"]); + table + .load_preset(presets::ASCII_BORDERS_ONLY_CONDENSED) + .set_aligned_header([ + ("Skill", CellAlignment::Left), + ("Rank", CellAlignment::Right), + ("Level", CellAlignment::Right), + ("XP", CellAlignment::Right), + ]); + for col in [1, 2, 3] { + let column = table.get_column_mut(col).unwrap(); + column.set_cell_alignment(CellAlignment::Right); + } for skill in player.skills { - table.add_row(row![ - skill.name, - r->fmt::fmt_int(&skill.rank), - r->fmt::fmt_int(&skill.level), - r->fmt::fmt_int(&skill.xp), + table.add_row(vec![ + skill.name.to_string(), + fmt::fmt_int(&skill.rank), + fmt::fmt_int(&skill.level), + fmt::fmt_int(&skill.xp), ]); } context.print_table(&table)?; @@ -49,15 +59,18 @@ impl Command for HiscoreCommand { // Print a table for minigames/bosses/etc. context.println("Minigames")?; let mut table = Table::new(); - table.set_format( - *prettytable::format::consts::FORMAT_NO_LINESEP_WITH_TITLE, - ); - table.set_titles(row!["Minigame", r->"Rank", r->"Score"]); + table + .load_preset(presets::ASCII_BORDERS_ONLY_CONDENSED) + .set_aligned_header([ + ("Minigame", CellAlignment::Left), + ("Rank", CellAlignment::Right), + ("Score", CellAlignment::Right), + ]); for minigame in player.minigames { - table.add_row(row![ + table.add_row(vec![ minigame.name, - r->fmt::fmt_int(&minigame.rank), - r->fmt::fmt_int(&minigame.score), + fmt::fmt_int(&minigame.rank), + fmt::fmt_int(&minigame.score), ]); } context.print_table(&table)?; diff --git a/src/commands/price.rs b/src/commands/price.rs index a7485ee..4a787f4 100644 --- a/src/commands/price.rs +++ b/src/commands/price.rs @@ -4,10 +4,11 @@ use crate::{ context::CommandContext, fmt, item::{ItemPrice, WIKI_ITEM_CLIENT}, + table::TableExt, }, }; use async_trait::async_trait; -use prettytable::{row, Table}; +use comfy_table::{presets, CellAlignment, Table}; use std::io::Write; use structopt::StructOpt; @@ -42,19 +43,14 @@ impl Command for PriceCommand { context.println("No results")?; } else { let mut table = Table::new(); - table.set_format( - *prettytable::format::consts::FORMAT_NO_LINESEP_WITH_TITLE, - ); - table.set_titles(row![ - "Item", - r->"Price", - ]); - - for (name, price) in items { - table.add_row(row![ - &name, - r->fmt::fmt_price(price.avg()) + table + .load_preset(presets::ASCII_BORDERS_ONLY_CONDENSED) + .set_aligned_header([ + ("Item", CellAlignment::Left), + ("Price", CellAlignment::Right), ]); + for (name, price) in items { + table.add_row(vec![&name, &fmt::fmt_price(price.avg())]); } context.print_table(&table)?; diff --git a/src/utils/context.rs b/src/utils/context.rs index 28920a4..b1ffe94 100644 --- a/src/utils/context.rs +++ b/src/utils/context.rs @@ -1,5 +1,5 @@ use crate::config::OsrsConfig; -use prettytable::Table; +use comfy_table::Table; use std::{fmt::Arguments, io::Write}; /// A helper type to encapsulate values that we are likely to use multiple @@ -43,7 +43,7 @@ impl CommandContext { /// Print a pretty table to output pub fn print_table(&mut self, table: &Table) -> anyhow::Result<()> { // TODO fix colors - table.print(&mut self.output)?; + self.println(&table.to_string())?; Ok(()) } } diff --git a/src/utils/mod.rs b/src/utils/mod.rs index d61c2fa..d76e0dc 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -7,3 +7,4 @@ pub mod http; pub mod item; pub mod math; pub mod skill; +pub mod table; diff --git a/src/utils/skill.rs b/src/utils/skill.rs index 3b881e1..a988bb1 100644 --- a/src/utils/skill.rs +++ b/src/utils/skill.rs @@ -77,6 +77,6 @@ impl Display for Skill { } } // Impossible because the macro creates an entry for all skills - panic!("Could not format name for skill: {}", self); + panic!("Could not format name for skill: {self:?}"); } } diff --git a/src/utils/table.rs b/src/utils/table.rs new file mode 100644 index 0000000..a501858 --- /dev/null +++ b/src/utils/table.rs @@ -0,0 +1,28 @@ +use comfy_table::{Cell, CellAlignment, Table}; + +/// Additional functionality for the [Table](comfy_table::Table) type +pub trait TableExt { + /// Set the headers of a table in conjunction with an alignment for each + /// column + fn set_aligned_header>( + &mut self, + headers: impl IntoIterator, + ) -> &mut Self; +} + +impl TableExt for Table { + fn set_aligned_header>( + &mut self, + headers: impl IntoIterator, + ) -> &mut Self { + let (header, alignments): (Vec<_>, Vec<_>) = + headers.into_iter().unzip(); + self.set_header(header); + for (i, alignment) in alignments.into_iter().enumerate() { + let column = + self.get_column_mut(i).expect("No column with index {i}"); + column.set_cell_alignment(alignment); + } + self + } +}