Initial fancy search result formatting

This commit is contained in:
marceline-cramer 2021-11-21 11:18:26 -07:00
parent 40fbf94ce1
commit 07891d62e5
4 changed files with 95 additions and 11 deletions

47
Cargo.lock generated
View File

@ -102,6 +102,21 @@ dependencies = [
"toml", "toml",
] ]
[[package]]
name = "console"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a28b32d32ca44b70c3e4acd7db1babf555fa026e385fb95f18028f88848b3c31"
dependencies = [
"encode_unicode",
"libc",
"once_cell",
"regex",
"terminal_size",
"unicode-width",
"winapi",
]
[[package]] [[package]]
name = "core-foundation" name = "core-foundation"
version = "0.9.2" version = "0.9.2"
@ -139,6 +154,12 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "encode_unicode"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
[[package]] [[package]]
name = "encoding_rs" name = "encoding_rs"
version = "0.8.29" version = "0.8.29"
@ -279,6 +300,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"confy", "confy",
"console",
"reqwest", "reqwest",
"serde", "serde",
"serde_json", "serde_json",
@ -710,6 +732,21 @@ dependencies = [
"redox_syscall", "redox_syscall",
] ]
[[package]]
name = "regex"
version = "1.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
dependencies = [
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.6.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
[[package]] [[package]]
name = "remove_dir_all" name = "remove_dir_all"
version = "0.5.3" version = "0.5.3"
@ -928,6 +965,16 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "terminal_size"
version = "0.1.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df"
dependencies = [
"libc",
"winapi",
]
[[package]] [[package]]
name = "textwrap" name = "textwrap"
version = "0.11.0" version = "0.11.0"

View File

@ -7,6 +7,7 @@ edition = "2021"
[dependencies] [dependencies]
anyhow = "1.0" anyhow = "1.0"
confy = "0.4" confy = "0.4"
console = "0.15.0"
reqwest = { version = "0.11", features = ["json"] } reqwest = { version = "0.11", features = ["json"] }
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"] }
serde_json = "1" serde_json = "1"

View File

@ -63,17 +63,25 @@ Updates all installed mods of a specific version, or a version set in the config
## `hopper add` ## `hopper add`
``` ```
$ hopper add xx $ hopper add sodium --mc-version 1.17
3> xxxy 4 Indium 1.0.0+mc1.17.1 [1.17.1] (21557 downloads)
Description for xxxy Sodium addon providing support for the Fabric Rendering API, based on Indigo
2> xxyz 3 Reese's Sodium Options 1.2.1 [1.16.5] (548 downloads)
Description for xxyz Alternative Options Menu for Sodium
1> xx 2 Sodium Extra mc1.17.1-0.3.6 [1.17.1] (16387 downloads)
Description for xx Features that shouldn't be in Sodium.
1 Sodium mc1.17.1-0.3.2 [1.17.1] (962361 downloads)
Modern rendering engine and client-side optimization mod for Minecraft
:: Select a mod :: Select a mod
:: ... :: ...
``` ```
- pad mod indices based on largest number
- option in config to reverse sorting order
- add parameter to restrict target Minecraft version
- manually pick out Minecraft version
- square creeper face progress indicator (from top-left clockwise spiral in)
## `hopper get` ## `hopper get`
Just like `hopper add` but simply downloads a mod jar. Just like `hopper add` but simply downloads a mod jar.

View File

@ -1,3 +1,4 @@
use console::style;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::path::PathBuf; use std::path::PathBuf;
use structopt::StructOpt; use structopt::StructOpt;
@ -48,7 +49,7 @@ struct Upstream {
impl Default for Upstream { impl Default for Upstream {
fn default() -> Self { fn default() -> Self {
Self { Self {
server_address: "api.modrinth.com".into() server_address: "api.modrinth.com".into(),
} }
} }
} }
@ -89,13 +90,41 @@ struct ModResult {
host: String, host: String,
} }
impl ModResult {
fn display(&self, index: usize) {
let index = style(index).cyan();
let title = style(self.title.clone()).bright();
let downloads = style(self.downloads.clone()).green();
if let Some(latest_release) = self.versions.last() {
// TODO fetch version numbers to display
let latest_release = style(latest_release).blue();
println!(
"{} {} [{}] ({} downloads)",
index, title, latest_release, downloads
);
} else {
println!("{} {} [no releases]", index, title)
}
let description = style(self.description.clone()).bright().white();
println!(" {}", description);
}
}
async fn cmd_install(config: &Config, package_name: String) -> anyhow::Result<()> { async fn cmd_install(config: &Config, package_name: String) -> anyhow::Result<()> {
let client = reqwest::Client::new(); let client = reqwest::Client::new();
let url = format!("https://{}/api/v1/mod", config.upstream.server_address); let url = format!("https://{}/api/v1/mod", config.upstream.server_address);
let params = [("query", package_name.as_str())]; let params = [("query", package_name.as_str())];
let url = reqwest::Url::parse_with_params(url.as_str(), &params)?; let url = reqwest::Url::parse_with_params(url.as_str(), &params)?;
let response = client.get(url).send().await?.json::<SearchResponse>().await?; let response = client
println!("response: {:#?}", response); .get(url)
.send()
.await?
.json::<SearchResponse>()
.await?;
for (i, result) in response.hits.iter().enumerate().rev() {
result.display(i + 1);
}
Ok(()) Ok(())
} }
@ -103,7 +132,6 @@ async fn cmd_install(config: &Config, package_name: String) -> anyhow::Result<()
async fn main() -> anyhow::Result<()> { async fn main() -> anyhow::Result<()> {
let args = Args::from_args(); let args = Args::from_args();
let config = args.load_config()?; let config = args.load_config()?;
println!("args: {:#?}\nconfig: {:#?}", args, config);
match args.command { match args.command {
Command::Install { package_name } => cmd_install(&config, package_name).await, Command::Install { package_name } => cmd_install(&config, package_name).await,
_ => unimplemented!("unimplemented subcommand"), _ => unimplemented!("unimplemented subcommand"),