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",
]
[[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]]
name = "core-foundation"
version = "0.9.2"
@ -139,6 +154,12 @@ dependencies = [
"winapi",
]
[[package]]
name = "encode_unicode"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
[[package]]
name = "encoding_rs"
version = "0.8.29"
@ -279,6 +300,7 @@ version = "0.1.0"
dependencies = [
"anyhow",
"confy",
"console",
"reqwest",
"serde",
"serde_json",
@ -710,6 +732,21 @@ dependencies = [
"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]]
name = "remove_dir_all"
version = "0.5.3"
@ -928,6 +965,16 @@ dependencies = [
"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]]
name = "textwrap"
version = "0.11.0"

View File

@ -7,6 +7,7 @@ edition = "2021"
[dependencies]
anyhow = "1.0"
confy = "0.4"
console = "0.15.0"
reqwest = { version = "0.11", features = ["json"] }
serde = { version = "1", features = ["derive"] }
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 xx
3> xxxy
Description for xxxy
2> xxyz
Description for xxyz
1> xx
Description for xx
$ hopper add sodium --mc-version 1.17
4 Indium 1.0.0+mc1.17.1 [1.17.1] (21557 downloads)
Sodium addon providing support for the Fabric Rendering API, based on Indigo
3 Reese's Sodium Options 1.2.1 [1.16.5] (548 downloads)
Alternative Options Menu for Sodium
2 Sodium Extra mc1.17.1-0.3.6 [1.17.1] (16387 downloads)
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
:: ...
```
- 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`
Just like `hopper add` but simply downloads a mod jar.

View File

@ -1,3 +1,4 @@
use console::style;
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
use structopt::StructOpt;
@ -48,7 +49,7 @@ struct Upstream {
impl Default for Upstream {
fn default() -> Self {
Self {
server_address: "api.modrinth.com".into()
server_address: "api.modrinth.com".into(),
}
}
}
@ -89,13 +90,41 @@ struct ModResult {
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<()> {
let client = reqwest::Client::new();
let url = format!("https://{}/api/v1/mod", config.upstream.server_address);
let params = [("query", package_name.as_str())];
let url = reqwest::Url::parse_with_params(url.as_str(), &params)?;
let response = client.get(url).send().await?.json::<SearchResponse>().await?;
println!("response: {:#?}", response);
let response = client
.get(url)
.send()
.await?
.json::<SearchResponse>()
.await?;
for (i, result) in response.hits.iter().enumerate().rev() {
result.display(i + 1);
}
Ok(())
}
@ -103,7 +132,6 @@ async fn cmd_install(config: &Config, package_name: String) -> anyhow::Result<()
async fn main() -> anyhow::Result<()> {
let args = Args::from_args();
let config = args.load_config()?;
println!("args: {:#?}\nconfig: {:#?}", args, config);
match args.command {
Command::Install { package_name } => cmd_install(&config, package_name).await,
_ => unimplemented!("unimplemented subcommand"),