diff --git a/src/app.rs b/src/app.rs index 6eb29db..978b0bd 100644 --- a/src/app.rs +++ b/src/app.rs @@ -31,7 +31,7 @@ pub struct App { pub config_paragraph_offset: u16, pub db: FileDatabase, pub show_help: bool, - pub config: Config, + pub _config: Config, } impl App { @@ -52,7 +52,7 @@ impl App { db, searcher: Searcher::new(), show_help: false, - config, + _config: config, }) } diff --git a/src/ssh_config_store.rs b/src/ssh_config_store.rs index 10b2e04..0053c18 100644 --- a/src/ssh_config_store.rs +++ b/src/ssh_config_store.rs @@ -2,6 +2,45 @@ use crate::database::FileDatabase; use anyhow::{format_err, Result}; use ssh_cfg::{SshConfig, SshConfigParser, SshHostConfig}; use std::fmt::Debug; +use std::collections::HashMap; +use std::fs::read_to_string; +use std::path::PathBuf; + +trait ConfigComments { + fn get_comments(&self) -> HashMap; +} + +impl ConfigComments for SshConfig { + fn get_comments(&self) -> HashMap { + let mut comments = HashMap::new(); + + let home = std::env::var("HOME").unwrap_or_else(|_| ".".to_string()); + let config_path = PathBuf::from(home).join(".ssh").join("config"); + + if let Ok(contents) = read_to_string(config_path) { + let mut current_comment = Vec::new(); + + for line in contents.lines() { + let trimmed = line.trim(); + + if trimmed.starts_with('#') { + let comment_text = trimmed[1..].trim().to_string(); + current_comment.push(comment_text); + } else if trimmed.starts_with("Host ") { + let host = trimmed["Host ".len()..].trim().to_string(); + if !current_comment.is_empty() { + comments.insert(host, current_comment.join("\n")); + current_comment.clear(); + } + } else if trimmed.is_empty() { + current_comment.clear(); + } + } + } + + comments + } +} #[derive(Debug)] pub struct SshGroupItem { @@ -10,6 +49,7 @@ pub struct SshGroupItem { pub connection_count: i64, pub last_used: i64, pub host_config: SshHostConfig, + pub comment: Option, } #[derive(Debug)] @@ -28,12 +68,14 @@ impl SshConfigStore { pub async fn new(db: &FileDatabase) -> Result { let ssh_config = SshConfigParser::parse_home().await?; + let comments = ssh_config.get_comments(); + let mut scs = SshConfigStore { config: ssh_config, groups: Vec::new(), }; - scs.create_ssh_groups(db); + scs.create_ssh_groups(db, &comments); if scs.groups.is_empty() { return Err(format_err!("Your configuration file contains no entries (or only wildcards) ! Please add at least one.")); @@ -42,7 +84,7 @@ impl SshConfigStore { Ok(scs) } - fn create_ssh_groups(&mut self, db: &FileDatabase) { + fn create_ssh_groups(&mut self, db: &FileDatabase, comments: &std::collections::HashMap) { let mut groups: Vec = vec![SshGroup { name: "Others".to_string(), items: Vec::new(), @@ -67,6 +109,7 @@ impl SshConfigStore { last_used: host_entry.last_used_date, full_name: key.to_string(), host_config: value.clone(), + comment: comments.get(key).cloned(), }; if group.is_none() { @@ -90,6 +133,7 @@ impl SshConfigStore { last_used: host_entry.last_used_date, name: key.to_string(), host_config: value.clone(), + comment: comments.get(key).cloned(), }); }); diff --git a/src/widgets/block.rs b/src/widgets/block.rs index 792073a..5f4a25f 100644 --- a/src/widgets/block.rs +++ b/src/widgets/block.rs @@ -5,7 +5,7 @@ use tui::{ widgets::{Block, Borders}, }; -pub fn new(title: &str) -> Block { +pub fn new(title: &str) -> Block<'_> { Block::default() .borders(Borders::ALL) .border_style(Style::default().fg(THEME.border_color())) diff --git a/src/widgets/config_widget.rs b/src/widgets/config_widget.rs index cc21cc3..416a70a 100644 --- a/src/widgets/config_widget.rs +++ b/src/widgets/config_widget.rs @@ -60,14 +60,16 @@ impl ConfigWidget { .wrap(Wrap { trim: false }) } - fn ssh_group_item_to_spans(config: &SshGroupItem) -> Vec { - let mut spans = vec![Spans::from(vec![ + fn ssh_group_item_to_spans(config: &SshGroupItem) -> Vec> { + let mut spans = Vec::new(); + + spans.push(Spans::from(vec![ Span::styled("Host ", Style::default().fg(THEME.text_primary())), Span::styled( &config.full_name, Style::default().fg(THEME.text_secondary()), ), - ])]; + ])); config.host_config.iter().for_each(|(key, value)| { spans.push(Spans::from(vec![ @@ -78,6 +80,20 @@ impl ConfigWidget { ])); }); + if let Some(comment) = &config.comment { + spans.push(Spans::from(vec![Span::styled( + " Notes", + Style::default().fg(THEME.text_primary()), + )])); + + for line in comment.lines() { + spans.push(Spans::from(vec![ + Span::styled(" ", Style::default().fg(THEME.text_primary())), + Span::styled(line, Style::default().fg(THEME.text_secondary())), + ])); + } + } + spans.push(Spans::from(vec![Span::styled( "\n", Style::default().fg(THEME.text_secondary()),