style: title and pad floating input windows
This commit is contained in:
+80
-28
@@ -1848,27 +1848,31 @@ fn draw_floating_input(frame: &mut Frame, editor: &Editor, area: Rect) -> Option
|
||||
height,
|
||||
);
|
||||
let bordered = panel.width >= 4 && panel.height >= 3;
|
||||
let block = Block::default()
|
||||
let padding = u16::from(panel.width.saturating_sub(2 * u16::from(bordered)) >= 3);
|
||||
let mut block = Block::default()
|
||||
.borders(if bordered {
|
||||
Borders::ALL
|
||||
} else {
|
||||
Borders::NONE
|
||||
})
|
||||
.border_style(Style::default().fg(Color::Cyan));
|
||||
.border_style(Style::default().fg(Color::Cyan))
|
||||
.padding(ratatui::widgets::Padding::horizontal(padding));
|
||||
if bordered {
|
||||
block = block.title(if editor.mode() == Mode::Search {
|
||||
" Search "
|
||||
} else {
|
||||
" Command "
|
||||
});
|
||||
}
|
||||
let content = block.inner(panel);
|
||||
frame.render_widget(Clear, panel);
|
||||
frame.render_widget(block, panel);
|
||||
let prefix = if editor.mode() == Mode::Search {
|
||||
'/'
|
||||
} else {
|
||||
':'
|
||||
};
|
||||
let command = format!("{prefix}{}", editor.command_line());
|
||||
let column = display_column(&command, usize::MAX);
|
||||
let command = editor.command_line();
|
||||
let column = display_column(command, usize::MAX);
|
||||
let width = usize::from(content.width);
|
||||
let offset = column.saturating_sub(width.saturating_sub(1));
|
||||
frame.render_widget(
|
||||
Paragraph::new(visible_line(&command, offset, width)),
|
||||
Paragraph::new(visible_line(command, offset, width)),
|
||||
content,
|
||||
);
|
||||
frame.set_cursor_position((content.x + (column - offset) as u16, content.y));
|
||||
@@ -1898,13 +1902,19 @@ fn draw_notification(frame: &mut Frame, editor: &Editor, area: Rect) -> Option<R
|
||||
} else {
|
||||
message
|
||||
};
|
||||
let width = (UnicodeWidthStr::width(message.as_ref()).saturating_add(2))
|
||||
.min(60)
|
||||
.min(usize::from(area.width)) as u16;
|
||||
let width = (UnicodeWidthStr::width(message.as_ref()).saturating_add(if area.height >= 3 {
|
||||
4
|
||||
} else {
|
||||
2
|
||||
}))
|
||||
.min(60)
|
||||
.min(usize::from(area.width)) as u16;
|
||||
let bordered = width >= 4 && area.height >= 3;
|
||||
let border = 2 * u16::from(bordered);
|
||||
let padding = u16::from(width.saturating_sub(border) >= 3);
|
||||
let paragraph = Paragraph::new(message).wrap(Wrap { trim: false });
|
||||
let height = (paragraph.line_count(width - border).min(6) as u16 + border).min(area.height);
|
||||
let height = (paragraph.line_count(width - border - 2 * padding).min(6) as u16 + border)
|
||||
.min(area.height);
|
||||
let panel = Rect::new(area.right() - width, area.bottom() - height, width, height);
|
||||
let block = Block::default()
|
||||
.borders(if bordered {
|
||||
@@ -1912,7 +1922,8 @@ fn draw_notification(frame: &mut Frame, editor: &Editor, area: Rect) -> Option<R
|
||||
} else {
|
||||
Borders::NONE
|
||||
})
|
||||
.border_style(Style::default().fg(Color::DarkGray));
|
||||
.border_style(Style::default().fg(Color::DarkGray))
|
||||
.padding(ratatui::widgets::Padding::horizontal(padding));
|
||||
let content = block.inner(panel);
|
||||
frame.render_widget(Clear, panel);
|
||||
frame.render_widget(block, panel);
|
||||
@@ -5582,6 +5593,58 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn floating_fields_use_border_titles_and_inner_horizontal_padding() {
|
||||
for (prefix, title) in [(':', "Command"), ('/', "Search")] {
|
||||
let mut editor = Editor::open(None, vec![]).unwrap();
|
||||
editor.handle(Input::Char(prefix));
|
||||
for ch in "needle".chars() {
|
||||
editor.handle(Input::Char(ch));
|
||||
}
|
||||
let mut terminal = Terminal::new(ratatui::backend::TestBackend::new(80, 12)).unwrap();
|
||||
let mut panel = Rect::default();
|
||||
terminal
|
||||
.draw(|frame| {
|
||||
panel = draw_floating_input(frame, &editor, frame.area()).unwrap();
|
||||
})
|
||||
.unwrap();
|
||||
assert!(
|
||||
pane_screen(&terminal, Rect::new(panel.x, panel.y, panel.width, 1)).contains(title)
|
||||
);
|
||||
let buffer = terminal.backend().buffer();
|
||||
assert_eq!(buffer[(panel.x + 1, panel.y + 1)].symbol(), " ");
|
||||
assert_eq!(buffer[(panel.x + 2, panel.y + 1)].symbol(), "n");
|
||||
assert_eq!(buffer[(panel.right() - 2, panel.y + 1)].symbol(), " ");
|
||||
assert_eq!(
|
||||
terminal.get_cursor_position().unwrap(),
|
||||
Position::new(panel.x + 8, panel.y + 1)
|
||||
);
|
||||
assert_eq!(
|
||||
pane_screen(
|
||||
&terminal,
|
||||
Rect::new(panel.x + 1, panel.y + 1, panel.width - 2, 1)
|
||||
)
|
||||
.trim(),
|
||||
"needle"
|
||||
);
|
||||
}
|
||||
let mut editor = Editor::open(None, vec![]).unwrap();
|
||||
editor.set_message("operation complete");
|
||||
let mut terminal = Terminal::new(ratatui::backend::TestBackend::new(80, 12)).unwrap();
|
||||
let mut panel = Rect::default();
|
||||
terminal
|
||||
.draw(|frame| {
|
||||
panel = draw_notification(frame, &editor, frame.area()).unwrap();
|
||||
})
|
||||
.unwrap();
|
||||
let buffer = terminal.backend().buffer();
|
||||
assert_eq!(buffer[(panel.x + 1, panel.y + 1)].symbol(), " ");
|
||||
assert_eq!(buffer[(panel.x + 2, panel.y + 1)].symbol(), "o");
|
||||
assert_eq!(buffer[(panel.right() - 2, panel.y + 1)].symbol(), " ");
|
||||
assert_eq!(panel.right(), 80);
|
||||
assert_eq!(panel.bottom(), 12);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn floating_inputs_share_workspace_geometry_across_documents_splits_and_diffs() {
|
||||
for context in ["document", "split", "diff", "split-diff", "selector"] {
|
||||
@@ -6357,7 +6420,6 @@ mod tests {
|
||||
if prompting {
|
||||
let input = views.panels.input.unwrap();
|
||||
assert!(input.contains(cursor));
|
||||
assert!(pane_screen(&terminal, input).contains(':'));
|
||||
} else {
|
||||
assert!(viewport.contains(cursor));
|
||||
assert!(pane_screen(&terminal, viewport).contains("DOCUMENT"));
|
||||
@@ -6456,7 +6518,6 @@ mod tests {
|
||||
.unwrap();
|
||||
assert_eq!(views.rects[0].1, before);
|
||||
let input = views.panels.input.unwrap();
|
||||
assert!(pane_screen(&terminal, input).contains(':'));
|
||||
assert!(input.contains(terminal.get_cursor_position().unwrap()));
|
||||
assert_eq!(pane_screen(&terminal, Rect::new(0, 11, 240, 1)), bottom);
|
||||
}
|
||||
@@ -7921,7 +7982,6 @@ mod tests {
|
||||
terminal
|
||||
.draw(|frame| views.draw(frame, &mut editor))
|
||||
.unwrap();
|
||||
assert!(screen_text(&terminal).contains(":diff.close"));
|
||||
editor.handle(Input::Enter);
|
||||
assert!(editor.diff().is_none());
|
||||
assert_eq!(editor.lines(), ["// live comment"]);
|
||||
@@ -12327,7 +12387,6 @@ end
|
||||
)
|
||||
})
|
||||
.unwrap();
|
||||
assert!(screen_text(&terminal).contains("/saved search"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -12976,9 +13035,8 @@ end
|
||||
.unwrap();
|
||||
let buffer = terminal.backend().buffer();
|
||||
let input = panels.input.unwrap();
|
||||
let content = Rect::new(input.x + 1, input.y + 1, input.width - 2, 1);
|
||||
let content = Rect::new(input.x + 2, input.y + 1, input.width - 4, 1);
|
||||
assert_eq!(buffer[(content.x, content.y)].symbol(), "界");
|
||||
assert_eq!(buffer[(content.x + 2, content.y)].symbol(), "界");
|
||||
editor.handle(Input::Backspace);
|
||||
editor.handle(Input::Backspace);
|
||||
editor.handle(Input::Char('\t'));
|
||||
@@ -12995,19 +13053,13 @@ end
|
||||
)
|
||||
})
|
||||
.unwrap();
|
||||
let query = format!("/{}", editor.command_line());
|
||||
let column = display_column(&query, usize::MAX);
|
||||
let offset = column.saturating_sub(usize::from(content.width).saturating_sub(1));
|
||||
assert!(
|
||||
panels
|
||||
.input
|
||||
.unwrap()
|
||||
.contains(terminal.get_cursor_position().unwrap())
|
||||
);
|
||||
assert_eq!(
|
||||
terminal.get_cursor_position().unwrap(),
|
||||
Position::new(content.x + (column - offset) as u16, content.y),
|
||||
);
|
||||
assert!(content.contains(terminal.get_cursor_position().unwrap()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user