Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions src/diagnostics.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
use std::path::Path;
use std::process::Command;

#[derive(Debug, Clone)]
pub struct DiagnosticEntry {
pub tool: String,
pub found: bool,
pub version: String,
}

pub fn run_diagnostics() -> Vec<DiagnosticEntry> {
let tools = ["apt", "brew", "pacman", "yay", "curl", "git"];
let mut results = Vec::new();

for tool in tools {
let found = command_exists(tool);

let version = if found { get_tool_version(tool) } else { "Not Found".to_string() };

results.push(DiagnosticEntry { tool: tool.to_string(), found, version });
}

results.push(DiagnosticEntry {
tool: "TRX".to_string(),
found: true,
version: env!("CARGO_PKG_VERSION").to_string(),
});

if let Some(proj_dirs) = directories::ProjectDirs::from("", "", "trx") {
let config_path = proj_dirs.config_dir().join("config.toml");

results.push(DiagnosticEntry {
tool: "Config".to_string(),
found: Path::new(&config_path).exists(),
version: config_path.display().to_string(),
});
}

results
}

fn command_exists(tool: &str) -> bool {
let check_command = if cfg!(windows) { "where" } else { "which" };

Command::new(check_command)
.arg(tool)
.output()
.map(|output| output.status.success())
.unwrap_or(false)
}

fn get_tool_version(tool: &str) -> String {
Command::new(tool)
.arg("--version")
.output()
.ok()
.and_then(|output| String::from_utf8(output.stdout).ok())
.and_then(|stdout| stdout.lines().next().map(|line| line.trim().to_string()))
.filter(|line| !line.is_empty())
.unwrap_or_else(|| "Unknown".to_string())
}
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod config;
mod diagnostics;
mod fuzzy;
mod managers;
mod sandbox;
Expand Down
40 changes: 29 additions & 11 deletions src/ui/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ pub enum DetailsState {
}

pub struct App {
pub diagnostics_results: Option<Vec<crate::diagnostics::DiagnosticEntry>>,
pub input: String,
pub character_index: usize,
pub input_mode: InputMode,
Expand Down Expand Up @@ -104,6 +105,7 @@ impl App {
};

let mut app = Self {
diagnostics_results: None,
input: String::new(),
input_mode: InputMode::Normal,
current_tab,
Expand Down Expand Up @@ -479,6 +481,17 @@ impl App {
self.set_popup(format!("Border Style: {}", self.config.settings.border_style), Color::Cyan);
}

fn diagnostics_settings_index(&self) -> usize {
let mgr_count = self.available_managers.len();
let mut index = 6 + mgr_count + 3;

if self.config.theme_name == "Custom" {
index += 6;
}

index
}

fn next_spinner_type(&mut self) {
let types = ["Dots", "Bars", "Pulse", "Classic", "Arc", "Braille"];
let current_pos =
Expand Down Expand Up @@ -615,6 +628,16 @@ impl App {
continue;
}

if self.diagnostics_results.is_some()
&& matches!(
key.code,
KeyCode::Esc | KeyCode::Enter | KeyCode::Char('q')
)
{
self.diagnostics_results = None;
continue;
}

match self.input_mode {
InputMode::Normal if key.kind == KeyEventKind::Press => {
let keys = &self.config.keys;
Expand Down Expand Up @@ -764,11 +787,7 @@ impl App {
}
KeyCode::Down | KeyCode::Char('j') => {
if self.current_tab == Tab::Settings {
let max = if self.config.theme_name == "Custom" {
15
} else {
9
};
let max = self.diagnostics_settings_index();
if self.settings_index < max {
self.settings_index += 1;
}
Expand Down Expand Up @@ -838,12 +857,7 @@ impl App {
match mouse_event.kind {
event::MouseEventKind::ScrollDown => {
if self.current_tab == Tab::Settings {
let mgr_count = self.available_managers.len();
let max = if self.config.theme_name == "Custom" {
6 + mgr_count + 6
} else {
6 + mgr_count
};
let max = self.diagnostics_settings_index();
if self.settings_index < max {
self.settings_index += 1;
}
Expand Down Expand Up @@ -987,6 +1001,10 @@ impl App {

fn handle_settings_toggle(&mut self) {
let mgr_count = self.available_managers.len();
if self.settings_index == self.diagnostics_settings_index() {
self.diagnostics_results = Some(crate::diagnostics::run_diagnostics());
return;
}
match self.settings_index {
1 => {
// Auto Update Check
Expand Down
62 changes: 62 additions & 0 deletions src/ui/draw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ pub fn draw_ui(frame: &mut Frame, app: &mut App) {
draw_update_prompt(frame, app, &theme_colors);
}

if app.diagnostics_results.is_some() {
draw_diagnostics_popup(frame, app, &theme_colors);
}

if let Some((msg, color)) = &app.popup_message {
draw_popup(frame, msg, *color, &theme_colors, &app.config.settings.border_style);
}
Expand Down Expand Up @@ -241,6 +245,53 @@ fn draw_popup(
frame.render_widget(paragraph, area);
}

fn draw_diagnostics_popup(frame: &mut Frame, app: &App, theme: &crate::config::Theme) {
let area = centered_rect(85, 80, frame.area());
frame.render_widget(Clear, area);

let border_type = get_border_type(&app.config.settings.border_style);
let border_color = app.config.get_color(&theme.border_color);
let highlight_color = app.config.get_color(&theme.highlight_color);
let primary_color = app.config.get_color(&theme.text_primary);
let secondary_color = app.config.get_color(&theme.text_secondary);

let mut lines = vec![
Line::from(vec![Span::styled(
"Tool Found Version / Path",
Style::default().fg(highlight_color).add_modifier(Modifier::BOLD),
)]),
Line::from(""),
];

if let Some(results) = &app.diagnostics_results {
for entry in results {
let found = if entry.found { "Yes" } else { "No" };
lines.push(Line::from(vec![
Span::styled(format!("{:<20}", entry.tool), Style::default().fg(primary_color)),
Span::styled(format!("{:<10}", found), Style::default().fg(secondary_color)),
Span::styled(entry.version.clone(), Style::default().fg(primary_color)),
]));
}
}

lines.push(Line::from(""));
lines.push(Line::from(Span::styled(
"Press Esc, Enter, or q to close",
Style::default().fg(secondary_color),
)));

let paragraph = Paragraph::new(lines)
.block(
Block::bordered()
.title("System Diagnostics")
.border_type(border_type)
.border_style(Style::default().fg(border_color)),
)
.wrap(Wrap { trim: false });

frame.render_widget(paragraph, area);
}

fn draw_settings_tab(frame: &mut Frame, app: &App, area: Rect, theme: &crate::config::Theme) {
let highlight_color = app.config.get_color(&theme.highlight_color);
let border_color = app.config.get_color(&theme.border_color);
Expand Down Expand Up @@ -357,6 +408,7 @@ fn draw_settings_tab(frame: &mut Frame, app: &App, area: Rect, theme: &crate::co
draw_setting!(current_idx, "Theme Preset", &app.config.theme_name, false);
draw_setting!(current_idx + 1, "Border Style", &app.config.settings.border_style, false);
draw_setting!(current_idx + 2, "Spinner Type", &app.config.settings.spinner_type, false);

current_idx += 3;

if app.config.theme_name == "Custom" {
Expand All @@ -365,6 +417,7 @@ fn draw_settings_tab(frame: &mut Frame, app: &App, area: Rect, theme: &crate::co
"--- Custom Colors ---",
Style::default().fg(highlight_color).add_modifier(Modifier::BOLD),
)));

if let Some(ref ct) = app.config.custom_theme {
draw_setting!(current_idx, "Border Color", &ct.border_color, false);
draw_setting!(current_idx + 1, "Highlight Color", &ct.highlight_color, false);
Expand All @@ -373,8 +426,17 @@ fn draw_settings_tab(frame: &mut Frame, app: &App, area: Rect, theme: &crate::co
draw_setting!(current_idx + 4, "Text Primary", &ct.text_primary, false);
draw_setting!(current_idx + 5, "Text Secondary", &ct.text_secondary, false);
}

current_idx += 6;
}

settings_lines.push(Line::from(""));
settings_lines.push(Line::from(Span::styled(
"--- Diagnostics ---",
Style::default().fg(highlight_color).add_modifier(Modifier::BOLD),
)));
draw_setting!(current_idx, "Run Diagnostics", "Press Enter", true);

let paragraph = Paragraph::new(settings_lines)
.block(
Block::bordered()
Expand Down