use clap::{Parser, Subcommand, ValueEnum};
use crossterm;
use crate::common::format_version_to_display;
use crate::input::{InitOptions, SizeOption};
use crate::pipeline::Pipeline;
const DEFAULT_UNIX_SOCKET_PATH: &str = "/tmp/snakepipe.sock";
const DEFAULT_TCP_PORT: &str = "8050";
const DEFAULT_TCP_HOST: &str = "127.0.0.1";
#[derive(Parser)]
#[command(author, version, about, long_about = None)]
#[command(propagate_version = true)]
pub struct Cli {
#[command(subcommand)]
pub command: Commands,
}
const DEFAULT_WIDTH: u32 = 25;
const DEFAULT_HEIGHT: u32 = 25;
#[derive(Subcommand)]
pub enum Commands {
Gamestate {
#[arg(long, default_value_t = 120)]
frame_duration: u32,
#[arg(long)]
width: Option<u32>,
#[arg(long)]
height: Option<u32>,
#[arg(long, default_value_t = 2)]
snake_length: u32,
#[arg(long, default_value_t = false)]
fit_terminal: bool,
},
Render,
Throttle {
#[arg(long, default_value_t = 120)]
frame_duration: u32,
#[arg(long)]
loop_infinite: bool,
},
RenderBrowser {
#[arg(long, default_value_t = 8080)]
port: u16,
},
StreamSse {
#[arg(long, default_value = "http://localhost:8080")]
address: String,
},
SocketPlay {
#[arg(long, default_value = DEFAULT_UNIX_SOCKET_PATH)]
path: String,
},
SocketWatch {
#[arg(long, default_value = DEFAULT_UNIX_SOCKET_PATH)]
path: String,
},
TcpPlay {
#[arg(long, default_value = DEFAULT_TCP_PORT)]
port: u16,
#[arg(long, default_value = DEFAULT_TCP_HOST)]
host: String,
},
TcpWatch {
#[arg(long, default_value = DEFAULT_TCP_PORT)]
port: u16,
#[arg(long, default_value = DEFAULT_TCP_HOST)]
host: String,
},
#[command(arg_required_else_help = true)]
Pipeline(PipelineArgs),
GenerateCompletions(GenerateCompletionsArgs),
}
#[derive(Parser)]
pub struct PipelineArgs {
#[command(subcommand)]
pub sub: Option<Pipeline>,
#[arg(long)]
pub list: bool,
}
#[derive(Parser)]
pub struct GenerateCompletionsArgs {
#[arg(long, value_enum)]
pub shell: AvailableShells,
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)]
pub enum AvailableShells {
Bash,
Fish,
Zsh,
}
pub struct CliOptions<'a> {
pub frame_duration: &'a u32,
pub width: &'a Option<u32>,
pub height: &'a Option<u32>,
pub snake_length: &'a u32,
pub fit_terminal: &'a bool,
}
impl Into<InitOptions> for CliOptions<'_> {
fn into(self) -> InitOptions {
let size: SizeOption;
if self.width.is_some() && self.height.is_some() {
size = SizeOption {
width: self.width.unwrap_or(DEFAULT_WIDTH),
height: self.height.unwrap_or(DEFAULT_HEIGHT),
}
} else if self.width.is_some() {
size = SizeOption {
width: self.width.unwrap_or(DEFAULT_WIDTH),
height: self.height.unwrap_or(DEFAULT_HEIGHT),
}
} else if self.fit_terminal.eq(&true) {
let (width, height) = crossterm::terminal::size()
.unwrap_or((DEFAULT_WIDTH as u16 + 2, DEFAULT_HEIGHT as u16 + 6));
size = SizeOption {
width: width as u32 - 2, height: height as u32 - 6, }
} else {
size = SizeOption {
width: DEFAULT_WIDTH,
height: DEFAULT_HEIGHT,
}
}
let mut features_with_version = std::collections::HashMap::new();
features_with_version.insert("gamestate".to_string(), format_version_to_display());
let metadatas = std::collections::HashMap::new();
return InitOptions {
frame_duration: *self.frame_duration,
snake_length: *self.snake_length,
size,
features_with_version: features_with_version,
metadatas,
};
}
}