Skip to content

Commit 12ee560

Browse files
committed
Horizontal scroll for source, context and stack
1 parent 283c43c commit 12ee560

File tree

11 files changed

+69
-52
lines changed

11 files changed

+69
-52
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ CHANGELOG
44
main
55
----
66

7+
- Horizontal scrolling
78
- Improved property rendering
89
- Introduced themes (including solarized and solarized dark)
910
- Show value of variables on current line

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ Prefix with number to repeat:
3434
- `J` scroll down 10
3535
- `k` scroll up
3636
- `K` scroll up 10
37+
- `h` scroll left
38+
- `H` scroll left 10
39+
- `l` scroll right
40+
- `L` scroll right 10
3741
- `+` increase context depth
3842
- `-` decrease context depth
3943
- `tab` switch pane

src/app.rs

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use crate::view::session::SessionViewMode;
1919
use crate::view::session::SessionViewState;
2020
use crate::view::View;
2121
use anyhow::Result;
22+
use better_panic::Verbosity;
2223
use crossterm::event::KeyCode;
2324
use log::info;
2425
use log::warn;
@@ -344,22 +345,13 @@ impl App {
344345
).await?;
345346
},
346347
AppEvent::ScrollSource(amount) => {
347-
self.session_view.source_scroll = Some(self
348-
.session_view
349-
.source_scroll.unwrap_or(0)
350-
.saturating_add(amount * self.take_motion() as i16));
348+
self.session_view.source_scroll = apply_scroll(self.session_view.source_scroll, amount, self.take_motion() as i16);
351349
}
352350
AppEvent::ScrollContext(amount) => {
353-
self.session_view.context_scroll = self
354-
.session_view
355-
.context_scroll
356-
.saturating_add_signed(amount * self.take_motion() as i16);
351+
self.session_view.context_scroll = apply_scroll(self.session_view.context_scroll, amount, self.take_motion() as i16);
357352
}
358353
AppEvent::ScrollStack(amount) => {
359-
self.session_view.stack_scroll = self
360-
.session_view
361-
.stack_scroll
362-
.saturating_add_signed(amount * self.take_motion() as i16);
354+
self.session_view.stack_scroll = apply_scroll(self.session_view.stack_scroll, amount, self.take_motion() as i16);
363355
}
364356
AppEvent::ToggleFullscreen => {
365357
self.session_view.full_screen = !self.session_view.full_screen;
@@ -522,3 +514,10 @@ impl App {
522514
self.theme.scheme()
523515
}
524516
}
517+
518+
fn apply_scroll(scroll: (u16, u16), amount: (i16, i16), motion: i16) -> (u16, u16) {
519+
(
520+
(scroll.0 as i16).saturating_add(amount.0 * motion).max(0) as u16,
521+
(scroll.1 as i16).saturating_add(amount.1 * motion).max(0) as u16,
522+
)
523+
}

src/event/input.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use tokio::sync::mpsc::Sender;
1414
use crate::app::CurrentView;
1515
use crate::dbgp::client::ContinuationStatus;
1616
use crate::view::session::SessionViewMode;
17+
use crate::view::Scroll;
1718

1819
#[derive(Debug)]
1920
pub enum AppEvent {
@@ -37,12 +38,11 @@ pub enum AppEvent {
3738
UpdateSourceContext(String, String, u32),
3839
UpdateStatus(ContinuationStatus),
3940
NextPane,
40-
ScrollDown(i16),
41-
ScrollUp(i16),
42-
ScrollSource(i16),
43-
ScrollContext(i16),
41+
Scroll(Scroll),
42+
ScrollSource(Scroll),
43+
ScrollContext(Scroll),
44+
ScrollStack(Scroll),
4445
ToggleFullscreen,
45-
ScrollStack(i16),
4646
PushInputPlurality(char),
4747
ContextDepth(i8),
4848
NextTheme,

src/theme.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ impl Theme {
3030
scheme.widget_mode_debug = scheme.widget_mode_debug.fg(Solarized::Base03.to_color()).bg(Solarized::Base3.to_color());
3131
scheme.widget_mode_history = scheme.widget_mode_debug.bg(Solarized::Base3.to_color()).fg(Solarized::Red.to_color());
3232

33-
return scheme;
33+
scheme
3434
}
3535
Theme::SolarizedDark => Scheme{
3636
syntax_variable: Style::default().fg(Solarized::Base00.to_color()),

src/view/context.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@ pub struct ContextComponent {}
1616
impl View for ContextComponent {
1717
fn handle(_app: &App, event: AppEvent) -> Option<AppEvent> {
1818
match event {
19-
AppEvent::ScrollDown(amount) => Some(AppEvent::ScrollContext(amount)),
20-
AppEvent::ScrollUp(amount) => Some(AppEvent::ScrollContext(-amount)),
19+
AppEvent::Scroll(scroll) => Some(AppEvent::ScrollContext(scroll)),
2120
_ => None,
2221
}
2322
}
@@ -31,9 +30,8 @@ impl View for ContextComponent {
3130
draw_properties(&app.theme(), &context.properties, &mut lines, 0);
3231

3332
frame.render_widget(
34-
Paragraph::new(lines)
35-
.wrap(Wrap { trim: false })
36-
.scroll((app.session_view.context_scroll, 0)),
33+
Paragraph::new(lines).scroll(app.session_view.context_scroll),
34+
3735
area,
3836
);
3937
}

src/view/help.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ Key mappings (prefix with number to repeat):
4343
[J] scroll down 10
4444
[k] scroll up
4545
[K] scroll up 10
46+
[h] scroll left
47+
[H] scroll left 10
48+
[l] scroll right
49+
[L] scroll right 10
4650
[+] increase context depth
4751
[-] decrease context depth
4852
[t] rotate the theme

src/view/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,5 @@ pub struct Pane {
2929
pub component_type: ComponentType,
3030
pub constraint: Constraint,
3131
}
32+
33+
pub type Scroll = (i16,i16);

src/view/session.rs

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use super::source::SourceComponent;
33
use super::stack::StackComponent;
44
use super::ComponentType;
55
use super::Pane;
6+
use super::Scroll;
67
use super::View;
78
use crate::app::App;
89
use crate::app::CurrentView;
@@ -29,10 +30,14 @@ impl View for SessionView {
2930
KeyCode::Tab => return Some(AppEvent::NextPane),
3031
KeyCode::Enter => return Some(AppEvent::ToggleFullscreen),
3132
KeyCode::Char(char) => match char {
32-
'j' => return Some(AppEvent::ScrollDown(1)),
33-
'k' => return Some(AppEvent::ScrollUp(1)),
34-
'J' => return Some(AppEvent::ScrollDown(10)),
35-
'K' => return Some(AppEvent::ScrollUp(10)),
33+
'j' => return Some(AppEvent::Scroll((1, 0))),
34+
'k' => return Some(AppEvent::Scroll((-1, 0))),
35+
'J' => return Some(AppEvent::Scroll((10, 0))),
36+
'K' => return Some(AppEvent::Scroll((-10, 0))),
37+
'l' => return Some(AppEvent::Scroll((0, 1))),
38+
'L' => return Some(AppEvent::Scroll((0, 10))),
39+
'h' => return Some(AppEvent::Scroll((0, -1))),
40+
'H' => return Some(AppEvent::Scroll((0, -10))),
3641
'0'..='9' => return Some(AppEvent::PushInputPlurality(char)),
3742
_ => (),
3843
},
@@ -74,7 +79,13 @@ impl View for SessionView {
7479

7580
fn draw(app: &App, frame: &mut Frame, area: ratatui::prelude::Rect) {
7681
if app.session_view.full_screen {
77-
build_pane_widget(frame, app, app.session_view.current_pane(), area, app.session_view.current_pane);
82+
build_pane_widget(
83+
frame,
84+
app,
85+
app.session_view.current_pane(),
86+
area,
87+
app.session_view.current_pane,
88+
);
7889
return;
7990
}
8091

@@ -122,12 +133,10 @@ fn build_pane_widget(frame: &mut Frame, app: &App, pane: &Pane, area: Rect, inde
122133
ComponentType::Context => format!("Context({})", app.context_depth),
123134
ComponentType::Stack => "Stack".to_string(),
124135
})
125-
.style(
126-
match index == app.session_view.current_pane {
127-
true => app.theme().pane_border_active,
128-
false => app.theme().pane_border_inactive,
129-
}
130-
);
136+
.style(match index == app.session_view.current_pane {
137+
true => app.theme().pane_border_active,
138+
false => app.theme().pane_border_inactive,
139+
});
131140

132141
frame.render_widget(&block, area);
133142

@@ -146,9 +155,9 @@ fn build_pane_widget(frame: &mut Frame, app: &App, pane: &Pane, area: Rect, inde
146155

147156
pub struct SessionViewState {
148157
pub full_screen: bool,
149-
pub source_scroll: Option<i16>,
150-
pub context_scroll: u16,
151-
pub stack_scroll: u16,
158+
pub source_scroll: (u16, u16),
159+
pub context_scroll: (u16, u16),
160+
pub stack_scroll: (u16, u16),
152161
pub mode: SessionViewMode,
153162
pub panes: Vec<Pane>,
154163
pub current_pane: usize,
@@ -164,9 +173,9 @@ impl SessionViewState {
164173
pub fn new() -> Self {
165174
Self {
166175
full_screen: false,
167-
source_scroll: None,
168-
context_scroll: 0,
169-
stack_scroll: 0,
176+
source_scroll: (0, 0),
177+
context_scroll: (0, 0),
178+
stack_scroll: (0, 0),
170179
current_pane: 0,
171180
mode: SessionViewMode::Current,
172181
panes: vec![
@@ -196,8 +205,9 @@ impl SessionViewState {
196205
}
197206

198207
pub(crate) fn reset(&mut self) {
199-
self.context_scroll = 0;
200-
self.source_scroll = None;
208+
self.context_scroll = (0, 0);
209+
self.stack_scroll = (0, 0);
210+
self.source_scroll = (0, 0);
201211
}
202212
}
203213

src/view/source.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use super::Scroll;
12
use super::View;
23
use crate::app::App;
34
use crate::dbgp::client::Property;
@@ -17,8 +18,7 @@ pub struct SourceComponent {}
1718
impl View for SourceComponent {
1819
fn handle(_: &App, event: AppEvent) -> Option<AppEvent> {
1920
match event {
20-
AppEvent::ScrollDown(amount) => Some(AppEvent::ScrollSource(amount)),
21-
AppEvent::ScrollUp(amount) => Some(AppEvent::ScrollSource(-amount)),
21+
AppEvent::Scroll(amount) => Some(AppEvent::ScrollSource(amount)),
2222
_ => None,
2323
}
2424
}
@@ -86,17 +86,17 @@ impl View for SourceComponent {
8686
let center = (history_entry.source.line_no as u16)
8787
.saturating_sub(area.height.div_ceil(2)) as i16;
8888
center
89-
.saturating_add(app.session_view.source_scroll.unwrap_or(0))
89+
.saturating_add(app.session_view.source_scroll.0 as i16)
9090
.max(0) as u16
9191
} else {
92-
app.session_view.source_scroll.unwrap_or(0).max(0) as u16
92+
app.session_view.source_scroll.0.max(0) as u16
9393
};
9494

95-
frame.render_widget(Paragraph::new(lines.clone()).scroll((scroll, 0)), rows[0]);
95+
frame.render_widget(Paragraph::new(lines.clone()).scroll((scroll, app.session_view.source_scroll.1)), rows[0]);
9696

9797
for (line_no, line_length, line) in annotations {
9898
let position = Position {
99-
x: line_length as u16,
99+
x: (line_length as u16).saturating_sub(app.session_view.source_scroll.1),
100100
y: (line_no as u32).saturating_sub(scroll as u32) as u16 + 1,
101101
};
102102
if !rows[0].contains(position) {
@@ -137,7 +137,7 @@ fn render_label(property: &Property) -> Option<String> {
137137
PropertyType::Float => property.value.clone().unwrap_or("".to_string()),
138138
PropertyType::String => format!("\"{}\"", property.value.clone().unwrap_or("".to_string())),
139139
PropertyType::Null => String::from("null"),
140-
PropertyType::Resource => String::from(property.value.clone().unwrap_or("".to_string())),
140+
PropertyType::Resource => property.value.clone().unwrap_or("".to_string()),
141141
PropertyType::Undefined => String::from("undefined"),
142142
})
143143
}

0 commit comments

Comments
 (0)