Skip to content

Commit 7698151

Browse files
committed
Merge #42: Fix/alignment in tables
d322a9c Fix code duplication in table display functions (Oleksandr Zahorodnyi) 41d5d79 Rework display_user_token_table to use comfy-table (Oleksandr Zahorodnyi) 779f9c3 Rework display_collateral_table to use comfy-table (Oleksandr Zahorodnyi) 9bc8d38 Rework display_swap_table to use comfy-table (Oleksandr Zahorodnyi) f431699 Rework display_token_table to use comfy-table (Oleksandr Zahorodnyi) df73a4e Move display tables functions to separate module (Oleksandr Zahorodnyi) Pull request description: - Move display table functions to a separate module. - Rework those four functions to use the comfy-table crate; the tables now look better. Fixes: #37 ACKs for top commit: KyrylR: ACK d322a9c Tree-SHA512: 78d665fc1417f3069de1b0b192251fcf969fa410664a4fe28614b9b36a4b989f8e6c3a205b2c433197abcebf996ad70caf973bbab91441669661537b72454c49
2 parents 1c119ff + d322a9c commit 7698151

File tree

6 files changed

+131
-85
lines changed

6 files changed

+131
-85
lines changed

crates/cli-client/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ toml = { version = "0.8" }
4242
hex = { version = "0.4" }
4343
dotenvy = { version = "0.15" }
4444
humantime = { version = "2.3.0" }
45-
45+
comfy-table = { version = "7.2.1" }
4646

4747
nostr = { version = "0.44.2" }
4848
nostr-sdk = { version = "0.44.1" }

crates/cli-client/src/cli/browse.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use crate::cli::Cli;
22
use crate::cli::interactive::{
3-
SwapDisplay, TokenDisplay, display_swap_table, display_token_table, format_relative_time, format_settlement_asset,
4-
truncate_with_ellipsis,
3+
SwapDisplay, TokenDisplay, format_relative_time, format_settlement_asset, truncate_with_ellipsis,
54
};
5+
use crate::cli::tables::{display_swap_table, display_token_table};
66
use crate::config::Config;
77
use crate::error::Error;
88

crates/cli-client/src/cli/interactive.rs

Lines changed: 1 addition & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::cli::tables::display_token_table;
12
use crate::error::Error;
23

34
use std::io::{self, Write};
@@ -116,46 +117,6 @@ pub fn format_relative_time(expiry_timestamp: i64) -> String {
116117
}
117118
}
118119

119-
pub fn display_token_table(tokens: &[TokenDisplay]) {
120-
if tokens.is_empty() {
121-
println!(" (No tokens found)");
122-
return;
123-
}
124-
125-
println!(
126-
" {:<3} | {:<18} | {:<14} | {:<18} | Contract",
127-
"#", "Collateral/Token", "Strike/Token", "Expires"
128-
);
129-
println!("{}", "-".repeat(80));
130-
131-
for token in tokens {
132-
println!(
133-
" {:<3} | {:<18} | {:<14} | {:<18} | {}",
134-
token.index, token.collateral, token.settlement, token.expires, token.status
135-
);
136-
}
137-
}
138-
139-
pub fn display_swap_table(swaps: &[SwapDisplay]) {
140-
if swaps.is_empty() {
141-
println!(" (No swaps found)");
142-
return;
143-
}
144-
145-
println!(
146-
" {:<3} | {:<20} | {:<14} | {:<15} | Seller",
147-
"#", "Price", "Wants", "Expires"
148-
);
149-
println!("{}", "-".repeat(80));
150-
151-
for swap in swaps {
152-
println!(
153-
" {:<3} | {:<20} | {:<14} | {:<15} | {}",
154-
swap.index, swap.offering, swap.wants, swap.expires, swap.seller
155-
);
156-
}
157-
}
158-
159120
pub fn prompt_selection(prompt: &str, max: usize) -> io::Result<Option<usize>> {
160121
print!("{prompt} (1-{max}, or 'q' to quit): ");
161122
io::stdout().flush()?;

crates/cli-client/src/cli/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ mod option;
55
mod positions;
66
mod swap;
77
mod sync;
8+
mod tables;
89
mod tx;
910
mod wallet;
1011

crates/cli-client/src/cli/positions.rs

Lines changed: 3 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
use crate::cli::Cli;
22
use crate::cli::interactive::{
3-
EnrichedTokenEntry, GRANTOR_TOKEN_TAG, OPTION_TOKEN_TAG, TokenDisplay, display_token_table,
4-
format_asset_value_with_tag, format_asset_with_tag, format_relative_time, format_settlement_asset, format_time_ago,
3+
EnrichedTokenEntry, GRANTOR_TOKEN_TAG, OPTION_TOKEN_TAG, TokenDisplay, format_asset_value_with_tag,
4+
format_asset_with_tag, format_relative_time, format_settlement_asset, format_time_ago,
55
get_grantor_tokens_from_wallet, get_option_tokens_from_wallet, truncate_with_ellipsis,
66
};
7+
use crate::cli::tables::{display_collateral_table, display_token_table, display_user_token_table};
78
use crate::config::Config;
89
use crate::error::Error;
910
use crate::metadata::ContractMetadata;
@@ -167,46 +168,6 @@ pub struct UserTokenDisplay {
167168
pub contract: String,
168169
}
169170

170-
fn display_collateral_table(displays: &[CollateralDisplay]) {
171-
if displays.is_empty() {
172-
println!(" (No locked assets found)");
173-
return;
174-
}
175-
176-
println!(
177-
" {:<3} | {:<18} | {:<14} | {:<18} | Contract",
178-
"#", "Locked Assets", "Settlement", "Expires"
179-
);
180-
println!("{}", "-".repeat(80));
181-
182-
for display in displays {
183-
println!(
184-
" {:<3} | {:<18} | {:<14} | {:<18} | {}",
185-
display.index, display.collateral, display.settlement, display.expires, display.contract
186-
);
187-
}
188-
}
189-
190-
fn display_user_token_table(displays: &[UserTokenDisplay]) {
191-
if displays.is_empty() {
192-
println!(" (No option/grantor tokens found)");
193-
return;
194-
}
195-
196-
println!(
197-
" {:<3} | {:<8} | {:<10} | {:<14} | {:<18} | Contract",
198-
"#", "Type", "Amount", "Strike/Token", "Expires"
199-
);
200-
println!("{}", "-".repeat(90));
201-
202-
for display in displays {
203-
println!(
204-
" {:<3} | {:<8} | {:<10} | {:<14} | {:<18} | {}",
205-
display.index, display.token_type, display.amount, display.strike, display.expires, display.contract
206-
);
207-
}
208-
}
209-
210171
/// Build locked asset displays, filtering to only show collateral or settlement assets (not reissuance tokens)
211172
async fn build_collateral_displays(
212173
wallet: &crate::wallet::Wallet,
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
use crate::cli::interactive::{SwapDisplay, TokenDisplay};
2+
use crate::cli::positions::{CollateralDisplay, UserTokenDisplay};
3+
use comfy_table::presets::UTF8_FULL;
4+
use comfy_table::{Attribute, Cell, Table};
5+
6+
trait TableData {
7+
fn get_header() -> Vec<String>;
8+
fn to_row(&self) -> Vec<String>;
9+
}
10+
11+
impl TableData for TokenDisplay {
12+
fn get_header() -> Vec<String> {
13+
vec!["#", "Collateral/Token", "Strike/Token", "Expires", "Contract"]
14+
.into_iter()
15+
.map(String::from)
16+
.collect()
17+
}
18+
fn to_row(&self) -> Vec<String> {
19+
vec![
20+
self.index.to_string(),
21+
self.collateral.clone(),
22+
self.settlement.clone(),
23+
self.expires.clone(),
24+
self.status.clone(),
25+
]
26+
}
27+
}
28+
29+
impl TableData for SwapDisplay {
30+
fn get_header() -> Vec<String> {
31+
vec!["#", "Price", "Wants", "Expires", "Seller"]
32+
.into_iter()
33+
.map(String::from)
34+
.collect()
35+
}
36+
fn to_row(&self) -> Vec<String> {
37+
vec![
38+
self.index.to_string(),
39+
self.offering.clone(),
40+
self.wants.clone(),
41+
self.expires.clone(),
42+
self.seller.clone(),
43+
]
44+
}
45+
}
46+
47+
impl TableData for CollateralDisplay {
48+
fn get_header() -> Vec<String> {
49+
vec!["#", "Locked Assets", "Settlement", "Expires", "Contract"]
50+
.into_iter()
51+
.map(String::from)
52+
.collect()
53+
}
54+
fn to_row(&self) -> Vec<String> {
55+
vec![
56+
self.index.to_string(),
57+
self.collateral.clone(),
58+
self.settlement.clone(),
59+
self.expires.clone(),
60+
self.contract.clone(),
61+
]
62+
}
63+
}
64+
65+
impl TableData for UserTokenDisplay {
66+
fn get_header() -> Vec<String> {
67+
vec!["#", "Type", "Amount", "Strike/Token", "Expires", "Contract"]
68+
.into_iter()
69+
.map(String::from)
70+
.collect()
71+
}
72+
fn to_row(&self) -> Vec<String> {
73+
vec![
74+
self.index.to_string(),
75+
self.token_type.clone(),
76+
self.amount.clone(),
77+
self.strike.clone(),
78+
self.expires.clone(),
79+
self.contract.clone(),
80+
]
81+
}
82+
}
83+
84+
fn render_table<T: TableData>(items: &[T], empty_msg: &str) {
85+
if items.is_empty() {
86+
println!(" ({empty_msg})");
87+
return;
88+
}
89+
90+
let mut table = Table::new();
91+
92+
table.load_preset(UTF8_FULL);
93+
94+
let header_cells: Vec<Cell> = T::get_header()
95+
.into_iter()
96+
.map(|h| Cell::new(h).add_attribute(Attribute::Bold))
97+
.collect();
98+
table.set_header(header_cells);
99+
100+
for item in items {
101+
table.add_row(item.to_row());
102+
}
103+
104+
for line in table.to_string().lines() {
105+
println!(" {line}");
106+
}
107+
}
108+
109+
pub fn display_token_table(tokens: &[TokenDisplay]) {
110+
render_table(tokens, "No tokens found");
111+
}
112+
113+
pub fn display_swap_table(swaps: &[SwapDisplay]) {
114+
render_table(swaps, "No swaps found");
115+
}
116+
117+
pub fn display_collateral_table(displays: &[CollateralDisplay]) {
118+
render_table(displays, "No locked assets found");
119+
}
120+
121+
pub fn display_user_token_table(displays: &[UserTokenDisplay]) {
122+
render_table(displays, "No option/grantor tokens found");
123+
}

0 commit comments

Comments
 (0)