use viuer for mcstat image output.

This commit is contained in:
LordMZTE 2021-04-29 13:03:33 +02:00
parent 27517a6994
commit 5068996284
3 changed files with 52 additions and 104 deletions

View File

@ -8,7 +8,6 @@ edition = "2018"
[dependencies]
anyhow = "1.0.40"
asciify = "0.1.6"
base64 = "0.13.0"
clap = "2.33.3"
image = "0.23.14"
@ -19,6 +18,7 @@ structopt = "0.3.21"
term_size = "0.3.2"
termcolor = "1.1.2"
unicode-width = "0.1.8"
viuer = "0.4.0"
[dependencies.async-minecraft-ping]
git = "https://github.com/LordMZTE/async-minecraft-ping.git"

View File

@ -3,7 +3,6 @@ extern crate smart_default;
use crate::output::Table;
use anyhow::{anyhow, bail, Context};
use asciify::AsciiBuilder;
use image::{DynamicImage, ImageFormat};
use itertools::Itertools;
use std::io::Cursor;
@ -27,22 +26,6 @@ macro_rules! none_if_empty {
}};
}
pub struct AsciiConfig {
pub size: Option<u32>,
pub colored: bool,
pub deep: bool,
pub invert: bool,
}
impl AsciiConfig {
pub fn apply(&self, mut builder: AsciiBuilder) -> AsciiBuilder {
if let Some(n) = self.size {
builder = builder.set_resize((n * 2, n))
}
builder.set_deep(self.deep).set_invert(self.invert)
}
}
pub fn remove_formatting(s: &str) -> String {
let chars = s.char_indices().rev();
let mut buf = s.to_owned();

View File

@ -1,21 +1,12 @@
use anyhow::{Context, Result};
use asciify::AsciiBuilder;
use anyhow::{anyhow, Context, Result};
use async_minecraft_ping::{ConnectionConfig, ServerDescription, StatusResponse};
use itertools::Itertools;
use structopt::StructOpt;
use termcolor::{Buffer, BufferWriter, ColorChoice, WriteColor};
use time::{Duration, Instant};
use tokio::time;
use mcstat::{
get_table,
none_if_empty,
output::Table,
parse_base64_image,
remove_formatting,
AsciiConfig,
};
use mcstat::{get_table, none_if_empty, output::Table, parse_base64_image, remove_formatting};
#[derive(Debug, StructOpt)]
#[structopt(
@ -62,35 +53,24 @@ struct Opt {
#[structopt(long, help = "displays forge mod channels if the server sends them")]
channels: bool,
#[structopt(long, short, help = "print the server's favicon as ASCII art")]
#[structopt(long, short, help = "print the server's favicon to stdout")]
image: bool,
#[structopt(
long,
short = "c",
requires = "image",
help = "print the server's favicon with color"
)]
color: bool,
#[structopt(short, requires = "image", help = "size of the favicon ascii art")]
size: Option<u32>,
}
#[structopt(
long,
short,
requires = "image",
help = "print the ascii art favicon with more diverse chars"
)]
deep: bool,
#[structopt(
long,
short = "n",
requires = "image",
help = "inverts ascii art favicon"
)]
invert: bool,
impl Opt {
fn get_viuer_conf(&self) -> viuer::Config {
let size = self.size.unwrap_or(16);
viuer::Config {
transparent: true,
absolute_offset: false,
width: Some(size * 2),
height: Some(size),
..viuer::Config::default()
}
}
}
#[tokio::main]
@ -132,23 +112,6 @@ async fn main() -> Result<()> {
let response = serde_json::from_str::<StatusResponse>(&raw_response)?;
// endregion
// region Image
let mut image = None;
if let (Some(favicon), true) = (&response.favicon, opt.image) {
// The image parsing and asciifying is done while the table is printing
image = Some(tokio::spawn(asciify_base64_image(
favicon.clone(),
AsciiConfig {
size: Some(opt.size.unwrap_or(16)),
colored: opt.color,
deep: opt.deep,
invert: opt.invert,
},
)));
}
// endregion
// region printing
// if the server has mods, and the user hasn't used the -m argument, notify
// that.
@ -165,45 +128,47 @@ async fn main() -> Result<()> {
)
.stdout()?;
if let Some(img) = image {
println!("\n{}", img.await??);
if let (Some(img), true) = (response.favicon, opt.image) {
let decoded = parse_base64_image(img)?;
viuer::print(&decoded, &opt.get_viuer_conf())
.map_err(|e| anyhow!("Failed to print favicon: {}", e))?;
}
// endregion
Ok(())
}
/// returns the asciifyed image from base64
/// returns Err if the base64 image is invalid
async fn asciify_base64_image(favicon: String, config: AsciiConfig) -> Result<String> {
let image = parse_base64_image(favicon)?;
let builder = config.apply(AsciiBuilder::new_from_image(image));
let mut buf = if config.colored {
// this does not write to stdout but just gets the correct color
// information for stdout
let mut buf = BufferWriter::stdout(ColorChoice::Always).buffer();
builder.to_stream_colored(&mut buf);
buf
} else {
let mut buf = Buffer::no_color();
builder.to_stream(&mut buf);
buf
};
// reset color
buf.reset()?;
let bytes = buf.as_slice().to_vec();
// only check utf8 format in debug mode
#[cfg(debug_assertions)]
let out = String::from_utf8(bytes).expect("asciifyed image is invalid utf8");
// bytes should always be valid utf8
#[cfg(not(debug_assertions))]
let out = unsafe { String::from_utf8_unchecked(bytes) };
Ok(out)
}
// returns the asciifyed image from base64
// returns Err if the base64 image is invalid
// async fn asciify_base64_image(favicon: String, config: AsciiConfig) ->
// Result<String> { let image = parse_base64_image(favicon)?;
//
// let builder = config.apply(AsciiBuilder::new_from_image(image));
//
// let mut buf = if config.colored {
// this does not write to stdout but just gets the correct color
// information for stdout
// let mut buf = BufferWriter::stdout(ColorChoice::Always).buffer();
// builder.to_stream_colored(&mut buf);
// buf
// } else {
// let mut buf = Buffer::no_color();
// builder.to_stream(&mut buf);
// buf
// };
// reset color
// buf.reset()?;
//
// let bytes = buf.as_slice().to_vec();
//
// only check utf8 format in debug mode
// #[cfg(debug_assertions)]
// let out = String::from_utf8(bytes).expect("asciifyed image is invalid utf8");
// bytes should always be valid utf8
// #[cfg(not(debug_assertions))]
// let out = unsafe { String::from_utf8_unchecked(bytes) };
//
// Ok(out)
// }
fn format_table(
response: &StatusResponse,