Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 83 additions & 18 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ pub(crate) struct State {
pub config: Arc<Config>,
pending_keys: Vec<(KeyModifiers, KeyCode)>,
pub quit: bool,
pub screens: Vec<Screen>,
focused_screen: usize,
screens: Vec<Screen>,
pub pending_menu: Option<PendingMenu>,
pending_cmd: Option<(Child, Arc<RwLock<CmdLogEntry>>)>,
enable_async_cmds: bool,
Expand Down Expand Up @@ -99,6 +100,7 @@ impl App {
enable_async_cmds,
quit: false,
screens,
focused_screen: 0,
pending_cmd: None,
pending_menu,
current_cmd_log: CmdLog::new(),
Expand Down Expand Up @@ -170,6 +172,17 @@ impl App {
let handle_pending_cmd_result = self.handle_pending_cmd();
self.handle_result(handle_pending_cmd_result)?;

if self.state.is_preview_screen_open() {
// TODO Make this cleaner, don't need to update so often too
let item_data = &self.state.get_focused_screen().get_selected_item().data;
if let Some(mut action) = Op::Preview.clone().implementation().get_action(item_data) {
let result = Rc::get_mut(&mut action).unwrap()(self, term);
self.handle_result(result)?;
} else {
self.state.pop_screen();
}
}

if self.state.needs_redraw {
self.redraw_now(term)?;
}
Expand Down Expand Up @@ -278,10 +291,15 @@ impl App {
match mouse.kind {
MouseEventKind::Down(MouseButton::Left) => {
let click_y = mouse.row as usize;
if self.screen().is_valid_screen_line(click_y) {
let old_selected_item_id = self.screen().get_selected_item().id;
if self
.state
.get_focused_screen()
.is_valid_screen_line(click_y)
{
let old_selected_item_id =
self.state.get_focused_screen().get_selected_item().id;
self.handle_op(Op::MoveToScreenLine(click_y), term)?;
let new_selected_item = self.screen().get_selected_item();
let new_selected_item = self.state.get_focused_screen().get_selected_item();

if old_selected_item_id == new_selected_item.id {
// If the item clicked was already the current item, then try to
Expand All @@ -296,21 +314,27 @@ impl App {
}
MouseEventKind::Down(MouseButton::Right) => {
let click_y = mouse.row as usize;
if self.screen().is_valid_screen_line(click_y) {
if self
.state
.get_focused_screen()
.is_valid_screen_line(click_y)
{
self.handle_op(Op::MoveToScreenLine(click_y), term)?;
self.handle_op(Op::Show, term)?;
}
}
MouseEventKind::ScrollUp => {
let scroll_lines = self.state.config.general.mouse_scroll_lines;
if scroll_lines > 0 {
self.screen_mut().scroll_up(scroll_lines);
self.state.get_mut_focused_screen().scroll_up(scroll_lines);
}
}
MouseEventKind::ScrollDown => {
let scroll_lines = self.state.config.general.mouse_scroll_lines;
if scroll_lines > 0 {
self.screen_mut().scroll_down(scroll_lines);
self.state
.get_mut_focused_screen()
.scroll_down(scroll_lines);
}
}
_ => return Ok(false),
Expand All @@ -320,8 +344,7 @@ impl App {
}

pub(crate) fn handle_op(&mut self, op: Op, term: &mut Term) -> Res<()> {
let screen_ref = self.screen();
let item_data = &screen_ref.get_selected_item().data;
let item_data = &self.state.get_focused_screen().get_selected_item().data;

if let Some(mut action) = op.clone().implementation().get_action(item_data) {
let result = Rc::get_mut(&mut action).unwrap()(self, term);
Expand Down Expand Up @@ -351,14 +374,6 @@ impl App {
self.state.pending_menu = root_menu(&self.state.config).map(PendingMenu::init)
}

pub fn screen_mut(&mut self) -> &mut Screen {
self.state.screens.last_mut().expect("No screen")
}

pub fn screen(&self) -> &Screen {
self.state.screens.last().expect("No screen")
}

/// Displays an `Info` message to the CmdLog.
pub fn display_info<S: Into<Cow<'static, str>>>(&mut self, message: S) {
self.state
Expand Down Expand Up @@ -531,7 +546,7 @@ impl App {
}

pub fn selected_rev(&self) -> Option<String> {
match &self.screen().get_selected_item().data {
match &self.state.get_focused_screen().get_selected_item().data {
ItemData::Reference { kind, .. } => match kind {
RefKind::Tag(tag) => Some(tag.to_owned()),
RefKind::Branch(branch) => Some(branch.to_owned()),
Expand Down Expand Up @@ -620,6 +635,56 @@ impl App {
}
}

impl State {
pub fn get_focused_screen(&self) -> &Screen {
&self.screens[self.focused_screen]
}

pub fn get_mut_focused_screen(&mut self) -> &mut Screen {
&mut self.screens[self.focused_screen]
}

pub fn get_screen_count(&self) -> usize {
self.screens.len()
}

pub fn return_to_main_screen(&mut self) {
self.screens.drain(1..);
self.focused_screen = 0;
}

pub fn push_screen(&mut self, screen: Screen) {
self.screens.push(screen);
self.focused_screen = self.screens.len() - 1;
}

pub fn pop_screen(&mut self) {
self.screens.pop();
self.focused_screen = self.screens.len() - 1;
}

pub fn set_preview_screen(&mut self, screen: Screen) {
if self.is_preview_screen_open() {
let last_i = self.screens.len() - 1;
self.screens[last_i] = screen;
} else {
self.screens.push(screen);
}
}

pub fn focus_preview_screen(&mut self) {
self.focused_screen = self.screens.len() - 1;
}

pub fn is_preview_screen_open(&self) -> bool {
self.focused_screen < self.screens.len() - 1
}

pub fn get_screens(&self) -> &[Screen] {
&self.screens
}
}

fn get_prompt_result(params: &PromptParams, app: &mut App) -> Res<String> {
let input = app.state.prompt.state.value();
let default_value = (params.create_default_value)(app);
Expand Down
1 change: 1 addition & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ pub struct GeneralConfig {
pub refresh_on_file_change: BoolConfigEntry,
pub confirm_discard: ConfirmDiscardOption,
pub collapsed_sections: Vec<String>,
pub split_view: BoolConfigEntry,
pub stash_list_limit: usize,
pub recent_commits_limit: usize,
pub mouse_support: bool,
Expand Down
2 changes: 2 additions & 0 deletions src/default_config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ confirm_quit.enabled = false
# collapsed_sections = ["untracked", "recent_commits", "branch_status"]
collapsed_sections = []
refresh_on_file_change.enabled = true
split_view.enabled = true
stash_list_limit = 10
recent_commits_limit = 10
mouse_support = false
Expand Down Expand Up @@ -101,6 +102,7 @@ root.half_page_up = ["ctrl+u"]
root.half_page_down = ["ctrl+d"]
root.show_refs = ["Y"]
root.show = ["enter"]
root.preview = ["space"]
root.discard = ["K"]
root.stage = ["s"]
root.unstage = ["u"]
Expand Down
58 changes: 42 additions & 16 deletions src/ops/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,21 @@ impl OpTrait for Quit {
.map(|pending_menu| pending_menu.menu);

if menu == root_menu(&app.state.config) {
if app.state.screens.len() == 1 {
if ({
let this = &mut *app;
this.state.get_screen_count()
}) == 1
{
if app.state.config.general.confirm_quit.enabled {
app.confirm(term, "Really quit? (y or n)")?;
};

app.state.quit = true;
} else {
app.state.screens.pop();
{
let this = &mut *app;
this.state.pop_screen();
};
}
} else {
app.close_menu();
Expand Down Expand Up @@ -137,7 +144,7 @@ impl OpTrait for ToggleSection {
fn get_action(&self, _target: &ItemData) -> Option<Action> {
Some(Rc::new(|app, _term| {
app.close_menu();
app.screen_mut().toggle_section();
app.state.get_mut_focused_screen().toggle_section();
Ok(())
}))
}
Expand All @@ -152,7 +159,9 @@ impl OpTrait for MoveUp {
fn get_action(&self, _target: &ItemData) -> Option<Action> {
Some(Rc::new(|app, _term| {
app.close_menu();
app.screen_mut().select_previous(NavMode::Normal);
app.state
.get_mut_focused_screen()
.select_previous(NavMode::Normal);
Ok(())
}))
}
Expand All @@ -167,7 +176,9 @@ impl OpTrait for MoveDown {
fn get_action(&self, _target: &ItemData) -> Option<Action> {
Some(Rc::new(|app, _term| {
app.close_menu();
app.screen_mut().select_next(NavMode::Normal);
app.state
.get_mut_focused_screen()
.select_next(NavMode::Normal);
Ok(())
}))
}
Expand All @@ -182,7 +193,9 @@ impl OpTrait for MoveDownLine {
fn get_action(&self, _target: &ItemData) -> Option<Action> {
Some(Rc::new(|app, _term| {
app.close_menu();
app.screen_mut().select_next(NavMode::IncludeHunkLines);
app.state
.get_mut_focused_screen()
.select_next(NavMode::IncludeHunkLines);
Ok(())
}))
}
Expand All @@ -197,7 +210,9 @@ impl OpTrait for MoveUpLine {
fn get_action(&self, _target: &ItemData) -> Option<Action> {
Some(Rc::new(|app, _term| {
app.close_menu();
app.screen_mut().select_previous(NavMode::IncludeHunkLines);
app.state
.get_mut_focused_screen()
.select_previous(NavMode::IncludeHunkLines);
Ok(())
}))
}
Expand All @@ -213,7 +228,9 @@ impl OpTrait for MoveToScreenLine {
let screen_line = self.0;
Some(Rc::new(move |app, _term| {
app.close_menu();
app.screen_mut().move_cursor_to_screen_line(screen_line);
app.state
.get_mut_focused_screen()
.move_cursor_to_screen_line(screen_line);
Ok(())
}))
}
Expand All @@ -228,8 +245,10 @@ impl OpTrait for MoveNextSection {
fn get_action(&self, _target: &ItemData) -> Option<Action> {
Some(Rc::new(|app, _term| {
app.close_menu();
let depth = app.screen().get_selected_item().depth;
app.screen_mut().select_next(NavMode::Siblings { depth });
let depth = app.state.get_focused_screen().get_selected_item().depth;
app.state
.get_mut_focused_screen()
.select_next(NavMode::Siblings { depth });
Ok(())
}))
}
Expand All @@ -244,8 +263,9 @@ impl OpTrait for MovePrevSection {
fn get_action(&self, _target: &ItemData) -> Option<Action> {
Some(Rc::new(|app, _term| {
app.close_menu();
let depth = app.screen().get_selected_item().depth;
app.screen_mut()
let depth = app.state.get_focused_screen().get_selected_item().depth;
app.state
.get_mut_focused_screen()
.select_previous(NavMode::Siblings { depth });
Ok(())
}))
Expand All @@ -261,8 +281,14 @@ impl OpTrait for MoveParentSection {
fn get_action(&self, _target: &ItemData) -> Option<Action> {
Some(Rc::new(|app, _term| {
app.close_menu();
let depth = app.screen().get_selected_item().depth.saturating_sub(1);
app.screen_mut()
let depth = app
.state
.get_focused_screen()
.get_selected_item()
.depth
.saturating_sub(1);
app.state
.get_mut_focused_screen()
.select_previous(NavMode::Siblings { depth });
Ok(())
}))
Expand All @@ -278,7 +304,7 @@ impl OpTrait for HalfPageUp {
fn get_action(&self, _target: &ItemData) -> Option<Action> {
Some(Rc::new(|app, _term| {
app.close_menu();
app.screen_mut().scroll_half_page_up();
app.state.get_mut_focused_screen().scroll_half_page_up();
Ok(())
}))
}
Expand All @@ -293,7 +319,7 @@ impl OpTrait for HalfPageDown {
fn get_action(&self, _target: &ItemData) -> Option<Action> {
Some(Rc::new(|app, _term| {
app.close_menu();
app.screen_mut().scroll_half_page_down();
app.state.get_mut_focused_screen().scroll_half_page_down();
Ok(())
}))
}
Expand Down
6 changes: 3 additions & 3 deletions src/ops/log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ fn log_other(app: &mut App, _term: &mut Term, result: &str) -> Res<()> {
}

fn goto_log_screen(app: &mut App, rev: Option<Oid>) {
app.state.screens.drain(1..);
let size = app.state.screens.last().unwrap().size;
app.state.return_to_main_screen();
let size = app.state.get_focused_screen().size;
let limit = *app
.state
.pending_menu
Expand All @@ -99,7 +99,7 @@ fn goto_log_screen(app: &mut App, rev: Option<Oid>) {

app.close_menu();

app.state.screens.push(
app.state.push_screen(
screen::log::create(
Arc::clone(&app.state.config),
Rc::clone(&app.state.repo),
Expand Down
3 changes: 3 additions & 0 deletions src/ops/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub(crate) mod editor;
pub(crate) mod fetch;
pub(crate) mod log;
pub(crate) mod merge;
pub(crate) mod preview;
pub(crate) mod pull;
pub(crate) mod push;
pub(crate) mod rebase;
Expand Down Expand Up @@ -60,6 +61,7 @@ pub(crate) enum Op {
FetchAll,
FetchElsewhere,
LogCurrent,
Preview,
PullFromPushRemote,
PullFromUpstream,
PullFromElsewhere,
Expand Down Expand Up @@ -150,6 +152,7 @@ impl Op {
Op::FetchAll => Box::new(fetch::FetchAll),
Op::FetchElsewhere => Box::new(fetch::FetchElsewhere),
Op::LogCurrent => Box::new(log::LogCurrent),
Op::Preview => Box::new(preview::Preview),
Op::PullFromPushRemote => Box::new(pull::PullFromPushRemote),
Op::PullFromUpstream => Box::new(pull::PullFromUpstream),
Op::PullFromElsewhere => Box::new(pull::PullFromElsewhere),
Expand Down
Loading
Loading