From 72307ba9ce94aea6ac827773af82a24fd4ba173b Mon Sep 17 00:00:00 2001 From: FujiApple Date: Tue, 5 Nov 2024 22:00:48 +0800 Subject: [PATCH 1/5] refactor(tui): simplify `frontend::run_app` --- crates/trippy-tui/src/frontend.rs | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/crates/trippy-tui/src/frontend.rs b/crates/trippy-tui/src/frontend.rs index 3f1011611..6d9cce7ea 100644 --- a/crates/trippy-tui/src/frontend.rs +++ b/crates/trippy-tui/src/frontend.rs @@ -43,7 +43,8 @@ pub fn run_frontend( let backend = CrosstermBackend::new(stdout); let mut terminal = Terminal::new(backend)?; let preserve_screen = tui_config.preserve_screen; - let res = run_app(&mut terminal, traces, tui_config, resolver, geoip_lookup); + let mut app = TuiApp::new(tui_config, resolver, geoip_lookup, traces); + let res = run_app(&mut terminal, &mut app); disable_raw_mode()?; if !preserve_screen { execute!(terminal.backend_mut(), LeaveAlternateScreen)?; @@ -56,21 +57,14 @@ pub fn run_frontend( } #[allow(clippy::too_many_lines, clippy::cognitive_complexity)] -fn run_app( - terminal: &mut Terminal, - trace_info: Vec, - tui_config: TuiConfig, - resolver: DnsResolver, - geoip_lookup: GeoIpLookup, -) -> io::Result<()> { - let mut app = TuiApp::new(tui_config, resolver, geoip_lookup, trace_info); +fn run_app(terminal: &mut Terminal, app: &mut TuiApp) -> io::Result<()> { loop { if app.frozen_start.is_none() { app.snapshot_trace_data(); app.clamp_selected_hop(); app.update_order_flow_counts(); }; - terminal.draw(|f| render::app::render(f, &mut app))?; + terminal.draw(|f| render::app::render(f, app))?; if event::poll(app.tui_config.refresh_rate)? { if let Event::Key(key) = event::read()? { if key.kind == KeyEventKind::Press { From bc7efea9308de2aa9b39eba6d84d4fea7d30058d Mon Sep 17 00:00:00 2001 From: FujiApple Date: Tue, 5 Nov 2024 20:59:28 +0800 Subject: [PATCH 2/5] fix(tui): cursor is not moved to the bottom on exit when using --tui-preserve-screen (#1375) --- crates/trippy-tui/src/frontend.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/trippy-tui/src/frontend.rs b/crates/trippy-tui/src/frontend.rs index 6d9cce7ea..7dbc0d69e 100644 --- a/crates/trippy-tui/src/frontend.rs +++ b/crates/trippy-tui/src/frontend.rs @@ -9,6 +9,7 @@ use crossterm::{ execute, terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, }; +use ratatui::layout::Position; use ratatui::{ backend::{Backend, CrosstermBackend}, Terminal, @@ -46,7 +47,10 @@ pub fn run_frontend( let mut app = TuiApp::new(tui_config, resolver, geoip_lookup, traces); let res = run_app(&mut terminal, &mut app); disable_raw_mode()?; - if !preserve_screen { + if preserve_screen { + terminal.set_cursor_position(Position::new(0, terminal.size()?.height))?; + terminal.backend_mut().append_lines(1)?; + } else { execute!(terminal.backend_mut(), LeaveAlternateScreen)?; } terminal.show_cursor()?; From 1b72aed3b8ed31aa425334cdf8695f072d4ebeb3 Mon Sep 17 00:00:00 2001 From: FujiApple Date: Tue, 5 Nov 2024 21:50:14 +0800 Subject: [PATCH 3/5] feat(tui): add `quit-preserve-screen` key binding (#1382) --- crates/trippy-tui/src/config/binding.rs | 15 +++++++++++++++ crates/trippy-tui/src/config/file.rs | 2 ++ crates/trippy-tui/src/frontend.rs | 16 +++++++++++++--- crates/trippy-tui/src/frontend/binding.rs | 2 ++ .../trippy-tui/src/frontend/render/settings.rs | 4 ++++ ...tests__output@tui_binding_commands_match.snap | 2 +- trippy-config-sample.toml | 1 + 7 files changed, 38 insertions(+), 4 deletions(-) diff --git a/crates/trippy-tui/src/config/binding.rs b/crates/trippy-tui/src/config/binding.rs index dde1da652..371975fc9 100644 --- a/crates/trippy-tui/src/config/binding.rs +++ b/crates/trippy-tui/src/config/binding.rs @@ -47,6 +47,7 @@ pub struct TuiBindings { pub toggle_as_info: TuiKeyBinding, pub toggle_hop_details: TuiKeyBinding, pub quit: TuiKeyBinding, + pub quit_preserve_screen: TuiKeyBinding, } impl Default for TuiBindings { @@ -98,6 +99,10 @@ impl Default for TuiBindings { toggle_as_info: TuiKeyBinding::new(KeyCode::Char('z')), toggle_hop_details: TuiKeyBinding::new(KeyCode::Char('d')), quit: TuiKeyBinding::new(KeyCode::Char('q')), + quit_preserve_screen: TuiKeyBinding::new_with_modifier( + KeyCode::Char('q'), + KeyModifiers::SHIFT, + ), } } } @@ -151,6 +156,10 @@ impl TuiBindings { (self.toggle_as_info, TuiCommandItem::ToggleASInfo), (self.toggle_hop_details, TuiCommandItem::ToggleHopDetails), (self.quit, TuiCommandItem::Quit), + ( + self.quit_preserve_screen, + TuiCommandItem::QuitPreserveScreen, + ), ] .iter() .fold( @@ -326,6 +335,10 @@ impl From<(HashMap, ConfigBindings)> for TuiBindi .get(&TuiCommandItem::Quit) .or(cfg.quit.as_ref()) .unwrap_or(&Self::default().quit), + quit_preserve_screen: *cmd_items + .get(&TuiCommandItem::QuitPreserveScreen) + .or(cfg.quit_preserve_screen.as_ref()) + .unwrap_or(&Self::default().quit_preserve_screen), } } } @@ -628,4 +641,6 @@ pub enum TuiCommandItem { ToggleHopDetails, /// Quit the application. Quit, + /// Quit the application and preserve the screen. + QuitPreserveScreen, } diff --git a/crates/trippy-tui/src/config/file.rs b/crates/trippy-tui/src/config/file.rs index 25b367a73..acada47e5 100644 --- a/crates/trippy-tui/src/config/file.rs +++ b/crates/trippy-tui/src/config/file.rs @@ -398,6 +398,7 @@ pub struct ConfigBindings { pub toggle_as_info: Option, pub toggle_hop_details: Option, pub quit: Option, + pub quit_preserve_screen: Option, } impl Default for ConfigBindings { @@ -442,6 +443,7 @@ impl Default for ConfigBindings { toggle_as_info: Some(bindings.toggle_as_info), toggle_hop_details: Some(bindings.toggle_hop_details), quit: Some(bindings.quit), + quit_preserve_screen: Some(bindings.quit_preserve_screen), } } } diff --git a/crates/trippy-tui/src/frontend.rs b/crates/trippy-tui/src/frontend.rs index 7dbc0d69e..4fd0fda68 100644 --- a/crates/trippy-tui/src/frontend.rs +++ b/crates/trippy-tui/src/frontend.rs @@ -47,7 +47,7 @@ pub fn run_frontend( let mut app = TuiApp::new(tui_config, resolver, geoip_lookup, traces); let res = run_app(&mut terminal, &mut app); disable_raw_mode()?; - if preserve_screen { + if preserve_screen || matches!(res, Ok(ExitAction::PreserveScreen)) { terminal.set_cursor_position(Position::new(0, terminal.size()?.height))?; terminal.backend_mut().append_lines(1)?; } else { @@ -60,8 +60,16 @@ pub fn run_frontend( Ok(()) } +/// The exit action to take when the frontend exits. +enum ExitAction { + /// Exit the frontend normally. + Normal, + /// Preserve the screen on exit. + PreserveScreen, +} + #[allow(clippy::too_many_lines, clippy::cognitive_complexity)] -fn run_app(terminal: &mut Terminal, app: &mut TuiApp) -> io::Result<()> { +fn run_app(terminal: &mut Terminal, app: &mut TuiApp) -> io::Result { loop { if app.frozen_start.is_none() { app.snapshot_trace_data(); @@ -221,7 +229,9 @@ fn run_app(terminal: &mut Terminal, app: &mut TuiApp) -> io::Resu } else if bindings.toggle_hop_details.check(key) { app.toggle_hop_details(); } else if bindings.quit.check(key) || CTRL_C.check(key) { - return Ok(()); + return Ok(ExitAction::Normal); + } else if bindings.quit_preserve_screen.check(key) { + return Ok(ExitAction::PreserveScreen); } } } diff --git a/crates/trippy-tui/src/frontend/binding.rs b/crates/trippy-tui/src/frontend/binding.rs index 8e0189b98..f74aea421 100644 --- a/crates/trippy-tui/src/frontend/binding.rs +++ b/crates/trippy-tui/src/frontend/binding.rs @@ -43,6 +43,7 @@ pub struct Bindings { pub toggle_as_info: KeyBinding, pub toggle_hop_details: KeyBinding, pub quit: KeyBinding, + pub quit_preserve_screen: KeyBinding, } impl From for Bindings { @@ -85,6 +86,7 @@ impl From for Bindings { toggle_as_info: KeyBinding::from(value.toggle_as_info), toggle_hop_details: KeyBinding::from(value.toggle_hop_details), quit: KeyBinding::from(value.quit), + quit_preserve_screen: KeyBinding::from(value.quit_preserve_screen), } } } diff --git a/crates/trippy-tui/src/frontend/render/settings.rs b/crates/trippy-tui/src/frontend/render/settings.rs index d62a4dce2..49fa5e7ca 100644 --- a/crates/trippy-tui/src/frontend/render/settings.rs +++ b/crates/trippy-tui/src/frontend/render/settings.rs @@ -393,6 +393,10 @@ fn format_binding_settings(app: &TuiApp) -> Vec { format!("{}", binds.toggle_hop_details), ), SettingsItem::new("quit", format!("{}", binds.quit)), + SettingsItem::new( + "quit-preserve-screen", + format!("{}", binds.quit_preserve_screen), + ), ] } diff --git a/crates/trippy-tui/tests/resources/snapshots/trippy_tui__print__tests__output@tui_binding_commands_match.snap b/crates/trippy-tui/tests/resources/snapshots/trippy_tui__print__tests__output@tui_binding_commands_match.snap index 21d0a648a..01e183af1 100644 --- a/crates/trippy-tui/tests/resources/snapshots/trippy_tui__print__tests__output@tui_binding_commands_match.snap +++ b/crates/trippy-tui/tests/resources/snapshots/trippy_tui__print__tests__output@tui_binding_commands_match.snap @@ -1,4 +1,4 @@ --- source: crates/trippy-tui/src/print.rs --- -TUIbindingcommands:toggle-help,toggle-help-alt,toggle-settings,toggle-settings-tui,toggle-settings-trace,toggle-settings-dns,toggle-settings-geoip,toggle-settings-bindings,toggle-settings-theme,toggle-settings-columns,next-hop,previous-hop,next-trace,previous-trace,next-hop-address,previous-hop-address,address-mode-ip,address-mode-host,address-mode-both,toggle-freeze,toggle-chart,toggle-map,toggle-flows,toggle-privacy,expand-privacy,contract-privacy,expand-hosts,expand-hosts-max,contract-hosts,contract-hosts-min,chart-zoom-in,chart-zoom-out,clear-trace-data,clear-dns-cache,clear-selection,toggle-as-info,toggle-hop-details,quit +TUIbindingcommands:toggle-help,toggle-help-alt,toggle-settings,toggle-settings-tui,toggle-settings-trace,toggle-settings-dns,toggle-settings-geoip,toggle-settings-bindings,toggle-settings-theme,toggle-settings-columns,next-hop,previous-hop,next-trace,previous-trace,next-hop-address,previous-hop-address,address-mode-ip,address-mode-host,address-mode-both,toggle-freeze,toggle-chart,toggle-map,toggle-flows,toggle-privacy,expand-privacy,contract-privacy,expand-hosts,expand-hosts-max,contract-hosts,contract-hosts-min,chart-zoom-in,chart-zoom-out,clear-trace-data,clear-dns-cache,clear-selection,toggle-as-info,toggle-hop-details,quit,quit-preserve-screen diff --git a/trippy-config-sample.toml b/trippy-config-sample.toml index 010d88ff7..64305c9d5 100644 --- a/trippy-config-sample.toml +++ b/trippy-config-sample.toml @@ -424,3 +424,4 @@ clear-selection = "esc" toggle-as-info = "z" toggle-hop-details = "d" quit = "q" +quit-preserve-screen = "shift+q" From b007ef6dced41bf124656b29fb726453ac2cb137 Mon Sep 17 00:00:00 2001 From: FujiApple Date: Fri, 15 Nov 2024 18:56:20 +0800 Subject: [PATCH 4/5] doc: updated `README.md` for #1382 --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index e7f601ffb..3b3f837d2 100644 --- a/README.md +++ b/README.md @@ -886,6 +886,7 @@ command line option or in the `bindings` section of the configuration file. | `toggle-as-info` | Toggle AS info display | `z` | | `toggle-hop-details` | Toggle hop details | `d` | | `quit` | Quit the application | `q` | +| `quit-preserve-screen` | Quit the application and preserve the screen | `shift+q`| The supported modifiers are: `shift`, `ctrl`, `alt`, `super`, `hyper` & `meta`. Multiple modifiers may be specified, for example `ctrl+shift+b`. From 42294d9331e4a488de7094fe4c8709a52b17466a Mon Sep 17 00:00:00 2001 From: FujiApple Date: Fri, 15 Nov 2024 18:59:56 +0800 Subject: [PATCH 5/5] doc: updated `CHANGELOG.md` for #1382 and #1375 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 205efa541..7ccf76547 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ### Added - Highlight lost probes in sample history ([#1247](https://github.com/fujiapple852/trippy/issues/1247)) +- Added `quit-preserve-screen` (default: `shift+q`) key binding to quit Tui without clearing the + screen ([#1382](https://github.com/fujiapple852/trippy/issues/1382)) ### Changed @@ -26,6 +28,8 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - Reverse dns enqueued multiple times when dns-ttl expires ([#1290](https://github.com/fujiapple852/trippy/issues/1290)) - Fixed panic for icmp extensions with malformed length ([#1287](https://github.com/fujiapple852/trippy/issues/1287)) +- Cursor not moved to the bottom on exit when using + `--tui-preserve-screen` ([#1375](https://github.com/fujiapple852/trippy/issues/1375)) ## [0.11.0] - 2024-08-11