cli: Improve pretty mode table

This commit is contained in:
wyhaya
2025-02-09 00:01:07 +08:00
parent a1a9218131
commit e9046fef78
3 changed files with 77 additions and 86 deletions

70
Cargo.lock generated
View File

@@ -399,29 +399,6 @@ version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
[[package]]
name = "cli-table"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b53f9241f288a7b12c56565f04aaeaeeab6b8923d42d99255d4ca428b4d97f89"
dependencies = [
"cli-table-derive",
"csv",
"termcolor",
"unicode-width",
]
[[package]]
name = "cli-table-derive"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e83a93253aaae7c74eb7428ce4faa6e219ba94886908048888701819f82fb94"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "clipboard-win"
version = "4.5.0"
@@ -449,6 +426,17 @@ dependencies = [
"memchr",
]
[[package]]
name = "comfy-table"
version = "7.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a65ebfec4fb190b6f90e944a817d60499ee0744e582530e2c9900a22e591d9a"
dependencies = [
"crossterm",
"unicode-segmentation",
"unicode-width 0.2.0",
]
[[package]]
name = "comma"
version = "1.0.0"
@@ -595,6 +583,28 @@ version = "0.8.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
[[package]]
name = "crossterm"
version = "0.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6"
dependencies = [
"bitflags 2.8.0",
"crossterm_winapi",
"parking_lot",
"rustix",
"winapi",
]
[[package]]
name = "crossterm_winapi"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b"
dependencies = [
"winapi",
]
[[package]]
name = "crunchy"
version = "0.2.2"
@@ -1564,7 +1574,7 @@ version = "0.0.14"
dependencies = [
"anyhow",
"clap",
"cli-table",
"comfy-table",
"csv",
"ctrlc",
"dirs",
@@ -1848,7 +1858,7 @@ dependencies = [
"terminal_size",
"textwrap",
"thiserror 1.0.69",
"unicode-width",
"unicode-width 0.1.14",
]
[[package]]
@@ -2704,7 +2714,7 @@ dependencies = [
"radix_trie",
"scopeguard",
"unicode-segmentation",
"unicode-width",
"unicode-width 0.1.14",
"utf8parse",
"winapi",
]
@@ -3033,7 +3043,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9"
dependencies = [
"unicode-linebreak",
"unicode-width",
"unicode-width 0.1.14",
]
[[package]]
@@ -3201,6 +3211,12 @@ version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
[[package]]
name = "unicode-width"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd"
[[package]]
name = "unindent"
version = "0.2.3"

View File

@@ -21,7 +21,7 @@ path = "main.rs"
[dependencies]
anyhow = "1.0.75"
clap = { version = "4.5", features = ["derive"] }
cli-table = "0.4.7"
comfy-table = "7.1.4"
dirs = "5.0.1"
env_logger = "0.10.1"
limbo_core = { path = "../core" }

View File

@@ -2,8 +2,7 @@ use crate::{
import::{ImportFile, IMPORT_HELP},
opcodes_dictionary::OPCODE_DESCRIPTIONS,
};
use cli_table::format::{Border, HorizontalLine, Separator, VerticalLine};
use cli_table::{Cell, Style, Table};
use comfy_table::{Attribute, Cell, CellAlignment, ContentArrangement, Row, Table};
use limbo_core::{Database, LimboError, Statement, StepResult, Value};
use clap::{Parser, ValueEnum};
@@ -670,35 +669,42 @@ impl Limbo {
println!("Query interrupted.");
return Ok(());
}
let mut table_rows: Vec<Vec<_>> = vec![];
let mut table = Table::new();
table
.set_content_arrangement(ContentArrangement::Dynamic)
.set_truncation_indicator("")
.apply_modifier("││──├─┼┤│─┼├┤┬┴┌┐└┘");
if rows.num_columns() > 0 {
let columns = (0..rows.num_columns())
let header = (0..rows.num_columns())
.map(|i| {
rows.get_column_name(i)
.map(|name| name.cell().bold(true))
.unwrap_or_else(|| " ".cell())
let name = rows.get_column_name(i).cloned().unwrap_or_default();
Cell::new(name).add_attribute(Attribute::Bold)
})
.collect::<Vec<_>>();
table_rows.push(columns);
table.set_header(header);
}
loop {
match rows.step() {
Ok(StepResult::Row) => {
let row = rows.row().unwrap();
table_rows.push(
row.values
.iter()
.map(|value| match value.to_value() {
Value::Null => self.opts.null_value.clone().cell(),
Value::Integer(i) => i.to_string().cell(),
Value::Float(f) => f.to_string().cell(),
Value::Text(s) => s.cell(),
Value::Blob(b) => {
format!("{}", String::from_utf8_lossy(b)).cell()
}
})
.collect(),
);
let record = rows.row().unwrap();
let mut row = Row::new();
row.max_height(1);
for value in &record.values {
let (content, alignment) = match value.to_value() {
Value::Null => {
(self.opts.null_value.clone(), CellAlignment::Left)
}
Value::Integer(i) => (i.to_string(), CellAlignment::Right),
Value::Float(f) => (f.to_string(), CellAlignment::Right),
Value::Text(s) => (s.to_string(), CellAlignment::Left),
Value::Blob(b) => (
String::from_utf8_lossy(b).to_string(),
CellAlignment::Left,
),
};
row.add_cell(Cell::new(content).set_alignment(alignment));
}
table.add_row(row);
}
Ok(StepResult::IO) => {
self.io.run_once()?;
@@ -718,7 +724,10 @@ impl Limbo {
}
}
}
self.print_table(table_rows);
if table.header().is_some() {
let _ = self.write_fmt(format_args!("{}", table));
}
}
},
Ok(None) => {}
@@ -734,40 +743,6 @@ impl Limbo {
Ok(())
}
fn print_table(&mut self, table_rows: Vec<Vec<cli_table::CellStruct>>) {
if table_rows.is_empty() {
return;
}
let horizontal_line = HorizontalLine::new('┌', '┐', '┬', '─');
let horizontal_line_mid = HorizontalLine::new('├', '┤', '┼', '─');
let horizontal_line_bottom = HorizontalLine::new('└', '┘', '┴', '─');
let vertical_line = VerticalLine::new('│');
let border = Border::builder()
.top(horizontal_line)
.bottom(horizontal_line_bottom)
.left(vertical_line.clone())
.right(vertical_line.clone())
.build();
let separator = Separator::builder()
.column(Some(vertical_line))
.row(Some(horizontal_line_mid))
.build();
if let Ok(table) = table_rows
.table()
.border(border)
.separator(separator)
.display()
{
let _ = self.write_fmt(format_args!("{}", table));
} else {
let _ = self.writeln("Error displaying table.");
}
}
fn display_schema(&mut self, table: Option<&str>) -> anyhow::Result<()> {
let sql = match table {
Some(table_name) => format!(