From 5921c19bc089a2de6d4066d61e8a8f1d3229c6e2 Mon Sep 17 00:00:00 2001 From: Maxim Zhiburt Date: Mon, 3 Oct 2022 19:40:16 +0300 Subject: [PATCH] WIP/ Checkout to new `tabled` (#6286) * nu-table/ Use latest tabled Signed-off-by: Maxim Zhiburt * nu-table/ Fix first column alignment Signed-off-by: Maxim Zhiburt * nu-table: Fix cargo clippy Signed-off-by: Maxim Zhiburt * nu-table: Fix color issue Signed-off-by: Maxim Zhiburt * nu-table: Fix footer row Signed-off-by: Maxim Zhiburt * nu-table: Bump tabled Signed-off-by: Maxim Zhiburt * nu-table: Bump tabled Signed-off-by: Maxim Zhiburt * nu-table: Bump tabled Signed-off-by: Maxim Zhiburt * Update Signed-off-by: Maxim Zhiburt * nu-table/ Update * Use latest tabled Signed-off-by: Maxim Zhiburt * Add optional -e, -c argument to `table` command for different view Signed-off-by: Maxim Zhiburt * Fix clippy Signed-off-by: Maxim Zhiburt * Fix clippy Signed-off-by: Maxim Zhiburt * Update Signed-off-by: Maxim Zhiburt * Fix cargo clippy Signed-off-by: Maxim Zhiburt * Fix tests Signed-off-by: Maxim Zhiburt * nu-table: Add footer into -e/c mode Signed-off-by: Maxim Zhiburt * Publish new expand mode Signed-off-by: Maxim Zhiburt * Add width ctrl for Expand mode Signed-off-by: Maxim Zhiburt * Refactorings Signed-off-by: Maxim Zhiburt * Refactorings Signed-off-by: Maxim Zhiburt * Add tests Signed-off-by: Maxim Zhiburt * Add tests Signed-off-by: Maxim Zhiburt * Merge with main Signed-off-by: Maxim Zhiburt * Fix clippy Signed-off-by: Maxim Zhiburt * Fix tests Signed-off-by: Maxim Zhiburt * Fix tests Signed-off-by: Maxim Zhiburt * Bump tabled Signed-off-by: Maxim Zhiburt * Add record expand and fix empty list issue Signed-off-by: Maxim Zhiburt * refactoring Signed-off-by: Maxim Zhiburt --- Cargo.lock | 729 ++++++------- Cargo.toml | 1 - crates/nu-command/src/viewers/table.rs | 1195 ++++++++++++++++----- crates/nu-command/tests/commands/mod.rs | 1 + crates/nu-command/tests/commands/table.rs | 137 +++ crates/nu-table/Cargo.toml | 4 +- crates/nu-table/src/lib.rs | 9 +- crates/nu-table/src/main.rs | 28 +- crates/nu-table/src/nu_protocol_table.rs | 218 ++++ crates/nu-table/src/table.rs | 423 ++++---- crates/nu-table/src/table_theme.rs | 25 +- crates/nu-table/src/textstyle.rs | 18 +- crates/nu-table/src/width_control.rs | 29 - crates/nu-table/tests/constrains.rs | 137 +-- crates/nu-table/tests/style.rs | 219 ++-- out.log | 7 + 16 files changed, 2126 insertions(+), 1054 deletions(-) create mode 100644 crates/nu-command/tests/commands/table.rs create mode 100644 crates/nu-table/src/nu_protocol_table.rs delete mode 100644 crates/nu-table/src/width_control.rs create mode 100644 out.log diff --git a/Cargo.lock b/Cargo.lock index 3424faa6a1..2ae8631b10 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -40,24 +40,24 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "0.7.18" +version = "0.7.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" dependencies = [ "memchr", ] [[package]] name = "alloc-no-stdlib" -version = "2.0.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35ef4730490ad1c4eae5c4325b2a95f521d023e5c885853ff7aca0a6a1631db3" +checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" [[package]] name = "alloc-stdlib" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "697ed7edc0f1711de49ce108c541623a0af97c6c60b2f6e2b65229847ac843c2" +checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" dependencies = [ "alloc-no-stdlib", ] @@ -79,9 +79,9 @@ dependencies = [ [[package]] name = "ansi-str" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e50acdf02a3ac61856d5c8d576a8b5fb452a6549f667ca29fefaa18c2cd05135" +checksum = "132f03d534a71638c1be79251027872d5dda24aa5eeeb6886960351f3087bdde" dependencies = [ "ansitok", ] @@ -106,9 +106,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.58" +version = "1.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb07d2053ccdbe10e2af2995a2f116c1330396493dc1269f6a91d0ae82e19704" +checksum = "98161a4e3e2184da77bb14f02184cdd111e83bbbcc9979dfee3c44b9a85f5602" [[package]] name = "array-init-cursor" @@ -214,9 +214,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.56" +version = "0.1.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96cf8829f67d2eab0b2dfa42c5d0ef737e0724e4a82b01b3e292456202b19716" +checksum = "76464446b8bc32758d7e88ee1a804d9914cd9b1cb264c029899680b0be29826f" dependencies = [ "proc-macro2", "quote", @@ -225,9 +225,9 @@ dependencies = [ [[package]] name = "atomic-polyfill" -version = "0.1.8" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14bf7b4f565e5e717d7a7a65b2a05c0b8c96e4db636d6f780f03b15108cdd1b" +checksum = "9c041a8d9751a520ee19656232a18971f18946a7900f1520ee4400002244dd89" dependencies = [ "critical-section", ] @@ -357,18 +357,9 @@ dependencies = [ [[package]] name = "block-buffer" -version = "0.9.0" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -dependencies = [ - "generic-array", -] - -[[package]] -name = "block-buffer" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" +checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" dependencies = [ "generic-array", ] @@ -417,9 +408,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.10.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" +checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d" [[package]] name = "byte-order" @@ -427,12 +418,6 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b021a13e4bf34a5679ada4609a01337ae82f2c4c97493b9d8cbf8aa9af9bd0f4" -[[package]] -name = "byte-slice-cast" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87c5fdd0166095e1d463fc6cc01aa8ce547ad77a4e84d42eb6762b084e28067e" - [[package]] name = "byte-unit" version = "4.0.14" @@ -450,18 +435,18 @@ checksum = "2c676a478f63e9fa2dd5368a42f28bba0d6c560b775f38583c8bbaa7fcd67c9c" [[package]] name = "bytemuck" -version = "1.11.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5377c8865e74a160d21f29c2d40669f53286db6eab59b88540cbb12ffc8b835" +checksum = "2f5715e491b5a1598fc2bef5a606847b5dc1d48ea625bd3c02c00de8285591da" dependencies = [ "bytemuck_derive", ] [[package]] name = "bytemuck_derive" -version = "1.1.1" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfd2f4180c5721da6335cc9e9061cce522b87a35e51cc57636d28d22a9863c80" +checksum = "1b9e1f5fa78f69496407a27ae9ed989e3c3b072310286f5ef385525e4cbc24a9" dependencies = [ "proc-macro2", "quote", @@ -476,9 +461,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0b3de4a0c5e67e16066a0715723abd91edc2f9001d09c46e1dca929351e130e" +checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db" [[package]] name = "bytesize" @@ -556,9 +541,9 @@ dependencies = [ [[package]] name = "chrono-humanize" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eddc119501d583fd930cb92144e605f44e0252c38dd89d9247fffa1993375cb" +checksum = "32dce1ea1988dbdf9f9815ff11425828523bd2a134ec0805d2ac8af26ee6096e" dependencies = [ "chrono", ] @@ -571,7 +556,7 @@ checksum = "29c39203181991a7dd4343b8005bd804e7a9a37afb8ac070e43771e8c820bbde" dependencies = [ "chrono", "chrono-tz-build", - "phf 0.11.0", + "phf 0.11.1", ] [[package]] @@ -581,15 +566,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f509c3a87b33437b05e2458750a0700e5bdd6956176773e6c7d6dd15a283a0c" dependencies = [ "parse-zoneinfo", - "phf 0.11.0", - "phf_codegen 0.11.0", + "phf 0.11.1", + "phf_codegen 0.11.1", ] [[package]] name = "clang-sys" -version = "1.3.3" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a050e2153c5be08febd6734e29298e844fdb0fa21aeddd63b4eb7baa106c69b" +checksum = "fa2e27ae6ab525c3d369ded447057bca5438d86dc3a68f6faafb8269ba82ebf3" dependencies = [ "glob", "libc", @@ -630,25 +615,18 @@ dependencies = [ [[package]] name = "console" -version = "0.15.0" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28b32d32ca44b70c3e4acd7db1babf555fa026e385fb95f18028f88848b3c31" +checksum = "c050367d967ced717c04b65d8c619d863ef9292ce0c5760028655a2fb298718c" dependencies = [ "encode_unicode", + "lazy_static", "libc", - "once_cell", - "regex", "terminal_size 0.1.17", "unicode-width", "winapi 0.3.9", ] -[[package]] -name = "const_fn" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbdcdcb6d86f71c5e97409ad45898af11cbc995b4ee8112d59095a28d376c935" - [[package]] name = "const_format" version = "0.2.26" @@ -693,9 +671,9 @@ checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" [[package]] name = "cortex-m" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd20d4ac4aa86f4f75f239d59e542ef67de87cce2c282818dc6e84155d3ea126" +checksum = "70858629a458fdfd39f9675c4dc309411f2a3f83bede76988d81bf1a0ecee9e0" dependencies = [ "bare-metal 0.2.5", "bitfield", @@ -792,26 +770,24 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.10" +version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "045ebe27666471bb549370b4b0b3e51b07f56325befa4284db65fc89c02511b1" +checksum = "f916dfc5d356b0ed9dae65f1db9fc9770aa2851d2662b988ccf4fe3516e86348" dependencies = [ "autocfg", "cfg-if 1.0.0", "crossbeam-utils", "memoffset", - "once_cell", "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc" +checksum = "edbafec5fa1f196ca66527c1b12c2ec4745ca14b50f1ad8f9f6f720b55d11fac" dependencies = [ "cfg-if 1.0.0", - "once_cell", ] [[package]] @@ -933,9 +909,9 @@ dependencies = [ [[package]] name = "ctor" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f877be4f7c9f246b183111634f75baa039715e3f46ce860677d3b19a69fb229c" +checksum = "cdffe87e1d521a10f9696f833fe502293ea446d7f256c06128293a4119bdf4cb" dependencies = [ "quote", "syn", @@ -943,11 +919,11 @@ dependencies = [ [[package]] name = "ctrlc" -version = "3.2.2" +version = "3.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b37feaa84e6861e00a1f5e5aa8da3ee56d605c9992d33e082786754828e20865" +checksum = "1d91974fbbe88ec1df0c24a4f00f99583667a7e2e6272b2b92d294d81e462173" dependencies = [ - "nix", + "nix 0.25.0", "winapi 0.3.9", ] @@ -996,20 +972,11 @@ checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" [[package]] name = "digest" -version = "0.9.0" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +checksum = "adfbc57365a37acbd2ebf2b64d7e69bb766e2fea813521ed536f5d0520dcf86c" dependencies = [ - "generic-array", -] - -[[package]] -name = "digest" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" -dependencies = [ - "block-buffer 0.10.2", + "block-buffer", "crypto-common", ] @@ -1095,9 +1062,9 @@ checksum = "453440c271cf5577fd2a40e4942540cb7d0d2f85e27c8d07dd0023c925a67541" [[package]] name = "dyn-clone" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d07a982d1fb29db01e5a59b1918e03da4df7297eaeee7686ac45542fd4e59c8" +checksum = "4f94fa09c2aeea5b8839e414b7b841bf429fd25b9c522116ac97ee87856d88b2" [[package]] name = "ego-tree" @@ -1107,9 +1074,9 @@ checksum = "3a68a4904193147e0a8dec3314640e6db742afd5f6e634f428a6af230d9b3591" [[package]] name = "either" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be" +checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" [[package]] name = "embedded-hal" @@ -1157,9 +1124,9 @@ dependencies = [ [[package]] name = "erased-serde" -version = "0.3.21" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81d013529d5574a60caeda29e179e695125448e5de52e3874f7b4c1d7360e18e" +checksum = "54558e0ba96fbe24280072642eceb9d7d442e32c7ec0ea9e7ecd7b4ea2cf4e11" dependencies = [ "serde", ] @@ -1287,11 +1254,10 @@ checksum = "ee1b05cbd864bcaecbd3455d6d967862d446e4ebfc3c2e5e5b9841e53cba6673" [[package]] name = "form_urlencoded" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" dependencies = [ - "matches", "percent-encoding", ] @@ -1354,9 +1320,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" +checksum = "7f21eda599937fba36daeb58a22e8f5cee2d14c4a17b5b7739c7c8e5e3b8230c" dependencies = [ "futures-channel", "futures-core", @@ -1369,9 +1335,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" +checksum = "30bdd20c28fadd505d0fd6712cdfcb0d4b5648baf45faef7f852afb2399bb050" dependencies = [ "futures-core", "futures-sink", @@ -1379,15 +1345,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" +checksum = "4e5aa3de05362c3fb88de6531e6296e85cde7739cccad4b9dfeeb7f6ebce56bf" [[package]] name = "futures-executor" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6" +checksum = "9ff63c23854bee61b6e9cd331d523909f238fc7636290b96826e9cfa5faa00ab" dependencies = [ "futures-core", "futures-task", @@ -1396,15 +1362,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" +checksum = "bbf4d2a7a308fd4578637c0b17c7e1c7ba127b8f6ba00b29f717e9655d85eb68" [[package]] name = "futures-macro" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" +checksum = "42cd15d1c7456c04dbdf7e88bcd69760d74f3a798d6444e16974b505b0e62f17" dependencies = [ "proc-macro2", "quote", @@ -1413,21 +1379,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" +checksum = "21b20ba5a92e727ba30e72834706623d94ac93a725410b6a6b6fbc1b07f7ba56" [[package]] name = "futures-task" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" +checksum = "a6508c467c73851293f390476d4491cf4d227dbabcd4170f3bb6044959b294f1" [[package]] name = "futures-util" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" +checksum = "44fb6cb1be61cc1d2e43b262516aafcf63b241cffdb1d3fa115f91d9c7b09c90" dependencies = [ "futures-channel", "futures-core", @@ -1461,9 +1427,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.5" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" +checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" dependencies = [ "typenum", "version_check", @@ -1524,9 +1490,9 @@ dependencies = [ [[package]] name = "ghost" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b93490550b1782c589a350f2211fff2e34682e25fed17ef53fc4fa8fe184975e" +checksum = "eb19fe8de3ea0920d282f7b77dd4227aea6b8b999b42cdf0ca41b2472b14443a" dependencies = [ "proc-macro2", "quote", @@ -1568,9 +1534,9 @@ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" [[package]] name = "h2" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37a82c6d637fc9515a4694bbf1cb2457b79d81ce52b3108bdeea58b07dd34a57" +checksum = "5ca32592cf21ac7ccab1825cd87f6c9b3d9022c44d086172ed0966bec8af30be" dependencies = [ "bytes", "fnv", @@ -1628,18 +1594,18 @@ dependencies = [ [[package]] name = "hashlink" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d452c155cb93fecdfb02a73dd57b5d8e442c2063bd7aac72f1bc5e4263a43086" +checksum = "69fe1fcf8b4278d860ad0548329f892a3631fb63f82574df68275f34cdbe0ffa" dependencies = [ "hashbrown", ] [[package]] name = "heapless" -version = "0.7.15" +version = "0.7.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f6733da246dc2af610133c8be0667170fd68e8ca5630936b520300eee8846f9" +checksum = "db04bc24a18b9ea980628ecf00e6c0264f3c1426dac36c00cb49b6fbad8b0743" dependencies = [ "atomic-polyfill", "hash32", @@ -1706,7 +1672,7 @@ checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" dependencies = [ "bytes", "fnv", - "itoa 1.0.2", + "itoa 1.0.3", ] [[package]] @@ -1722,9 +1688,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.7.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" [[package]] name = "httpdate" @@ -1747,7 +1713,7 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa 1.0.2", + "itoa 1.0.3", "pin-project-lite", "socket2", "tokio", @@ -1771,14 +1737,13 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.47" +version = "0.1.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c495f162af0bf17656d0014a0eded5f3cd2f365fdd204548c2869db89359dc7" +checksum = "fd911b35d940d2bd0bea0f9100068e5b97b51a1cbe13d13382f132e0365257a0" dependencies = [ "android_system_properties", "core-foundation-sys", "js-sys", - "once_cell", "wasm-bindgen", "winapi 0.3.9", ] @@ -1794,11 +1759,10 @@ dependencies = [ [[package]] name = "idna" -version = "0.2.3" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" dependencies = [ - "matches", "unicode-bidi", "unicode-normalization", ] @@ -1871,9 +1835,9 @@ dependencies = [ [[package]] name = "io-lifetimes" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24c3f4eff5495aee4c0399d7b6a0dc2b6e81be84242ffbfcf253ebacccc1d0cb" +checksum = "1ea37f355c05dde75b84bba2d767906ad522e97cd9e2eef2be7a4ab7fb442c06" [[package]] name = "iovec" @@ -1923,9 +1887,9 @@ dependencies = [ [[package]] name = "itertools" -version = "0.10.3" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" dependencies = [ "either", ] @@ -1938,15 +1902,15 @@ checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] name = "itoa" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" +checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" [[package]] name = "jobserver" -version = "0.1.24" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa" +checksum = "068b1ee6743e4d11fb9c6a1e6064b3693a1b600e7f5f5988047d98b3dc9fb90b" dependencies = [ "libc", ] @@ -1959,9 +1923,9 @@ checksum = "72167d68f5fce3b8655487b8038691a3c9984ee769590f93f2a631f4ad64e4f5" [[package]] name = "js-sys" -version = "0.3.59" +version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "258451ab10b34f8af53416d1fdab72c22e805f0c92a1136d59470ec0b11138b2" +checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" dependencies = [ "wasm-bindgen", ] @@ -1972,6 +1936,16 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47631885425c482fcf2dc4b182fc973c3c5b81a8f43a028055559bd24cccfa6e" +[[package]] +name = "json_to_table" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fe97d58ab96691e90f26c10ecc1fc098a4c072714d2d126cc8a2234b89f3456" +dependencies = [ + "serde_json", + "tabled", +] + [[package]] name = "kernel32-sys" version = "0.2.2" @@ -2069,9 +2043,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.126" +version = "0.2.134" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" +checksum = "329c933548736bc49fd575ee68c89e8be4d260064184389a5b77517cddd99ffb" [[package]] name = "libgit2-sys" @@ -2099,9 +2073,9 @@ dependencies = [ [[package]] name = "libm" -version = "0.2.2" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33a33a362ce288760ec6a508b94caaec573ae7d3bbbd91b87aa0bad4456839db" +checksum = "292a948cd991e376cf75541fe5b97a1081d713c618b4f1b9500f8844e49eb565" [[package]] name = "libproc" @@ -2168,9 +2142,9 @@ checksum = "d4d2456c373231a208ad294c33dc5bff30051eafd954cd4caae83a712b12854d" [[package]] name = "lock_api" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" dependencies = [ "autocfg", "scopeguard", @@ -2197,9 +2171,9 @@ dependencies = [ [[package]] name = "lz4" -version = "1.23.3" +version = "1.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4edcb94251b1c375c459e5abe9fb0168c1c826c3370172684844f8f3f8d1a885" +checksum = "7e9e2dd86df36ce760a60f6ff6ad526f7ba1f14ba0356f8254fb6905e6494df1" dependencies = [ "libc", "lz4-sys", @@ -2261,11 +2235,11 @@ checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" [[package]] name = "md-5" -version = "0.10.1" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658646b21e0b72f7866c7038ab086d3d5e1cd6271f060fd37defb241949d0582" +checksum = "6365506850d44bff6e2fbcb5176cf63650e48bd45ef2fe2665ae1570e0f4b9ca" dependencies = [ - "digest 0.10.3", + "digest", ] [[package]] @@ -2276,9 +2250,9 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memmap2" -version = "0.5.5" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a79b39c93a7a5a27eeaf9a23b5ff43f1b9e0ad6b1cdd441140ae53c35613fc7" +checksum = "95af15f345b17af2efc8ead6080fb8bc376f8cec1b35277b935637595fe77498" dependencies = [ "libc", ] @@ -2316,20 +2290,20 @@ dependencies = [ [[package]] name = "miette" -version = "5.1.1" +version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d67f6972a70e33dbb5551875c6a3e46ae0a7cddd4661a2811ee48be51054e9" +checksum = "a28d6092d7e94a90bb9ea8e6c26c99d5d112d49dda2afdb4f7ea8cf09e1a5a6d" dependencies = [ "atty", "backtrace", - "miette-derive 5.1.1", + "miette-derive 5.3.0", "once_cell", "owo-colors", "supports-color", "supports-hyperlinks", "supports-unicode", "terminal_size 0.1.17", - "textwrap 0.15.0", + "textwrap 0.15.1", "thiserror", "unicode-width", ] @@ -2347,9 +2321,9 @@ dependencies = [ [[package]] name = "miette-derive" -version = "5.1.1" +version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "426594bc7266dedee4d687cdaebc121c74c52a667e4ce933c83694ad035990a6" +checksum = "4f2485ed7d1fe80704928e3eb86387439609bd0c6bb96db8208daa364cfd1e09" dependencies = [ "proc-macro2", "quote", @@ -2370,9 +2344,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc" +checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34" dependencies = [ "adler", ] @@ -2514,6 +2488,18 @@ dependencies = [ "memoffset", ] +[[package]] +name = "nix" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e322c04a9e3440c327fca7b6c8a63e6890a32fa2ad689db972425f07e0d22abb" +dependencies = [ + "autocfg", + "bitflags", + "cfg-if 1.0.0", + "libc", +] + [[package]] name = "nodrop" version = "0.1.14" @@ -2576,6 +2562,15 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "ntapi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc51db7b362b205941f71232e56c625156eb9a929f8cf74a428fd5bc094a4afc" +dependencies = [ + "winapi 0.3.9", +] + [[package]] name = "nu" version = "0.69.2" @@ -2589,8 +2584,8 @@ dependencies = [ "is_executable", "itertools", "log", - "miette 5.1.1", - "nix", + "miette 5.3.0", + "nix 0.24.2", "nu-ansi-term", "nu-cli", "nu-color-config", @@ -2616,7 +2611,7 @@ dependencies = [ "signal-hook", "simplelog", "tempfile", - "time 0.3.13", + "time 0.3.14", "winres", ] @@ -2642,7 +2637,7 @@ dependencies = [ "is_executable", "lazy_static", "log", - "miette 5.1.1", + "miette 5.3.0", "nu-ansi-term", "nu-color-config", "nu-command", @@ -2687,7 +2682,7 @@ dependencies = [ "crossterm 0.24.0", "csv", "dialoguer", - "digest 0.10.3", + "digest", "dirs-next", "dtparse", "eml-parser", @@ -2730,7 +2725,7 @@ dependencies = [ "polars", "powierza-coefficient", "proptest", - "quick-xml 0.23.0", + "quick-xml 0.23.1", "quickcheck", "quickcheck_macros", "rand 0.8.5", @@ -2746,7 +2741,7 @@ dependencies = [ "serde_ini", "serde_urlencoded", "serde_yaml", - "sha2 0.10.2", + "sha2", "shadow-rs", "sqlparser", "strip-ansi-escapes", @@ -2808,7 +2803,7 @@ dependencies = [ "chrono", "itertools", "log", - "miette 5.1.1", + "miette 5.3.0", "nu-engine", "nu-path", "nu-plugin", @@ -2860,7 +2855,7 @@ dependencies = [ "chrono-humanize", "fancy-regex", "indexmap", - "miette 5.1.1", + "miette 5.3.0", "nu-json", "nu-path", "nu-utils", @@ -2882,8 +2877,8 @@ dependencies = [ "libc", "libproc", "mach2", - "nix", - "ntapi", + "nix 0.24.2", + "ntapi 0.3.7", "once_cell", "procfs", "winapi 0.3.9", @@ -2894,8 +2889,10 @@ name = "nu-table" version = "0.69.2" dependencies = [ "atty", + "json_to_table", "nu-ansi-term", "nu-protocol", + "serde_json", "strip-ansi-escapes", "tabled", ] @@ -3157,9 +3154,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.13.1" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "074864da206b4973b84eb91683020dbefd6a8c3f0f38e054d93954e891935e4e" +checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1" [[package]] name = "oorandom" @@ -3167,17 +3164,11 @@ version = "11.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" -[[package]] -name = "opaque-debug" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" - [[package]] name = "openssl" -version = "0.10.41" +version = "0.10.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "618febf65336490dfcf20b73f885f5651a0c89c64c2d4a8c3662585a70bf5bd0" +checksum = "12fc0523e3bd51a692c8850d075d74dc062ccf251c0110668cbd921917118a13" dependencies = [ "bitflags", "cfg-if 1.0.0", @@ -3216,9 +3207,9 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.75" +version = "0.9.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5f9bd0c2710541a3cda73d6f9ac4f1b240de4ae261065d309dbe73d9dceb42f" +checksum = "5230151e44c0f05157effb743e8d517472843121cf9243e8b81393edb5acd9ce" dependencies = [ "autocfg", "cc", @@ -3245,17 +3236,18 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "owo-colors" -version = "3.4.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "decf7381921fea4dcb2549c5667eda59b3ec297ab7e2b5fc33eac69d2e7da87b" +checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" [[package]] name = "papergrid" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453cf71f2a37af495a1a124bf30d4d7469cfbea58e9f2479be9d222396a518a2" +checksum = "ae9bed2481d5ab6e31056945f4704ca7348a3858148c30725b8946b7a7818498" dependencies = [ "ansi-str", + "ansitok", "bytecount", "fnv", "strip-ansi-escapes", @@ -3298,9 +3290,9 @@ dependencies = [ [[package]] name = "parquet2" -version = "0.14.1" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33e434af3293ba384075a56d4b400ce659868ca7823142194ef204f01ab35e50" +checksum = "b8fa7afeef767fb16a37216cdf906268ae10db9825aa1ed8723b8493b1e99b0b" dependencies = [ "async-stream", "bitpacking", @@ -3325,9 +3317,9 @@ dependencies = [ [[package]] name = "paste" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9423e2b32f7a043629287a536f21951e8c6a82482d0acb1eeebfc90bc2225b22" +checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1" [[package]] name = "pathdiff" @@ -3343,9 +3335,9 @@ checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" [[package]] name = "percent-encoding" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "peresil" @@ -3355,10 +3347,11 @@ checksum = "f658886ed52e196e850cfbbfddab9eaa7f6d90dd0929e264c31e5cec07e09e57" [[package]] name = "pest" -version = "2.1.3" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" +checksum = "cb779fcf4bb850fbbb0edc96ff6cf34fd90c4b1a112ce042653280d9a7364048" dependencies = [ + "thiserror", "ucd-trie", ] @@ -3384,11 +3377,11 @@ dependencies = [ [[package]] name = "phf" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4724fa946c8d1e7cd881bd3dbee63ce32fc1e9e191e35786b3dc1320a3f68131" +checksum = "928c6535de93548188ef63bb7c4036bd415cd8f36ad25af44b9789b2ee72a48c" dependencies = [ - "phf_shared 0.11.0", + "phf_shared 0.11.1", ] [[package]] @@ -3413,12 +3406,12 @@ dependencies = [ [[package]] name = "phf_codegen" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32ba0c43d7a1b6492b2924a62290cfd83987828af037b0743b38e6ab092aee58" +checksum = "a56ac890c5e3ca598bbdeaa99964edb5b0258a583a9eb6ef4e89fc85d9224770" dependencies = [ - "phf_generator 0.11.0", - "phf_shared 0.11.0", + "phf_generator 0.11.1", + "phf_shared 0.11.1", ] [[package]] @@ -3443,11 +3436,11 @@ dependencies = [ [[package]] name = "phf_generator" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b450720b6f75cfbfabc195814bd3765f337a4f9a83186f8537297cac12f6705" +checksum = "b1181c94580fa345f50f19d738aaa39c0ed30a600d95cb2d3e23f94266f14fbf" dependencies = [ - "phf_shared 0.11.0", + "phf_shared 0.11.1", "rand 0.8.5", ] @@ -3485,9 +3478,9 @@ dependencies = [ [[package]] name = "phf_shared" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dd5609d4b2df87167f908a32e1b146ce309c16cf35df76bc11f440b756048e4" +checksum = "e1fb5f6f826b772a8d4c0394209441e7d37cbbb967ae9c7e0e8134365c9ee676" dependencies = [ "siphasher", "uncased", @@ -3522,9 +3515,9 @@ dependencies = [ [[package]] name = "plotters" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "716b4eeb6c4a1d3ecc956f75b43ec2e8e8ba80026413e70a3f41fd3313d3492b" +checksum = "2538b639e642295546c50fcd545198c9d64ee2a38620a628724a3b266d5fbf97" dependencies = [ "num-traits", "plotters-backend", @@ -3740,14 +3733,14 @@ dependencies = [ [[package]] name = "pretty_assertions" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c89f989ac94207d048d92db058e4f6ec7342b0971fc58d1271ca148b799b3563" +checksum = "a25e9bcb20aa780fd0bb16b72403a9064d6b3f22f026946029acb941a50af755" dependencies = [ - "ansi_term", "ctor", "diff", "output_vt100", + "yansi", ] [[package]] @@ -3782,18 +3775,18 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" [[package]] name = "proc-macro2" -version = "1.0.42" +version = "1.0.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c278e965f1d8cf32d6e0e96de3d3e79712178ae67986d9cf9151f51e95aac89b" +checksum = "94e2ef8dbfc347b10c094890f778ee2e36ca9bb4262e86dc99cd217e35f3470b" dependencies = [ "unicode-ident", ] [[package]] name = "procfs" -version = "0.14.0" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1391b61957e3b6f25a59ca2e057d22a44415917d87893986f6627fef109d32f" +checksum = "2dfb6451c91904606a1abe93e83a8ec851f45827fa84273f256ade45dc095818" dependencies = [ "bitflags", "byteorder", @@ -3864,9 +3857,9 @@ dependencies = [ [[package]] name = "quick-xml" -version = "0.23.0" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9279fbdacaad3baf559d8cabe0acc3d06e30ea14931af31af79578ac0946decc" +checksum = "11bafc859c6815fbaffbbbf4229ecb767ac913fecb27f9ad4343662e9ef099ea" dependencies = [ "memchr", ] @@ -3895,9 +3888,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.20" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" dependencies = [ "proc-macro2", ] @@ -3937,7 +3930,7 @@ checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha 0.3.1", - "rand_core 0.6.3", + "rand_core 0.6.4", ] [[package]] @@ -3957,7 +3950,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core 0.6.3", + "rand_core 0.6.4", ] [[package]] @@ -3986,9 +3979,9 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ "getrandom 0.2.7", ] @@ -4027,7 +4020,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" dependencies = [ - "rand_core 0.6.3", + "rand_core 0.6.4", ] [[package]] @@ -4065,9 +4058,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534cfe58d6a18cc17120fbf4635d53d14691c1fe4d951064df9bd326178d7d5a" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ "bitflags", ] @@ -4100,7 +4093,7 @@ dependencies = [ "serde_json", "strip-ansi-escapes", "strum 0.24.1", - "strum_macros 0.24.2", + "strum_macros 0.24.3", "thiserror", "unicode-segmentation", "unicode-width", @@ -4140,9 +4133,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.11" +version = "0.11.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b75aa69a3f06bbcc66ede33af2af253c6f7a86b1ca0033f60c580a27074fbf92" +checksum = "431949c384f4e2ae07605ccaa56d1d9d2ecdb5cadd4f9577ccfab29f2e5149fc" dependencies = [ "base64", "bytes", @@ -4156,10 +4149,10 @@ dependencies = [ "hyper-tls", "ipnet", "js-sys", - "lazy_static", "log", "mime", "native-tls", + "once_cell", "percent-encoding", "pin-project-lite", "serde", @@ -4215,9 +4208,9 @@ dependencies = [ [[package]] name = "rmp-serde" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25786b0d276110195fa3d6f3f31299900cf71dfbd6c28450f3f58a0e7f7a347e" +checksum = "c5b13be192e0220b8afb7222aa5813cb62cc269ebb5cac346ca6487681d2913e" dependencies = [ "byteorder", "rmp", @@ -4282,9 +4275,9 @@ dependencies = [ [[package]] name = "rust-embed" -version = "6.4.0" +version = "6.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a17e5ac65b318f397182ae94e532da0ba56b88dd1200b774715d36c4943b1c3" +checksum = "e26934cd67a1da1165efe61cba4047cc1b4a526019da609fcce13a1000afb5fa" dependencies = [ "rust-embed-impl", "rust-embed-utils", @@ -4293,9 +4286,9 @@ dependencies = [ [[package]] name = "rust-embed-impl" -version = "6.2.0" +version = "6.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94e763e24ba2bf0c72bc6be883f967f794a019fafd1b86ba1daff9c91a7edd30" +checksum = "e35d7b402e273544cc08e0824aa3404333fab8a90ac43589d3d5b72f4b346e12" dependencies = [ "proc-macro2", "quote", @@ -4306,19 +4299,19 @@ dependencies = [ [[package]] name = "rust-embed-utils" -version = "7.2.0" +version = "7.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "756feca3afcbb1487a1d01f4ecd94cf8ec98ea074c55a69e7136d29fb6166029" +checksum = "c1669d81dfabd1b5f8e2856b8bbe146c6192b0ba22162edc738ac0a5de18f054" dependencies = [ - "sha2 0.9.9", + "sha2", "walkdir", ] [[package]] name = "rust_decimal" -version = "1.25.0" +version = "1.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34a3bb58e85333f1ab191bf979104b586ebd77475bc6681882825f4532dfe87c" +checksum = "ee9164faf726e4f3ece4978b25ca877ddc6802fa77f38cdccb32c7f805ecd70c" dependencies = [ "arrayvec 0.7.2", "num-traits", @@ -4351,14 +4344,14 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.12", + "semver 1.0.14", ] [[package]] name = "rustix" -version = "0.35.7" +version = "0.35.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51cc38aa10f6bbb377ed28197aa052aa4e2b762c22be9d3153d01822587e787" +checksum = "fbb2fda4666def1433b1b05431ab402e42a1084285477222b72d6c564c417cef" dependencies = [ "bitflags", "errno", @@ -4370,9 +4363,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24c8ad4f0c00e1eb5bc7614d236a7f1300e3dbd76b68cac8e06fb00b015ad8d8" +checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8" [[package]] name = "rusty-fork" @@ -4388,9 +4381,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" +checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" [[package]] name = "same-file" @@ -4435,9 +4428,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.6.1" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc" +checksum = "2bc1bb97804af6631813c55739f771071e0f2ed33ee20b68c86ec505d906356c" dependencies = [ "bitflags", "core-foundation", @@ -4496,9 +4489,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2333e6df6d6598f2b1974829f853c2b4c5f4a6e503c10af918081aa6f8564e1" +checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" [[package]] name = "semver-parser" @@ -4517,9 +4510,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.144" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860" +checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b" dependencies = [ "serde_derive", ] @@ -4536,9 +4529,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.144" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00" +checksum = "81fa1584d3d1bcacd84c277a0dfe21f5b0f6accf4a23d04d4c6d61f1af522b4c" dependencies = [ "proc-macro2", "quote", @@ -4558,11 +4551,11 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.82" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82c2c1fdcd807d1098552c5b9a36e425e42e9fbd7c6a37a8425f390f781f7fa7" +checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" dependencies = [ - "itoa 1.0.2", + "itoa 1.0.3", "ryu", "serde", ] @@ -4574,19 +4567,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa 1.0.2", + "itoa 1.0.3", "ryu", "serde", ] [[package]] name = "serde_yaml" -version = "0.9.4" +version = "0.9.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79b7c9017c64a49806c6e8df8ef99b92446d09c92457f85f91835b01a8064ae0" +checksum = "8613d593412a0deb7bbd8de9d908efff5a0cb9ccd8f62c641e7b2ed2f57291d1" dependencies = [ "indexmap", - "itoa 1.0.2", + "itoa 1.0.3", "ryu", "serde", "unsafe-libyaml", @@ -4630,38 +4623,24 @@ dependencies = [ [[package]] name = "sha2" -version = "0.9.9" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" -dependencies = [ - "block-buffer 0.9.0", - "cfg-if 1.0.0", - "cpufeatures", - "digest 0.9.0", - "opaque-debug", -] - -[[package]] -name = "sha2" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676" +checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest 0.10.3", + "digest", ] [[package]] name = "shadow-rs" -version = "0.16.1" +version = "0.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2d399ad15b5c90d8e6461da75c751c77501598dd915d81a108401b252aaa99f" +checksum = "8c0ea0c68418544f725eba5401a5b965a2263254c92458d04aeae74e9d88ff4e" dependencies = [ "const_format", "is_debug", - "time 0.3.13", - "tzdb", + "time 0.3.14", ] [[package]] @@ -4714,7 +4693,7 @@ checksum = "48dfff04aade74dd495b007c831cd6f4e0cee19c344dd9dc0884c0289b70a786" dependencies = [ "log", "termcolor", - "time 0.3.13", + "time 0.3.14", ] [[package]] @@ -4763,9 +4742,9 @@ checksum = "45456094d1983e2ee2a18fdfebce3189fa451699d0502cb8e3b49dba5ba41451" [[package]] name = "socket2" -version = "0.4.4" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" +checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" dependencies = [ "libc", "winapi 0.3.9", @@ -4804,18 +4783,18 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "streaming-decompression" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bc687acd5dc742c4a7094f2927a8614a68e4743ef682e7a2f9f0f711656cc92" +checksum = "bf6cc3b19bfb128a8ad11026086e31d3ce9ad23f8ea37354b31383a187c44cf3" dependencies = [ "fallible-streaming-iterator", ] [[package]] name = "streaming-iterator" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4817bfdf8f0b576330b83b55bed0ec89204aa7da62c2fa11fad2119f33a70014" +checksum = "0085b81d5d4e57f264d492641cf80ea508c96d9a0e47c6296e8f016504e28fd7" [[package]] name = "strength_reduce" @@ -4855,7 +4834,7 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "011cbb39cf7c1f62871aea3cc46e5817b0937b49e9447370c93cacbe93a766d8" dependencies = [ - "vte", + "vte 0.10.1", ] [[package]] @@ -4885,9 +4864,9 @@ dependencies = [ [[package]] name = "strum_macros" -version = "0.24.2" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4faebde00e8ff94316c01800f9054fd2ba77d30d9e922541913051d1d978918b" +checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" dependencies = [ "heck 0.4.0", "proc-macro2", @@ -4947,9 +4926,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.98" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd" +checksum = "e90cde112c4b9690b8cbe810cba9ddd8bc1d7472e2cae317b69e9438c1cba7d2" dependencies = [ "proc-macro2", "quote", @@ -4973,14 +4952,14 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.26.2" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae2421f3e16b3afd4aa692d23b83d0ba42ee9b0081d5deeb7d21428d7195fb1" +checksum = "7890fff842b8db56f2033ebee8f6efe1921475c3830c115995552914fb967580" dependencies = [ "cfg-if 1.0.0", "core-foundation-sys", "libc", - "ntapi", + "ntapi 0.4.0", "once_cell", "rayon", "winapi 0.3.9", @@ -4988,21 +4967,22 @@ dependencies = [ [[package]] name = "tabled" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5b2f8c37d26d87d2252187b0a45ea3cbf42baca10377c7e7eaaa2800fa9bf97" +checksum = "0c8a1ea336f84dc7dfae1025b73904551b3c6a42347f4243387e990f94325895" dependencies = [ "ansi-str", "papergrid", "tabled_derive", "unicode-width", + "vte 0.11.0", ] [[package]] name = "tabled_derive" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9ee618502f497abf593e1c5c9577f34775b111480009ffccd7ad70d23fcaba8" +checksum = "beca1b4eaceb4f2755df858b88d9b9315b7ccfd1ffd0d7a48a52602301f01a57" dependencies = [ "heck 0.4.0", "proc-macro-error", @@ -5092,9 +5072,9 @@ dependencies = [ [[package]] name = "textwrap" -version = "0.15.0" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" +checksum = "949517c0cf1bf4ee812e2e07e08ab448e3ae0d23472aee8a06c985f0c8815b16" dependencies = [ "smawk", "unicode-linebreak", @@ -5109,18 +5089,18 @@ checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c" [[package]] name = "thiserror" -version = "1.0.31" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a" +checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.31" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" +checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" dependencies = [ "proc-macro2", "quote", @@ -5149,11 +5129,11 @@ dependencies = [ [[package]] name = "time" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db76ff9fa4b1458b3c7f077f3ff9887394058460d21e634355b273aaf11eea45" +checksum = "3c3f9a28b618c3a6b9251b6908e9c99e04b9e5c02e6581ccbb67d59c34ef7f9b" dependencies = [ - "itoa 1.0.2", + "itoa 1.0.3", "libc", "num_threads", "time-macros", @@ -5192,19 +5172,20 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "titlecase" -version = "2.0.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea7a2f1a76e892e6c07c275e6e851400257304a6e34c0e4e32ebbd3871808802" +checksum = "268c82cc8fdb739c2bcf9daed9a46d0e26ea2d3e70d070e4cac83bdcc40d6a49" dependencies = [ + "joinery", "lazy_static", "regex", ] [[package]] name = "tokio" -version = "1.20.1" +version = "1.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a8325f63a7d4774dd041e363b2409ed1c5cbbd0f867795e661df066b2b0a581" +checksum = "a9e03c497dc955702ba729190dc4aac6f2a0ce97f913e5b1b5912fc5039d9099" dependencies = [ "autocfg", "bytes", @@ -5212,7 +5193,6 @@ dependencies = [ "memchr", "mio 0.8.4", "num_cpus", - "once_cell", "pin-project-lite", "socket2", "winapi 0.3.9", @@ -5230,9 +5210,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc463cd8deddc3770d20f9852143d50bf6094e640b485cb2e189a2099085ff45" +checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" dependencies = [ "bytes", "futures-core", @@ -5259,9 +5239,9 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.35" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160" +checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307" dependencies = [ "cfg-if 1.0.0", "pin-project-lite", @@ -5270,9 +5250,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.28" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b7358be39f2f274f322d2aaed611acc57f382e8eb1e5b48cb9ae30933495ce7" +checksum = "5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7" dependencies = [ "once_cell", ] @@ -5335,33 +5315,11 @@ dependencies = [ "syn", ] -[[package]] -name = "tz-rs" -version = "0.6.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb454313e3d79601e2116bb6c7a93ec0eda1dbb52f9204f831f897204182c5f" -dependencies = [ - "const_fn", -] - -[[package]] -name = "tzdb" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70cb9dbeb3119afb148b2737802ee3c6d5e9652ae92102562fc017f356ab0f68" -dependencies = [ - "byte-slice-cast", - "iana-time-zone", - "phf 0.10.1", - "phf_shared 0.10.0", - "tz-rs", -] - [[package]] name = "ucd-trie" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89570599c4fe5585de2b388aab47e99f7fa4e9238a1399f707a02e356058141c" +checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" [[package]] name = "umask" @@ -5386,61 +5344,61 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" [[package]] name = "unicode-ident" -version = "1.0.2" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15c61ba63f9235225a22310255a29b806b907c9b8c964bcbd0a2c70f3f2deea7" +checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd" [[package]] name = "unicode-linebreak" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a52dcaab0c48d931f7cc8ef826fa51690a08e1ea55117ef26f89864f532383f" +checksum = "c5faade31a542b8b35855fff6e8def199853b2da8da256da52f52f1316ee3137" dependencies = [ + "hashbrown", "regex", ] [[package]] name = "unicode-normalization" -version = "0.1.21" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854cbdc4f7bc6ae19c820d44abdc3277ac3e1b2b93db20a636825d9322fb60e6" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" dependencies = [ "tinyvec", ] [[package]] name = "unicode-segmentation" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" +checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a" [[package]] name = "unicode-width" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" [[package]] name = "unicode-xid" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" [[package]] name = "unsafe-libyaml" -version = "0.2.2" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "931179334a56395bcf64ba5e0ff56781381c1a5832178280c7d7f91d1679aeb0" +checksum = "c1e5fa573d8ac5f1a856f8d7be41d390ee973daf97c806b2c1a465e4e1406e68" [[package]] name = "url" -version = "2.2.2" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" +checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" dependencies = [ "form_urlencoded", "idna", - "matches", "percent-encoding", ] @@ -5541,6 +5499,17 @@ dependencies = [ "vte_generate_state_changes", ] +[[package]] +name = "vte" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aae21c12ad2ec2d168c236f369c38ff332bc1134f7246350dca641437365045" +dependencies = [ + "arrayvec 0.7.2", + "utf8parse", + "vte_generate_state_changes", +] + [[package]] name = "vte_generate_state_changes" version = "0.1.1" @@ -5601,9 +5570,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7652e3f6c4706c8d9cd54832c4a4ccb9b5336e2c3bd154d5cccfbf1c1f5f7d" +checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-macro", @@ -5611,9 +5580,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "662cd44805586bd52971b9586b1df85cdbbd9112e4ef4d8f41559c334dc6ac3f" +checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" dependencies = [ "bumpalo", "log", @@ -5626,9 +5595,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.32" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa76fb221a1f8acddf5b54ace85912606980ad661ac7a503b4570ffd3a624dad" +checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -5638,9 +5607,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b260f13d3012071dfb1512849c033b1925038373aea48ced3012c09df952c602" +checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -5648,9 +5617,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be8e654bdd9b79216c2929ab90721aa82faf65c48cdf08bdc4e7f51357b80da" +checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" dependencies = [ "proc-macro2", "quote", @@ -5661,9 +5630,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6598dd0bd3c7d51095ff6531a5b23e02acdc81804e30d8f07afb77b7215a140a" +checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" [[package]] name = "wax" @@ -5687,9 +5656,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.59" +version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed055ab27f941423197eb86b2035720b1a3ce40504df082cac2ecc6ed73335a1" +checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" dependencies = [ "js-sys", "wasm-bindgen", @@ -5869,6 +5838,12 @@ version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "114ba2b24d2167ef6d67d7d04c8cc86522b87f490025f39f0303b7db5bf5e3d8" +[[package]] +name = "yansi" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" + [[package]] name = "zeroize" version = "1.5.7" diff --git a/Cargo.toml b/Cargo.toml index 2043aeae8b..73b00870d8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,6 @@ exclude = ["images"] homepage = "https://www.nushell.sh" license = "MIT" name = "nu" -readme = "README.md" repository = "https://github.com/nushell/nushell" rust-version = "1.60" version = "0.69.2" diff --git a/crates/nu-command/src/viewers/table.rs b/crates/nu-command/src/viewers/table.rs index d2974bcde3..3584dfb495 100644 --- a/crates/nu-command/src/viewers/table.rs +++ b/crates/nu-command/src/viewers/table.rs @@ -4,15 +4,17 @@ use nu_engine::{column::get_columns, env_to_string, CallExt}; use nu_protocol::{ ast::{Call, PathMember}, engine::{Command, EngineState, Stack, StateWorkingSet}, - format_error, Category, Config, DataSource, Example, IntoPipelineData, ListStream, + format_error, Category, Config, DataSource, Example, FooterMode, IntoPipelineData, ListStream, PipelineData, PipelineMetadata, RawStream, ShellError, Signature, Span, SyntaxShape, TableIndexMode, Value, }; -use nu_table::{Alignments, StyledString, TableTheme, TextStyle}; +use nu_table::{Alignment, Alignments, Table as NuTable, TableTheme, TextStyle}; use nu_utils::get_ls_colors; use std::sync::Arc; use std::time::Instant; use std::{ + cmp::max, + collections::HashMap, path::PathBuf, sync::atomic::{AtomicBool, Ordering}, }; @@ -69,6 +71,29 @@ impl Command for Table { "number of terminal columns wide (not output columns)", Some('w'), ) + .switch( + "expand", + "expand the table structure in a light mode", + Some('e'), + ) + .named( + "expand-deep", + SyntaxShape::Int, + "an expand limit of recursion which will take place", + Some('d'), + ) + .switch("flatten", "Flatten simple arrays", None) + .named( + "flatten-separator", + SyntaxShape::String, + "sets a seperator when 'flatten' used", + None, + ) + .switch( + "collapse", + "expand the table structure in colapse mode.\nBe aware collapse mode currently doesn't support width controll", + Some('c'), + ) .category(Category::Viewers) } @@ -78,11 +103,7 @@ impl Command for Table { stack: &mut Stack, call: &Call, input: PipelineData, - ) -> Result { - let head = call.head; - let ctrlc = engine_state.ctrlc.clone(); - let config = engine_state.get_config(); - let color_hm = get_color_config(config); + ) -> Result { let start_num: Option = call.get_flag(engine_state, stack, "start-number")?; let row_offset = start_num.unwrap_or_default() as usize; let list: bool = call.has_flag("list"); @@ -90,25 +111,31 @@ impl Command for Table { let width_param: Option = call.get_flag(engine_state, stack, "width")?; let term_width = get_width_param(width_param); + let expand: bool = call.has_flag("expand"); + let expand_limit: Option = call.get_flag(engine_state, stack, "expand-deep")?; + let collapse: bool = call.has_flag("collapse"); + let flatten: bool = call.has_flag("flatten"); + let flatten_separator: Option = + call.get_flag(engine_state, stack, "flatten-separator")?; + + let table_view = match (expand, collapse) { + (false, false) => TableView::General, + (_, true) => TableView::Collapsed, + (true, _) => TableView::Expanded { + limit: expand_limit, + flatten, + flatten_separator, + }, + }; + + // if list argument is present we just need to return a list of supported table themes if list { - let table_modes = vec![ - Value::string("basic", Span::test_data()), - Value::string("compact", Span::test_data()), - Value::string("compact_double", Span::test_data()), - Value::string("default", Span::test_data()), - Value::string("heavy", Span::test_data()), - Value::string("light", Span::test_data()), - Value::string("none", Span::test_data()), - Value::string("reinforced", Span::test_data()), - Value::string("rounded", Span::test_data()), - Value::string("thin", Span::test_data()), - Value::string("with_love", Span::test_data()), - ]; - return Ok(Value::List { - vals: table_modes, + let val = Value::List { + vals: supported_table_modes(), span: Span::test_data(), - } - .into_pipeline_data()); + }; + + return Ok(val.into_pipeline_data()); } // reset vt processing, aka ansi because illbehaved externals can break it @@ -117,96 +144,15 @@ impl Command for Table { let _ = nu_utils::enable_vt_processing(); } - match input { - PipelineData::ExternalStream { .. } => Ok(input), - PipelineData::Value(Value::Binary { val, .. }, ..) => { - Ok(PipelineData::ExternalStream { - stdout: Some(RawStream::new( - Box::new( - vec![Ok(format!("{}\n", nu_pretty_hex::pretty_hex(&val)) - .as_bytes() - .to_vec())] - .into_iter(), - ), - ctrlc, - head, - )), - stderr: None, - exit_code: None, - span: head, - metadata: None, - }) - } - PipelineData::Value(Value::List { vals, .. }, metadata) => handle_row_stream( - engine_state, - stack, - ListStream::from_stream(vals.into_iter(), ctrlc.clone()), - call, - row_offset, - ctrlc, - metadata, - ), - PipelineData::ListStream(stream, metadata) => handle_row_stream( - engine_state, - stack, - stream, - call, - row_offset, - ctrlc, - metadata, - ), - PipelineData::Value(Value::Record { cols, vals, .. }, ..) => { - let mut output = vec![]; - - for (c, v) in cols.into_iter().zip(vals.into_iter()) { - output.push(vec![ - StyledString { - contents: c, - style: TextStyle::default_field(), - }, - StyledString { - contents: v.into_abbreviated_string(config), - style: TextStyle::default(), - }, - ]) - } - - let table = - nu_table::Table::new(Vec::new(), output, load_theme_from_config(config)); - - let result = table - .draw_table(config, &color_hm, Alignments::default(), term_width) - .unwrap_or_else(|| format!("Couldn't fit table into {} columns!", term_width)); - - Ok(Value::String { - val: result, - span: call.head, - } - .into_pipeline_data()) - } - PipelineData::Value(Value::Error { error }, ..) => { - let working_set = StateWorkingSet::new(engine_state); - Ok(Value::String { - val: format_error(&working_set, &error), - span: call.head, - } - .into_pipeline_data()) - } - PipelineData::Value(Value::CustomValue { val, span }, ..) => { - let base_pipeline = val.to_base_value(span)?.into_pipeline_data(); - self.run(engine_state, stack, call, base_pipeline) - } - PipelineData::Value(Value::Range { val, .. }, metadata) => handle_row_stream( - engine_state, - stack, - ListStream::from_stream(val.into_range_iter(ctrlc.clone())?, ctrlc.clone()), - call, - row_offset, - ctrlc, - metadata, - ), - x => Ok(x), - } + handle_table_command( + engine_state, + stack, + call, + input, + row_offset, + table_view, + term_width, + ) } fn examples(&self) -> Vec { @@ -236,10 +182,328 @@ impl Command for Table { span, }), }, + Example { + description: "Render data in table view (expanded)", + example: r#"echo [[a b]; [1 2] [2 [4 4]]] | table --expand"#, + result: Some(Value::List { + vals: vec![ + Value::Record { + cols: vec!["a".to_string(), "b".to_string()], + vals: vec![Value::test_int(1), Value::test_int(2)], + span, + }, + Value::Record { + cols: vec!["a".to_string(), "b".to_string()], + vals: vec![Value::test_int(3), Value::test_int(4)], + span, + }, + ], + span, + }), + }, + Example { + description: "Render data in table view (collapsed)", + example: r#"echo [[a b]; [1 2] [2 [4 4]]] | table --collapse"#, + result: Some(Value::List { + vals: vec![ + Value::Record { + cols: vec!["a".to_string(), "b".to_string()], + vals: vec![Value::test_int(1), Value::test_int(2)], + span, + }, + Value::Record { + cols: vec!["a".to_string(), "b".to_string()], + vals: vec![Value::test_int(3), Value::test_int(4)], + span, + }, + ], + span, + }), + }, ] } } +fn handle_table_command( + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + input: PipelineData, + row_offset: usize, + table_view: TableView, + term_width: usize, +) -> Result { + let ctrlc = engine_state.ctrlc.clone(); + let config = engine_state.get_config(); + + match input { + PipelineData::ExternalStream { .. } => Ok(input), + PipelineData::Value(Value::Binary { val, .. }, ..) => Ok(PipelineData::ExternalStream { + stdout: Some(RawStream::new( + Box::new( + vec![Ok(format!("{}\n", nu_pretty_hex::pretty_hex(&val)) + .as_bytes() + .to_vec())] + .into_iter(), + ), + ctrlc, + call.head, + )), + stderr: None, + exit_code: None, + span: call.head, + metadata: None, + }), + PipelineData::Value(Value::List { vals, .. }, metadata) => handle_row_stream( + engine_state, + stack, + ListStream::from_stream(vals.into_iter(), ctrlc.clone()), + call, + row_offset, + ctrlc, + metadata, + ), + PipelineData::ListStream(stream, metadata) => handle_row_stream( + engine_state, + stack, + stream, + call, + row_offset, + ctrlc, + metadata, + ), + PipelineData::Value(Value::Record { cols, vals, span }, ..) => { + let result = match table_view { + TableView::General => build_general_table2(cols, vals, ctrlc, config, term_width), + TableView::Expanded { + limit, + flatten, + flatten_separator, + } => { + let sep = flatten_separator.as_deref().unwrap_or(" "); + build_expanded_table( + cols, vals, span, ctrlc, config, term_width, limit, flatten, sep, + ) + } + TableView::Collapsed => build_collapsed_table(cols, vals, config, term_width), + }?; + + let result = result + .unwrap_or_else(|| format!("Couldn't fit table into {} columns!", term_width)); + + let val = Value::String { + val: result, + span: call.head, + }; + + Ok(val.into_pipeline_data()) + } + PipelineData::Value(Value::Error { error }, ..) => { + let working_set = StateWorkingSet::new(engine_state); + Ok(Value::String { + val: format_error(&working_set, &error), + span: call.head, + } + .into_pipeline_data()) + } + PipelineData::Value(Value::CustomValue { val, span }, ..) => { + let base_pipeline = val.to_base_value(span)?.into_pipeline_data(); + Table.run(engine_state, stack, call, base_pipeline) + } + PipelineData::Value(Value::Range { val, .. }, metadata) => handle_row_stream( + engine_state, + stack, + ListStream::from_stream(val.into_range_iter(ctrlc.clone())?, ctrlc.clone()), + call, + row_offset, + ctrlc, + metadata, + ), + x => Ok(x), + } +} + +fn supported_table_modes() -> Vec { + vec![ + Value::string("basic", Span::test_data()), + Value::string("compact", Span::test_data()), + Value::string("compact_double", Span::test_data()), + Value::string("default", Span::test_data()), + Value::string("heavy", Span::test_data()), + Value::string("light", Span::test_data()), + Value::string("none", Span::test_data()), + Value::string("reinforced", Span::test_data()), + Value::string("rounded", Span::test_data()), + Value::string("thin", Span::test_data()), + Value::string("with_love", Span::test_data()), + ] +} + +fn build_collapsed_table( + cols: Vec, + vals: Vec, + config: &Config, + term_width: usize, +) -> Result, ShellError> { + let value = Value::Record { + cols, + vals, + span: Span::new(0, 0), + }; + + let color_hm = get_color_config(config); + let theme = load_theme_from_config(config); + let table = nu_table::NuTable::new(value, true, term_width, config, &color_hm, &theme, false); + + let table = table.draw(); + + Ok(table) +} + +fn build_general_table2( + cols: Vec, + vals: Vec, + ctrlc: Option>, + config: &Config, + term_width: usize, +) -> Result, ShellError> { + let mut data = Vec::with_capacity(vals.len()); + for (column, value) in cols.into_iter().zip(vals.into_iter()) { + // handle CTRLC event + if let Some(ctrlc) = &ctrlc { + if ctrlc.load(Ordering::SeqCst) { + return Ok(None); + } + } + + let row = vec![ + NuTable::create_cell(column, TextStyle::default_field()), + NuTable::create_cell(value.into_abbreviated_string(config), TextStyle::default()), + ]; + + data.push(row); + } + + let data_len = data.len(); + let table = NuTable::new(data, (data_len, 2), term_width, false, false); + + let theme = load_theme_from_config(config); + let color_hm = get_color_config(config); + + let table = table.draw_table(config, &color_hm, Alignments::default(), &theme, term_width); + + Ok(table) +} + +#[allow(clippy::too_many_arguments)] +fn build_expanded_table( + cols: Vec, + vals: Vec, + span: Span, + ctrlc: Option>, + config: &Config, + term_width: usize, + expand_limit: Option, + flatten: bool, + flatten_sep: &str, +) -> Result, ShellError> { + let theme = load_theme_from_config(config); + let color_hm = get_color_config(config); + let alignments = Alignments::default(); + + // calculate the width of a key part + the rest of table so we know the rest of the table width available for value. + let key_width = cols + .iter() + .map(|col| nu_table::string_width(col)) + .max() + .unwrap_or(0); + let key = NuTable::create_cell(" ".repeat(key_width), TextStyle::default()); + let key_table = NuTable::new(vec![vec![key]], (1, 2), term_width, false, false); + let key_width = key_table + .draw_table(config, &color_hm, alignments, &theme, usize::MAX) + .map(|table| nu_table::string_width(&table)) + .unwrap_or(0); + + if key_width > term_width { + return Ok(None); + } + + let remaining_width = term_width - key_width; + let mut data = Vec::with_capacity(cols.len()); + for (key, value) in cols.into_iter().zip(vals) { + // handle CTRLC event + if let Some(ctrlc) = &ctrlc { + if ctrlc.load(Ordering::SeqCst) { + return Ok(None); + } + } + + let is_limited = matches!(expand_limit, Some(0)); + let value = if is_limited { + value_to_styled_string(&value, 0, config, &color_hm).0 + } else { + let vals = match value { + Value::List { vals, .. } => vals, + value => vec![value], + }; + + let deep = expand_limit.map(|i| i - 1); + let table = convert_to_table2( + 0, + &vals, + ctrlc.clone(), + config, + span, + &color_hm, + &theme, + deep, + flatten, + flatten_sep, + )?; + + match table { + Some(mut table) => { + // controll width via removing table columns. + let theme = load_theme_from_config(config); + table.truncate(remaining_width, &theme); + + let result = + table.draw_table(config, &color_hm, alignments, &theme, remaining_width); + match result { + Some(result) => result, + None => return Ok(None), + } + } + None => { + // it means that the list is empty + let value = Value::List { vals, span }; + value_to_styled_string(&value, 0, config, &color_hm).0 + } + } + }; + + let key = Value::String { + val: key, + span: Span::new(0, 0), + }; + + let key = value_to_styled_string(&key, 0, config, &color_hm); + + let key = NuTable::create_cell(key.0, key.1); + let val = NuTable::create_cell(value, TextStyle::default()); + + let row = vec![key, val]; + data.push(row); + } + + let data_len = data.len(); + let table = NuTable::new(data, (data_len, 2), term_width, false, false); + + let table = table.draw_table(config, &color_hm, alignments, &theme, usize::MAX); + + Ok(table) +} + #[allow(clippy::too_many_arguments)] fn handle_row_stream( engine_state: &EngineState, @@ -249,7 +513,7 @@ fn handle_row_stream( row_offset: usize, ctrlc: Option>, metadata: Option, -) -> Result { +) -> Result { let stream = match metadata { Some(PipelineMetadata { data_source: DataSource::Ls, @@ -269,10 +533,9 @@ fn handle_row_stream( while idx < cols.len() { if cols[idx] == "name" { - if let Some(Value::String { val: path, span }) = vals.get(idx) { - if let Some(val) = - render_path_name(path, &config, &ls_colors, *span) - { + if let Some(Value::String { val, span }) = vals.get(idx) { + let val = render_path_name(val, &config, &ls_colors, *span); + if let Some(val) = val { vals[idx] = val; } } @@ -294,6 +557,24 @@ fn handle_row_stream( let head = call.head; let width_param: Option = call.get_flag(engine_state, stack, "width")?; + let collapse: bool = call.has_flag("collapse"); + + let expand: bool = call.has_flag("expand"); + let limit: Option = call.get_flag(engine_state, stack, "expand-deep")?; + let flatten: bool = call.has_flag("flatten"); + let flatten_separator: Option = + call.get_flag(engine_state, stack, "flatten-separator")?; + + let table_view = match (expand, collapse) { + (_, true) => TableView::Collapsed, + (true, _) => TableView::Expanded { + flatten, + flatten_separator, + limit, + }, + _ => TableView::General, + }; + Ok(PipelineData::ExternalStream { stdout: Some(RawStream::new( Box::new(PagingTableCreator { @@ -303,6 +584,7 @@ fn handle_row_stream( head, stream, width_param, + view: table_view, }), ctrlc, head, @@ -344,10 +626,11 @@ fn convert_to_table( ctrlc: Option>, config: &Config, head: Span, -) -> Result, ShellError> { + termwidth: usize, + color_hm: &HashMap, +) -> Result, ShellError> { let mut headers = get_columns(input); let mut input = input.iter().peekable(); - let color_hm = get_color_config(config); let float_precision = config.float_precision as usize; let with_index = match config.table_index_mode { TableIndexMode::Always => true, @@ -355,121 +638,423 @@ fn convert_to_table( TableIndexMode::Auto => headers.iter().any(|header| header == INDEX_COLUMN_NAME), }; - if input.peek().is_some() { - if !headers.is_empty() && with_index { - headers.insert(0, "#".into()); - } + if input.peek().is_none() { + return Ok(None); + } - // The header with the INDEX is removed from the table headers since - // it is added to the natural table index - headers.retain(|header| header != INDEX_COLUMN_NAME); + if !headers.is_empty() && with_index { + headers.insert(0, "#".into()); + } - // Vec of Vec of String1, String2 where String1 is datatype and String2 is value - let mut data: Vec> = Vec::new(); + // The header with the INDEX is removed from the table headers since + // it is added to the natural table index + let headers: Vec<_> = headers + .into_iter() + .filter(|header| header != INDEX_COLUMN_NAME) + .map(|text| { + NuTable::create_cell( + text, + TextStyle { + alignment: Alignment::Center, + color_style: Some(color_hm["header"]), + }, + ) + }) + .collect(); - for (row_num, item) in input.enumerate() { - if let Some(ctrlc) = &ctrlc { - if ctrlc.load(Ordering::SeqCst) { - return Ok(None); - } - } - if let Value::Error { error } = item { - return Err(error.clone()); - } - // String1 = datatype, String2 = value as string - let mut row: Vec<(String, String)> = vec![]; - if with_index { - let row_val = match &item { - Value::Record { .. } => item - .get_data_by_key(INDEX_COLUMN_NAME) - .map(|value| value.into_string("", config)), - _ => None, - } - .unwrap_or_else(|| (row_num + row_offset).to_string()); - row = vec![("string".to_string(), (row_val).to_string())]; - } + let with_header = !headers.is_empty(); + let mut count_columns = headers.len(); - if headers.is_empty() { - row.push(( - item.get_type().to_string(), - item.into_abbreviated_string(config), - )); - } else { - let skip_num = if with_index { 1 } else { 0 }; - for header in headers.iter().skip(skip_num) { - let result = match item { - Value::Record { .. } => item.clone().follow_cell_path( - &[PathMember::String { - val: header.into(), - span: head, - }], - false, - ), - _ => Ok(item.clone()), - }; - - match result { - Ok(value) => row.push(( - value.get_type().to_string(), - value.into_abbreviated_string(config), - )), - Err(_) => row.push(("empty".to_string(), "❎".into())), - } - } - } - - data.push(row); - } - - Ok(Some(nu_table::Table::new( - headers - .into_iter() - .map(|x| StyledString { - contents: x, - style: TextStyle { - alignment: nu_table::Alignment::Center, - color_style: Some(color_hm["header"]), - }, - }) - .collect(), - data.into_iter() - .map(|x| { - x.into_iter() - .enumerate() - .map(|(col, y)| { - if col == 0 && with_index { - StyledString { - contents: y.1, - style: TextStyle { - alignment: nu_table::Alignment::Right, - color_style: Some(color_hm["row_index"]), - }, - } - } else if &y.0 == "float" { - // set dynamic precision from config - let precise_number = - match convert_with_precision(&y.1, float_precision) { - Ok(num) => num, - Err(e) => e.to_string(), - }; - StyledString { - contents: precise_number, - style: style_primitive(&y.0, &color_hm), - } - } else { - StyledString { - contents: y.1, - style: style_primitive(&y.0, &color_hm), - } - } - }) - .collect::>() - }) - .collect(), - load_theme_from_config(config), - ))) + let mut data: Vec> = if headers.is_empty() { + Vec::new() } else { - Ok(None) + vec![headers] + }; + + for (row_num, item) in input.enumerate() { + if let Some(ctrlc) = &ctrlc { + if ctrlc.load(Ordering::SeqCst) { + return Ok(None); + } + } + + if let Value::Error { error } = item { + return Err(error.clone()); + } + + let mut row = vec![]; + if with_index { + let text = match &item { + Value::Record { .. } => item + .get_data_by_key(INDEX_COLUMN_NAME) + .map(|value| value.into_string("", config)), + _ => None, + } + .unwrap_or_else(|| (row_num + row_offset).to_string()); + + let value = + make_styled_string(text, "string", 0, with_index, color_hm, float_precision); + let value = NuTable::create_cell(value.0, value.1); + + row.push(value); + } + + if !with_header { + let text = item.into_abbreviated_string(config); + let text_type = item.get_type().to_string(); + let col = if with_index { 1 } else { 0 }; + let value = + make_styled_string(text, &text_type, col, with_index, color_hm, float_precision); + let value = NuTable::create_cell(value.0, value.1); + + row.push(value); + } else { + let skip_num = if with_index { 1 } else { 0 }; + for (col, header) in data[0].iter().enumerate().skip(skip_num) { + let result = match item { + Value::Record { .. } => item.clone().follow_cell_path( + &[PathMember::String { + val: header.as_ref().to_owned(), + span: head, + }], + false, + ), + _ => Ok(item.clone()), + }; + + let value = match result { + Ok(value) => make_styled_string( + value.into_abbreviated_string(config), + &value.get_type().to_string(), + col, + with_index, + color_hm, + float_precision, + ), + Err(_) => make_styled_string( + String::from("❎"), + "empty", + col, + with_index, + color_hm, + float_precision, + ), + }; + + let value = NuTable::create_cell(value.0, value.1); + row.push(value); + } + } + + count_columns = max(count_columns, row.len()); + + data.push(row); + } + + let count_rows = data.len(); + let table = NuTable::new( + data, + (count_rows, count_columns), + termwidth, + with_header, + with_index, + ); + + Ok(Some(table)) +} + +#[allow(clippy::too_many_arguments)] +#[allow(clippy::into_iter_on_ref)] +fn convert_to_table2( + row_offset: usize, + input: &[Value], + ctrlc: Option>, + config: &Config, + head: Span, + color_hm: &HashMap, + theme: &TableTheme, + deep: Option, + flatten: bool, + flatten_sep: &str, +) -> Result, ShellError> { + if input.is_empty() { + return Ok(None); + } + + let float_precision = config.float_precision as usize; + + let mut headers = get_columns(input); + let with_index = match config.table_index_mode { + TableIndexMode::Always => true, + TableIndexMode::Never => false, + TableIndexMode::Auto => headers.iter().any(|header| header == INDEX_COLUMN_NAME), + }; + + if !headers.is_empty() && with_index { + headers.insert(0, "#".into()); + } + + // The header with the INDEX is removed from the table headers since + // it is added to the natural table index + let headers: Vec<_> = headers + .into_iter() + .filter(|header| header != INDEX_COLUMN_NAME) + .map(|text| { + NuTable::create_cell( + text, + TextStyle { + alignment: Alignment::Center, + color_style: Some(color_hm["header"]), + }, + ) + }) + .collect(); + + let with_header = !headers.is_empty(); + let mut count_columns = headers.len(); + + let mut data: Vec> = if headers.is_empty() { + Vec::new() + } else { + vec![headers] + }; + + for (row_num, item) in input.into_iter().enumerate() { + if let Some(ctrlc) = &ctrlc { + if ctrlc.load(Ordering::SeqCst) { + return Ok(None); + } + } + + if let Value::Error { error } = item { + return Err(error.clone()); + } + + let mut row = vec![]; + if with_index { + let text = match &item { + Value::Record { .. } => item + .get_data_by_key(INDEX_COLUMN_NAME) + .map(|value| value.into_string("", config)), + _ => None, + } + .unwrap_or_else(|| (row_num + row_offset).to_string()); + + let value = + make_styled_string(text, "string", 0, with_index, color_hm, float_precision); + let value = NuTable::create_cell(value.0, value.1); + + row.push(value); + } + + if !with_header { + let value = convert_to_table2_entry( + Some(item), + config, + &ctrlc, + color_hm, + 0, + theme, + with_index, + deep, + flatten, + flatten_sep, + ); + + let value = NuTable::create_cell(value.0, value.1); + row.push(value); + } else { + let skip_num = if with_index { 1 } else { 0 }; + for (col, header) in data[0].iter().enumerate().skip(skip_num) { + let result = match item { + Value::Record { .. } => item.clone().follow_cell_path( + &[PathMember::String { + val: header.as_ref().to_owned(), + span: head, + }], + false, + ), + _ => Ok(item.clone()), + }; + + let value = convert_to_table2_entry( + result.ok().as_ref(), + config, + &ctrlc, + color_hm, + col, + theme, + with_index, + deep, + flatten, + flatten_sep, + ); + + let value = NuTable::create_cell(value.0, value.1); + row.push(value); + } + } + + count_columns = max(count_columns, row.len()); + data.push(row); + } + + let count_rows = data.len(); + let table = NuTable::new( + data, + (count_rows, count_columns), + usize::MAX, + with_header, + with_index, + ); + + Ok(Some(table)) +} + +#[allow(clippy::too_many_arguments)] +fn convert_to_table2_entry( + item: Option<&Value>, + config: &Config, + ctrlc: &Option>, + color_hm: &HashMap, + col: usize, + theme: &TableTheme, + with_index: bool, + deep: Option, + flatten: bool, + flatten_sep: &str, +) -> (String, TextStyle) { + let float_precision = config.float_precision as usize; + let alignments = Alignments::default(); + + let item = match item { + Some(item) => item, + None => { + return make_styled_string( + String::from("❎"), + "empty", + col, + with_index, + color_hm, + float_precision, + ) + } + }; + + let is_record_or_list = matches!(item, Value::Record { .. } | Value::List { .. }); + let is_simple = matches!(deep, Some(0)) || !is_record_or_list; + + let mut text = None; + if !is_simple { + let mut arr: [Value; 1] = [Value::default()]; + let (list, span): (&[Value], Span) = match item { + Value::Record { span, .. } => { + arr[0] = item.clone(); + (&arr, *span) + } + Value::List { vals, span } => (vals, *span), + _ => unreachable!("we checked the values already"), + }; + + let is_simple_list = list + .iter() + .all(|v| !matches!(v, Value::Record { .. } | Value::List { .. })); + + text = if flatten && is_simple_list { + let mut buf = Vec::new(); + for value in list { + let (text, _) = make_styled_string( + value.into_abbreviated_string(config), + &value.get_type().to_string(), + col, + with_index, + color_hm, + float_precision, + ); + + buf.push(text); + } + + let text = buf.join(flatten_sep); + + Some(text) + } else { + let table = convert_to_table2( + 0, + list, + ctrlc.clone(), + config, + span, + color_hm, + theme, + deep.map(|i| i - 1), + flatten, + flatten_sep, + ); + + if let Ok(Some(table)) = table { + table.draw_table(config, color_hm, alignments, theme, usize::MAX) + } else { + None + } + } + }; + + match text { + Some(text) => (text, TextStyle::default()), + None => make_styled_string( + item.into_abbreviated_string(config), + &item.get_type().to_string(), + col, + with_index, + color_hm, + float_precision, + ), + } +} + +fn value_to_styled_string( + value: &Value, + col: usize, + config: &Config, + color_hm: &HashMap, +) -> (String, TextStyle) { + let float_precision = config.float_precision as usize; + make_styled_string( + value.into_abbreviated_string(config), + &value.get_type().to_string(), + col, + false, + color_hm, + float_precision, + ) +} + +fn make_styled_string( + text: String, + text_type: &str, + col: usize, + with_index: bool, + color_hm: &HashMap, + float_precision: usize, +) -> (String, TextStyle) { + if col == 0 && with_index { + ( + text, + TextStyle { + alignment: Alignment::Right, + color_style: Some(color_hm["row_index"]), + }, + ) + } else if text_type == "float" { + // set dynamic precision from config + let precise_number = match convert_with_precision(&text, float_precision) { + Ok(num) => num, + Err(e) => e.to_string(), + }; + (precise_number, style_primitive(text_type, color_hm)) + } else { + (text, style_primitive(text_type, color_hm)) } } @@ -497,6 +1082,113 @@ struct PagingTableCreator { config: Config, row_offset: usize, width_param: Option, + view: TableView, +} + +impl PagingTableCreator { + fn build_extended( + &self, + batch: &[Value], + limit: Option, + flatten: bool, + flatten_separator: Option, + ) -> Result, ShellError> { + if batch.is_empty() { + return Ok(None); + } + + let theme = load_theme_from_config(&self.config); + let term_width = get_width_param(self.width_param); + let color_hm = get_color_config(&self.config); + let table = convert_to_table2( + self.row_offset, + batch, + self.ctrlc.clone(), + &self.config, + self.head, + &color_hm, + &theme, + limit, + flatten, + flatten_separator.as_deref().unwrap_or(" "), + )?; + + let mut table = match table { + Some(table) => table, + None => return Ok(None), + }; + + table.truncate(term_width, &theme); + + let table = table.draw_table( + &self.config, + &color_hm, + Alignments::default(), + &theme, + term_width, + ); + + Ok(table) + } + + fn build_collapsed(&self, batch: Vec) -> Result, ShellError> { + if batch.is_empty() { + return Ok(None); + } + + let color_hm = get_color_config(&self.config); + let theme = load_theme_from_config(&self.config); + let term_width = get_width_param(self.width_param); + let need_footer = matches!(self.config.footer_mode, FooterMode::RowCount(limit) if batch.len() as u64 > limit) + || matches!(self.config.footer_mode, FooterMode::Always); + let value = Value::List { + vals: batch, + span: Span::new(0, 0), + }; + + let table = nu_table::NuTable::new( + value, + true, + term_width, + &self.config, + &color_hm, + &theme, + need_footer, + ); + + Ok(table.draw()) + } + + fn build_general(&self, batch: &[Value]) -> Result, ShellError> { + let term_width = get_width_param(self.width_param); + let color_hm = get_color_config(&self.config); + let theme = load_theme_from_config(&self.config); + + let table = convert_to_table( + self.row_offset, + batch, + self.ctrlc.clone(), + &self.config, + self.head, + term_width, + &color_hm, + )?; + + let table = match table { + Some(table) => table, + None => return Ok(None), + }; + + let table = table.draw_table( + &self.config, + &color_hm, + Alignments::default(), + &theme, + term_width, + ); + + Ok(table) + } } impl Iterator for PagingTableCreator { @@ -534,26 +1226,18 @@ impl Iterator for PagingTableCreator { } } - let color_hm = get_color_config(&self.config); - let term_width = get_width_param(self.width_param); - - let table = convert_to_table( - self.row_offset, - &batch, - self.ctrlc.clone(), - &self.config, - self.head, - ); - self.row_offset += idx; + let table = match &self.view { + TableView::General => self.build_general(&batch), + TableView::Collapsed => self.build_collapsed(batch), + TableView::Expanded { + limit, + flatten, + flatten_separator, + } => self.build_extended(&batch, *limit, *flatten, flatten_separator.clone()), + }; match table { - Ok(Some(table)) => { - let result = table - .draw_table(&self.config, &color_hm, Alignments::default(), term_width) - .unwrap_or_else(|| format!("Couldn't fit table into {} columns!", term_width)); - - Some(Ok(result.as_bytes().to_vec())) - } + Ok(Some(table)) => Some(Ok(table.as_bytes().to_vec())), Err(err) => Some(Err(err)), _ => None, } @@ -577,7 +1261,7 @@ fn load_theme_from_config(config: &Config) -> TableTheme { } fn render_path_name( - path: &String, + path: &str, config: &Config, ls_colors: &LsColors, span: Span, @@ -621,3 +1305,14 @@ fn render_path_name( let val = ansi_style.apply(full_path_link).to_string(); Some(Value::String { val, span }) } + +#[derive(Debug)] +enum TableView { + General, + Collapsed, + Expanded { + limit: Option, + flatten: bool, + flatten_separator: Option, + }, +} diff --git a/crates/nu-command/tests/commands/mod.rs b/crates/nu-command/tests/commands/mod.rs index fcda999b67..1be98ba91d 100644 --- a/crates/nu-command/tests/commands/mod.rs +++ b/crates/nu-command/tests/commands/mod.rs @@ -74,6 +74,7 @@ mod split_by; mod split_column; mod split_row; mod str_; +mod table; mod take; mod touch; mod transpose; diff --git a/crates/nu-command/tests/commands/table.rs b/crates/nu-command/tests/commands/table.rs new file mode 100644 index 0000000000..a3468b5070 --- /dev/null +++ b/crates/nu-command/tests/commands/table.rs @@ -0,0 +1,137 @@ +use nu_test_support::nu; + +#[test] +fn table_0() { + let actual = nu!(r#"[[a b, c]; [1 2 3] [4 5 [1 2 3]]] | table"#); + assert_eq!( + actual.out, + "╭───┬───┬───┬────────────────╮\ + │ # │ a │ b │ c │\ + ├───┼───┼───┼────────────────┤\ + │ 0 │ 1 │ 2 │ 3 │\ + │ 1 │ 4 │ 5 │ [list 3 items] │\ + ╰───┴───┴───┴────────────────╯" + ); +} + +#[test] +fn table_collapse_0() { + let actual = nu!(r#"[[a b, c]; [1 2 3] [4 5 [1 2 3]]] | table --collapse"#); + assert_eq!( + actual.out, + "\u{1b}[37m╭───\u{1b}[39m\u{1b}[37m┬───\u{1b}[39m\u{1b}[37m┬───╮\u{1b}[39m\u{1b}[37m│\u{1b}[39m a \u{1b}[37m│\u{1b}[39m b \u{1b}[37m│\u{1b}[39m c \u{1b}[37m│\u{1b}[39m\u{1b}[37m ───\u{1b}[39m\u{1b}[37m ───\u{1b}[39m\u{1b}[37m ─── \u{1b}[39m\u{1b}[37m│\u{1b}[39m 1 \u{1b}[37m│\u{1b}[39m 2 \u{1b}[37m│\u{1b}[39m 3 \u{1b}[37m│\u{1b}[39m\u{1b}[37m ───\u{1b}[39m\u{1b}[37m ───\u{1b}[39m\u{1b}[37m ─── \u{1b}[39m\u{1b}[37m│\u{1b}[39m 4 \u{1b}[37m│\u{1b}[39m 5 \u{1b}[37m│\u{1b}[39m 1 \u{1b}[37m│\u{1b}[39m\u{1b}[37m│\u{1b}[39m \u{1b}[37m│\u{1b}[39m \u{1b}[37m ─── \u{1b}[39m\u{1b}[37m│\u{1b}[39m \u{1b}[37m│\u{1b}[39m \u{1b}[37m│\u{1b}[39m 2 \u{1b}[37m│\u{1b}[39m\u{1b}[37m│\u{1b}[39m \u{1b}[37m│\u{1b}[39m \u{1b}[37m ─── \u{1b}[39m\u{1b}[37m│\u{1b}[39m \u{1b}[37m│\u{1b}[39m \u{1b}[37m│\u{1b}[39m 3 \u{1b}[37m│\u{1b}[39m\u{1b}[37m╰───\u{1b}[39m\u{1b}[37m┴───\u{1b}[39m\u{1b}[37m┴───╯\u{1b}[39m" + ); +} + +#[test] +fn table_expand_0() { + let actual = nu!(r#"[[a b, c]; [1 2 3] [4 5 [1 2 3]]] | table --expand"#); + assert_eq!( + actual.out, + "╭───┬───┬───┬───────────╮\ + │ # │ a │ b │ c │\ + ├───┼───┼───┼───────────┤\ + │ 0 │ 1 │ 2 │ 3 │\ + │ 1 │ 4 │ 5 │ ╭───┬───╮ │\ + │ │ │ │ │ 0 │ 1 │ │\ + │ │ │ │ │ 1 │ 2 │ │\ + │ │ │ │ │ 2 │ 3 │ │\ + │ │ │ │ ╰───┴───╯ │\ + ╰───┴───┴───┴───────────╯" + ); +} + +#[test] +fn table_expand_deep_0() { + let actual = nu!(r#"[[a b, c]; [1 2 3] [4 5 [1 2 [1 2 3]]]] | table --expand --expand-deep=1"#); + assert_eq!( + actual.out, + "╭───┬───┬───┬────────────────────────╮\ + │ # │ a │ b │ c │\ + ├───┼───┼───┼────────────────────────┤\ + │ 0 │ 1 │ 2 │ 3 │\ + │ 1 │ 4 │ 5 │ ╭───┬────────────────╮ │\ + │ │ │ │ │ 0 │ 1 │ │\ + │ │ │ │ │ 1 │ 2 │ │\ + │ │ │ │ │ 2 │ [list 3 items] │ │\ + │ │ │ │ ╰───┴────────────────╯ │\ + ╰───┴───┴───┴────────────────────────╯" + ); +} + +#[test] +fn table_expand_deep_1() { + let actual = nu!(r#"[[a b, c]; [1 2 3] [4 5 [1 2 [1 2 3]]]] | table --expand --expand-deep=0"#); + assert_eq!( + actual.out, + "╭───┬───┬───┬────────────────╮\ + │ # │ a │ b │ c │\ + ├───┼───┼───┼────────────────┤\ + │ 0 │ 1 │ 2 │ 3 │\ + │ 1 │ 4 │ 5 │ [list 3 items] │\ + ╰───┴───┴───┴────────────────╯" + ); +} + +#[test] +fn table_expand_flatten_0() { + let actual = nu!(r#"[[a b, c]; [1 2 3] [4 5 [1 2 [1 1 1]]]] | table --expand --flatten "#); + assert_eq!( + actual.out, + "╭───┬───┬───┬───────────────╮\ + │ # │ a │ b │ c │\ + ├───┼───┼───┼───────────────┤\ + │ 0 │ 1 │ 2 │ 3 │\ + │ 1 │ 4 │ 5 │ ╭───┬───────╮ │\ + │ │ │ │ │ 0 │ 1 │ │\ + │ │ │ │ │ 1 │ 2 │ │\ + │ │ │ │ │ 2 │ 1 1 1 │ │\ + │ │ │ │ ╰───┴───────╯ │\ + ╰───┴───┴───┴───────────────╯" + ); +} + +#[test] +fn table_expand_flatten_1() { + let actual = nu!( + r#"[[a b, c]; [1 2 3] [4 5 [1 2 [1 1 1]]]] | table --expand --flatten --flatten-separator=,"# + ); + assert_eq!( + actual.out, + "╭───┬───┬───┬───────────────╮\ + │ # │ a │ b │ c │\ + ├───┼───┼───┼───────────────┤\ + │ 0 │ 1 │ 2 │ 3 │\ + │ 1 │ 4 │ 5 │ ╭───┬───────╮ │\ + │ │ │ │ │ 0 │ 1 │ │\ + │ │ │ │ │ 1 │ 2 │ │\ + │ │ │ │ │ 2 │ 1,1,1 │ │\ + │ │ │ │ ╰───┴───────╯ │\ + ╰───┴───┴───┴───────────────╯" + ); +} + +#[test] +fn table_expand_flatten_and_deep_1() { + let actual = nu!( + r#"[[a b, c]; [1 2 3] [4 5 [1 2 [1 [1 1 1] 1]]]] | table --expand --expand-deep=2 --flatten --flatten-separator=,"# + ); + + assert_eq!( + actual.out, + "╭───┬───┬───┬────────────────────────────────╮\ + │ # │ a │ b │ c │\ + ├───┼───┼───┼────────────────────────────────┤\ + │ 0 │ 1 │ 2 │ 3 │\ + │ 1 │ 4 │ 5 │ ╭───┬────────────────────────╮ │\ + │ │ │ │ │ 0 │ 1 │ │\ + │ │ │ │ │ 1 │ 2 │ │\ + │ │ │ │ │ 2 │ ╭───┬────────────────╮ │ │\ + │ │ │ │ │ │ │ 0 │ 1 │ │ │\ + │ │ │ │ │ │ │ 1 │ [list 3 items] │ │ │\ + │ │ │ │ │ │ │ 2 │ 1 │ │ │\ + │ │ │ │ │ │ ╰───┴────────────────╯ │ │\ + │ │ │ │ ╰───┴────────────────────────╯ │\ + ╰───┴───┴───┴────────────────────────────────╯" + ); +} diff --git a/crates/nu-table/Cargo.toml b/crates/nu-table/Cargo.toml index 4e3d5fa140..8afcb6dbdc 100644 --- a/crates/nu-table/Cargo.toml +++ b/crates/nu-table/Cargo.toml @@ -17,4 +17,6 @@ nu-ansi-term = "0.46.0" nu-protocol = { path = "../nu-protocol", version = "0.69.2" } strip-ansi-escapes = "0.1.1" atty = "0.2.14" -tabled = { version = "0.8.0", features = ["color"] } +tabled = { version = "0.9.0", features = ["color"], default-features = false } +json_to_table = { version = "0.1.0", features = ["color"] } +serde_json = "*" diff --git a/crates/nu-table/src/lib.rs b/crates/nu-table/src/lib.rs index f476bb26a4..fd9ca4c06c 100644 --- a/crates/nu-table/src/lib.rs +++ b/crates/nu-table/src/lib.rs @@ -1,8 +1,13 @@ +mod nu_protocol_table; mod table; mod table_theme; mod textstyle; -mod width_control; +pub use nu_protocol_table::NuTable; pub use table::{Alignments, Table}; pub use table_theme::TableTheme; -pub use textstyle::{Alignment, StyledString, TextStyle}; +pub use textstyle::{Alignment, TextStyle}; + +pub fn string_width(text: &str) -> usize { + tabled::papergrid::util::string_width_multiline_tab(text, 4) +} diff --git a/crates/nu-table/src/main.rs b/crates/nu-table/src/main.rs index 9ecc2a65c8..f96acbdf54 100644 --- a/crates/nu-table/src/main.rs +++ b/crates/nu-table/src/main.rs @@ -1,6 +1,7 @@ use nu_protocol::Config; -use nu_table::{Alignments, StyledString, Table, TableTheme, TextStyle}; +use nu_table::{Alignments, Table, TableTheme, TextStyle}; use std::collections::HashMap; +use tabled::papergrid::records::{cell_info::CellInfo, tcell::TCell}; fn main() { let args: Vec<_> = std::env::args().collect(); @@ -23,14 +24,23 @@ fn main() { // The table rows let rows = vec_of_str_to_vec_of_styledstr(&row_data, false); // The table itself - let table = Table::new(headers, vec![rows; 3], TableTheme::rounded()); + let count_cols = std::cmp::max(rows.len(), headers.len()); + let mut rows = vec![rows; 3]; + rows.insert(0, headers); + let table = Table::new(rows, (3, count_cols), width, true, false); // FIXME: Config isn't available from here so just put these here to compile let color_hm: HashMap = HashMap::new(); // get the default config let config = Config::default(); // Capture the table as a string let output_table = table - .draw_table(&config, &color_hm, Alignments::default(), width) + .draw_table( + &config, + &color_hm, + Alignments::default(), + &TableTheme::rounded(), + width, + ) .unwrap_or_else(|| format!("Couldn't fit table into {} columns!", width)); // Draw the table println!("{}", output_table) @@ -74,17 +84,23 @@ fn make_table_data() -> (Vec<&'static str>, Vec<&'static str>) { (table_headers, row_data) } -fn vec_of_str_to_vec_of_styledstr(data: &[&str], is_header: bool) -> Vec { +fn vec_of_str_to_vec_of_styledstr( + data: &[&str], + is_header: bool, +) -> Vec, TextStyle>> { let mut v = vec![]; for x in data { if is_header { - v.push(StyledString::new( + v.push(Table::create_cell( String::from(*x), TextStyle::default_header(), )) } else { - v.push(StyledString::new(String::from(*x), TextStyle::basic_left())) + v.push(Table::create_cell( + String::from(*x), + TextStyle::basic_left(), + )) } } v diff --git a/crates/nu-table/src/nu_protocol_table.rs b/crates/nu-table/src/nu_protocol_table.rs new file mode 100644 index 0000000000..f170d0ff72 --- /dev/null +++ b/crates/nu-table/src/nu_protocol_table.rs @@ -0,0 +1,218 @@ +use std::collections::HashMap; + +use nu_protocol::{Config, Span, Value}; +use tabled::{color::Color, papergrid::records::Records, Table}; + +use crate::{table::TrimStrategyModifier, TableTheme}; + +/// NuTable has a recursive table representation of nu_prorocol::Value. +/// +/// It doesn't support alignement and a proper width controll. +pub struct NuTable { + inner: tabled::Table, +} + +impl NuTable { + pub fn new( + value: Value, + collapse: bool, + termwidth: usize, + config: &Config, + color_hm: &HashMap, + theme: &TableTheme, + with_footer: bool, + ) -> Self { + let mut table = tabled::Table::new([""]); + load_theme(&mut table, color_hm, theme); + let cfg = table.get_config().clone(); + + let val = nu_protocol_value_to_json(value, config, with_footer); + let mut table = json_to_table::json_to_table(&val); + table.set_config(cfg); + + if collapse { + table.collapse(); + } + + let mut table: Table<_> = table.into(); + table.with(TrimStrategyModifier::new(termwidth, &config.trim_strategy)); + + Self { inner: table } + } + + pub fn draw(&self) -> Option { + Some(self.inner.to_string()) + } +} + +fn nu_protocol_value_to_json( + value: Value, + config: &Config, + with_footer: bool, +) -> serde_json::Value { + match value { + Value::Record { cols, vals, .. } => { + let mut map = serde_json::Map::new(); + for (key, value) in cols.into_iter().zip(vals) { + let val = nu_protocol_value_to_json(value, config, false); + map.insert(key, val); + } + + serde_json::Value::Object(map) + } + Value::List { vals, .. } => { + let mut used_cols: Option<&[String]> = None; + for val in &vals { + match val { + Value::Record { cols, .. } => match &used_cols { + Some(_cols) => { + if _cols != cols { + used_cols = None; + break; + } + } + None => used_cols = Some(cols), + }, + _ => { + used_cols = None; + break; + } + } + } + + if let Some(cols) = used_cols { + // rebuild array as a map + if cols.len() > 1 { + let mut arr = vec![]; + + let head = cols.iter().map(|s| Value::String { + val: s.to_owned(), + span: Span::new(0, 0), + }); + let head = build_map(head, config); + + arr.push(serde_json::Value::Object(head.clone())); + + for value in &vals { + if let Ok((_, vals)) = value.as_record() { + let vals = build_map(vals.iter().cloned(), config); + + let mut map = serde_json::Map::new(); + connect_maps(&mut map, serde_json::Value::Object(vals)); + + arr.push(serde_json::Value::Object(map)); + } + } + + if with_footer { + arr.push(serde_json::Value::Object(head)); + } + + return serde_json::Value::Array(arr); + } else { + let mut map = vec![]; + let head = serde_json::Value::Array(vec![serde_json::Value::String( + cols[0].to_owned(), + )]); + + map.push(head.clone()); + for value in vals { + if let Value::Record { vals, .. } = value { + let list = Value::List { + vals, + span: Span::new(0, 0), + }; + let val = nu_protocol_value_to_json(list, config, false); // rebuild array as a map + + map.push(val); + } + } + + if with_footer { + map.push(head); + } + + return serde_json::Value::Array(map); + }; + } + + let mut map = Vec::new(); + for value in vals { + let val = nu_protocol_value_to_json(value, config, false); + map.push(val); + } + + serde_json::Value::Array(map) + } + val => serde_json::Value::String(val.into_abbreviated_string(config)), + } +} + +fn build_map( + values: impl Iterator + DoubleEndedIterator, + config: &Config, +) -> serde_json::Map { + let mut map = serde_json::Map::new(); + let mut last_val: Option = None; + for val in values.rev() { + if map.is_empty() { + match last_val.take() { + Some(prev_val) => { + let col = val.into_abbreviated_string(&Config::default()); + let prev = nu_protocol_value_to_json(prev_val, config, false); + map.insert(col, prev); + } + None => { + last_val = Some(val); + } + } + } else { + let mut new_m = serde_json::Map::new(); + let col = val.into_abbreviated_string(&Config::default()); + + new_m.insert(col, serde_json::Value::Object(map)); + map = new_m; + } + } + + // if last_val.is_some() && map.is_empty() { + // let val = nu_protocol_value_to_json(last_val.unwrap()); + // return serde_json::Value::Array(vec![val]); + // } + + map +} + +fn connect_maps(map: &mut serde_json::Map, value: serde_json::Value) { + if let serde_json::Value::Object(m) = value { + for (key, value) in m { + if value.is_object() { + let mut new_m = serde_json::Map::new(); + connect_maps(&mut new_m, value); + map.insert(key, serde_json::Value::Object(new_m)); + } else { + map.insert(key, value); + } + } + } +} + +fn load_theme( + table: &mut tabled::Table, + color_hm: &HashMap, + theme: &TableTheme, +) where + R: Records, +{ + let mut theme = theme.theme.clone(); + theme.set_horizontals(HashMap::default()); + + table.with(theme); + + if let Some(color) = color_hm.get("separator") { + let color = color.paint(" ").to_string(); + if let Ok(color) = Color::try_from(color) { + table.with(color); + } + } +} diff --git a/crates/nu-table/src/table.rs b/crates/nu-table/src/table.rs index 368791470b..5da62419ac 100644 --- a/crates/nu-table/src/table.rs +++ b/crates/nu-table/src/table.rs @@ -1,31 +1,127 @@ -use std::collections::HashMap; +use std::{collections::HashMap, fmt::Display}; -use nu_ansi_term::Style; -use nu_protocol::{Config, FooterMode, TableIndexMode, TrimStrategy}; +use nu_protocol::{Config, FooterMode, TrimStrategy}; use tabled::{ + alignment::AlignmentHorizontal, builder::Builder, - formatting_settings::AlignmentStrategy, + color::Color, + formatting::AlignmentStrategy, object::{Cell, Columns, Rows, Segment}, - papergrid, - style::Color, - Alignment, AlignmentHorizontal, Modify, ModifyObject, TableOption, Width, + papergrid::{ + self, + records::{ + cell_info::CellInfo, tcell::TCell, vec_records::VecRecords, Records, RecordsMut, + }, + width::CfgWidthFunction, + }, + Alignment, Modify, ModifyObject, TableOption, Width, }; -use crate::{table_theme::TableTheme, width_control::maybe_truncate_columns, StyledString}; +use crate::{table_theme::TableTheme, TextStyle}; /// Table represent a table view. #[derive(Debug)] pub struct Table { - headers: Option>, - data: Vec>, - theme: TableTheme, + data: Data, + is_empty: bool, + with_header: bool, + with_index: bool, } -#[derive(Debug)] +type Data = VecRecords, TextStyle>>; + +impl Table { + /// Creates a [Table] instance. + /// + /// If `headers.is_empty` then no headers will be rendered. + pub fn new( + mut data: Vec, TextStyle>>>, + size: (usize, usize), + termwidth: usize, + with_header: bool, + with_index: bool, + ) -> Table { + // it's not guaranted that data will have all rows with the same number of columns. + // but VecRecords::with_hint require this constrain. + for row in &mut data { + if row.len() < size.1 { + row.extend( + std::iter::repeat(Self::create_cell(String::default(), TextStyle::default())) + .take(size.1 - row.len()), + ); + } + } + + let mut data = VecRecords::with_hint(data, size.1); + let is_empty = maybe_truncate_columns(&mut data, size.1, termwidth); + + Table { + data, + is_empty, + with_header, + with_index, + } + } + + pub fn create_cell(text: String, style: TextStyle) -> TCell, TextStyle> { + TCell::new(CellInfo::new(text, CfgWidthFunction::new(4)), style) + } + + pub fn is_empty(&self) -> bool { + self.is_empty + } + + pub fn truncate(&mut self, width: usize, theme: &TableTheme) -> bool { + let mut truncated = false; + while self.data.count_rows() > 0 && self.data.count_columns() > 0 { + let mut table = Builder::custom(self.data.clone()).build(); + load_theme(&mut table, &HashMap::new(), theme, false, false); + let total = table.total_width(); + drop(table); + + if total > width { + truncated = true; + self.data.truncate(self.data.count_columns() - 1); + } else { + break; + } + } + + let is_empty = self.data.count_rows() == 0 || self.data.count_columns() == 0; + if is_empty { + return true; + } + + if truncated { + self.data.push(Table::create_cell( + String::from("..."), + TextStyle::default(), + )); + } + + false + } + + /// Draws a trable on a String. + /// + /// It returns None in case where table cannot be fit to a terminal width. + pub fn draw_table( + self, + config: &Config, + color_hm: &HashMap, + alignments: Alignments, + theme: &TableTheme, + termwidth: usize, + ) -> Option { + draw_table(self, config, color_hm, alignments, theme, termwidth) + } +} + +#[derive(Debug, Clone, Copy)] pub struct Alignments { - data: AlignmentHorizontal, - index: AlignmentHorizontal, - header: AlignmentHorizontal, + pub(crate) data: AlignmentHorizontal, + pub(crate) index: AlignmentHorizontal, + pub(crate) header: AlignmentHorizontal, } impl Default for Alignments { @@ -38,84 +134,30 @@ impl Default for Alignments { } } -impl Table { - /// Creates a [Table] instance. - /// - /// If `headers.is_empty` then no headers will be rendered. - pub fn new( - headers: Vec, - data: Vec>, - theme: TableTheme, - ) -> Table { - let headers = if headers.is_empty() { - None - } else { - Some(headers) - }; - - Table { - headers, - data, - theme, - } - } - - /// Draws a trable on a String. - /// - /// It returns None in case where table cannot be fit to a terminal width. - pub fn draw_table( - &self, - config: &Config, - color_hm: &HashMap, - alignments: Alignments, - termwidth: usize, - ) -> Option { - draw_table(self, config, color_hm, alignments, termwidth) - } -} - fn draw_table( - table: &Table, + mut table: Table, config: &Config, - color_hm: &HashMap, + color_hm: &HashMap, alignments: Alignments, + theme: &TableTheme, termwidth: usize, ) -> Option { - let mut headers = colorize_headers(table.headers.as_deref()); - let mut data = colorize_data(&table.data, table.headers.as_ref().map_or(0, |h| h.len())); - - let count_columns = table_fix_lengths(headers.as_mut(), &mut data); - - let is_empty = maybe_truncate_columns(&mut headers, &mut data, count_columns, termwidth); - if is_empty { + if table.is_empty { return None; } - let table_data = &table.data; - let theme = &table.theme; - let with_header = headers.is_some(); - let with_footer = with_header && need_footer(config, data.len() as u64); - let with_index = match config.table_index_mode { - TableIndexMode::Always => true, - TableIndexMode::Never => false, - TableIndexMode::Auto => table - .headers - .iter() - .flatten() - .any(|header| header.contents == "index"), - }; + let with_header = table.with_header; + let with_footer = with_header && need_footer(config, (&table.data).size().0 as u64); + let with_index = table.with_index; - let table = build_table(data, headers, with_footer); - let table = load_theme(table, color_hm, theme, with_footer, with_header); - let table = align_table( - table, - alignments, - with_index, - with_header, - with_footer, - table_data, - ); - let table = table_trim_columns(table, termwidth, &config.trim_strategy); + if with_footer { + table.data.duplicate_row(0); + } + + let mut table = Builder::custom(table.data).build(); + load_theme(&mut table, color_hm, theme, with_footer, with_header); + align_table(&mut table, alignments, with_index, with_header, with_footer); + table_trim_columns(&mut table, termwidth, &config.trim_strategy); let table = print_table(table, config); if table_width(&table) > termwidth { @@ -125,7 +167,7 @@ fn draw_table( } } -fn print_table(table: tabled::Table, config: &Config) -> String { +fn print_table(table: tabled::Table, config: &Config) -> String { let output = table.to_string(); // the atty is for when people do ls from vim, there should be no coloring there @@ -142,72 +184,20 @@ fn print_table(table: tabled::Table, config: &Config) -> String { } fn table_width(table: &str) -> usize { - table.lines().next().map_or(0, papergrid::string_width) -} - -fn colorize_data(table_data: &[Vec], count_columns: usize) -> Vec> { - let mut data = vec![Vec::with_capacity(count_columns); table_data.len()]; - for (row, row_data) in table_data.iter().enumerate() { - for cell in row_data { - let colored_text = cell - .style - .color_style - .as_ref() - .map(|color| color.paint(&cell.contents).to_string()) - .unwrap_or_else(|| cell.contents.clone()); - - data[row].push(colored_text) - } - } - - data -} - -fn colorize_headers(headers: Option<&[StyledString]>) -> Option> { - headers.map(|table_headers| { - let mut headers = Vec::with_capacity(table_headers.len()); - for cell in table_headers { - let colored_text = cell - .style - .color_style - .as_ref() - .map(|color| color.paint(&cell.contents).to_string()) - .unwrap_or_else(|| cell.contents.clone()); - - headers.push(colored_text) - } - - headers - }) -} - -fn build_table( - data: Vec>, - headers: Option>, - need_footer: bool, -) -> tabled::Table { - let mut builder = Builder::from(data); - - if let Some(headers) = headers { - builder.set_columns(headers.clone()); - - if need_footer { - builder.add_record(headers); - } - } - - builder.build() + table + .lines() + .next() + .map_or(0, papergrid::util::string_width) } fn align_table( - mut table: tabled::Table, + table: &mut tabled::Table, alignments: Alignments, with_index: bool, with_header: bool, with_footer: bool, - data: &[Vec], -) -> tabled::Table { - table = table.with( +) { + table.with( Modify::new(Segment::all()) .with(Alignment::Horizontal(alignments.data)) .with(AlignmentStrategy::PerLine), @@ -216,81 +206,77 @@ fn align_table( if with_header { let alignment = Alignment::Horizontal(alignments.header); if with_footer { - table = table.with(Modify::new(Rows::last()).with(alignment.clone())); + table.with(Modify::new(Rows::last()).with(alignment.clone())); } - table = table.with(Modify::new(Rows::first()).with(alignment)); + table.with(Modify::new(Rows::first()).with(alignment)); } if with_index { - table = - table.with(Modify::new(Columns::first()).with(Alignment::Horizontal(alignments.index))); + table.with(Modify::new(Columns::first()).with(Alignment::Horizontal(alignments.index))); } - table = override_alignments(table, data, with_header, with_index, alignments); - - table + override_alignments(table, with_header, with_index, alignments); } fn override_alignments( - mut table: tabled::Table, - data: &[Vec], + table: &mut tabled::Table, header_present: bool, index_present: bool, alignments: Alignments, -) -> tabled::Table { +) { let offset = if header_present { 1 } else { 0 }; - for (row, rows) in data.iter().enumerate() { - for (col, s) in rows.iter().enumerate() { - if index_present && col == 0 && s.style.alignment == alignments.index { + let (count_rows, count_columns) = table.shape(); + for row in offset..count_rows { + for col in 0..count_columns { + let alignment = table.get_records()[(row, col)].get_data().alignment; + if index_present && col == 0 && alignment == alignments.index { continue; } - if s.style.alignment == alignments.data { + if alignment == alignments.data { continue; } - table = table.with( - Cell(row + offset, col) + table.with( + Cell(row, col) .modify() - .with(Alignment::Horizontal(s.style.alignment)), + .with(Alignment::Horizontal(alignment)), ); } } - - table } -fn load_theme( - mut table: tabled::Table, - color_hm: &HashMap, +fn load_theme( + table: &mut tabled::Table, + color_hm: &HashMap, theme: &TableTheme, with_footer: bool, with_header: bool, -) -> tabled::Table { +) where + R: Records, +{ let mut theme = theme.theme.clone(); if !with_header { - theme.set_lines(HashMap::default()); + theme.set_horizontals(HashMap::default()); } - table = table.with(theme); + table.with(theme); if let Some(color) = color_hm.get("separator") { let color = color.paint(" ").to_string(); if let Ok(color) = Color::try_from(color) { - table = table.with(color); + table.with(color); } } if with_footer { - table = table.with(FooterStyle).with( + table.with(FooterStyle).with( Modify::new(Rows::last()) .with(Alignment::center()) .with(AlignmentStrategy::PerCell), ); } - - table } fn need_footer(config: &Config, count_records: u64) -> bool { @@ -300,27 +286,30 @@ fn need_footer(config: &Config, count_records: u64) -> bool { struct FooterStyle; -impl TableOption for FooterStyle { - fn change(&mut self, grid: &mut papergrid::Grid) { - if grid.count_columns() == 0 || grid.count_rows() == 0 { +impl TableOption for FooterStyle +where + R: Records, +{ + fn change(&mut self, table: &mut tabled::Table) { + if table.is_empty() { return; } - if let Some(line) = grid.clone().get_split_line(1) { - grid.set_split_line(grid.count_rows() - 1, line.clone()); + if let Some(line) = table.get_config().get_horizontal_line(1).cloned() { + let count_rows = table.shape().0; + table + .get_config_mut() + .set_horizontal_line(count_rows - 1, line); } } } fn table_trim_columns( - table: tabled::Table, + table: &mut tabled::Table, termwidth: usize, trim_strategy: &TrimStrategy, -) -> tabled::Table { - table.with(&TrimStrategyModifier { - termwidth, - trim_strategy, - }) +) { + table.with(TrimStrategyModifier::new(termwidth, trim_strategy)); } pub struct TrimStrategyModifier<'a> { @@ -328,49 +317,77 @@ pub struct TrimStrategyModifier<'a> { trim_strategy: &'a TrimStrategy, } -impl tabled::TableOption for &TrimStrategyModifier<'_> { - fn change(&mut self, grid: &mut papergrid::Grid) { +impl<'a> TrimStrategyModifier<'a> { + pub fn new(termwidth: usize, trim_strategy: &'a TrimStrategy) -> Self { + Self { + termwidth, + trim_strategy, + } + } +} + +impl tabled::TableOption for TrimStrategyModifier<'_> +where + R: Records + RecordsMut, +{ + fn change(&mut self, table: &mut tabled::Table) { match self.trim_strategy { TrimStrategy::Wrap { try_to_keep_words } => { - let mut w = Width::wrap(self.termwidth).priority::(); + let mut w = Width::wrap(self.termwidth).priority::(); if *try_to_keep_words { w = w.keep_words(); } - w.change(grid) + w.change(table) } TrimStrategy::Truncate { suffix } => { let mut w = - Width::truncate(self.termwidth).priority::(); + Width::truncate(self.termwidth).priority::(); if let Some(suffix) = suffix { w = w.suffix(suffix).suffix_try_color(true); } - w.change(grid); + w.change(table); } }; } } -fn table_fix_lengths(headers: Option<&mut Vec>, data: &mut [Vec]) -> usize { - let length = table_find_max_length(headers.as_deref(), data); - - if let Some(headers) = headers { - headers.extend(std::iter::repeat(String::default()).take(length - headers.len())); +fn maybe_truncate_columns(data: &mut Data, length: usize, termwidth: usize) -> bool { + // Make sure we have enough space for the columns we have + let max_num_of_columns = termwidth / 10; + if max_num_of_columns == 0 { + return true; } - for row in data { - row.extend(std::iter::repeat(String::default()).take(length - row.len())); + // If we have too many columns, truncate the table + if max_num_of_columns < length { + data.truncate(max_num_of_columns); + data.push(Table::create_cell( + String::from("..."), + TextStyle::default(), + )); } - length + false } -fn table_find_max_length(headers: Option<&Vec>, data: &[Vec]) -> usize { - let mut length = headers.map_or(0, |h| h.len()); - for row in data { - length = std::cmp::max(length, row.len()); +impl papergrid::Color for TextStyle { + fn fmt_prefix(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + if let Some(color) = &self.color_style { + color.prefix().fmt(f)?; + } + + Ok(()) } - length + fn fmt_suffix(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + if let Some(color) = &self.color_style { + if !color.is_plain() { + f.write_str("\u{1b}[0m")?; + } + } + + Ok(()) + } } diff --git a/crates/nu-table/src/table_theme.rs b/crates/nu-table/src/table_theme.rs index 0d7974f64f..6101a3b8f1 100644 --- a/crates/nu-table/src/table_theme.rs +++ b/crates/nu-table/src/table_theme.rs @@ -1,4 +1,7 @@ -use tabled::style::{Line, RawStyle, Style}; +use tabled::{ + style::RawStyle, + style::{HorizontalLine, Line, Style}, +}; #[derive(Debug, Clone)] pub struct TableTheme { @@ -21,7 +24,10 @@ impl TableTheme { pub fn light() -> TableTheme { Self { theme: Style::blank() - .lines([(1, Line::new(Some('─'), Some('─'), None, None))]) + .horizontals([HorizontalLine::new( + 1, + Line::new(Some('─'), Some('─'), None, None), + )]) .into(), } } @@ -32,7 +38,9 @@ impl TableTheme { .off_left() .off_right() .off_horizontal() - .lines([(1, Style::modern().get_horizontal().left(None).right(None))]) + .horizontals([HorizontalLine::new(1, Style::modern().get_horizontal()) + .left(None) + .right(None)]) .into(), } } @@ -43,7 +51,10 @@ impl TableTheme { .top('❤') .bottom('❤') .vertical('❤') - .lines([(1, Line::new(Some('❤'), Some('❤'), None, None))]) + .horizontals([HorizontalLine::new( + 1, + Line::new(Some('❤'), Some('❤'), None, None), + )]) .into(), } } @@ -54,7 +65,9 @@ impl TableTheme { .off_left() .off_right() .off_horizontal() - .lines([(1, Style::extended().get_horizontal().left(None).right(None))]) + .horizontals([HorizontalLine::new(1, Style::extended().get_horizontal()) + .left(None) + .right(None)]) .into(), } } @@ -91,7 +104,7 @@ impl TableTheme { .top_right_corner('┓') .bottom_left_corner('┗') .bottom_right_corner('┛') - .lines([(1, Line::full('━', '╋', '┣', '┫'))]) + .horizontals([HorizontalLine::new(1, Line::full('━', '╋', '┣', '┫'))]) .into(), } } diff --git a/crates/nu-table/src/textstyle.rs b/crates/nu-table/src/textstyle.rs index 1f60982d95..8fbe7228bb 100644 --- a/crates/nu-table/src/textstyle.rs +++ b/crates/nu-table/src/textstyle.rs @@ -1,6 +1,6 @@ use nu_ansi_term::{Color, Style}; -pub type Alignment = tabled::AlignmentHorizontal; +pub type Alignment = tabled::alignment::AlignmentHorizontal; #[derive(Debug, Clone, Copy)] pub struct TextStyle { @@ -239,19 +239,3 @@ impl Default for TextStyle { Self::new() } } - -#[derive(Debug, Clone, Default)] -pub struct StyledString { - pub contents: String, - pub style: TextStyle, -} - -impl StyledString { - pub fn new(contents: String, style: TextStyle) -> StyledString { - StyledString { contents, style } - } - - pub fn set_style(&mut self, style: TextStyle) { - self.style = style; - } -} diff --git a/crates/nu-table/src/width_control.rs b/crates/nu-table/src/width_control.rs deleted file mode 100644 index 1185a2e14f..0000000000 --- a/crates/nu-table/src/width_control.rs +++ /dev/null @@ -1,29 +0,0 @@ -pub(crate) fn maybe_truncate_columns( - headers: &mut Option>, - data: &mut [Vec], - length: usize, - termwidth: usize, -) -> bool { - // Make sure we have enough space for the columns we have - let max_num_of_columns = termwidth / 10; - if max_num_of_columns == 0 { - return true; - } - - // If we have too many columns, truncate the table - if let Some(headers) = headers { - if max_num_of_columns < length { - headers.truncate(max_num_of_columns); - headers.push(String::from("...")); - } - } - - if max_num_of_columns < length { - for entry in data.iter_mut() { - entry.truncate(max_num_of_columns); - entry.push(String::from("...")); - } - } - - false -} diff --git a/crates/nu-table/tests/constrains.rs b/crates/nu-table/tests/constrains.rs index ed4ee1fa7b..6ab4ba510e 100644 --- a/crates/nu-table/tests/constrains.rs +++ b/crates/nu-table/tests/constrains.rs @@ -1,11 +1,20 @@ use std::{collections::HashMap, usize}; use nu_protocol::{Config, TrimStrategy}; -use nu_table::{Alignments, StyledString, Table, TableTheme as theme, TextStyle}; +use nu_table::{Alignments, Table, TableTheme as theme, TextStyle}; +use tabled::papergrid::records::{cell_info::CellInfo, tcell::TCell}; #[test] fn data_and_header_has_different_size() { - let table = Table::new(row(3), vec![row(5); 2], theme::heavy()); + let table = Table::new( + vec![row(3), row(5), row(5)], + (3, 5), + usize::MAX, + true, + false, + ); + + let table = draw_table(table, usize::MAX, &Config::default()); let expected = "┏━━━┳━━━┳━━━┳━━━┳━━━┓\n\ ┃ 0 ┃ 1 ┃ 2 ┃ ┃ ┃\n\ @@ -14,12 +23,16 @@ fn data_and_header_has_different_size() { ┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃ 4 ┃\n\ ┗━━━┻━━━┻━━━┻━━━┻━━━┛"; - assert_eq!( - draw_table(&table, usize::MAX, &Config::default()).as_deref(), - Some(expected) - ); + assert_eq!(table.as_deref(), Some(expected)); - let table = Table::new(row(5), vec![row(3); 2], theme::heavy()); + let table = Table::new( + vec![row(5), row(3), row(3)], + (3, 5), + usize::MAX, + true, + false, + ); + let table = draw_table(table, usize::MAX, &Config::default()); let expected = "┏━━━┳━━━┳━━━┳━━━┳━━━┓\n\ ┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃ 4 ┃\n\ @@ -28,22 +41,19 @@ fn data_and_header_has_different_size() { ┃ 0 ┃ 1 ┃ 2 ┃ ┃ ┃\n\ ┗━━━┻━━━┻━━━┻━━━┻━━━┛"; - assert_eq!( - draw_table(&table, usize::MAX, &Config::default()).as_deref(), - Some(expected) - ); + assert_eq!(table.as_deref(), Some(expected)); } #[test] fn termwidth_too_small() { - let table = Table::new(row(3), vec![row(5); 2], theme::heavy()); let cfg = Config::default(); - for i in 0..10 { - assert!(draw_table(&table, i, &cfg).is_none()); + let table = Table::new(vec![row(3), row(3), row(5)], (3, 5), i, true, false); + assert!(draw_table(table, i, &cfg).is_none()); } - assert!(draw_table(&table, 11, &cfg).is_some()); + let table = Table::new(vec![row(3), row(3), row(5)], (3, 5), 11, true, false); + assert!(draw_table(table, 11, &cfg).is_some()); let cfg = Config { trim_strategy: TrimStrategy::Truncate { suffix: None }, @@ -51,10 +61,12 @@ fn termwidth_too_small() { }; for i in 0..10 { - assert!(draw_table(&table, i, &cfg).is_none()); + let table = Table::new(vec![row(3), row(3), row(5)], (3, 5), i, true, false); + assert!(draw_table(table, i, &cfg).is_none()); } - assert!(draw_table(&table, 11, &cfg).is_some()); + let table = Table::new(vec![row(3), row(3), row(5)], (3, 5), 11, true, false); + assert!(draw_table(table, 11, &cfg).is_some()); } #[test] @@ -65,24 +77,23 @@ fn wrap_test() { }, ..Default::default() }; - let table = table_with_data(); for i in 0..10 { - assert!(draw_table(&table, i, &cfg).is_none()); + assert!(draw_table(table_with_data(i), i, &cfg).is_none()); } - assert_eq!(draw_table(&table, 10, &cfg).unwrap(), "┏━━━━┳━━━┓\n┃ 12 ┃ . ┃\n┃ 3 ┃ . ┃\n┃ 45 ┃ . ┃\n┃ 67 ┃ ┃\n┃ 8 ┃ ┃\n┣━━━━╋━━━┫\n┃ 0 ┃ . ┃\n┃ ┃ . ┃\n┃ ┃ . ┃\n┃ 0 ┃ . ┃\n┃ ┃ . ┃\n┃ ┃ . ┃\n┗━━━━┻━━━┛"); + assert_eq!(draw_table(table_with_data(10), 10, &cfg).unwrap(), "┏━━━━┳━━━┓\n┃ 12 ┃ . ┃\n┃ 3 ┃ . ┃\n┃ 45 ┃ . ┃\n┃ 67 ┃ ┃\n┃ 8 ┃ ┃\n┣━━━━╋━━━┫\n┃ 0 ┃ . ┃\n┃ ┃ . ┃\n┃ ┃ . ┃\n┃ 0 ┃ . ┃\n┃ ┃ . ┃\n┃ ┃ . ┃\n┗━━━━┻━━━┛"); assert_eq!( - draw_table(&table, 21, &cfg).unwrap(), - "┏━━━━━━┳━━━━━━┳━━━━━┓\n┃ 123 ┃ qweq ┃ ... ┃\n┃ 4567 ┃ w eq ┃ ┃\n┃ 8 ┃ we ┃ ┃\n┣━━━━━━╋━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ ... ┃\n┃ 0 ┃ 1 ┃ ... ┃\n┗━━━━━━┻━━━━━━┻━━━━━┛" + draw_table(table_with_data(21), 21, &cfg).unwrap(), + "┏━━━━━━┳━━━━━━┳━━━━━┓\n┃ 123 ┃ qweq ┃ ... ┃\n┃ 4567 ┃ w eq ┃ ┃\n┃ 8 ┃ we ┃ ┃\n┣━━━━━━╋━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ ... ┃\n┃ 0 ┃ 1 ┃ ... ┃\n┗━━━━━━┻━━━━━━┻━━━━━┛" ); assert_eq!( - draw_table(&table, 29, &cfg).unwrap(), - "┏━━━━━━━━━━┳━━━━━━━━━━┳━━━━━┓\n┃ 123 4567 ┃ qweqw eq ┃ ... ┃\n┃ 8 ┃ we ┃ ┃\n┣━━━━━━━━━━╋━━━━━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ ... ┃\n┃ 0 ┃ 1 ┃ ... ┃\n┗━━━━━━━━━━┻━━━━━━━━━━┻━━━━━┛" + draw_table(table_with_data(29), 29, &cfg).unwrap(), + "┏━━━━━━━━━━┳━━━━━━━━━━┳━━━━━┓\n┃ 123 4567 ┃ qweqw eq ┃ ... ┃\n┃ 8 ┃ we ┃ ┃\n┣━━━━━━━━━━╋━━━━━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ ... ┃\n┃ 0 ┃ 1 ┃ ... ┃\n┗━━━━━━━━━━┻━━━━━━━━━━┻━━━━━┛" ); assert_eq!( - draw_table(&table, 49, &cfg).unwrap(), - "┏━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┳━━━━━┓\n┃ 123 4567 ┃ qweqw eq ┃ xxx xx ┃ qqq qqq ┃ ... ┃\n┃ 8 ┃ we ┃ xx x xx ┃ qqqq q ┃ ┃\n┃ ┃ ┃ x xx x ┃ qq qq ┃ ┃\n┃ ┃ ┃ x ┃ ┃ ┃\n┣━━━━━━━━━━╋━━━━━━━━━━╋━━━━━━━━━╋━━━━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃ ... ┃\n┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃ ... ┃\n┗━━━━━━━━━━┻━━━━━━━━━━┻━━━━━━━━━┻━━━━━━━━━┻━━━━━┛" + draw_table(table_with_data(49), 49, &cfg).unwrap(), + "┏━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┳━━━━━┓\n┃ 123 4567 ┃ qweqw eq ┃ xxx xx ┃ qqq qqq ┃ ... ┃\n┃ 8 ┃ we ┃ xx x xx ┃ qqqq q ┃ ┃\n┃ ┃ ┃ x xx x ┃ qq qq ┃ ┃\n┃ ┃ ┃ x ┃ ┃ ┃\n┣━━━━━━━━━━╋━━━━━━━━━━╋━━━━━━━━━╋━━━━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃ ... ┃\n┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃ ... ┃\n┗━━━━━━━━━━┻━━━━━━━━━━┻━━━━━━━━━┻━━━━━━━━━┻━━━━━┛" ); } @@ -94,24 +105,23 @@ fn wrap_keep_words_test() { }, ..Default::default() }; - let table = table_with_data(); for i in 0..10 { - assert!(draw_table(&table, i, &cfg).is_none()); + assert!(draw_table(table_with_data(i), i, &cfg).is_none()); } - assert_eq!(draw_table(&table, 10, &cfg).unwrap(), "┏━━━━┳━━━┓\n┃ 12 ┃ . ┃\n┃ 34 ┃ . ┃\n┃ 56 ┃ . ┃\n┃ 78 ┃ ┃\n┣━━━━╋━━━┫\n┃ 0 ┃ . ┃\n┃ ┃ . ┃\n┃ ┃ . ┃\n┃ 0 ┃ . ┃\n┃ ┃ . ┃\n┃ ┃ . ┃\n┗━━━━┻━━━┛"); + assert_eq!(draw_table(table_with_data(10), 10, &cfg).unwrap(), "┏━━━━┳━━━┓\n┃ 12 ┃ . ┃\n┃ 3 ┃ . ┃\n┃ 45 ┃ . ┃\n┃ 67 ┃ ┃\n┃ 8 ┃ ┃\n┣━━━━╋━━━┫\n┃ 0 ┃ . ┃\n┃ ┃ . ┃\n┃ ┃ . ┃\n┃ 0 ┃ . ┃\n┃ ┃ . ┃\n┃ ┃ . ┃\n┗━━━━┻━━━┛"); assert_eq!( - draw_table(&table, 21, &cfg).unwrap(), - "┏━━━━━━┳━━━━━━┳━━━━━┓\n┃ 123 ┃ qweq ┃ ... ┃\n┃ 4567 ┃ w ┃ ┃\n┃ 8 ┃ eqwe ┃ ┃\n┣━━━━━━╋━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ ... ┃\n┃ 0 ┃ 1 ┃ ... ┃\n┗━━━━━━┻━━━━━━┻━━━━━┛" + draw_table(table_with_data(21), 21, &cfg).unwrap(), + "┏━━━━━━┳━━━━━━┳━━━━━┓\n┃ 123 ┃ qweq ┃ ... ┃\n┃ 4567 ┃ w ┃ ┃\n┃ 8 ┃ eqwe ┃ ┃\n┣━━━━━━╋━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ ... ┃\n┃ 0 ┃ 1 ┃ ... ┃\n┗━━━━━━┻━━━━━━┻━━━━━┛" ); assert_eq!( - draw_table(&table, 29, &cfg).unwrap(), - "┏━━━━━━━━━━┳━━━━━━━━━━┳━━━━━┓\n┃ 123 ┃ qweqw ┃ ... ┃\n┃ 45678 ┃ eqwe ┃ ┃\n┣━━━━━━━━━━╋━━━━━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ ... ┃\n┃ 0 ┃ 1 ┃ ... ┃\n┗━━━━━━━━━━┻━━━━━━━━━━┻━━━━━┛" + draw_table(table_with_data(29), 29, &cfg).unwrap(), + "┏━━━━━━━━━━┳━━━━━━━━━━┳━━━━━┓\n┃ 123 ┃ qweqw ┃ ... ┃\n┃ 45678 ┃ eqwe ┃ ┃\n┣━━━━━━━━━━╋━━━━━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ ... ┃\n┃ 0 ┃ 1 ┃ ... ┃\n┗━━━━━━━━━━┻━━━━━━━━━━┻━━━━━┛" ); assert_eq!( - draw_table(&table, 49, &cfg).unwrap(), - "┏━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┳━━━━━┓\n┃ 123 ┃ qweqw ┃ xxx xx ┃ qqq qqq ┃ ... ┃\n┃ 45678 ┃ eqwe ┃ xx x xx ┃ qqqq ┃ ┃\n┃ ┃ ┃ x xx xx ┃ qqq qq ┃ ┃\n┣━━━━━━━━━━╋━━━━━━━━━━╋━━━━━━━━━╋━━━━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃ ... ┃\n┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃ ... ┃\n┗━━━━━━━━━━┻━━━━━━━━━━┻━━━━━━━━━┻━━━━━━━━━┻━━━━━┛" + draw_table(table_with_data(49), 49, &cfg).unwrap(), + "┏━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┳━━━━━┓\n┃ 123 ┃ qweqw ┃ xxx xx ┃ qqq qqq ┃ ... ┃\n┃ 45678 ┃ eqwe ┃ xx x xx ┃ qqqq ┃ ┃\n┃ ┃ ┃ x xx ┃ qqq qq ┃ ┃\n┃ ┃ ┃ xx ┃ ┃ ┃\n┣━━━━━━━━━━╋━━━━━━━━━━╋━━━━━━━━━╋━━━━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃ ... ┃\n┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃ ... ┃\n┗━━━━━━━━━━┻━━━━━━━━━━┻━━━━━━━━━┻━━━━━━━━━┻━━━━━┛" ); } @@ -121,26 +131,25 @@ fn truncate_test() { trim_strategy: TrimStrategy::Truncate { suffix: None }, ..Default::default() }; - let table = table_with_data(); for i in 0..10 { - assert!(draw_table(&table, i, &cfg).is_none()); + assert!(draw_table(table_with_data(i), i, &cfg).is_none()); } assert_eq!( - draw_table(&table, 10, &cfg).unwrap(), + draw_table(table_with_data(10), 10, &cfg).unwrap(), "┏━━━━┳━━━┓\n┃ 12 ┃ . ┃\n┣━━━━╋━━━┫\n┃ 0 ┃ . ┃\n┃ 0 ┃ . ┃\n┗━━━━┻━━━┛" ); assert_eq!( - draw_table(&table, 21, &cfg).unwrap(), + draw_table(table_with_data(21), 21, &cfg).unwrap(), "┏━━━━━━┳━━━━━━┳━━━━━┓\n┃ 123 ┃ qweq ┃ ... ┃\n┣━━━━━━╋━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ ... ┃\n┃ 0 ┃ 1 ┃ ... ┃\n┗━━━━━━┻━━━━━━┻━━━━━┛" ); assert_eq!( - draw_table(&table, 29, &cfg).unwrap(), + draw_table(table_with_data(29), 29, &cfg).unwrap(), "┏━━━━━━━━━━┳━━━━━━━━━━┳━━━━━┓\n┃ 123 4567 ┃ qweqw eq ┃ ... ┃\n┣━━━━━━━━━━╋━━━━━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ ... ┃\n┃ 0 ┃ 1 ┃ ... ┃\n┗━━━━━━━━━━┻━━━━━━━━━━┻━━━━━┛" ); assert_eq!( - draw_table(&table, 49, &cfg).unwrap(), + draw_table(table_with_data(49), 49, &cfg).unwrap(), "┏━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┳━━━━━┓\n┃ 123 4567 ┃ qweqw eq ┃ xxx xx ┃ qqq qqq ┃ ... ┃\n┣━━━━━━━━━━╋━━━━━━━━━━╋━━━━━━━━━╋━━━━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃ ... ┃\n┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃ ... ┃\n┗━━━━━━━━━━┻━━━━━━━━━━┻━━━━━━━━━┻━━━━━━━━━┻━━━━━┛" ); } @@ -153,60 +162,58 @@ fn truncate_with_suffix_test() { }, ..Default::default() }; - let table = table_with_data(); for i in 0..10 { - assert!(draw_table(&table, i, &cfg).is_none()); + assert!(draw_table(table_with_data(i), i, &cfg).is_none()); } assert_eq!( - draw_table(&table, 10, &cfg).unwrap(), + draw_table(table_with_data(10), 10, &cfg).unwrap(), "┏━━━━┳━━━┓\n┃ .. ┃ . ┃\n┣━━━━╋━━━┫\n┃ 0 ┃ . ┃\n┃ 0 ┃ . ┃\n┗━━━━┻━━━┛" ); assert_eq!( - draw_table(&table, 21, &cfg).unwrap(), + draw_table(table_with_data(21), 21, &cfg).unwrap(), "┏━━━━━━┳━━━━━━┳━━━━━┓\n┃ 1... ┃ q... ┃ ... ┃\n┣━━━━━━╋━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ ... ┃\n┃ 0 ┃ 1 ┃ ... ┃\n┗━━━━━━┻━━━━━━┻━━━━━┛" ); assert_eq!( - draw_table(&table, 29, &cfg).unwrap(), + draw_table(table_with_data(29), 29, &cfg).unwrap(), "┏━━━━━━━━━━┳━━━━━━━━━━┳━━━━━┓\n┃ 123 4... ┃ qweqw... ┃ ... ┃\n┣━━━━━━━━━━╋━━━━━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ ... ┃\n┃ 0 ┃ 1 ┃ ... ┃\n┗━━━━━━━━━━┻━━━━━━━━━━┻━━━━━┛" ); assert_eq!( - draw_table(&table, 49, &cfg).unwrap(), + draw_table(table_with_data(49), 49, &cfg).unwrap(), "┏━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┳━━━━━┓\n┃ 123 4... ┃ qweqw... ┃ xxx ... ┃ qqq ... ┃ ... ┃\n┣━━━━━━━━━━╋━━━━━━━━━━╋━━━━━━━━━╋━━━━━━━━━╋━━━━━┫\n┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃ ... ┃\n┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃ ... ┃\n┗━━━━━━━━━━┻━━━━━━━━━━┻━━━━━━━━━┻━━━━━━━━━┻━━━━━┛" ); } -fn draw_table(table: &Table, limit: usize, cfg: &Config) -> Option { +fn draw_table(table: Table, limit: usize, cfg: &Config) -> Option { let styles = HashMap::default(); let alignments = Alignments::default(); - table.draw_table(cfg, &styles, alignments, limit) + table.draw_table(cfg, &styles, alignments, &theme::heavy(), limit) } -fn row(count_columns: usize) -> Vec { +fn row(count_columns: usize) -> Vec, TextStyle>> { let mut row = Vec::with_capacity(count_columns); for i in 0..count_columns { - row.push(StyledString::new(i.to_string(), TextStyle::default())); + row.push(Table::create_cell(i.to_string(), TextStyle::default())); } row } -fn styled_str(s: &str) -> StyledString { - StyledString::new(s.to_string(), TextStyle::default()) +fn styled_str(s: &str) -> TCell, TextStyle> { + Table::create_cell(s.to_string(), TextStyle::default()) } -fn table_with_data() -> Table { - Table::new( - vec![ - styled_str("123 45678"), - styled_str("qweqw eqwe"), - styled_str("xxx xx xx x xx x xx xx"), - styled_str("qqq qqq qqqq qqq qq"), - styled_str("qw"), - ], - vec![row(5); 2], - theme::heavy(), - ) +fn table_with_data(termwidth: usize) -> Table { + let header = vec![ + styled_str("123 45678"), + styled_str("qweqw eqwe"), + styled_str("xxx xx xx x xx x xx xx"), + styled_str("qqq qqq qqqq qqq qq"), + styled_str("qw"), + ]; + let data = vec![header, row(5), row(5)]; + + Table::new(data, (3, 5), termwidth, true, false) } diff --git a/crates/nu-table/tests/style.rs b/crates/nu-table/tests/style.rs index 323f35646e..bd01012432 100644 --- a/crates/nu-table/tests/style.rs +++ b/crates/nu-table/tests/style.rs @@ -1,12 +1,13 @@ use std::collections::HashMap; use nu_protocol::Config; -use nu_table::{Alignments, StyledString, Table, TableTheme as theme, TextStyle}; +use nu_table::{Alignments, Table, TableTheme as theme, TextStyle}; +use tabled::papergrid::records::{cell_info::CellInfo, tcell::TCell}; #[test] fn test_rounded() { assert_eq!( - draw_table(&Table::new(row(4), vec![row(4); 2], theme::rounded())), + draw_table(vec![row(4); 3], 4, true, theme::rounded()), "╭───┬───┬───┬───╮\n\ │ 0 │ 1 │ 2 │ 3 │\n\ ├───┼───┼───┼───┤\n\ @@ -16,7 +17,7 @@ fn test_rounded() { ); assert_eq!( - draw_table(&Table::new(row(4), vec![row(4); 1], theme::rounded())), + draw_table(vec![row(4); 2], 4, true, theme::rounded()), "╭───┬───┬───┬───╮\n\ │ 0 │ 1 │ 2 │ 3 │\n\ ├───┼───┼───┼───┤\n\ @@ -25,30 +26,34 @@ fn test_rounded() { ); assert_eq!( - draw_table(&Table::new(row(4), vec![row(4); 0], theme::rounded())), + draw_table(vec![row(4); 1], 4, true, theme::rounded()), "╭───┬───┬───┬───╮\n\ │ 0 │ 1 │ 2 │ 3 │\n\ ╰───┴───┴───┴───╯" ); assert_eq!( - draw_table(&Table::new(row(0), vec![row(4); 2], theme::rounded())), + draw_table(vec![row(4); 1], 4, false, theme::rounded()), + "╭───┬───┬───┬───╮\n\ + │ 0 │ 1 │ 2 │ 3 │\n\ + ╰───┴───┴───┴───╯" + ); + + assert_eq!( + draw_table(vec![row(4); 2], 4, false, theme::rounded()), "╭───┬───┬───┬───╮\n\ │ 0 │ 1 │ 2 │ 3 │\n\ │ 0 │ 1 │ 2 │ 3 │\n\ ╰───┴───┴───┴───╯" ); - assert_eq!( - draw_table(&Table::new(row(0), vec![row(0); 0], theme::rounded())), - "" - ); + assert_eq!(draw_table(vec![row(4); 0], 4, false, theme::rounded()), ""); } #[test] fn test_basic() { assert_eq!( - draw_table(&Table::new(row(4), vec![row(4); 2], theme::basic())), + draw_table(vec![row(4); 3], 4, true, theme::basic()), "+---+---+---+---+\n\ | 0 | 1 | 2 | 3 |\n\ +---+---+---+---+\n\ @@ -59,7 +64,7 @@ fn test_basic() { ); assert_eq!( - draw_table(&Table::new(row(4), vec![row(4); 1], theme::basic())), + draw_table(vec![row(4); 2], 4, true, theme::basic()), "+---+---+---+---+\n\ | 0 | 1 | 2 | 3 |\n\ +---+---+---+---+\n\ @@ -68,14 +73,21 @@ fn test_basic() { ); assert_eq!( - draw_table(&Table::new(row(4), vec![row(4); 0], theme::basic())), + draw_table(vec![row(4); 1], 4, true, theme::basic()), "+---+---+---+---+\n\ | 0 | 1 | 2 | 3 |\n\ +---+---+---+---+" ); assert_eq!( - draw_table(&Table::new(row(0), vec![row(4); 2], theme::basic())), + draw_table(vec![row(4); 1], 4, false, theme::basic()), + "+---+---+---+---+\n\ + | 0 | 1 | 2 | 3 |\n\ + +---+---+---+---+" + ); + + assert_eq!( + draw_table(vec![row(4); 2], 4, false, theme::basic()), "+---+---+---+---+\n\ | 0 | 1 | 2 | 3 |\n\ +---+---+---+---+\n\ @@ -83,16 +95,13 @@ fn test_basic() { +---+---+---+---+" ); - assert_eq!( - draw_table(&Table::new(row(0), vec![row(0); 0], theme::basic())), - "" - ); + assert_eq!(draw_table(vec![row(4); 0], 4, false, theme::basic()), ""); } #[test] fn test_reinforced() { assert_eq!( - draw_table(&Table::new(row(4), vec![row(4); 2], theme::reinforced())), + draw_table(vec![row(4); 3], 4, true, theme::reinforced()), "┏───┬───┬───┬───┓\n\ │ 0 │ 1 │ 2 │ 3 │\n\ │ 0 │ 1 │ 2 │ 3 │\n\ @@ -101,7 +110,7 @@ fn test_reinforced() { ); assert_eq!( - draw_table(&Table::new(row(4), vec![row(4); 1], theme::reinforced())), + draw_table(vec![row(4); 2], 4, true, theme::reinforced()), "┏───┬───┬───┬───┓\n\ │ 0 │ 1 │ 2 │ 3 │\n\ │ 0 │ 1 │ 2 │ 3 │\n\ @@ -109,14 +118,21 @@ fn test_reinforced() { ); assert_eq!( - draw_table(&Table::new(row(4), vec![row(4); 0], theme::reinforced())), + draw_table(vec![row(4); 1], 4, true, theme::reinforced()), "┏───┬───┬───┬───┓\n\ │ 0 │ 1 │ 2 │ 3 │\n\ ┗───┴───┴───┴───┛" ); assert_eq!( - draw_table(&Table::new(row(0), vec![row(4); 2], theme::reinforced())), + draw_table(vec![row(4); 1], 4, false, theme::reinforced()), + "┏───┬───┬───┬───┓\n\ + │ 0 │ 1 │ 2 │ 3 │\n\ + ┗───┴───┴───┴───┛" + ); + + assert_eq!( + draw_table(vec![row(4); 2], 4, false, theme::reinforced()), "┏───┬───┬───┬───┓\n\ │ 0 │ 1 │ 2 │ 3 │\n\ │ 0 │ 1 │ 2 │ 3 │\n\ @@ -124,7 +140,7 @@ fn test_reinforced() { ); assert_eq!( - draw_table(&Table::new(row(0), vec![row(0); 0], theme::reinforced())), + draw_table(vec![row(4); 0], 2, false, theme::reinforced()), "" ); } @@ -132,7 +148,7 @@ fn test_reinforced() { #[test] fn test_compact() { assert_eq!( - draw_table(&Table::new(row(4), vec![row(4); 2], theme::compact())), + draw_table(vec![row(4); 3], 4, true, theme::compact()), concat!( "───┬───┬───┬───\n", " 0 │ 1 │ 2 │ 3 \n", @@ -144,7 +160,7 @@ fn test_compact() { ); assert_eq!( - draw_table(&Table::new(row(4), vec![row(4); 1], theme::compact())), + draw_table(vec![row(4); 2], 4, true, theme::compact()), concat!( "───┬───┬───┬───\n", " 0 │ 1 │ 2 │ 3 \n", @@ -155,12 +171,17 @@ fn test_compact() { ); assert_eq!( - draw_table(&Table::new(row(4), vec![row(4); 0], theme::compact())), + draw_table(vec![row(4); 1], 4, true, theme::compact()), concat!("───┬───┬───┬───\n", " 0 │ 1 │ 2 │ 3 \n", "───┴───┴───┴───",) ); assert_eq!( - draw_table(&Table::new(row(0), vec![row(4); 2], theme::compact())), + draw_table(vec![row(4); 1], 4, false, theme::compact()), + concat!("───┬───┬───┬───\n", " 0 │ 1 │ 2 │ 3 \n", "───┴───┴───┴───",) + ); + + assert_eq!( + draw_table(vec![row(4); 2], 4, false, theme::compact()), concat!( "───┬───┬───┬───\n", " 0 │ 1 │ 2 │ 3 \n", @@ -169,20 +190,13 @@ fn test_compact() { ) ); - assert_eq!( - draw_table(&Table::new(row(0), vec![row(0); 0], theme::compact())), - "" - ); + assert_eq!(draw_table(vec![row(4); 0], 4, false, theme::compact()), ""); } #[test] fn test_compact_double() { assert_eq!( - draw_table(&Table::new( - row(4), - vec![row(4); 2], - theme::compact_double() - )), + draw_table(vec![row(4); 3], 4, true, theme::compact_double()), concat!( "═══╦═══╦═══╦═══\n", " 0 ║ 1 ║ 2 ║ 3 \n", @@ -194,11 +208,7 @@ fn test_compact_double() { ); assert_eq!( - draw_table(&Table::new( - row(4), - vec![row(4); 1], - theme::compact_double() - )), + draw_table(vec![row(4); 2], 4, true, theme::compact_double()), concat!( "═══╦═══╦═══╦═══\n", " 0 ║ 1 ║ 2 ║ 3 \n", @@ -209,20 +219,17 @@ fn test_compact_double() { ); assert_eq!( - draw_table(&Table::new( - row(4), - vec![row(4); 0], - theme::compact_double() - )), + draw_table(vec![row(4); 1], 4, true, theme::compact_double()), concat!("═══╦═══╦═══╦═══\n", " 0 ║ 1 ║ 2 ║ 3 \n", "═══╩═══╩═══╩═══",) ); assert_eq!( - draw_table(&Table::new( - row(0), - vec![row(4); 2], - theme::compact_double() - )), + draw_table(vec![row(4); 1], 4, false, theme::compact_double()), + concat!("═══╦═══╦═══╦═══\n", " 0 ║ 1 ║ 2 ║ 3 \n", "═══╩═══╩═══╩═══",) + ); + + assert_eq!( + draw_table(vec![row(4); 2], 4, false, theme::compact_double()), concat!( "═══╦═══╦═══╦═══\n", " 0 ║ 1 ║ 2 ║ 3 \n", @@ -232,11 +239,7 @@ fn test_compact_double() { ); assert_eq!( - draw_table(&Table::new( - row(0), - vec![row(0); 0], - theme::compact_double() - )), + draw_table(vec![row(4); 0], 4, false, theme::compact_double()), "" ); } @@ -244,7 +247,7 @@ fn test_compact_double() { #[test] fn test_heavy() { assert_eq!( - draw_table(&Table::new(row(4), vec![row(4); 2], theme::heavy())), + draw_table(vec![row(4); 3], 4, true, theme::heavy()), "┏━━━┳━━━┳━━━┳━━━┓\n\ ┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃\n\ ┣━━━╋━━━╋━━━╋━━━┫\n\ @@ -254,7 +257,7 @@ fn test_heavy() { ); assert_eq!( - draw_table(&Table::new(row(4), vec![row(4); 1], theme::heavy())), + draw_table(vec![row(4); 2], 4, true, theme::heavy()), "┏━━━┳━━━┳━━━┳━━━┓\n\ ┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃\n\ ┣━━━╋━━━╋━━━╋━━━┫\n\ @@ -263,30 +266,34 @@ fn test_heavy() { ); assert_eq!( - draw_table(&Table::new(row(4), vec![row(4); 0], theme::heavy())), + draw_table(vec![row(4); 1], 4, true, theme::heavy()), "┏━━━┳━━━┳━━━┳━━━┓\n\ ┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃\n\ ┗━━━┻━━━┻━━━┻━━━┛" ); assert_eq!( - draw_table(&Table::new(row(0), vec![row(4); 2], theme::heavy())), + draw_table(vec![row(4); 1], 4, false, theme::heavy()), + "┏━━━┳━━━┳━━━┳━━━┓\n\ + ┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃\n\ + ┗━━━┻━━━┻━━━┻━━━┛" + ); + + assert_eq!( + draw_table(vec![row(4); 2], 4, false, theme::heavy()), "┏━━━┳━━━┳━━━┳━━━┓\n\ ┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃\n\ ┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃\n\ ┗━━━┻━━━┻━━━┻━━━┛" ); - assert_eq!( - draw_table(&Table::new(row(0), vec![row(0); 0], theme::heavy())), - "" - ); + assert_eq!(draw_table(vec![row(4); 0], 4, false, theme::heavy()), ""); } #[test] fn test_light() { assert_eq!( - draw_table(&Table::new(row(4), vec![row(4); 2], theme::light())), + draw_table(vec![row(4); 3], 4, true, theme::light()), concat!( " 0 1 2 3 \n", "───────────────\n", @@ -296,58 +303,62 @@ fn test_light() { ); assert_eq!( - draw_table(&Table::new(row(4), vec![row(4); 1], theme::light())), + draw_table(vec![row(4); 2], 4, true, theme::light()), concat!(" 0 1 2 3 \n", "───────────────\n", " 0 1 2 3 ") ); assert_eq!( - draw_table(&Table::new(row(4), vec![row(4); 0], theme::light())), + draw_table(vec![row(4); 1], 4, true, theme::light()), concat!(" 0 1 2 3 ") ); assert_eq!( - draw_table(&Table::new(row(0), vec![row(4); 2], theme::light())), - concat!(" 0 1 2 3 \n", " 0 1 2 3 ") + draw_table(vec![row(4); 1], 4, false, theme::light()), + concat!(" 0 1 2 3 ") ); assert_eq!( - draw_table(&Table::new(row(0), vec![row(0); 0], theme::light())), - "" + draw_table(vec![row(4); 2], 4, false, theme::light()), + concat!(" 0 1 2 3 \n", " 0 1 2 3 ") ); + + assert_eq!(draw_table(vec![row(4); 0], 4, true, theme::light()), ""); } #[test] fn test_none() { assert_eq!( - draw_table(&Table::new(row(4), vec![row(4); 2], theme::none())), + draw_table(vec![row(4); 3], 4, true, theme::none()), concat!(" 0 1 2 3 \n", " 0 1 2 3 \n", " 0 1 2 3 ") ); assert_eq!( - draw_table(&Table::new(row(4), vec![row(4); 1], theme::none())), + draw_table(vec![row(4); 2], 4, true, theme::none()), concat!(" 0 1 2 3 \n", " 0 1 2 3 ") ); assert_eq!( - draw_table(&Table::new(row(4), vec![row(4); 0], theme::none())), + draw_table(vec![row(4); 1], 4, true, theme::none()), concat!(" 0 1 2 3 ") ); assert_eq!( - draw_table(&Table::new(row(0), vec![row(4); 2], theme::none())), - concat!(" 0 1 2 3 \n", " 0 1 2 3 ") + draw_table(vec![row(4); 1], 4, false, theme::none()), + concat!(" 0 1 2 3 ") ); assert_eq!( - draw_table(&Table::new(row(0), vec![row(0); 0], theme::none())), - "" + draw_table(vec![row(4); 2], 4, true, theme::none()), + concat!(" 0 1 2 3 \n", " 0 1 2 3 ") ); + + assert_eq!(draw_table(vec![row(4); 0], 4, true, theme::none()), ""); } #[test] fn test_thin() { assert_eq!( - draw_table(&Table::new(row(4), vec![row(4); 2], theme::thin())), + draw_table(vec![row(4); 3], 4, true, theme::thin()), "┌───┬───┬───┬───┐\n\ │ 0 │ 1 │ 2 │ 3 │\n\ ├───┼───┼───┼───┤\n\ @@ -358,7 +369,7 @@ fn test_thin() { ); assert_eq!( - draw_table(&Table::new(row(4), vec![row(4); 1], theme::thin())), + draw_table(vec![row(4); 2], 4, true, theme::thin()), "┌───┬───┬───┬───┐\n\ │ 0 │ 1 │ 2 │ 3 │\n\ ├───┼───┼───┼───┤\n\ @@ -367,14 +378,21 @@ fn test_thin() { ); assert_eq!( - draw_table(&Table::new(row(4), vec![row(4); 0], theme::thin())), + draw_table(vec![row(4); 1], 4, true, theme::thin()), "┌───┬───┬───┬───┐\n\ │ 0 │ 1 │ 2 │ 3 │\n\ └───┴───┴───┴───┘" ); assert_eq!( - draw_table(&Table::new(row(0), vec![row(4); 2], theme::thin())), + draw_table(vec![row(4); 1], 4, false, theme::thin()), + "┌───┬───┬───┬───┐\n\ + │ 0 │ 1 │ 2 │ 3 │\n\ + └───┴───┴───┴───┘" + ); + + assert_eq!( + draw_table(vec![row(4); 2], 4, false, theme::thin()), "┌───┬───┬───┬───┐\n\ │ 0 │ 1 │ 2 │ 3 │\n\ ├───┼───┼───┼───┤\n\ @@ -382,16 +400,13 @@ fn test_thin() { └───┴───┴───┴───┘" ); - assert_eq!( - draw_table(&Table::new(row(0), vec![row(0); 0], theme::thin())), - "" - ); + assert_eq!(draw_table(vec![row(4); 0], 4, true, theme::thin()), ""); } #[test] fn test_with_love() { assert_eq!( - draw_table(&Table::new(row(4), vec![row(4); 2], theme::with_love())), + draw_table(vec![row(4); 3], 4, true, theme::with_love()), concat!( "❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤\n", " 0 ❤ 1 ❤ 2 ❤ 3 \n", @@ -403,7 +418,7 @@ fn test_with_love() { ); assert_eq!( - draw_table(&Table::new(row(4), vec![row(4); 1], theme::with_love())), + draw_table(vec![row(4); 2], 4, true, theme::with_love()), concat!( "❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤\n", " 0 ❤ 1 ❤ 2 ❤ 3 \n", @@ -414,12 +429,17 @@ fn test_with_love() { ); assert_eq!( - draw_table(&Table::new(row(4), vec![row(4); 0], theme::with_love())), + draw_table(vec![row(4); 1], 4, true, theme::with_love()), concat!("❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤\n", " 0 ❤ 1 ❤ 2 ❤ 3 \n", "❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤",) ); assert_eq!( - draw_table(&Table::new(row(0), vec![row(4); 2], theme::with_love())), + draw_table(vec![row(4); 1], 4, false, theme::with_love()), + concat!("❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤\n", " 0 ❤ 1 ❤ 2 ❤ 3 \n", "❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤",) + ); + + assert_eq!( + draw_table(vec![row(4); 2], 4, false, theme::with_love()), concat!( "❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤\n", " 0 ❤ 1 ❤ 2 ❤ 3 \n", @@ -428,26 +448,31 @@ fn test_with_love() { ) ); - assert_eq!( - draw_table(&Table::new(row(0), vec![row(0); 0], theme::with_love())), - "" - ); + assert_eq!(draw_table(vec![row(4); 0], 4, true, theme::with_love()), ""); } -fn draw_table(table: &Table) -> String { +fn draw_table( + data: Vec, TextStyle>>>, + count_columns: usize, + with_header: bool, + theme: theme, +) -> String { + let size = (data.len(), count_columns); + let table = Table::new(data, size, usize::MAX, with_header, false); + let cfg = Config::default(); let styles = HashMap::default(); let alignments = Alignments::default(); table - .draw_table(&cfg, &styles, alignments, std::usize::MAX) + .draw_table(&cfg, &styles, alignments, &theme, std::usize::MAX) .expect("Unexpectdly got no table") } -fn row(count_columns: usize) -> Vec { +fn row(count_columns: usize) -> Vec, TextStyle>> { let mut row = Vec::with_capacity(count_columns); for i in 0..count_columns { - row.push(StyledString::new(i.to_string(), TextStyle::default())); + row.push(Table::create_cell(i.to_string(), TextStyle::default())); } row diff --git a/out.log b/out.log new file mode 100644 index 0000000000..8f98aadfbd --- /dev/null +++ b/out.log @@ -0,0 +1,7 @@ +String { + val: "\u{1b}[35m╭────┬────────────────────────────────────────┬──────┬───────────┬──────────────╮\u{1b}[39m\n\u{1b}[35m│\u{1b}[39m \u{1b}[1;32m#\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[1;32mname\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[1;32mtype\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[1;32msize\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[1;32mmodified\u{1b}[0m \u{1b}[35m│\u{1b}[39m\n\u{1b}[35m├────┼────────────────────────────────────────┼──────┼───────────┼──────────────┤\u{1b}[39m\n\u{1b}[35m│\u{1b}[39m \u{1b}[1;36m0\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37m\u{1b}[38;5;185m\u{1b}]8;;file:///home/maxim/trash/nushell/CODE_OF_CONDUCT.md\u{1b}\\CODE_OF_CONDUCT.md\u{1b}]8;;\u{1b}\\\u{1b}[39m\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37mfile\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[36m3.4 KiB\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[2;37ma week ago\u{1b}[0m \u{1b}[35m│\u{1b}[39m\n\u{1b}[35m│\u{1b}[39m \u{1b}[1;36m1\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37m\u{1b}[38;5;185m\u{1b}]8;;file:///home/maxim/trash/nushell/CONTRIBUTING.md\u{1b}\\CONTRIBUTING.md\u{1b}]8;;\u{1b}\\\u{1b}[39m\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37mfile\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[36m1.8 KiB\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[2;37ma week ago\u{1b}[0m \u{1b}[35m│\u{1b}[39m\n\u{1b}[35m│\u{1b}[39m \u{1b}[1;36m2\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37m\u{1b}[38;5;243m\u{1b}]8;;file:///home/maxim/trash/nushell/Cargo.lock\u{1b}\\Cargo.lock\u{1b}]8;;\u{1b}\\\u{1b}[39m\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37mfile\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[36m139.0 KiB\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[2;37ma week ago\u{1b}[0m \u{1b}[35m│\u{1b}[39m\n\u{1b}[35m│\u{1b}[39m \u{1b}[1;36m3\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37m\u{1b}[38;5;149m\u{1b}]8;;file:///home/maxim/trash/nushell/Cargo.toml\u{1b}\\Cargo.toml\u{1b}]8;;\u{1b}\\\u{1b}[39m\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37mfile\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[36m3.8 KiB\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[2;37ma week ago\u{1b}[0m \u{1b}[35m│\u{1b}[39m\n\u{1b}[35m│\u{1b}[39m \u{1b}[1;36m4\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37m\u{1b}[38;5;249m\u{1b}]8;;file:///home/maxim/trash/nushell/LICENSE\u{1b}\\LICENSE\u{1b}]8;;\u{1b}\\\u{1b}[39m\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37mfile\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[36m1.1 KiB\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[2;37ma week ago\u{1b}[0m \u{1b}[35m│\u{1b}[39m\n\u{1b}[35m│\u{1b}[39m \u{1b}[1;36m5\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37m\u{1b}[48;5;186m\u{1b}[38;5;16m\u{1b}]8;;file:///home/maxim/trash/nushell/README.md\u{1b}\\README.md\u{1b}]8;;\u{1b}\\\u{1b}[49m\u{1b}[39m\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37mfile\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[36m12.8 KiB\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[2;37ma week ago\u{1b}[0m \u{1b}[35m│\u{1b}[39m\n\u{1b}[35m│\u{1b}[39m \u{1b}[1;36m6\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37m\u{1b}[38;5;185m\u{1b}]8;;file:///home/maxim/trash/nushell/README.release.txt\u{1b}\\README.release.txt\u{1b}]8;;\u{1b}\\\u{1b}[39m\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37mfile\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[36m132 B\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[2;37ma week ago\u{1b}[0m \u{1b}[35m│\u{1b}[39m\n\u{1b}[35m│\u{1b}[39m \u{1b}[1;36m7\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37m\u{1b}[38;5;203m\u{1b}[4m\u{1b}]8;;file:///home/maxim/trash/nushell/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.zip\u{1b}\\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.zip\u{1b}]8;;\u{1b}\\\u{1b}[0m\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37mfile\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[36m0 B\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[2;37ma minute ago\u{1b}[0m \u{1b}[35m│\u{1b}[39m\n\u{1b}[35m│\u{1b}[39m \u{1b}[1;36m8\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37m\u{1b}[38;5;81m\u{1b}]8;;file:///home/maxim/trash/nushell/assets\u{1b}\\assets\u{1b}]8;;\u{1b}\\\u{1b}[39m\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37mdir\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[36m4.0 KiB\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[2;37ma week ago\u{1b}[0m \u{1b}[35m│\u{1b}[39m\n\u{1b}[35m│\u{1b}[39m \u{1b}[1;36m9\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37m\u{1b}[38;5;203m\u{1b}[1m\u{1b}]8;;file:///home/maxim/trash/nushell/build-all-maclin.sh\u{1b}\\build-all-maclin.sh\u{1b}]8;;\u{1b}\\\u{1b}[0m\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37mfile\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[36m594 B\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[2;37ma week ago\u{1b}[0m \u{1b}[35m│\u{1b}[39m\n\u{1b}[35m│\u{1b}[39m \u{1b}[1;36m10\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37m\u{1b}]8;;file:///home/maxim/trash/nushell/build-all-windows.cmd\u{1b}\\build-all-windows.cmd\u{1b}]8;;\u{1b}\\\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37mfile\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[36m757 B\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[2;37ma week ago\u{1b}[0m \u{1b}[35m│\u{1b}[39m\n\u{1b}[35m│\u{1b}[39m \u{1b}[1;36m11\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37m\u{1b}]8;;file:///home/maxim/trash/nushell/build-all.nu\u{1b}\\build-all.nu\u{1b}]8;;\u{1b}\\\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37mfile\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[36m605 B\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[2;37ma week ago\u{1b}[0m \u{1b}[35m│\u{1b}[39m\n\u{1b}[35m│\u{1b}[39m \u{1b}[1;36m12\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37m\u{1b}[38;5;48m\u{1b}]8;;file:///home/maxim/trash/nushell/build.rs\u{1b}\\build.rs\u{1b}]8;;\u{1b}\\\u{1b}[39m\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37mfile\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[36m381 B\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[2;37ma week ago\u{1b}[0m \u{1b}[35m│\u{1b}[39m\n\u{1b}[35m│\u{1b}[39m \u{1b}[1;36m13\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37m\u{1b}[38;5;81m\u{1b}]8;;file:///home/maxim/trash/nushell/crates\u{1b}\\crates\u{1b}]8;;\u{1b}\\\u{1b}[39m\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37mdir\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[36m4.0 KiB\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[2;37ma week ago\u{1b}[0m \u{1b}[35m│\u{1b}[39m\n\u{1b}[35m│\u{1b}[39m \u{1b}[1;36m14\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37m\u{1b}[38;5;81m\u{1b}]8;;file:///home/maxim/trash/nushell/docker\u{1b}\\docker\u{1b}]8;;\u{1b}\\\u{1b}[39m\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37mdir\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[36m4.0 KiB\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[2;37ma week ago\u{1b}[0m \u{1b}[35m│\u{1b}[39m\n\u{1b}[35m│\u{1b}[39m \u{1b}[1;36m15\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37m\u{1b}[38;5;81m\u{1b}]8;;file:///home/maxim/trash/nushell/docs\u{1b}\\docs\u{1b}]8;;\u{1b}\\\u{1b}[39m\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37mdir\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[36m4.0 KiB\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[2;37ma week ago\u{1b}[0m \u{1b}[35m│\u{1b}[39m\n\u{1b}[35m│\u{1b}[39m \u{1b}[1;36m16\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37m\u{1b}[38;5;81m\u{1b}]8;;file:///home/maxim/trash/nushell/images\u{1b}\\images\u{1b}]8;;\u{1b}\\\u{1b}[39m\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37mdir\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[36m4.0 KiB\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[2;37ma week ago\u{1b}[0m \u{1b}[35m│\u{1b}[39m\n\u{1b}[35m│\u{1b}[39m \u{1b}[1;36m17\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37m\u{1b}[38;5;48m\u{1b}]8;;file:///home/maxim/trash/nushell/install-all.ps1\u{1b}\\install-all.ps1\u{1b}]8;;\u{1b}\\\u{1b}[39m\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37mfile\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[36m955 B\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[2;37ma week ago\u{1b}[0m \u{1b}[35m│\u{1b}[39m\n\u{1b}[35m│\u{1b}[39m \u{1b}[1;36m18\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37m\u{1b}[38;5;203m\u{1b}[1m\u{1b}]8;;file:///home/maxim/trash/nushell/install-all.sh\u{1b}\\install-all.sh\u{1b}]8;;\u{1b}\\\u{1b}[0m\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37mfile\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[36m848 B\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[2;37ma week ago\u{1b}[0m \u{1b}[35m│\u{1b}[39m\n\u{1b}[35m│\u{1b}[39m \u{1b}[1;36m19\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37m\u{1b}[38;5;81m\u{1b}]8;;file:///home/maxim/trash/nushell/pkg_mgrs\u{1b}\\pkg_mgrs\u{1b}]8;;\u{1b}\\\u{1b}[39m\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37mdir\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[36m4.0 KiB\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[2;37ma week ago\u{1b}[0m \u{1b}[35m│\u{1b}[39m\n\u{1b}[35m│\u{1b}[39m \u{1b}[1;36m20\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37m\u{1b}]8;;file:///home/maxim/trash/nushell/register-plugins.nu\u{1b}\\register-plugins.nu\u{1b}]8;;\u{1b}\\\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37mfile\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[36m1.1 KiB\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[2;37ma week ago\u{1b}[0m \u{1b}[35m│\u{1b}[39m\n\u{1b}[35m│\u{1b}[39m \u{1b}[1;36m21\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37m\u{1b}[38;5;149m\u{1b}]8;;file:///home/maxim/trash/nushell/rust-toolchain.toml\u{1b}\\rust-toolchain.toml\u{1b}]8;;\u{1b}\\\u{1b}[39m\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37mfile\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[36m1.1 KiB\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[2;37ma week ago\u{1b}[0m \u{1b}[35m│\u{1b}[39m\n\u{1b}[35m│\u{1b}[39m \u{1b}[1;36m22\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37m\u{1b}[38;5;81m\u{1b}]8;;file:///home/maxim/trash/nushell/samples\u{1b}\\samples\u{1b}]8;;\u{1b}\\\u{1b}[39m\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37mdir\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[36m4.0 KiB\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[2;37ma week ago\u{1b}[0m \u{1b}[35m│\u{1b}[39m\n\u{1b}[35m│\u{1b}[39m \u{1b}[1;36m23\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37m\u{1b}[38;5;81m\u{1b}]8;;file:///home/maxim/trash/nushell/src\u{1b}\\src\u{1b}]8;;\u{1b}\\\u{1b}[39m\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37mdir\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[36m4.0 KiB\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[2;37ma week ago\u{1b}[0m \u{1b}[35m│\u{1b}[39m\n\u{1b}[35m│\u{1b}[39m \u{1b}[1;36m24\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37m\u{1b}[38;5;81m\u{1b}]8;;file:///home/maxim/trash/nushell/target\u{1b}\\target\u{1b}]8;;\u{1b}\\\u{1b}[39m\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37mdir\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[36m4.0 KiB\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[2;37ma week ago\u{1b}[0m \u{1b}[35m│\u{1b}[39m\n\u{1b}[35m│\u{1b}[39m \u{1b}[1;36m25\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37m\u{1b}[38;5;81m\u{1b}]8;;file:///home/maxim/trash/nushell/tests\u{1b}\\tests\u{1b}]8;;\u{1b}\\\u{1b}[39m\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37mdir\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[36m4.0 KiB\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[2;37ma week ago\u{1b}[0m \u{1b}[35m│\u{1b}[39m\n\u{1b}[35m│\u{1b}[39m \u{1b}[1;36m26\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37m\u{1b}[38;5;203m\u{1b}[1m\u{1b}]8;;file:///home/maxim/trash/nushell/uninstall-all.sh\u{1b}\\uninstall-all.sh\u{1b}]8;;\u{1b}\\\u{1b}[0m\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37mfile\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[36m374 B\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[2;37ma week ago\u{1b}[0m \u{1b}[35m│\u{1b}[39m\n\u{1b}[35m│\u{1b}[39m \u{1b}[1;36m27\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37m\u{1b}[38;5;81m\u{1b}]8;;file:///home/maxim/trash/nushell/wix\u{1b}\\wix\u{1b}]8;;\u{1b}\\\u{1b}[39m\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[37mdir\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[36m4.0 KiB\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[2;37ma week ago\u{1b}[0m \u{1b}[35m│\u{1b}[39m\n\u{1b}[35m├────┼────────────────────────────────────────┼──────┼───────────┼──────────────┤\u{1b}[39m\n\u{1b}[35m│\u{1b}[39m \u{1b}[1;32m#\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[1;32mname\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[1;32mtype\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[1;32msize\u{1b}[0m \u{1b}[35m│\u{1b}[39m \u{1b}[1;32mmodified\u{1b}[0m \u{1b}[35m│\u{1b}[39m\n\u{1b}[35m╰────┴────────────────────────────────────────┴──────┴───────────┴──────────────╯\u{1b}[39m", + span: Span { + start: 22121, + end: 22126, + }, +} \ No newline at end of file