fix: place help below both panes and status in table border

This commit is contained in:
Valdemar Lorenzen
2026-10-19 13:46:59 +02:00
parent de7d373cca
commit 0ffcef494f
3 changed files with 69 additions and 44 deletions
+61 -43
View File
@@ -152,18 +152,17 @@ impl App {
}
pub(crate) fn draw(&mut self, frame: &mut Frame, area: Rect, focused: bool) {
if area.width < 38 || area.height < 12 {
if area.width < 38 || area.height < 10 {
frame.render_widget(
Paragraph::new("Enlarge terminal to at least 70×12. q to quit."),
area,
);
return;
}
let [header, body, status, help] = Layout::vertical([
let [header, body, error_area] = Layout::vertical([
Constraint::Length(1),
Constraint::Min(4),
Constraint::Length(2),
Constraint::Length(2),
Constraint::Length(1),
])
.areas(area);
frame.render_widget(
@@ -181,7 +180,6 @@ impl App {
} else {
" Rows · s for schema "
};
let content_block = panel(title, focused);
let count = if self.show_schema {
5
} else {
@@ -197,6 +195,40 @@ impl App {
Constraint::Length(20)
}
});
let description = if let Some(index) = self.active {
let relation = &self.relations[index];
if self.show_schema {
format!(
" {} [{}] · {} columns · fields {}–{}/5",
relation.label,
relation.kind,
self.columns.len(),
self.column_offset + 1,
self.column_offset + visible
)
} else {
let start = if self.page.rows.is_empty() {
0
} else {
self.page_index * PAGE_SIZE + 1
};
let end = self.page_index * PAGE_SIZE + self.page.rows.len();
format!(
" {} [{}] · rows {start}–{end} · page {}{} · columns {}–{}/{}",
relation.label,
relation.kind,
self.page_index + 1,
if self.page.has_next { " (more)" } else { "" },
if count > 0 { self.column_offset + 1 } else { 0 },
self.column_offset + visible,
count
)
}
} else {
" No readable relations. r to refresh.".into()
};
let content_block =
panel(title, focused).title_bottom(Line::from(description).left_aligned());
if self.active.is_none() {
frame.render_widget(
Paragraph::new("Choose a relation and press Enter.").block(content_block),
@@ -266,50 +298,12 @@ impl App {
.highlight_symbol("› ");
frame.render_stateful_widget(table, content, &mut self.rows_state);
}
let description = if let Some(index) = self.active {
let relation = &self.relations[index];
if self.show_schema {
format!(
" {} [{}] · {} columns · fields {}–{}/5",
relation.label,
relation.kind,
self.columns.len(),
self.column_offset + 1,
self.column_offset + visible
)
} else {
let start = if self.page.rows.is_empty() {
0
} else {
self.page_index * PAGE_SIZE + 1
};
let end = self.page_index * PAGE_SIZE + self.page.rows.len();
format!(
" {} [{}] · rows {start}–{end} · page {}{} · columns {}–{}/{}",
relation.label,
relation.kind,
self.page_index + 1,
if self.page.has_next { " (more)" } else { "" },
if count > 0 { self.column_offset + 1 } else { 0 },
self.column_offset + visible,
count
)
}
} else {
" No readable relations. r to refresh.".into()
};
let [description_area, error_area] =
Layout::vertical([Constraint::Length(1), Constraint::Length(1)]).areas(status);
frame.render_widget(Paragraph::new(description), description_area);
if let Some(error) = &self.error {
frame.render_widget(
Paragraph::new(error.as_str()).style(Style::default().fg(Color::Red)),
error_area,
);
}
frame.render_widget(Paragraph::new(
" Tab focus · Esc explorer · ↑↓/jk move · Enter open · s schema/rows\n ←→/hl columns · n/p page · r refresh · c add database · q quit"
).style(Style::default().fg(Color::DarkGray)), help);
}
}
@@ -358,4 +352,28 @@ mod tests {
assert_eq!(moved_index(Some(1), 3, isize::MIN), Some(0));
assert_eq!(moved_index(Some(1), 3, isize::MAX), Some(2));
}
#[test]
fn relation_status_is_in_the_bottom_border() -> crate::Result<()> {
let file = tempfile::NamedTempFile::new()?;
rusqlite::Connection::open(file.path())?.execute_batch(
"CREATE TABLE comments (id INTEGER); INSERT INTO comments VALUES (1);",
)?;
let mut app = super::App::new(crate::db::Database::open_sqlite(file.path())?)?;
let mut terminal = ratatui::Terminal::new(ratatui::backend::TestBackend::new(100, 20))?;
for schema in [false, true] {
app.show_schema = schema;
terminal.draw(|frame| app.draw(frame, frame.area(), true))?;
let buffer = terminal.backend().buffer();
let border: String = (0..100).map(|x| buffer[(x, 18)].symbol()).collect();
assert!(border.starts_with("└ main.comments [table]"), "{border}");
assert!(border.ends_with('┘'), "{border}");
assert!(border.contains(if schema {
"fields 1–4/5"
} else {
"rows 1–1"
}));
}
Ok(())
}
}