diff --git a/TODO.md b/TODO.md index 24f3394..ffb1995 100644 --- a/TODO.md +++ b/TODO.md @@ -1,5 +1,11 @@ -- [x] feature: ability to give the connection configs a custom name (control how they're displayed in the sidebar) -- [x] feature: ability to remove a database connection -- [x] feature: line numbers in gutter of sql editor -- [x] bug: database type should display nothing instead of `-` when no database is connected. (it should only show the type when it's available) -- [x] feature: per-connection read-only/read-write access, sidebar badges, and atomic single-statement SQL editing with affected counts and RETURNING \ No newline at end of file +- [ ] add selection + copy support in the rows panel. + - should be able to select/highlight an arbitrary rectangle (like vim visual block basically) + - should be able to copy selection + - copied data should be formatted nicely before inserting into the clipboard (system clipboard) + - let's go for a markdown table format and csv format depending on copy action + - should be able to copy with row names (`y` keybinding) + - `ym` should copy to markdown format + - `yc` should copy to csv format + - should be able to copy without row names (`Y` keybinding) + - `Ym` should copy to markdown format + - `Yc` should copy to csv format \ No newline at end of file diff --git a/src/connection.rs b/src/connection.rs index b7d99a8..3ffa38d 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -566,7 +566,7 @@ fn draw_bars( }; let access_width = (access.len() as u16 + if access.is_empty() { 0 } else { 2 }) .min(bottom.width.saturating_sub(position_width + mode_width)); - let provider_width = (Span::raw(provider).width() as u16 + 2) + let provider_width = (Span::raw(provider).width() as u16 + if access.is_empty() { 2 } else { 1 }) .min(bottom.width.saturating_sub(position_width + mode_width + access_width)); let [mode, name_area, provider_area, access_area, cursor] = Layout::horizontal([ Constraint::Length(mode_width), @@ -586,7 +586,11 @@ fn draw_bars( ); frame.render_widget(Paragraph::new(format!(" {name}")).style(base), name_area); frame.render_widget( - Paragraph::new(provider).centered().style(base), + Paragraph::new(provider).alignment(if access.is_empty() { + ratatui::layout::Alignment::Center + } else { + ratatui::layout::Alignment::Right + }).style(base), provider_area, ); if !access.is_empty() { @@ -1626,8 +1630,8 @@ mod tests { let buffer = terminal.backend().buffer(); let footer: String = (0..80).map(|x| buffer[(x, 5)].symbol()).collect(); let expected = match access { - Some(AccessMode::ReadOnly) => "SQLite readonly ░▓ 1:1 ", - Some(AccessMode::ReadWrite) => "SQLite readwrite ░▓ 1:1 ", + Some(AccessMode::ReadOnly) => "SQLite readonly ░▓ 1:1 ", + Some(AccessMode::ReadWrite) => "SQLite readwrite ░▓ 1:1 ", None => "SQLite ░▓ 1:1 ", }; assert!(footer.ends_with(expected), "{footer}"); @@ -1637,6 +1641,7 @@ mod tests { assert_eq!(buffer[(x, 5)].fg, Color::Black); assert_eq!(buffer[(x - 1, 5)].bg, Color::Cyan); assert_eq!(buffer[(x - 2, 5)].bg, Color::Reset); + assert_eq!(buffer[(x - 3, 5)].symbol(), "e"); let end = x + access.map_or("", AccessMode::label).len() as u16 - 1; assert_eq!(buffer[(end, 5)].bg, Color::Cyan); assert_eq!(buffer[(end + 1, 5)].bg, Color::Reset);