use clap::Parser;
use std::io::{BufRead, Write};
use std::path::PathBuf;
#[derive(Parser, Debug)]
#[command(name = "fsv", author, version, about, long_about = None)]
struct Args {
#[arg(value_name = "PATH", default_value = ".")]
path: PathBuf,
#[arg(short = 'p', long, default_value_t = 8888)]
port: u16,
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let args = Args::parse();
if !args.path.exists() {
eprintln!("error: path '{}' does not exist", args.path.display());
std::process::exit(1);
}
let (ips, port, mut handle) = fsv::run(fsv::Config {
path: args.path,
port: args.port,
})
.await?;
println!("fsv running on port {port}");
for ip in &ips {
if ip.is_ipv6() {
println!(" http://[{ip}]:{port}");
} else {
println!(" http://{ip}:{port}");
}
}
let primary = ips
.iter()
.find(|ip| ip.is_ipv4() && !ip.is_loopback())
.or_else(|| ips.first())
.copied();
if let Some(ip) = primary {
let url = format!("http://{}:{}", ip, port);
println!("\nScan to open:");
qr2term::print_qr(&url).unwrap_or_else(|e| eprintln!("QR error: {e}"));
println!("{url}\n");
}
let stdin = std::io::stdin();
let stdout = std::io::stdout();
loop {
{
let mut out = stdout.lock();
out.write_all(b"> ").ok();
out.flush().ok();
}
let mut line = String::new();
match stdin.lock().read_line(&mut line) {
Ok(0) | Err(_) => break, Ok(_) => {}
}
let text = line.trim();
if text.is_empty() {
continue;
}
match handle.send(text) {
Ok(n) => println!("sent to {n} client(s)"),
Err(e) => eprintln!("broadcast error: {e}"),
}
}
handle.shutdown().ok();
Ok(())
}