support common nav for syntax view (closes #725)

This commit is contained in:
Stephan Dilly
2021-05-24 11:07:32 +02:00
parent 0dd1afb9db
commit a5b63e5936
4 changed files with 77 additions and 35 deletions
+5
View File
@@ -13,6 +13,8 @@ pub enum MoveSelection {
Right,
Top,
End,
PageDown,
PageUp,
}
#[derive(Debug, Clone, Copy)]
@@ -121,6 +123,9 @@ impl FileTree {
Self::selection_start(selection)
}
MoveSelection::End => self.selection_end(selection),
MoveSelection::PageDown | MoveSelection::PageUp => {
None
}
};
let changed_index =
+4 -14
View File
@@ -6,7 +6,7 @@ use crate::{
keys::SharedKeyConfig,
queue::{InternalEvent, Queue},
strings::{self, order},
ui::{self, style::SharedTheme},
ui::{self, common_nav, style::SharedTheme},
};
use anyhow::Result;
use asyncgit::{
@@ -15,7 +15,7 @@ use asyncgit::{
};
use crossbeam_channel::Sender;
use crossterm::event::Event;
use filetree::{FileTree, MoveSelection};
use filetree::FileTree;
use std::{
cell::Cell, collections::BTreeSet, convert::From, path::Path,
};
@@ -376,18 +376,8 @@ fn tree_nav(
key_config: &SharedKeyConfig,
key: crossterm::event::KeyEvent,
) -> bool {
if key == key_config.move_down {
tree.move_selection(MoveSelection::Down)
} else if key == key_config.move_up {
tree.move_selection(MoveSelection::Up)
} else if key == key_config.move_right {
tree.move_selection(MoveSelection::Right)
} else if key == key_config.move_left {
tree.move_selection(MoveSelection::Left)
} else if key == key_config.home || key == key_config.shift_up {
tree.move_selection(MoveSelection::Top)
} else if key == key_config.end || key == key_config.shift_down {
tree.move_selection(MoveSelection::End)
if let Some(common_nav) = common_nav(key, key_config) {
tree.move_selection(common_nav)
} else if key == key_config.tree_collapse_recursive {
tree.collapse_recursive();
true
+39 -21
View File
@@ -6,8 +6,8 @@ use crate::{
keys::SharedKeyConfig,
strings,
ui::{
self, style::SharedTheme, AsyncSyntaxJob, ParagraphState,
ScrollPos, StatefulParagraph,
self, common_nav, style::SharedTheme, AsyncSyntaxJob,
ParagraphState, ScrollPos, StatefulParagraph,
},
};
use anyhow::Result;
@@ -18,6 +18,7 @@ use asyncgit::{
};
use crossbeam_channel::Sender;
use crossterm::event::Event;
use filetree::MoveSelection;
use itertools::Either;
use std::{cell::Cell, convert::From, path::Path};
use tui::{
@@ -120,27 +121,41 @@ impl SyntaxTextComponent {
}
}
fn scroll(&self, down: Option<bool>) {
let mut state = self.paragraph_state.get();
let new_scroll_pos = down.map_or_else(
|| state.scroll().y,
|down| {
if down {
state.scroll().y.saturating_add(1)
} else {
state.scroll().y.saturating_sub(1)
}
},
);
fn scroll(&self, nav: MoveSelection) -> bool {
let state = self.paragraph_state.get();
let new_scroll_pos = new_scroll_pos.min(
let new_scroll_pos = match nav {
MoveSelection::Down => state.scroll().y.saturating_add(1),
MoveSelection::Up => state.scroll().y.saturating_sub(1),
MoveSelection::Top => 0,
MoveSelection::End => state
.lines()
.saturating_sub(state.height().saturating_sub(2)),
MoveSelection::PageUp => state
.scroll()
.y
.saturating_sub(state.height().saturating_sub(2)),
MoveSelection::PageDown => state
.scroll()
.y
.saturating_add(state.height().saturating_sub(2)),
_ => state.scroll().y,
};
self.set_scroll(new_scroll_pos)
}
fn set_scroll(&self, pos: u16) -> bool {
let mut state = self.paragraph_state.get();
let new_scroll_pos = pos.min(
state
.lines()
.saturating_sub(state.height().saturating_sub(2)),
);
if new_scroll_pos == state.scroll().y {
return;
return false;
}
state.set_scroll(ScrollPos {
@@ -148,6 +163,8 @@ impl SyntaxTextComponent {
y: new_scroll_pos,
});
self.paragraph_state.set(state);
true
}
}
@@ -185,7 +202,7 @@ impl DrawableComponent for SyntaxTextComponent {
self.paragraph_state.set(state);
self.scroll(None);
self.set_scroll(state.scroll().y);
if self.focused() {
ui::draw_scrollbar(
@@ -227,10 +244,11 @@ impl Component for SyntaxTextComponent {
event: crossterm::event::Event,
) -> Result<EventState> {
if let Event::Key(key) = event {
if key == self.key_config.move_down {
self.scroll(Some(true));
} else if key == self.key_config.move_up {
self.scroll(Some(false));
if let Some(nav) = common_nav(key, &self.key_config) {
return Ok(self
.scroll(nav)
.then(|| EventState::Consumed)
.unwrap_or(EventState::NotConsumed));
}
}
+29
View File
@@ -5,6 +5,7 @@ mod stateful_paragraph;
pub mod style;
mod syntax_text;
use filetree::MoveSelection;
pub use scrollbar::draw_scrollbar;
pub use scrolllist::{draw_list, draw_list_block};
pub use stateful_paragraph::{
@@ -13,6 +14,8 @@ pub use stateful_paragraph::{
pub use syntax_text::{AsyncSyntaxJob, SyntaxText};
use tui::layout::{Constraint, Direction, Layout, Rect};
use crate::keys::SharedKeyConfig;
/// return the scroll position (line) necessary to have the `selection` in view if it is not already
pub const fn calc_scroll_top(
current_top: usize,
@@ -109,3 +112,29 @@ pub fn centered_rect_absolute(
height.min(r.height),
)
}
///
pub fn common_nav(
key: crossterm::event::KeyEvent,
key_config: &SharedKeyConfig,
) -> Option<MoveSelection> {
if key == key_config.move_down {
Some(MoveSelection::Down)
} else if key == key_config.move_up {
Some(MoveSelection::Up)
} else if key == key_config.page_up {
Some(MoveSelection::PageUp)
} else if key == key_config.page_down {
Some(MoveSelection::PageDown)
} else if key == key_config.move_right {
Some(MoveSelection::Right)
} else if key == key_config.move_left {
Some(MoveSelection::Left)
} else if key == key_config.home || key == key_config.shift_up {
Some(MoveSelection::Top)
} else if key == key_config.end || key == key_config.shift_down {
Some(MoveSelection::End)
} else {
None
}
}