use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum SshHostSource {
Config,
KnownHosts,
History,
Mdns,
}
impl std::fmt::Display for SshHostSource {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Config => write!(f, "SSH Config"),
Self::KnownHosts => write!(f, "Known Hosts"),
Self::History => write!(f, "History"),
Self::Mdns => write!(f, "mDNS"),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SshHost {
pub alias: String,
pub hostname: Option<String>,
pub user: Option<String>,
pub port: Option<u16>,
pub identity_file: Option<String>,
pub proxy_jump: Option<String>,
pub source: SshHostSource,
}
impl SshHost {
pub fn display_name(&self) -> &str {
&self.alias
}
pub fn connection_target(&self) -> &str {
self.hostname.as_deref().unwrap_or(&self.alias)
}
pub fn ssh_args(&self) -> Vec<String> {
let mut args = Vec::new();
if let Some(port) = self.port
&& port != 22
{
args.push("-p".to_string());
args.push(port.to_string());
}
if let Some(ref identity) = self.identity_file {
args.push("-i".to_string());
args.push(identity.clone());
}
if let Some(ref proxy) = self.proxy_jump {
args.push("-J".to_string());
args.push(proxy.clone());
}
let target = if let Some(ref user) = self.user {
format!("{}@{}", user, self.connection_target())
} else {
self.connection_target().to_string()
};
args.push(target);
args
}
pub fn connection_string(&self) -> String {
let mut s = String::new();
if let Some(ref user) = self.user {
s.push_str(user);
s.push('@');
}
s.push_str(self.connection_target());
if let Some(port) = self.port
&& port != 22
{
s.push(':');
s.push_str(&port.to_string());
}
s
}
}