From 9bb6854125162ed26e5465b869a4b55e3746f425 Mon Sep 17 00:00:00 2001 From: rain-bus Date: Wed, 30 Oct 2024 21:18:02 +0800 Subject: [PATCH] Debug --- Cargo.lock | 7 +++ Cargo.toml | 1 + src/global.rs | 1 + src/main.rs | 19 +++++-- src/session.rs | 2 + src/session/connection.rs | 99 +++++++++++++++++++++++++++++++++++++ src/session/credential.rs | 58 ++++++++++++++++++++++ src/util.rs | 1 + src/util/file.rs | 2 + src/view/component.rs | 2 +- src/view/component/block.rs | 11 ++++- src/view/component/help.rs | 2 +- src/view/component/input.rs | 7 ++- src/view/home.rs | 4 +- src/view/setting.rs | 24 ++++----- 15 files changed, 216 insertions(+), 24 deletions(-) create mode 100644 src/global.rs create mode 100644 src/session.rs create mode 100644 src/session/connection.rs create mode 100644 src/session/credential.rs create mode 100644 src/util.rs create mode 100644 src/util/file.rs diff --git a/Cargo.lock b/Cargo.lock index 638d48e..c5e57cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -172,6 +172,12 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.159" @@ -326,6 +332,7 @@ name = "rstemp" version = "0.1.0" dependencies = [ "crossterm", + "lazy_static", "ratatui", "unicode-width 0.2.0", ] diff --git a/Cargo.toml b/Cargo.toml index 6f8c9fb..975defc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,5 +5,6 @@ edition = "2021" [dependencies] crossterm = { version = "0.28.1", features = ["event-stream"] } +lazy_static = "1.5.0" ratatui = { version = "0.28.1", features = ["all-widgets"] } unicode-width = "0.2.0" diff --git a/src/global.rs b/src/global.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/global.rs @@ -0,0 +1 @@ + diff --git a/src/main.rs b/src/main.rs index d255063..4e3a017 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,13 +1,24 @@ use std::io; use app::App; +use session::connection::{Connection, ShConnection}; mod app; +mod session; mod view; +mod global; +mod util; + +// fn main() -> io::Result<()> { +// let mut terminal = ratatui::init(); +// let app_result = App::default().run(&mut terminal); +// ratatui::restore(); +// app_result +// } +// fn main() -> io::Result<()> { - let mut terminal = ratatui::init(); - let app_result = App::default().run(&mut terminal); - ratatui::restore(); - app_result + let sh = ShConnection::new("zsh".to_string(), "/usr/bin/nu".to_string(), None); + let _ = sh.exec_cmd(); + Ok(()) } diff --git a/src/session.rs b/src/session.rs new file mode 100644 index 0000000..5548632 --- /dev/null +++ b/src/session.rs @@ -0,0 +1,2 @@ +pub mod connection; +mod credential; diff --git a/src/session/connection.rs b/src/session/connection.rs new file mode 100644 index 0000000..c90d3ee --- /dev/null +++ b/src/session/connection.rs @@ -0,0 +1,99 @@ +use std::{env, io, path::Path, process::Command}; + +use super::credential::{Credential, CredentialType}; + +pub trait Connection { + fn exec_cmd(&self) -> io::Result<()>; +} + +pub struct ShConnection { + name: String, + path: String, + args: Vec, +} + +impl Connection for ShConnection { + fn exec_cmd(&self) -> io::Result<()> { + Command::new(&self.path).args(&self.args).spawn()?.wait()?; + Ok(()) + + // if output.status.success() { + // Ok(String::from_utf8_lossy(&output.stdout).into_owned()) + // } else { + // Err(io::Error::new( + // io::ErrorKind::Other, + // String::from_utf8_lossy(&output.stderr).into_owned(), + // )) + // } + } +} + +impl ShConnection { + pub fn new(name: String, path: String, args: Option>) -> Self { + ShConnection { + name, + path, + args: args.unwrap_or_else(Vec::new), + } + } +} + +pub struct SshConnection { + name: String, + host: String, + port: u16, + user: String, + credential_name: String, +} + +impl SshConnection { + pub fn new( + name: String, + host: String, + port: u16, + user: String, + credential_name: String, + ) -> Self { + Self { + name, + host, + port, + user, + credential_name, + } + } +} + +impl Connection for SshConnection { + fn exec_cmd(&self) -> io::Result<()> { + let credential = + Credential::new("zsh".to_string(), CredentialType::Password("".to_string())); + let mut ssh_command = Command::new("ssh"); + let secret_path = env::temp_dir().join("tethers").join("secret.tmp"); + ssh_command + .args(["-p", &self.port.to_string()]) + .args(["-l", &self.user]); + match credential.credential() { + CredentialType::Password(pwd) => { + println!("{}", pwd); + } + CredentialType::Secret(secret) => { + let _ = credential.write_secret(&secret_path); + ssh_command.args(["-i", secret_path.to_str().unwrap()]); + println!("{}", secret); + } + } + ssh_command.arg(&self.host); + ssh_command.spawn()?.wait()?; + Ok(()) + } +} + +pub enum Connections { + Sh(ShConnection), + Ssh(SshConnection), +} + +pub struct ConnectionManager { + connections: Vec, +} diff --git a/src/session/credential.rs b/src/session/credential.rs new file mode 100644 index 0000000..73d0bf0 --- /dev/null +++ b/src/session/credential.rs @@ -0,0 +1,58 @@ +use std::{ + fs::OpenOptions, + io::{self, Write}, + os::unix::fs::OpenOptionsExt, + path::Path, +}; + +pub enum CredentialType { + Password(String), + Secret(String), +} + +pub struct Credential { + credential: CredentialType, + name: String, +} + +impl Credential { + pub fn write_secret(&self, secret_path: &Path) -> io::Result<()> { + match &self.credential { + CredentialType::Secret(secret) => { + let mut secret_file = OpenOptions::new() + .write(true) + .create(true) + .mode(0o600) + .open(secret_path)?; + let _ = secret_file.set_len(0); + let _ = secret_file.write_all(secret.as_bytes()); + } + _ => {} + } + Ok(()) + } +} + +impl Credential { + pub fn new(name: String, credential: CredentialType) -> Self { + Self { name, credential } + } + + pub fn credential(&self) -> &CredentialType { + &self.credential + } +} + +#[derive(Default)] +pub struct CredentialManager { + credentials: Vec, +} + +impl CredentialManager { + pub fn find_by_name(&self, name: &str) -> io::Result<&Credential> { + self.credentials + .iter() + .find(|credential| credential.name == name) + .ok_or_else(|| io::Error::new(io::ErrorKind::NotFound, "Credential not found")) + } +} diff --git a/src/util.rs b/src/util.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/util.rs @@ -0,0 +1 @@ + diff --git a/src/util/file.rs b/src/util/file.rs new file mode 100644 index 0000000..139597f --- /dev/null +++ b/src/util/file.rs @@ -0,0 +1,2 @@ + + diff --git a/src/view/component.rs b/src/view/component.rs index 870d35d..c24a191 100644 --- a/src/view/component.rs +++ b/src/view/component.rs @@ -6,10 +6,10 @@ use ratatui::widgets::Widget; use super::ActiveState; pub mod block; +pub mod button; pub mod help; pub mod input; pub mod list; -pub mod button; pub trait Component { type EventResult; diff --git a/src/view/component/block.rs b/src/view/component/block.rs index d7bdb0c..4e74c1a 100644 --- a/src/view/component/block.rs +++ b/src/view/component/block.rs @@ -1,6 +1,9 @@ use std::marker::PhantomData; -use ratatui::{style::{Style, Stylize}, widgets::{Block, Borders}}; +use ratatui::{ + style::{Style, Stylize}, + widgets::{Block, Borders}, +}; #[derive(Default)] pub struct BlockComponent<'a> { @@ -13,7 +16,11 @@ impl<'a> BlockComponent<'a> { pub fn widget(&self) -> Block<'a> { Block::default() .borders(Borders::ALL) - .border_style(if self.active {Style::new().blue()} else {Style::new().white()}) + .border_style(if self.active { + Style::new().blue() + } else { + Style::new().white() + }) .title(self.title.clone()) } diff --git a/src/view/component/help.rs b/src/view/component/help.rs index e4e1cea..417e7a5 100644 --- a/src/view/component/help.rs +++ b/src/view/component/help.rs @@ -9,7 +9,7 @@ use super::{block::BlockComponent, Component}; #[derive(Default)] pub struct HelpComponent { - active_state: ActiveState + active_state: ActiveState, } impl Component for HelpComponent { diff --git a/src/view/component/input.rs b/src/view/component/input.rs index 3d09e40..3742e68 100644 --- a/src/view/component/input.rs +++ b/src/view/component/input.rs @@ -21,7 +21,7 @@ pub struct InputComponent { name: String, value: String, cursor: usize, - active_state: ActiveState + active_state: ActiveState, } impl InputComponent { @@ -39,7 +39,10 @@ impl Component for InputComponent { type EventResult = InputEvent; fn widget(&self) -> impl Widget { - let block = BlockComponent::default().title(self.name.clone()).active(self.active_state.is_active()).widget(); + let block = BlockComponent::default() + .title(self.name.clone()) + .active(self.active_state.is_active()) + .widget(); let input = Paragraph::new(self.value.clone()).block(block); input } diff --git a/src/view/home.rs b/src/view/home.rs index b28b851..224219d 100644 --- a/src/view/home.rs +++ b/src/view/home.rs @@ -37,8 +37,8 @@ impl Default for Home { help: HelpComponent::default(), setting: SettingView::default(), }; - home.table.active_state().set_active(true); - // home.setting.active_state().set_active(true); + // home.table.active_state().set_active(true); + home.setting.active_state().set_active(true); home } } diff --git a/src/view/setting.rs b/src/view/setting.rs index 3fa71d5..1c74c55 100644 --- a/src/view/setting.rs +++ b/src/view/setting.rs @@ -25,32 +25,32 @@ impl SettingView {} impl Default for SettingView { fn default() -> Self { - SettingView { + let mut seting = SettingView { area: Rect::new(0, 0, 10, 5), menu: ListComponent::default().selectable(), activate_state: Default::default(), - } + }; + seting.menu.active_state().set_active(true); + seting } } impl View for SettingView { fn draw(&self, frame: &mut ratatui::Frame) { - let area = center_rect(frame.area(), self.area.width, self.area.height); - if self.activate_state.is_active() { - let layout = Layout::default() - .constraints([Constraint::default()]) - .split(area); - frame.render_widget(Clear, area); - frame.render_widget(self.menu.widget(), layout[0]); - } else { - frame.render_widget(Clear, area); + if !self.activate_state.is_active() { + return; } + let area = center_rect(frame.area(), self.area.width, self.area.height); + let layout = Layout::default() + .constraints([Constraint::default()]) + .split(area); + frame.render_widget(self.menu.widget(), layout[0]); } fn handle_event(&mut self, event: &crossterm::event::Event) -> io::Result<()> { match self.menu.event_handler(event) { Ok(ListEvent::Select(idx)) => { - // self.menu.active_state().set_active(false); + self.activate_state.set_active(false); println!("{}", idx); } _ => {}