From f5f72017286869cb65a3ad30e894f71e699fbede Mon Sep 17 00:00:00 2001 From: Sebastian Miasojed Date: Thu, 1 Feb 2024 14:15:13 +0100 Subject: [PATCH] Add a new tabular layout for the contract storage data (#1485) --- CHANGELOG.md | 1 + Cargo.lock | 33 +++++- crates/cargo-contract/Cargo.toml | 2 +- crates/cargo-contract/src/cmd/storage.rs | 130 ++++++----------------- 4 files changed, 67 insertions(+), 99 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a2db6620e..024873ad2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Mandatory dylint-based lints - [#1412](https://github.com/paritytech/cargo-contract/pull/1412) +- Add a new tabular layout for the contract storage data - [#1485](https://github.com/paritytech/cargo-contract/pull/1485) ## [4.0.0-rc.1] diff --git a/Cargo.lock b/Cargo.lock index aad0979fd..524c846ee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -892,12 +892,12 @@ dependencies = [ "assert_cmd", "clap", "colored", + "comfy-table", "contract-analyze", "contract-build", "contract-extrinsics", "contract-metadata", "contract-transcode", - "crossterm", "current_platform", "hex", "ink_metadata", @@ -1075,6 +1075,18 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "comfy-table" +version = "7.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c64043d6c7b7a4c58e39e7efccfdea7b93d885a795d0c054a69dbbf4dd52686" +dependencies = [ + "crossterm", + "strum 0.25.0", + "strum_macros 0.25.3", + "unicode-width", +] + [[package]] name = "common-path" version = "1.0.0" @@ -5298,6 +5310,12 @@ dependencies = [ "strum_macros 0.24.3", ] +[[package]] +name = "strum" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" + [[package]] name = "strum" version = "0.26.1" @@ -5320,6 +5338,19 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "strum_macros" +version = "0.25.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.48", +] + [[package]] name = "strum_macros" version = "0.26.1" diff --git a/crates/cargo-contract/Cargo.toml b/crates/cargo-contract/Cargo.toml index bd96eaffb..bf8c5e57f 100644 --- a/crates/cargo-contract/Cargo.toml +++ b/crates/cargo-contract/Cargo.toml @@ -38,7 +38,7 @@ semver = "1.0" jsonschema = "0.17" schemars = "0.8" ink_metadata = "5.0.0-rc" -crossterm = "0.27.0" +comfy-table = "7.1.0" # dependencies for extrinsics (deploying and calling a contract) tokio = { version = "1", features = ["macros", "rt-multi-thread"] } diff --git a/crates/cargo-contract/src/cmd/storage.rs b/crates/cargo-contract/src/cmd/storage.rs index 85520e50f..bd8d095ea 100644 --- a/crates/cargo-contract/src/cmd/storage.rs +++ b/crates/cargo-contract/src/cmd/storage.rs @@ -15,11 +15,12 @@ // along with cargo-contract. If not, see . use super::DefaultConfig; -use anyhow::{ - anyhow, - Result, -}; +use anyhow::Result; use colored::Colorize; +use comfy_table::{ + ContentArrangement, + Table, +}; use contract_extrinsics::{ ContractArtifacts, ContractStorage, @@ -27,11 +28,7 @@ use contract_extrinsics::{ ContractStorageRpc, ErrorVariant, }; -use crossterm::terminal; -use std::{ - cmp, - path::PathBuf, -}; +use std::path::PathBuf; use subxt::Config; #[derive(Debug, clap::Args)] @@ -96,8 +93,8 @@ impl StorageCommand { json = serde_json::to_string_pretty(&contract_storage)? ); } else { - let table = StorageDisplayTable::new(&contract_storage)?; - table.display()?; + let table = StorageDisplayTable::new(&contract_storage); + table.display(); } } Err(_) => { @@ -120,110 +117,49 @@ impl StorageCommand { } } -struct StorageDisplayTable<'a> { - storage_layout: &'a ContractStorageLayout, - parent_width: usize, - value_width: usize, -} +struct StorageDisplayTable(Table); -impl<'a> StorageDisplayTable<'a> { - const KEY_WIDTH: usize = 8; - const INDEX_WIDTH: usize = 5; +impl StorageDisplayTable { const INDEX_LABEL: &'static str = "Index"; const KEY_LABEL: &'static str = "Root Key"; const PARENT_LABEL: &'static str = "Parent"; const VALUE_LABEL: &'static str = "Value"; - fn new(storage_layout: &'a ContractStorageLayout) -> Result { - let parent_len = storage_layout - .iter() - .map(|c| c.parent().len()) - .max() - .unwrap_or_default(); - let parent_width = cmp::max(parent_len, Self::PARENT_LABEL.len()); - let terminal_width = terminal::size().unwrap_or((80, 24)).0 as usize; - - // There are tree separators in the table ' | ' - let value_width = terminal_width - .checked_sub(Self::KEY_WIDTH + Self::INDEX_WIDTH + 3 * 3 + parent_width) - .filter(|&w| w > Self::VALUE_LABEL.len()) - .ok_or(anyhow!( - "Terminal width to small to display the storage layout correctly" - ))?; - - Ok(Self { - storage_layout, - parent_width, - value_width, - }) + fn new(storage_layout: &ContractStorageLayout) -> Self { + let mut table = Table::new(); + Self::table_add_header(&mut table); + Self::table_add_rows(&mut table, storage_layout); + Self(table) } - fn table_row_println(&self, index: usize, key: &str, parent: &str, value: &str) { - let mut result = value.split_whitespace().fold( - (Vec::new(), String::new()), - |(mut result, mut current_line), word| { - if current_line.len() + word.len() + 1 > self.value_width { - if !current_line.is_empty() { - result.push(current_line.clone()); - current_line.clear(); - } - current_line.push_str(word); - (result, current_line) - } else { - if !current_line.is_empty() { - current_line.push(' '); - } - current_line.push_str(word); - (result, current_line) - } - }, - ); - - if !result.1.is_empty() { - result.0.push(result.1); - } + fn table_add_header(table: &mut Table) { + table.set_content_arrangement(ContentArrangement::Dynamic); - for (i, value) in result.0.iter().enumerate() { - println!( - "{: Result<()> { - // Print the table header - println!( - "{: