refactor
This commit is contained in:
parent
8d8d90efd1
commit
8ea359d6df
5 changed files with 243 additions and 208 deletions
113
src/args.rs
113
src/args.rs
|
@ -1,6 +1,117 @@
|
|||
use clap::{arg, command, ArgMatches};
|
||||
|
||||
pub fn get_args() -> ArgMatches {
|
||||
use crate::quit_err;
|
||||
|
||||
pub struct Args {
|
||||
pub root_dir: String,
|
||||
pub output_json: bool,
|
||||
pub no_header: bool,
|
||||
pub limit: usize,
|
||||
pub offset: usize,
|
||||
pub ignoretags: bool,
|
||||
pub sort_by: Option<String>,
|
||||
pub group_by: Option<String>,
|
||||
pub reversed: bool,
|
||||
pub columns: Vec<String>,
|
||||
pub headers: Vec<String>,
|
||||
pub filters: serde_json::Value,
|
||||
}
|
||||
|
||||
pub fn get_args() -> Args {
|
||||
let args = get_args_match();
|
||||
|
||||
let root_dir = args.get_one::<String>("dir").unwrap();
|
||||
|
||||
let output_json = args.get_flag("json");
|
||||
|
||||
let no_header = args.get_flag("noheader");
|
||||
|
||||
let limit: usize = args
|
||||
.get_one::<String>("limit")
|
||||
.unwrap()
|
||||
.parse()
|
||||
.unwrap_or_else(|e| quit_err(e, "Limit is not a number"));
|
||||
|
||||
let offset: usize = args
|
||||
.get_one::<String>("offset")
|
||||
.unwrap()
|
||||
.parse()
|
||||
.unwrap_or_else(|e| quit_err(e, "Offset is not a number"));
|
||||
|
||||
let ignoretags: bool = args.get_flag("ignoretags");
|
||||
|
||||
let sort_by = args
|
||||
.get_one::<String>("sortby")
|
||||
.map(std::borrow::ToOwned::to_owned);
|
||||
|
||||
let group_by = args
|
||||
.get_one::<String>("groupby")
|
||||
.map(std::borrow::ToOwned::to_owned);
|
||||
|
||||
let reversed = args.get_flag("reverse");
|
||||
|
||||
let columns: Vec<_> = args
|
||||
.get_many::<String>("column")
|
||||
.unwrap()
|
||||
.cloned()
|
||||
.collect();
|
||||
log::debug!("columns: {columns:?}");
|
||||
|
||||
let (columns, headers): (Vec<_>, Vec<_>) = columns
|
||||
.into_iter()
|
||||
.map(|x| {
|
||||
let (column, header_rename) = x.split_once(':').unwrap_or((&x, &x));
|
||||
|
||||
(column.to_owned(), header_rename.to_owned())
|
||||
})
|
||||
.unzip();
|
||||
|
||||
if columns != headers {
|
||||
log::debug!("renamed headers: {headers:?}");
|
||||
}
|
||||
|
||||
let filters = args
|
||||
.get_many::<String>("filter")
|
||||
.map_or_else(std::vec::Vec::new, std::iter::Iterator::collect);
|
||||
|
||||
log::debug!("raw filters: {filters:?}");
|
||||
|
||||
let filters = if filters.len() == 1 {
|
||||
let filter = filters.first().unwrap();
|
||||
serde_json::from_str(filter)
|
||||
.unwrap_or_else(|e| quit_err(e, &format!("filter '{filter}' could not be parsed")))
|
||||
} else {
|
||||
let filters: Vec<_> = filters
|
||||
.iter()
|
||||
.map(|x| {
|
||||
serde_json::from_str::<serde_json::Value>(x)
|
||||
.unwrap_or_else(|e| quit_err(e, &format!("filter '{x}' could not be parsed")))
|
||||
})
|
||||
.collect();
|
||||
serde_json::json!({
|
||||
"$and": filters
|
||||
})
|
||||
};
|
||||
|
||||
log::debug!("parsed filters: {filters:?}");
|
||||
|
||||
Args {
|
||||
root_dir: root_dir.to_string(),
|
||||
output_json,
|
||||
no_header,
|
||||
limit,
|
||||
offset,
|
||||
ignoretags,
|
||||
sort_by,
|
||||
group_by,
|
||||
reversed,
|
||||
columns,
|
||||
headers,
|
||||
filters,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_args_match() -> ArgMatches {
|
||||
command!()
|
||||
.about("Query markdown files")
|
||||
.arg(arg!([dir] "Directory to scan").required(true))
|
||||
|
|
19
src/lib.rs
19
src/lib.rs
|
@ -106,7 +106,7 @@ impl Index {
|
|||
.as_mapping()
|
||||
.unwrap()
|
||||
.get("tags")
|
||||
.map(|x| x.as_sequence().unwrap().clone())
|
||||
.map(|x| x.as_sequence().unwrap_or(&Vec::new()).clone())
|
||||
.unwrap_or_default();
|
||||
let inline_tags = get_inline_tags(&content);
|
||||
|
||||
|
@ -123,6 +123,7 @@ impl Index {
|
|||
.insert("tags".into(), unique_tags.into_iter().collect());
|
||||
}
|
||||
|
||||
log::trace!("Adding {path} to Index");
|
||||
let doc = Document { path, frontmatter };
|
||||
i.documents.push(doc);
|
||||
}
|
||||
|
@ -149,15 +150,17 @@ impl Index {
|
|||
scope.reverse();
|
||||
}
|
||||
|
||||
let scope: Vec<_> = scope.into_iter().skip(offset).collect();
|
||||
let scope = scope.into_iter().skip(offset);
|
||||
|
||||
let scope = if limit == 0 {
|
||||
scope
|
||||
if limit == 0 {
|
||||
Self {
|
||||
documents: scope.collect(),
|
||||
}
|
||||
} else {
|
||||
scope.into_iter().take(limit).collect()
|
||||
};
|
||||
|
||||
Self { documents: scope }
|
||||
Self {
|
||||
documents: scope.take(limit).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
|
|
123
src/main.rs
123
src/main.rs
|
@ -4,98 +4,41 @@ use mdq::Index;
|
|||
|
||||
mod args;
|
||||
|
||||
pub fn quit_err(e: impl std::error::Error, msg: &str) -> ! {
|
||||
eprintln!("Error: {msg}. {e}");
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
env_logger::init();
|
||||
let args = args::get_args();
|
||||
|
||||
let root_dir = args.get_one::<String>("dir").unwrap();
|
||||
|
||||
let output_json = args.get_flag("json");
|
||||
|
||||
let no_header = args.get_flag("noheader");
|
||||
|
||||
let limit: usize = args.get_one::<String>("limit").unwrap().parse().unwrap();
|
||||
|
||||
let offset: usize = args.get_one::<String>("offset").unwrap().parse().unwrap();
|
||||
|
||||
let ignoretags: bool = args.get_flag("ignoretags");
|
||||
|
||||
let sort_by = args
|
||||
.get_one::<String>("sortby")
|
||||
.map(std::borrow::ToOwned::to_owned);
|
||||
|
||||
let group_by = args
|
||||
.get_one::<String>("groupby")
|
||||
.map(std::borrow::ToOwned::to_owned);
|
||||
|
||||
let reversed = args.get_flag("reverse");
|
||||
|
||||
let columns: Vec<_> = args
|
||||
.get_many::<String>("column")
|
||||
.unwrap()
|
||||
.cloned()
|
||||
.collect();
|
||||
log::debug!("columns: {columns:?}");
|
||||
|
||||
let (columns, headers): (Vec<_>, Vec<_>) = columns
|
||||
.into_iter()
|
||||
.map(|x| {
|
||||
let (column, header_rename) = x.split_once(':').unwrap_or((&x, &x));
|
||||
|
||||
(column.to_owned(), header_rename.to_owned())
|
||||
})
|
||||
.unzip();
|
||||
|
||||
if columns != headers {
|
||||
log::debug!("renamed headers: {headers:?}");
|
||||
let mut i = Index::new(&args.root_dir, args.ignoretags);
|
||||
if !args.filters.is_null() {
|
||||
i = i.filter_documents(&args.filters);
|
||||
}
|
||||
|
||||
let filters = args
|
||||
.get_many::<String>("filter")
|
||||
.map_or_else(std::vec::Vec::new, std::iter::Iterator::collect);
|
||||
i = i.apply(args.limit, args.offset, args.sort_by, args.reversed);
|
||||
|
||||
log::debug!("raw filters: {filters:?}");
|
||||
|
||||
let filters = if filters.len() == 1 {
|
||||
serde_json::from_str(filters.first().unwrap()).unwrap()
|
||||
} else {
|
||||
let filters: Vec<_> = filters
|
||||
.iter()
|
||||
.map(|x| serde_json::from_str::<serde_json::Value>(x).unwrap())
|
||||
.collect();
|
||||
serde_json::json!({
|
||||
"$and": filters
|
||||
})
|
||||
};
|
||||
|
||||
log::debug!("parsed filters: {filters:?}");
|
||||
|
||||
let mut i = Index::new(root_dir, ignoretags);
|
||||
if !filters.is_null() {
|
||||
i = i.filter_documents(&filters);
|
||||
}
|
||||
|
||||
i = i.apply(limit, offset, sort_by, reversed);
|
||||
|
||||
if group_by.is_some() {
|
||||
let grouped = i.group_by(&group_by.clone().unwrap());
|
||||
if args.group_by.is_some() {
|
||||
let grouped = i.group_by(&args.group_by.clone().unwrap());
|
||||
let grouped: HashMap<_, _> = grouped
|
||||
.into_iter()
|
||||
.map(|(key, val)| (key, val.create_table_data(&columns)))
|
||||
.map(|(key, val)| (key, val.create_table_data(&args.columns)))
|
||||
.collect();
|
||||
|
||||
if output_json {
|
||||
if args.output_json {
|
||||
let mut data = serde_json::json!(
|
||||
{
|
||||
"columns": columns,
|
||||
"groupby": group_by.unwrap(),
|
||||
"columns": args.columns,
|
||||
"groupby": args.group_by.unwrap(),
|
||||
"results": grouped
|
||||
}
|
||||
);
|
||||
if columns != headers {
|
||||
if args.columns != args.headers {
|
||||
data.as_object_mut()
|
||||
.unwrap()
|
||||
.insert("headers".into(), headers.into());
|
||||
.insert("headers".into(), args.headers.into());
|
||||
}
|
||||
println!("{}", serde_json::to_string(&data).unwrap());
|
||||
return;
|
||||
|
@ -111,13 +54,20 @@ fn main() {
|
|||
});
|
||||
for group in grouped_keys {
|
||||
println!("# {group}");
|
||||
print_result(grouped.get(group).unwrap().clone(), &headers);
|
||||
print_result(grouped.get(group).unwrap().clone(), &args.headers);
|
||||
}
|
||||
} else {
|
||||
let mut first = true;
|
||||
for (_, val) in grouped {
|
||||
if first {
|
||||
print_csv(val, if no_header { None } else { Some(&headers) });
|
||||
print_csv(
|
||||
val,
|
||||
if args.no_header {
|
||||
None
|
||||
} else {
|
||||
Some(&args.headers)
|
||||
},
|
||||
);
|
||||
first = false;
|
||||
continue;
|
||||
}
|
||||
|
@ -127,27 +77,34 @@ fn main() {
|
|||
return;
|
||||
}
|
||||
|
||||
let data = i.create_table_data(&columns);
|
||||
let data = i.create_table_data(&args.columns);
|
||||
|
||||
if output_json {
|
||||
if args.output_json {
|
||||
let mut data = serde_json::json!(
|
||||
{
|
||||
"columns": columns,
|
||||
"columns": args.columns,
|
||||
"results": data
|
||||
}
|
||||
);
|
||||
if columns != headers {
|
||||
if args.columns != args.headers {
|
||||
data.as_object_mut()
|
||||
.unwrap()
|
||||
.insert("headers".into(), headers.into());
|
||||
.insert("headers".into(), args.headers.into());
|
||||
}
|
||||
println!("{}", serde_json::to_string(&data).unwrap());
|
||||
return;
|
||||
}
|
||||
if std::io::stdout().is_terminal() {
|
||||
print_result(data, &headers);
|
||||
print_result(data, &args.headers);
|
||||
} else {
|
||||
print_csv(data, if no_header { None } else { Some(&headers) });
|
||||
print_csv(
|
||||
data,
|
||||
if args.no_header {
|
||||
None
|
||||
} else {
|
||||
Some(&args.headers)
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue