mod attach;
mod bootstrap;
#[allow(dead_code)]
mod buffers;
mod cli;
mod client;
#[allow(dead_code)]
mod clipboard;
mod commands;
mod config;
mod copy_mode;
mod env_interp;
#[allow(dead_code)]
mod events;
#[allow(dead_code)]
mod fuzzy;
#[allow(dead_code)]
mod hooks;
mod ipc;
mod keymap;
mod layout;
mod observability;
mod pane;
mod project;
mod protocol;
mod render;
#[cfg(feature = "render-diff")]
mod render_diff;
mod server;
mod session;
mod settings;
#[cfg(unix)]
mod signals;
#[cfg(unix)]
mod socket_security;
mod tab;
mod terminal_state;
#[allow(dead_code)]
mod theme;
mod workspace;
pub(crate) use bootstrap::{
base64_encode, build_initial_state, close_pane, collect_render_targets, do_split,
extract_selected_text, handle_ipc_command, kill_all_panes, make_inner, replace_pane,
reset_render_targets, resize_all, resize_zoomed_pane, selection_char_count_from_synced,
spawn_layout_panes, spawn_pane, spawn_snapshot_panes, sync_render_targets, RenderUpdate,
};
pub(crate) use cli::{parse_args_from, SocketKind};
fn main() -> anyhow::Result<()> {
let args: Vec<String> = std::env::args().collect();
match args.get(1).map(|s| s.as_str()) {
Some("init") => return bootstrap::cmd_init(),
Some("from") => return bootstrap::cmd_from(args.get(2).map(|s| s.as_str())),
Some("ls") => return attach::cmd_ls(),
Some("kill") => return attach::cmd_kill(args.get(2).map(|s| s.as_str())),
Some("a") | Some("attach") => return attach::cmd_attach(&args[2..]),
Some("rename") => {
return attach::cmd_rename(
args.get(2).map(|s| s.as_str()),
args.get(3).map(|s| s.as_str()),
)
}
Some("upgrade-snapshot") => return attach::cmd_upgrade_snapshot(&args[2..]),
Some("-h") | Some("--help") => {
cli::print_help();
return Ok(());
}
Some("-V") | Some("--version") => {
println!("ezpn {}", env!("CARGO_PKG_VERSION"));
return Ok(());
}
Some("--server") => {
let session_name = args
.get(2)
.ok_or_else(|| anyhow::anyhow!("--server requires session name"))?;
let remaining: Vec<String> = args[3..].to_vec();
return server::run(session_name, &remaining);
}
_ => {}
}
if std::env::var("EZPN").is_ok() {
eprintln!("ezpn: cannot run inside an existing ezpn session");
std::process::exit(1);
}
let config = cli::parse_args()?;
let original_args: Vec<String> = args[1..].to_vec();
if original_args.iter().any(|a| a == "--no-daemon") {
return bootstrap::run_direct(&config);
}
let session_name = {
let mut custom = None;
let mut i = 1;
while i < args.len() {
if (args[i] == "-S" || args[i] == "--session") && i + 1 < args.len() {
custom = Some(args[i + 1].clone());
break;
}
i += 1;
}
custom.unwrap_or_else(session::auto_name)
};
if let Some((existing_name, existing_path)) = session::find(Some(&session_name)) {
match client::run(&existing_path, &existing_name) {
Ok(()) => return Ok(()),
Err(e) => {
if let Some(ic) = e.downcast_ref::<client::IncompatibleServerError>() {
eprintln!("ezpn: {ic}");
std::process::exit(2);
}
session::cleanup(&existing_name);
}
}
}
let sock_path = session::spawn_server(&session_name, &original_args)?;
client::run(&sock_path, &session_name)
}