use clap::Parser;
use gdbc::{Command, Error, GdbClient};
use rustyline::history::History;
use rustyline::{DefaultEditor, error::ReadlineError};
use std::path::PathBuf;
use std::str::FromStr;
#[derive(Parser, Debug)]
#[command(name = "gdbc")]
#[command(author = "Your Name <your.email@example.com>")]
#[command(version = "0.1.0")]
#[command(about = "A GDB client for terminal", long_about = None)]
struct Cli {
#[arg(short = 'H', long, default_value = "localhost")]
host: String,
#[arg(short, long, default_value_t = 55555)]
port: u16,
#[arg(short, long)]
instruction: Option<String>,
#[arg(long, default_value_t = false)]
no_color: bool,
#[arg(short, long, default_value_t = false)]
debug: bool,
}
fn main() -> Result<(), Error> {
let cli = Cli::parse();
if cli.debug {
env_logger::init();
}
let mut client = GdbClient::new();
let use_colors = !cli.no_color;
if let Some(instruction) = cli.instruction {
let cmd = Command::from_str(&instruction)?;
if !matches!(cmd, Command::Connect(_, _)) {
let addr = format!("{}:{}", cli.host, cli.port);
match client.connect(addr) {
Ok(_) => println!("Connected to GDB server at {}:{}", cli.host, cli.port),
Err(e) => {
eprintln!("Failed to connect to GDB server: {}", e);
return Err(e);
}
}
}
gdbc::commands::execute_command(cmd, &mut client, use_colors)?;
if client.is_connected() {
client.disconnect()?;
}
return Ok(());
}
println!("GDB Client (gdbc) v0.1.0");
println!("Type 'help' for available commands, 'quit' to exit");
if cli.host != "localhost" || cli.port != 55555 {
let addr = format!("{}:{}", cli.host, cli.port);
match client.connect(addr) {
Ok(_) => println!("Connected to GDB server at {}:{}", cli.host, cli.port),
Err(e) => eprintln!("Failed to connect to GDB server: {}", e),
}
}
let mut rl = DefaultEditor::new().map_err(|e| Error::Unknown(e.to_string()))?;
let history_file = PathBuf::from(dirs::home_dir().unwrap_or_default()).join(".gdbc_history");
if history_file.exists() {
let _ = rl.history_mut().load(&history_file);
}
loop {
let prompt = if client.is_connected() {
"gdb> "
} else {
"gdb (not connected)> "
};
match rl.readline(prompt) {
Ok(line) => {
let line = line.trim();
if !line.is_empty() {
rl.add_history_entry(line)
.map_err(|e| Error::Unknown(e.to_string()))?;
match Command::from_str(line) {
Ok(cmd) => {
if let Err(e) =
gdbc::commands::execute_command(cmd, &mut client, use_colors)
{
eprintln!("Error: {}", e);
}
}
Err(e) => {
eprintln!("Parse error: {}", e);
}
}
}
}
Err(ReadlineError::Interrupted) => {
println!("Press Ctrl+D or type 'quit' to exit");
}
Err(ReadlineError::Eof) => {
println!("Exiting...");
if client.is_connected() {
let _ = client.disconnect();
}
break;
}
Err(e) => {
eprintln!("Error: {}", e);
break;
}
}
}
let _ = rl.save_history(&history_file);
Ok(())
}