From 98d151f345e96cbad77016055fb975c6be79df3b Mon Sep 17 00:00:00 2001 From: Edward Langley Date: Tue, 31 Mar 2026 23:10:52 -0700 Subject: [PATCH] refactor: unsloth/Qwen3.5-35B-A3B-GGUF:Q5_K_M --- src/main.rs | 227 ++++++++++++++++++++++++++++------------------------ 1 file changed, 122 insertions(+), 105 deletions(-) diff --git a/src/main.rs b/src/main.rs index 58526be..c20de04 100644 --- a/src/main.rs +++ b/src/main.rs @@ -295,28 +295,10 @@ fn draw(f: &mut Frame, app: &App) { draw_title(f, main_chunks[0], app); draw_content(f, main_chunks[1], app); draw_tile_bar(f, main_chunks[2], app); - - if is_cmd_mode { - draw_command_bar(f, main_chunks[3], app); - } else { - draw_status(f, main_chunks[3], app); - } + draw_bottom_bar(f, main_chunks[3], app, is_cmd_mode); // Overlays (rendered last so they appear on top) - if matches!(app.mode, AppMode::Help) { - f.render_widget(HelpWidget, size); - } - if matches!(app.mode, AppMode::ImportWizard) { - if let Some(wizard) = &app.wizard { - f.render_widget(ImportWizardWidget::new(wizard), size); - } - } - if matches!(app.mode, AppMode::ExportPrompt { .. }) { - draw_export_prompt(f, size, app); - } - if app.is_empty_model() && matches!(app.mode, AppMode::Normal | AppMode::CommandMode { .. }) { - draw_welcome(f, main_chunks[1], app); - } + draw_overlays(f, main_chunks[1], app); } fn draw_title(f: &mut Frame, area: Rect, app: &App) { @@ -330,17 +312,8 @@ fn draw_title(f: &mut Frame, area: Rect, app: &App) { .unwrap_or_default(); let title = format!(" improvise · {}{}{} ", app.model.name, file, dirty); let right = " ?:help :q quit "; - let pad = " ".repeat((area.width as usize).saturating_sub(title.len() + right.len())); - let line = format!("{title}{pad}{right}"); - f.render_widget( - Paragraph::new(line).style( - Style::default() - .fg(Color::Black) - .bg(Color::Blue) - .add_modifier(Modifier::BOLD), - ), - area, - ); + let line = fill_line(title, right, area.width); + f.render_widget(Paragraph::new(line).style(title_bar_style()), area); } fn draw_content(f: &mut Frame, area: Rect, app: &App) { @@ -406,51 +379,22 @@ fn draw_tile_bar(f: &mut Frame, area: Rect, app: &App) { } fn draw_status(f: &mut Frame, area: Rect, app: &App) { - let mode_badge = match &app.mode { - AppMode::Normal => "NORMAL", - AppMode::Editing { .. } => "INSERT", - AppMode::FormulaEdit { .. } => "FORMULA", - AppMode::FormulaPanel => "FORMULAS", - AppMode::CategoryPanel => "CATEGORIES", - AppMode::CategoryAdd { .. } => "NEW CATEGORY", - AppMode::ItemAdd { .. } => "ADD ITEMS", - AppMode::ViewPanel => "VIEWS", - AppMode::TileSelect { .. } => "TILES", - AppMode::ImportWizard => "IMPORT", - AppMode::ExportPrompt { .. } => "EXPORT", - AppMode::CommandMode { .. } => "COMMAND", - AppMode::Help => "HELP", - AppMode::Quit => "QUIT", - }; - - let search_part = if app.search_mode { - format!(" /{}▌", app.search_query) - } else { - String::new() - }; - + let mode_badge = mode_badge_text(&app.mode); + let search_part = search_indicator(&app.search_query, app.search_mode); let msg = if !app.status_msg.is_empty() { app.status_msg.as_str() } else { app.hint_text() }; - let yank_indicator = if app.yanked.is_some() { " [yank]" } else { "" }; let view_badge = format!(" {}{} ", app.model.active_view, yank_indicator); let left = format!(" {mode_badge}{search_part} {msg}"); - let right = view_badge; - let pad = " ".repeat((area.width as usize).saturating_sub(left.len() + right.len())); - let line = format!("{left}{pad}{right}"); - - let badge_style = match &app.mode { - AppMode::Editing { .. } => Style::default().fg(Color::Black).bg(Color::Green), - AppMode::CommandMode { .. } => Style::default().fg(Color::Black).bg(Color::Yellow), - AppMode::TileSelect { .. } => Style::default().fg(Color::Black).bg(Color::Magenta), - _ => Style::default().fg(Color::Black).bg(Color::DarkGray), - }; - - f.render_widget(Paragraph::new(line).style(badge_style), area); + let line = fill_line(left, &view_badge, area.width); + f.render_widget( + Paragraph::new(line).style(status_bar_style(&app.mode)), + area, + ); } fn draw_command_bar(f: &mut Frame, area: Rect, app: &App) { @@ -460,10 +404,7 @@ fn draw_command_bar(f: &mut Frame, area: Rect, app: &App) { "" }; let line = format!(":{buf}▌"); - f.render_widget( - Paragraph::new(line).style(Style::default().fg(Color::White).bg(Color::Black)), - area, - ); + f.render_widget(Paragraph::new(line).style(command_bar_style()), area); } fn draw_export_prompt(f: &mut Frame, area: Rect, app: &App) { @@ -472,18 +413,15 @@ fn draw_export_prompt(f: &mut Frame, area: Rect, app: &App) { } else { "" }; - let popup_w = 64u16.min(area.width); - let x = area.x + area.width.saturating_sub(popup_w) / 2; - let y = area.y + area.height / 2; - let popup_area = Rect::new(x, y, popup_w, 3); + let popup = centered_popup(area, 64, 3); + f.render_widget(Clear, popup); - f.render_widget(Clear, popup_area); let block = Block::default() .borders(Borders::ALL) .border_style(Style::default().fg(Color::Yellow)) .title(" Export CSV — path (Esc cancel) "); - let inner = block.inner(popup_area); - f.render_widget(block, popup_area); + let inner = block.inner(popup); + f.render_widget(block, popup); f.render_widget( Paragraph::new(format!("{buf}▌")).style(Style::default().fg(Color::Green)), inner, @@ -491,12 +429,7 @@ fn draw_export_prompt(f: &mut Frame, area: Rect, app: &App) { } fn draw_welcome(f: &mut Frame, area: Rect, _app: &App) { - let w = 58u16.min(area.width.saturating_sub(4)); - let h = 20u16.min(area.height.saturating_sub(2)); - let x = area.x + area.width.saturating_sub(w) / 2; - let y = area.y + area.height.saturating_sub(h) / 2; - let popup = Rect::new(x, y, w, h); - + let popup = centered_popup(area, 58, 20); f.render_widget(Clear, popup); let block = Block::default() @@ -506,7 +439,35 @@ fn draw_welcome(f: &mut Frame, area: Rect, _app: &App) { let inner = block.inner(popup); f.render_widget(block, popup); - let lines: &[(&str, Style)] = &[ + let lines = welcome_lines(); + for (i, (text, style)) in lines.iter().enumerate() { + if i >= inner.height as usize { + break; + } + f.render_widget( + Paragraph::new(*text).style(*style), + Rect::new( + inner.x + 1, + inner.y + i as u16, + inner.width.saturating_sub(2), + 1, + ), + ); + } +} + +// ── Drawing Helpers ────────────────────────────────────────────────────────── + +fn title_bar_style() -> Style { + Style::default().fg(Color::Black).bg(Color::Blue).add_modifier(Modifier::BOLD) +} + +fn command_bar_style() -> Style { + Style::default().fg(Color::White).bg(Color::Black) +} + +fn welcome_lines() -> Vec<(&'static str, Style)> { + vec![ ( "Multi-dimensional data modeling — in your terminal.", Style::default().fg(Color::White), @@ -514,9 +475,7 @@ fn draw_welcome(f: &mut Frame, area: Rect, _app: &App) { ("", Style::default()), ( "Getting started", - Style::default() - .fg(Color::Blue) - .add_modifier(Modifier::BOLD), + Style::default().fg(Color::Blue).add_modifier(Modifier::BOLD), ), ("", Style::default()), ( @@ -546,9 +505,7 @@ fn draw_welcome(f: &mut Frame, area: Rect, _app: &App) { ("", Style::default()), ( "Navigation", - Style::default() - .fg(Color::Blue) - .add_modifier(Modifier::BOLD), + Style::default().fg(Color::Blue).add_modifier(Modifier::BOLD), ), ("", Style::default()), ( @@ -569,20 +526,80 @@ fn draw_welcome(f: &mut Frame, area: Rect, _app: &App) { Style::default(), ), (":q Quit", Style::default()), - ]; + ] +} - for (i, (text, style)) in lines.iter().enumerate() { - if i >= inner.height as usize { - break; - } - f.render_widget( - Paragraph::new(*text).style(*style), - Rect::new( - inner.x + 1, - inner.y + i as u16, - inner.width.saturating_sub(2), - 1, - ), - ); +fn fill_line(left: String, right: &str, width: u16) -> String { + let pad = " ".repeat((width as usize).saturating_sub(left.len() + right.len())); + format!("{left}{pad}{right}") +} + +fn status_bar_style(mode: &AppMode) -> Style { + match mode { + AppMode::Editing { .. } => Style::default().fg(Color::Black).bg(Color::Green), + AppMode::CommandMode { .. } => Style::default().fg(Color::Black).bg(Color::Yellow), + AppMode::TileSelect { .. } => Style::default().fg(Color::Black).bg(Color::Magenta), + _ => Style::default().fg(Color::Black).bg(Color::DarkGray), + } +} + +fn mode_badge_text(mode: &AppMode) -> &'static str { + match mode { + AppMode::Normal => "NORMAL", + AppMode::Editing { .. } => "INSERT", + AppMode::FormulaEdit { .. } => "FORMULA", + AppMode::FormulaPanel => "FORMULAS", + AppMode::CategoryPanel => "CATEGORIES", + AppMode::CategoryAdd { .. } => "NEW CATEGORY", + AppMode::ItemAdd { .. } => "ADD ITEMS", + AppMode::ViewPanel => "VIEWS", + AppMode::TileSelect { .. } => "TILES", + AppMode::ImportWizard => "IMPORT", + AppMode::ExportPrompt { .. } => "EXPORT", + AppMode::CommandMode { .. } => "COMMAND", + AppMode::Help => "HELP", + AppMode::Quit => "QUIT", + } +} + +fn search_indicator(query: &str, active: bool) -> String { + if active { + format!(" /{}▌", query) + } else { + String::new() + } +} + +fn centered_popup(area: Rect, width: u16, height: u16) -> Rect { + let w = width.min(area.width); + let h = height.min(area.height); + let x = area.x + area.width.saturating_sub(w) / 2; + let y = area.y + area.height.saturating_sub(h) / 2; + Rect::new(x, y, w, h) +} + +fn draw_bottom_bar(f: &mut Frame, area: Rect, app: &App, is_cmd_mode: bool) { + if is_cmd_mode { + draw_command_bar(f, area, app); + } else { + draw_status(f, area, app); + } +} + +fn draw_overlays(f: &mut Frame, content_area: Rect, app: &App) { + let size = f.area(); + if matches!(app.mode, AppMode::Help) { + f.render_widget(HelpWidget, size); + } + if matches!(app.mode, AppMode::ImportWizard) { + if let Some(wizard) = &app.wizard { + f.render_widget(ImportWizardWidget::new(wizard), size); + } + } + if matches!(app.mode, AppMode::ExportPrompt { .. }) { + draw_export_prompt(f, size, app); + } + if app.is_empty_model() && matches!(app.mode, AppMode::Normal | AppMode::CommandMode { .. }) { + draw_welcome(f, content_area, app); } }