Skip to content

Commit

Permalink
feat: add custom pattern option (#62)
Browse files Browse the repository at this point in the history
  • Loading branch information
quantumsheep authored Feb 16, 2024
1 parent d6e3d7e commit f3fc600
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 15 deletions.
72 changes: 62 additions & 10 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ crossterm = "0.27.0"
fuzzy-matcher = "0.3.7"
itertools = "0.12.1"
ratatui = "0.26.1"
regex = { version = "1.10.3", default-features = false, features = ["std"] }
shellexpand = "3.1.0"
shlex = "1.3.0"
ssh2-config = "0.2.3"
tui-input = "0.8.0"
unicode-width = "0.1.11"
10 changes: 7 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ struct Args {
config: String,

/// Shows ProxyCommand
#[arg(short, long, default_value_t = false)]
proxy: bool,
#[arg(long, default_value_t = false)]
show_proxy_command: bool,

/// Host search filter
#[arg(short, long)]
Expand All @@ -24,6 +24,9 @@ struct Args {
#[arg(long, default_value_t = true)]
sort: bool,

#[arg(short, long)]
pattern: Option<String>,

/// Exit after ending the SSH session
#[arg(short, long, default_value_t = false)]
exit: bool,
Expand All @@ -36,7 +39,8 @@ fn main() -> Result<(), Box<dyn Error>> {
config_path: args.config,
search_filter: args.search,
sort_by_name: args.sort,
display_proxy_command: args.proxy,
show_proxy_command: args.show_proxy_command,
ssh_pattern: args.pattern,
exit_after_ssh: args.exit,
})?;
app.start()?;
Expand Down
43 changes: 43 additions & 0 deletions src/ssh.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use itertools::Itertools;
use regex::Regex;
use ssh2_config::{ParseRule, SshConfig};
use std::collections::VecDeque;
use std::error::Error;
use std::fs::File;
use std::{io::BufReader, process::Command};
Expand Down Expand Up @@ -27,6 +29,47 @@ pub fn connect(host: &Host) -> Result<(), Box<dyn Error>> {
Ok(())
}

/// # Format
/// - %h - Hostname
/// - %u - User
/// - %p - Port
///
/// Use %% to escape the % character.
///
/// # Errors
///
/// Will return `Err` if the command cannot be executed.
///
/// # Panics
///
/// Will panic if the regex cannot be compiled.
pub fn run_with_pattern(pattern: &str, host: &Host) -> Result<(), Box<dyn Error>> {
let re = Regex::new(r"(?P<skip>%%)|(?P<h>%h)|(?P<u>%u)|(?P<p>%p)").unwrap();
let command = re.replace_all(pattern, |caps: &regex::Captures| {
if let Some(p) = caps.name("skip") {
p.as_str().to_string()
} else if caps.name("h").is_some() {
host.hostname.clone()
} else if caps.name("u").is_some() {
host.user.clone()
} else if caps.name("p").is_some() {
host.port.clone()
} else {
String::new()
}
});

let mut args = shlex::split(&command)
.ok_or(format!("Failed to parse command: {command}"))?
.into_iter()
.collect::<VecDeque<String>>();
let command = args.pop_front().ok_or("Failed to get command")?;

Command::new(command).args(args).spawn()?.wait()?;

Ok(())
}

/// # Errors
///
/// Will return `Err` if the SSH configuration file cannot be parsed.
Expand Down
10 changes: 8 additions & 2 deletions src/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ pub struct AppConfig {

pub search_filter: Option<String>,
pub sort_by_name: bool,
pub display_proxy_command: bool,
pub show_proxy_command: bool,

pub ssh_pattern: Option<String>,
pub exit_after_ssh: bool,
}

Expand Down Expand Up @@ -120,7 +121,12 @@ impl App {
let host = &self.hosts[selected];

restore_terminal(terminal).expect("Failed to restore terminal");
ssh::connect(host)?;

if let Some(pattern) = &self.config.ssh_pattern {
ssh::run_with_pattern(pattern, host)?;
} else {
ssh::connect(host)?;
}

if self.config.exit_after_ssh {
return Ok(());
Expand Down

0 comments on commit f3fc600

Please sign in to comment.