komiterm/src/main.rs
2026-07-17 09:30:05 +03:00

108 lines
3.5 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

mod app;
mod hoststats;
mod hotkeys;
mod localfs;
mod profiles;
mod resolve;
mod session;
mod sftp;
mod sshconfig;
mod term;
mod transport;
mod ui;
use anyhow::Result;
use clap::{Parser, Subcommand};
/// KomiTerm — минималистичный MobaXterm-подобный клиент (SSH/Telnet) на Rust
#[derive(Parser, Debug)]
#[command(name = "komiterm")]
struct Cli {
#[command(subcommand)]
command: Option<Command>,
/// Имена сохранённых сессий — каждая откроется в своём табе
/// (`komiterm myserver staging-box`). Без аргументов и без subcommand —
/// открывается менеджер сессий и запускается один таб.
session: Vec<String>,
}
#[derive(Subcommand, Debug)]
enum Command {
/// Управление профилями входа (логин + пароль/ключ/agent),
/// переиспользуемыми между сессиями.
Profile {
#[command(subcommand)]
action: ProfileAction,
},
}
#[derive(Subcommand, Debug)]
enum ProfileAction {
/// Добавить новый профиль (интерактивно спросит логин и способ входа)
Add,
/// Показать все сохранённые профили
List,
/// Удалить профиль по имени
Remove { name: String },
}
#[tokio::main]
async fn main() -> Result<()> {
let cli = Cli::parse();
if let Some(Command::Profile { action }) = cli.command {
return handle_profile_action(action);
}
let sessions = session::SessionStore::load()?;
// Пустой список — не ошибка: app::run покажет список сессий прямо
// в TUI (уже в raw-режиме), а не будет спрашивать тут через stdin.
let targets = cli
.session
.iter()
.map(|name| {
sessions
.get(name)
.cloned()
.ok_or_else(|| anyhow::anyhow!("сессия '{name}' не найдена"))
})
.collect::<Result<Vec<_>>>()?;
let credentials = profiles::CredentialStore::load()?;
let ssh_config = sshconfig::SshConfig::load_default()?;
app::run(targets, sessions, credentials, ssh_config).await
}
fn handle_profile_action(action: ProfileAction) -> Result<()> {
let mut store = profiles::CredentialStore::load()?;
match action {
ProfileAction::Add => {
let profile = profiles::prompt_new_profile()?;
store.profiles.retain(|p| p.name != profile.name);
store.profiles.push(profile);
store.save()?;
println!("Профиль сохранён в {}", profiles::CredentialStore::config_path()?.display());
}
ProfileAction::List => {
if store.profiles.is_empty() {
println!("Профилей пока нет. Добавь через `komiterm profile add`.");
}
for p in &store.profiles {
println!("- {} ({})", p.name, p.username);
}
}
ProfileAction::Remove { name } => {
let before = store.profiles.len();
store.profiles.retain(|p| p.name != name);
if store.profiles.len() == before {
anyhow::bail!("профиль '{name}' не найден");
}
store.save()?;
println!("Профиль '{name}' удалён.");
}
}
Ok(())
}