mirror of
https://github.com/gitui-org/gitui.git
synced 2026-10-12 02:14:16 +00:00
support common nav for syntax view (closes #725)
This commit is contained in:
@@ -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 =
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user