diff --git a/.github/ci/release_notes.md b/.github/ci/release_notes.md index e0f831f5..bc8f9323 100644 --- a/.github/ci/release_notes.md +++ b/.github/ci/release_notes.md @@ -2,12 +2,12 @@ --- -## Bug Fixes - ## Features ## Changes +## Bug Fixes + ## Other ## Internal Changes diff --git a/CHANGELOG.md b/CHANGELOG.md index 5544fe0b..b36cf4d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,14 +18,12 @@ Versioning for this project is based on [Semantic Versioning](https://semver.org That said, these are more guidelines rather than hard rules, though the project will generally try to follow them. + + --- ## 0.15.0 - Unreleased -### Bug Fixes - -- [#2225](https://github.com/ClementTsang/bottom/pull/2225): Fix waking up NVIDIA GPUs when getting stats on Linux. - ### Features - [#2239](https://github.com/ClementTsang/bottom/pull/2239): Initial Intel GPU support for Linux to get process GPU usage. @@ -34,6 +32,15 @@ That said, these are more guidelines rather than hard rules, though the project - [#2251](https://github.com/ClementTsang/bottom/pull/2251): Add configurable binary disk capacity units for disk widget I/O. - [#2224](https://github.com/ClementTsang/bottom/pull/2224): Add swap column for processes for Linux. +### Changes + +- [#2260](https://github.com/ClementTsang/bottom/pull/2260): Enable scrollbars by default. + +### Bug Fixes + +- [#2225](https://github.com/ClementTsang/bottom/pull/2225): Fix waking up NVIDIA GPUs when getting stats on Linux. +- [#2261](https://github.com/ClementTsang/bottom/pull/2261): Fix scrollbars not drawing when height of bar was 2 or less. + ### Other - [#2227](https://github.com/ClementTsang/bottom/pull/2227): Add missing documentation around disk I/O graph. diff --git a/src/canvas/components/data_table.rs b/src/canvas/components/data_table.rs index e9d859bc..1cee4d80 100644 --- a/src/canvas/components/data_table.rs +++ b/src/canvas/components/data_table.rs @@ -192,7 +192,7 @@ mod test { left_to_right: false, is_basic: false, show_table_scroll_position: true, - show_table_scroll_bar: false, + show_table_scroll_bar: true, show_current_entry_when_unfocused: false, }; let styling = DataTableStyling::default(); diff --git a/src/canvas/components/pipe_gauge.rs b/src/canvas/components/pipe_gauge.rs index 90261d18..7ca324c0 100644 --- a/src/canvas/components/pipe_gauge.rs +++ b/src/canvas/components/pipe_gauge.rs @@ -315,7 +315,7 @@ mod tests { } /// Create a [`PipeGauge`] and return what it would have rendered. - fn render_gauge( + fn render_test_gauge( ratio: f64, bar_type: BarType, start_label: Option<&str>, inner_label: Option<&str>, ) -> String { const WIDTH: u16 = 12; @@ -339,35 +339,44 @@ mod tests { #[test] fn test_pipe_bars() { - assert_eq!(render_gauge(0.0, BarType::Pipe, None, None), "[ ]"); - assert_eq!(render_gauge(0.5, BarType::Pipe, None, None), "[||||| ]"); assert_eq!( - render_gauge(0.95, BarType::Pipe, None, None), + render_test_gauge(0.0, BarType::Pipe, None, None), + "[ ]" + ); + assert_eq!( + render_test_gauge(0.5, BarType::Pipe, None, None), + "[||||| ]" + ); + assert_eq!( + render_test_gauge(0.95, BarType::Pipe, None, None), "[||||||||| ]" ); - assert_eq!(render_gauge(1.0, BarType::Pipe, None, None), "[||||||||||]"); + assert_eq!( + render_test_gauge(1.0, BarType::Pipe, None, None), + "[||||||||||]" + ); } #[test] fn test_solid_bars() { assert_eq!( - render_gauge(0.0, BarType::Block, None, None), + render_test_gauge(0.0, BarType::Block, None, None), "[ ]" ); assert_eq!( - render_gauge(0.5, BarType::Block, None, None), + render_test_gauge(0.5, BarType::Block, None, None), "[█████ ]" ); assert_eq!( - render_gauge(0.55, BarType::Block, None, None), + render_test_gauge(0.55, BarType::Block, None, None), "[█████▌ ]" ); assert_eq!( - render_gauge(0.9, BarType::Block, None, None), + render_test_gauge(0.9, BarType::Block, None, None), "[█████████ ]" ); assert_eq!( - render_gauge(1.0, BarType::Block, None, None), + render_test_gauge(1.0, BarType::Block, None, None), "[██████████]" ); } @@ -375,15 +384,15 @@ mod tests { #[test] fn test_labelled_bars() { assert_eq!( - render_gauge(0.5, BarType::Pipe, Some("CPU"), Some(" 50%")), + render_test_gauge(0.5, BarType::Pipe, Some("CPU"), Some(" 50%")), "CPU[||| 50%]" ); assert_eq!( - render_gauge(0.5, BarType::Block, Some("CPU"), Some(" 50%")), + render_test_gauge(0.5, BarType::Block, Some("CPU"), Some(" 50%")), "CPU[███ 50%]" ); assert_eq!( - render_gauge(1.0, BarType::Block, Some("CPU"), Some("100%")), + render_test_gauge(1.0, BarType::Block, Some("CPU"), Some("100%")), "CPU[███100%]" ); } diff --git a/src/canvas/components/scroll_bar.rs b/src/canvas/components/scroll_bar.rs index 47897a9a..b88d050a 100644 --- a/src/canvas/components/scroll_bar.rs +++ b/src/canvas/components/scroll_bar.rs @@ -44,9 +44,20 @@ pub fn draw_scroll_bar(f: &mut Frame<'_>, area: Rect, args: ScrollBarArgs) { end: "▼", }; - let scrollbar = Scrollbar::new(ScrollbarOrientation::VerticalRight) - .style(args.style) - .symbols(SYMBOLS); + // If the height is only 2, then there's no room for the thumb, + // so instead we just draw a track with no arrows. + let scrollbar = { + let tmp = Scrollbar::new(ScrollbarOrientation::VerticalRight).style(args.style); + + if area.height > 2 { + tmp.symbols(SYMBOLS) + } else { + tmp.track_symbol(Some(SYMBOLS.track)) + .thumb_symbol(SYMBOLS.thumb) + .begin_symbol(None) + .end_symbol(None) + } + }; let mut state = ScrollbarState::new(args.content_length) .position(args.position) @@ -54,3 +65,53 @@ pub fn draw_scroll_bar(f: &mut Frame<'_>, area: Rect, args: ScrollBarArgs) { f.render_stateful_widget(scrollbar, area, &mut state); } + +#[cfg(test)] +mod test { + use super::*; + use ratatui::{Terminal, backend::TestBackend}; + + fn render_test_bar(height: u16, content_length: usize, position: usize) -> Vec { + let mut terminal = Terminal::new(TestBackend::new(1, height)).unwrap(); + terminal + .draw(|f| { + draw_scroll_bar( + f, + Rect::new(0, 0, 1, height), + ScrollBarArgs { + content_length, + viewport_length: 2, + position, + style: Style::default(), + }, + ); + }) + .unwrap(); + + let buf = terminal.backend().buffer().clone(); + (0..height) + .map(|y| buf[(0, y)].symbol().to_string()) + .collect() + } + + /// Make sure that a short scrollbar (height <= 2) is still drawn, just without the head/tail arrows. + #[test] + fn test_small_height_scroll_still_drawn() { + assert_eq!(render_test_bar(1, 3, 0), ["█"]); + assert_eq!(render_test_bar(2, 3, 0), ["█", " "]); + assert_eq!(render_test_bar(2, 3, 2), [" ", "█"]); + } + + #[test] + fn test_normal_height_scroll_all_drawn() { + assert_eq!(render_test_bar(3, 3, 0), ["▲", "█", "▼"]); + assert_eq!(render_test_bar(4, 3, 0), ["▲", "█", " ", "▼"]); + assert_eq!(render_test_bar(4, 3, 2), ["▲", " ", "█", "▼"]); + } + + #[test] + fn test_no_scroll_bar_when_list_fits() { + assert_eq!(render_test_bar(4, 2, 0), [" ", " ", " ", " "]); + assert_eq!(render_test_bar(2, 1, 0), [" ", " "]); + } +}