added simple tui interface

This commit is contained in:
hendrik 2025-06-07 01:07:45 +02:00
parent 9f0f94a9f5
commit e802e87c28
5 changed files with 107 additions and 11 deletions

View File

@ -7,7 +7,4 @@ edition = "2024"
anyhow = "1.0.98"
clap = { version = "4.5.39", features = ["derive"] }
colored = "3.0.0"
[dev-dependencies]
predicates = "3.1.3"
assert_cmd = "2.0.17"
cursive = "0.21.1"

View File

@ -7,7 +7,7 @@ use anyhow::Error;
use clap::Parser;
use colored::Colorize;
use crate::img::{cat_picture, woof_err};
use crate::img::{cat_picture, cat_picture_coloured, woof_err};
#[derive(Parser, Debug)]
struct Options {
@ -46,7 +46,7 @@ pub fn run_cli() -> Result<(), Error> {
fn run_cli_with_args(mut options: Options) -> Result<(), Error> {
let message = get_message(&mut options)?;
// get picture before printing message - this way if theres an error it gets printed first
let cat_picture = cat_picture(options.file, options.dead)?;
let cat_picture = cat_picture_coloured(options.file, options.dead)?;
woof_err(&message);
println!("{}", format_msg(&message));
println!("{}", cat_picture);

View File

@ -9,9 +9,13 @@ const DEFAULT_TEMPLATE: &str = r#" \
( {eye} {eye} )
=( I )="#;
fn get_eye(dead: bool) -> String {
fn get_eye(dead: bool, colored: bool) -> String {
let eye = if dead { "x" } else { "o" };
format!("{}", eye.red().bold())
if colored {
format!("{}", eye.red().bold())
} else {
eye.to_string()
}
}
pub fn woof_err(message: &str) {
@ -31,7 +35,19 @@ fn get_template(file: Option<PathBuf>) -> Result<String, Error> {
}
}
pub fn cat_picture(file: Option<PathBuf>, dead: bool) -> Result<String, Error> {
pub fn cat_picture(file: Option<PathBuf>, dead: bool, colored: bool) -> Result<String, Error> {
let template = get_template(file)?;
Ok(template.replace("{eye}", &get_eye(dead)))
Ok(template.replace("{eye}", &get_eye(dead, colored)))
}
pub fn cat_picture_coloured(file: Option<PathBuf>, dead: bool) -> Result<String, Error> {
cat_picture(file, dead, true)
}
pub fn cat_picture_uncoloured(file: Option<PathBuf>, dead: bool) -> Result<String, Error> {
cat_picture(file, dead, false)
}
pub fn default_cat() -> String {
cat_picture_uncoloured(None, false).expect("This shouldnt happen")
}

View File

@ -1,2 +1,3 @@
pub mod cli;
pub(crate) mod img;
pub mod run;
pub mod tui;

82
cat_cli/src/tui.rs Normal file
View File

@ -0,0 +1,82 @@
use std::ops::{Deref, DerefMut};
use cursive::{
Cursive, CursiveRunnable,
event::Key,
view::Nameable,
views::{Checkbox, Dialog, EditView, ListView},
};
use crate::img::cat_picture_uncoloured;
#[derive(Default)]
struct GlobalView(CursiveRunnable);
unsafe impl Send for GlobalView {}
impl GlobalView {
fn add_quit_callback(&mut self) {
self.0.add_global_callback(Key::Esc, |k| k.quit());
}
}
impl Deref for GlobalView {
type Target = CursiveRunnable;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for GlobalView {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
struct Options<'a> {
message: &'a str,
dead: bool,
}
fn cat_output_dialog(msg: &str, dead: bool) -> Dialog {
let cat = cat_picture_uncoloured(None, dead).unwrap();
Dialog::text(format!("{}\n{}", msg, cat))
.title("The cat says")
.button("Ok", |s| s.quit())
}
fn cat_input_form() -> Dialog {
Dialog::new()
.title("Fill cat form")
.content(
ListView::new()
.child("Say?:", EditView::new().with_name("message"))
.child("dead?:", Checkbox::new().with_name("dead")),
)
.button("Ok", |s| {
let message = s
.call_on_name("message", |t: &mut EditView| t.get_content())
.unwrap();
let is_dead = s
.call_on_name("dead", |t: &mut Checkbox| t.is_checked())
.unwrap();
let options = Options {
message: &message.clone(),
dead: is_dead,
};
print_cat(s, &options);
})
}
fn print_cat(view: &mut Cursive, options: &Options<'_>) {
view.pop_layer();
view.add_layer(cat_output_dialog(options.message, options.dead));
}
pub fn run_tui() {
let mut siv = GlobalView::default();
siv.add_quit_callback();
siv.add_layer(cat_input_form());
siv.run();
}