summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBryan Newbold <bnewbold@archive.org>2021-02-10 11:01:07 -0800
committerBryan Newbold <bnewbold@archive.org>2021-02-10 11:01:07 -0800
commitea843b324ce3d453356bfc356fd9163336130c48 (patch)
treeb3e54bfde9f5e9e23306361c654bba8b6d90fb4f
parentd4d8caf98bd3595f182d014e4606bbb79dafee05 (diff)
downloadfatcat-cli-ea843b324ce3d453356bfc356fd9163336130c48.tar.gz
fatcat-cli-ea843b324ce3d453356bfc356fd9163336130c48.zip
default search output as a table
-rw-r--r--fatcat-cli/src/commands.rs34
-rw-r--r--fatcat-cli/src/lib.rs23
-rw-r--r--fatcat-cli/src/main.rs68
-rw-r--r--fatcat-cli/src/search.rs18
4 files changed, 104 insertions, 39 deletions
diff --git a/fatcat-cli/src/commands.rs b/fatcat-cli/src/commands.rs
index 15bfc81..3074937 100644
--- a/fatcat-cli/src/commands.rs
+++ b/fatcat-cli/src/commands.rs
@@ -12,7 +12,7 @@ use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor};
use crate::{
entity_model_from_json_str, read_entity_file, ApiModelSer, EntityType, FatcatApiClient,
- Mutation, Specifier,
+ Mutation, Specifier, SearchEntityType, SearchResults,
};
// Want to show:
@@ -274,6 +274,38 @@ pub fn print_entity_histories(
Ok(())
}
+pub fn print_search_table(results: SearchResults, entity_type: SearchEntityType) -> Result<()> {
+ let mut tw = TabWriter::new(std::io::stdout());
+ match entity_type {
+ SearchEntityType::Release => {
+ writeln!(
+ tw,
+ "release_ident\ttype\tstage\tyear\tcontainer_name\ttitle"
+ )?;
+ }
+ //"ident\tissnl\tname"
+ }
+ for hit in results {
+ let hit = hit?;
+ match entity_type {
+ SearchEntityType::Release => {
+ writeln!(
+ tw,
+ "{}\t{}\t{}\t{}\t{}\t{}",
+ hit["ident"].as_str().unwrap_or("-"),
+ hit["release_type"].as_str().unwrap_or("-"),
+ hit["release_stage"].as_str().unwrap_or("-"),
+ hit["release_year"].as_u64().map_or("-".to_string(), |v| v.to_string()),
+ hit["container_name"].as_str().unwrap_or("-"),
+ hit["title"].as_str().unwrap_or("-"),
+ )?;
+ }
+ }
+ }
+ tw.flush()?;
+ Ok(())
+}
+
pub fn edit_entity_locally(
api_client: &mut FatcatApiClient,
specifier: Specifier,
diff --git a/fatcat-cli/src/lib.rs b/fatcat-cli/src/lib.rs
index d648c1c..8706774 100644
--- a/fatcat-cli/src/lib.rs
+++ b/fatcat-cli/src/lib.rs
@@ -14,6 +14,7 @@ mod specifier;
pub use api::FatcatApiClient;
pub use commands::{
edit_entity_locally, print_changelog_entries, print_editgroups, print_entity_histories,
+ print_search_table,
BatchGrouper, BatchOp, ClientStatus,
};
pub use download::{download_batch, download_file, download_release};
@@ -21,7 +22,7 @@ pub use entities::{
entity_model_from_json_str, read_entity_file, ApiEntityModel, ApiModelIdent, ApiModelSer,
Mutation,
};
-pub use search::crude_search;
+pub use search::{crude_search, SearchResults};
pub use specifier::Specifier;
#[derive(Debug, PartialEq, Clone, Copy)]
@@ -52,6 +53,26 @@ impl FromStr for EntityType {
}
}
+#[derive(Debug, PartialEq, Clone, Copy)]
+pub enum SearchEntityType {
+ Release,
+ // TODO: Container,
+ // TODO: Fulltext,
+}
+
+impl FromStr for SearchEntityType {
+ type Err = anyhow::Error;
+
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ match s {
+ "release" | "releases" => Ok(SearchEntityType::Release),
+ //"container" | "containers" => Ok(SearchEntityType::Container),
+ //"fulltext" | "scholar" => Ok(SearchEntityType::Fulltext),
+ _ => Err(anyhow!("invalid entity type : {}", s)),
+ }
+ }
+}
+
/// Takes a macaroon token (as base64-encoded string) and tries to parse out an editor id
pub fn parse_macaroon_editor_id(s: &str) -> Result<String> {
let raw = BASE64
diff --git a/fatcat-cli/src/main.rs b/fatcat-cli/src/main.rs
index 6e3f2c7..72cb169 100644
--- a/fatcat-cli/src/main.rs
+++ b/fatcat-cli/src/main.rs
@@ -224,9 +224,9 @@ enum Command {
json: bool,
},
Search {
- entity_type: EntityType,
+ entity_type: SearchEntityType,
- terms: Vec<String>,
+ query: Vec<String>,
#[structopt(long = "--expand")]
expand: Option<String>,
@@ -234,11 +234,17 @@ enum Command {
#[structopt(long = "--hide")]
hide: Option<String>,
+ #[structopt(long = "--count")]
+ count: bool,
+
#[structopt(long, short = "-n", default_value = "20")]
limit: i64,
- #[structopt(long = "--search-schema")]
- search_schema: bool,
+ #[structopt(long = "--entity-json")]
+ entity_json: bool,
+
+ #[structopt(long = "--index-json")]
+ index_json: bool,
},
Editgroup {
#[structopt(subcommand)]
@@ -509,34 +515,46 @@ fn run(opt: Opt) -> Result<()> {
}
Command::Search {
entity_type,
- terms,
+ query,
limit,
- search_schema,
+ count,
+ entity_json,
+ index_json,
expand,
hide,
} => {
- let limit: Option<u64> = match limit {
- l if l <= 0 => None,
- l => Some(l as u64),
+ // TODO: ensure that we don't try print more than ~1000 hits with tabwriter?
+ let limit: Option<u64> = match (count, limit) {
+ (true, _) => Some(0),
+ (false, l) if l <= 0 => None,
+ (false, l) => Some(l as u64),
};
- let results = fatcat_cli::crude_search(&opt.search_host, entity_type, limit, terms)
+ let results = fatcat_cli::crude_search(&opt.search_host, entity_type, limit, query)
.with_context(|| format!("searching for {:?}", entity_type))?;
- eprintln!("Got {} hits in {}ms", results.count, results.took_ms);
- for hit in results {
- let hit = hit?;
- match (search_schema, entity_type) {
- (true, _) => writeln!(&mut std::io::stdout(), "{}", hit.to_string())?,
- (false, EntityType::Release) => {
- let specifier =
- Specifier::Release(hit["ident"].as_str().unwrap().to_string());
- let entity = specifier.get_from_api(
- &mut api_client,
- expand.clone(),
- hide.clone(),
- )?;
- writeln!(&mut std::io::stdout(), "{}", entity.to_json_string()?)?
+ if count {
+ println!("{}", results.count);
+ } else {
+ eprintln!("Got {} hits in {}ms", results.count, results.took_ms);
+ if !(index_json || entity_json) {
+ print_search_table(results, entity_type)?;
+ } else {
+ for hit in results {
+ let hit = hit?;
+ match (index_json, entity_json, entity_type) {
+ (false, false, _) => unreachable!("case handled above"),
+ (true, _, _) => writeln!(&mut std::io::stdout(), "{}", hit.to_string())?,
+ (false, true, SearchEntityType::Release) => {
+ let specifier =
+ Specifier::Release(hit["ident"].as_str().unwrap().to_string());
+ let entity = specifier.get_from_api(
+ &mut api_client,
+ expand.clone(),
+ hide.clone(),
+ )?;
+ writeln!(&mut std::io::stdout(), "{}", entity.to_json_string()?)?
+ }
+ }
}
- (false, _) => unimplemented!("searching other entity types"),
}
}
}
diff --git a/fatcat-cli/src/search.rs b/fatcat-cli/src/search.rs
index f778477..f328ee9 100644
--- a/fatcat-cli/src/search.rs
+++ b/fatcat-cli/src/search.rs
@@ -1,11 +1,11 @@
-use crate::EntityType;
+use crate::SearchEntityType;
use anyhow::{anyhow, Result};
use log::{self, info};
use serde_json::json;
use std::time::Duration;
pub struct SearchResults {
- pub entity_type: EntityType,
+ pub entity_type: SearchEntityType,
pub limit: Option<u64>,
pub count: u64,
pub took_ms: u64,
@@ -71,20 +71,14 @@ impl Iterator for SearchResults {
pub fn crude_search(
api_host: &str,
- entity_type: EntityType,
+ entity_type: SearchEntityType,
limit: Option<u64>,
terms: Vec<String>,
) -> Result<SearchResults> {
let index = match entity_type {
- EntityType::Release => "fatcat_release",
- EntityType::File => "fatcat_file",
- EntityType::Container => "fatcat_container",
- _ => {
- return Err(anyhow!(
- "No search index for entity type: {:?}",
- entity_type
- ))
- }
+ SearchEntityType::Release => "fatcat_release",
+ //SearchEntityType::File => "fatcat_file",
+ //SearchEntityType::Container => "fatcat_container",
};
let http_client = reqwest::blocking::Client::builder()
.timeout(Duration::from_secs(10))