Switch --list-meta to --list-format

This commit is contained in:
Andrew Phillips
2023-09-20 18:58:58 +00:00
parent c100ef9436
commit 97670b1860

View File

@@ -135,9 +135,9 @@ struct OptionsArgs {
#[arg(help("Specify the directory to use for storage"))] #[arg(help("Specify the directory to use for storage"))]
dir: Option<PathBuf>, dir: Option<PathBuf>,
#[arg(long, env("KEEP_LIST_META"), default_value("hostname"))] #[arg(long, env("KEEP_LIST_FORMAT"), default_value("id,time,size,tags,meta:hostname"))]
#[arg(help("A comma separated list of item metadata names to display with --list"))] #[arg(help("A comma separated list of columns to display with --list"))]
list_meta: String, list_format: String,
#[arg(short, long, action = clap::ArgAction::Count, conflicts_with("quiet"))] #[arg(short, long, action = clap::ArgAction::Count, conflicts_with("quiet"))]
#[arg(help("Increase message verbosity, can be given more than once"))] #[arg(help("Increase message verbosity, can be given more than once"))]
@@ -190,12 +190,25 @@ enum NumberOrString {
impl FromStr for NumberOrString { impl FromStr for NumberOrString {
type Err = Error; type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> { fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok (s.parse::<i64>() Ok(s.parse::<i64>()
.map(NumberOrString::Number) .map(NumberOrString::Number)
.unwrap_or_else(|_| NumberOrString::Str (s.to_string()))) .unwrap_or_else(|_| NumberOrString::Str(s.to_string())))
} }
} }
#[derive(Debug, Eq, PartialEq, Clone, strum::EnumIter, strum::Display, strum::EnumString)]
#[strum(ascii_case_insensitive)]
pub enum ColumnType {
Id,
Time,
Size,
Compression,
FileSize,
FilePath,
Tags,
Meta
}
fn main() -> Result<(), Error> { fn main() -> Result<(), Error> {
let proj_dirs = ProjectDirs::from("gt0.ca", "Andrew Phillips", "Keep"); let proj_dirs = ProjectDirs::from("gt0.ca", "Andrew Phillips", "Keep");
@@ -489,56 +502,91 @@ fn mode_list(cmd: &mut Command, args: Args, ids: &mut Vec<i64>, tags: &Vec<Strin
meta_by_item.insert(item_id, item_meta); meta_by_item.insert(item_id, item_meta);
}; };
let meta_columns = args.options.list_meta.split(",");
let mut table = Table::new(); let mut table = Table::new();
table.set_format(*format::consts::FORMAT_CLEAN); table.set_format(*format::consts::FORMAT_CLEAN);
let mut title_row = row!( let list_format = args.options.list_format.split(",");
b->"ID",
b->"Time",
b->"Stream Size",
b->"Comp",
b->"File Size",
b->"Tags",
);
for name in meta_columns.clone() { let mut title_row = row!();
title_row.add_cell(Cell::new(name).with_style(Attr::Bold));
for column in list_format.clone() {
let mut column_format = column.split(":").into_iter();
let column_name = column_format.next().expect("Unable to parse column name");
let column_type = ColumnType::from_str(column_name.clone()).expect(format!("Unknown column {:?}", column_name).as_str());
if column_type == ColumnType::Meta {
let meta_name = column_format.next().expect("Unable to parse metadata name for meta column");
title_row.add_cell(Cell::new(meta_name).with_style(Attr::Bold));
} else {
title_row.add_cell(Cell::new(&column_type.to_string()).with_style(Attr::Bold));
}
} }
table.set_titles(title_row); table.set_titles(title_row);
for item in items { for item in items {
let item_id = item.id.unwrap(); let item_id = item.id.unwrap();
let tags = tags_by_item.get(&item_id).unwrap();
let meta = meta_by_item.get(&item_id).unwrap();
let mut item_path = data_path.clone(); let mut item_path = data_path.clone();
item_path.push(item.id.unwrap().to_string()); item_path.push(item.id.unwrap().to_string());
let id_cell = Cell::new_align(&item.id.unwrap_or(0).to_string(), Alignment::RIGHT); let mut table_row = Row::new(vec![]);
let ts_cell = Cell::new(&item.ts.with_timezone(&Local).format("%F %T").to_string());
let size_cell = match item.size {
Some(size) => Cell::new_align(format_size(size as u64, BINARY).as_str(), Alignment::RIGHT),
None => Cell::new_align("Missing", Alignment::RIGHT).with_style(Attr::ForegroundColor(color::RED)).with_style(Attr::Bold)
};
let compression_cell = Cell::new(&item.compression);
let file_size_cell = match item_path.metadata() {
Ok(metadata) => Cell::new_align(format_size(metadata.len(), BINARY).as_str(), Alignment::RIGHT),
Err(_) => Cell::new_align("Missing", Alignment::RIGHT).with_style(Attr::ForegroundColor(color::RED)).with_style(Attr::Bold)
};
let item_tags = tags_by_item.get(&item_id).unwrap(); for column in list_format.clone() {
let tags_cell = Cell::new(&item_tags.join(" ")); let mut column_format = column.split(":").into_iter();
let column_name = column_format.next().expect("Unable to parse column name");
let column_type = ColumnType::from_str(column_name.clone()).expect(format!("Unknown column {:?}", column_name).as_str());
let mut meta_name: Option<&str> = None;
let mut table_row = Row::new(vec![id_cell,ts_cell,size_cell, compression_cell, file_size_cell, tags_cell]); if column_type == ColumnType::Meta {
meta_name = column_format.next();
}
let item_meta = meta_by_item.get(&item_id).unwrap(); let column_width: usize = match column_format.next() {
for name in meta_columns.clone() { Some(len) => len.parse().unwrap_or(0),
match item_meta.get(name) { None => 0
Some(value) => table_row.add_cell(Cell::new(value)),
None => table_row.add_cell(Cell::new(""))
}; };
}
let cell = match column_type {
ColumnType::Id => Cell::new_align(
truncate_column(&item.id.unwrap_or(0).to_string(), column_width),
Alignment::RIGHT),
ColumnType::Time => Cell::new(
truncate_column(&item.ts.with_timezone(&Local).format("%F %T").to_string(), column_width)),
ColumnType::Size => match item.size {
Some(size) => Cell::new_align(
truncate_column(format_size(size as u64, BINARY).as_str(), column_width),
Alignment::RIGHT),
None => match item_path.metadata() {
Ok(_) => Cell::new_align("Unknown", Alignment::RIGHT)
.with_style(Attr::ForegroundColor(color::YELLOW))
.with_style(Attr::Bold),
Err(_) => Cell::new_align("Missing", Alignment::RIGHT)
.with_style(Attr::ForegroundColor(color::RED))
.with_style(Attr::Bold)
}
},
ColumnType::Compression => Cell::new(truncate_column(&item.compression, column_width)),
ColumnType::FileSize => match item_path.metadata() {
Ok(metadata) => Cell::new_align(
truncate_column(format_size(metadata.len(), BINARY).as_str(), column_width),
Alignment::RIGHT),
Err(_) => Cell::new_align("Missing", Alignment::RIGHT)
.with_style(Attr::ForegroundColor(color::RED)).with_style(Attr::Bold)
},
ColumnType::FilePath => Cell::new(truncate_column(&item_path.clone().into_os_string().into_string().unwrap(), column_width)),
ColumnType::Tags => Cell::new(truncate_column(tags.join(" ").as_str(), column_width)),
ColumnType::Meta => match meta_name {
Some(meta_name) => match meta.get(meta_name) {
Some(meta_value) => Cell::new(truncate_column(meta_value, column_width)),
None => Cell::new("")
},
None => Cell::new("")
}
};
table_row.add_cell(cell);
}
table.add_row(table_row); table.add_row(table_row);
} }
@@ -814,3 +862,14 @@ fn get_meta_from_env() -> HashMap<String,String> {
} }
meta_env meta_env
} }
fn truncate_column(s: &str, column_width: usize) -> &str {
if column_width > 0 {
match s.char_indices().nth(column_width) {
None => s,
Some((idx, _)) => &s[..idx],
}
} else {
s
}
}