From 9534e4c2f99111c928dcd2e91ca9fe49364a7ed5 Mon Sep 17 00:00:00 2001 From: extrawurst <776816+extrawurst@users.noreply.github.com> Date: Sun, 18 Sep 2022 18:05:29 +0200 Subject: [PATCH] persist current tab as options (#1339) --- CHANGELOG.md | 3 +- src/app.rs | 24 ++++++--- src/components/changes.rs | 3 +- src/components/file_revlog.rs | 5 +- src/components/mod.rs | 4 +- src/components/options_popup.rs | 20 +++----- src/main.rs | 3 +- src/options.rs | 90 +++++++++++++++++++++++++++++++++ src/tabs/status.rs | 5 +- 9 files changed, 126 insertions(+), 31 deletions(-) create mode 100644 src/options.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 72dab0f1a9..5feaf03942 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,8 +13,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added * submodules support ([#1087](https://github.com/extrawurst/gitui/issues/1087)) +* remember tab between app starts ([#1338](https://github.com/extrawurst/gitui/issues/1338)) * customizable `cmdbar_bg` theme color & screen spanning selected line bg [[@gigitsu](https://github.com/gigitsu)] ([#1299](https://github.com/extrawurst/gitui/pull/1299)) -* use filewatcher instead of polling updates ([#1](https://github.com/extrawurst/gitui/issues/1)) * word motions to text input [[@Rodrigodd](https://github.com/Rodrigodd)] ([#1256](https://github.com/extrawurst/gitui/issues/1256)) * file blame at right revision from commit-details [[@heiskane](https://github.com/heiskane)] ([#1122](https://github.com/extrawurst/gitui/issues/1122)) * add `regex-fancy` and `regex-onig` features to allow building Syntect with Onigumara regex engine instead of the default engine based on fancy-regex [[@jirutka](https://github.com/jirutka)] @@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixes * remove insecure dependency `ansi_term` ([#1290](https://github.com/extrawurst/gitui/issues/1290)) +* use filewatcher instead of polling updates ([#1](https://github.com/extrawurst/gitui/issues/1)) ## [0.21.0] - 2021-08-17 diff --git a/src/app.rs b/src/app.rs index a2d7b07ae0..b443a58073 100644 --- a/src/app.rs +++ b/src/app.rs @@ -10,12 +10,13 @@ use crate::{ FileRevlogComponent, HelpComponent, InspectCommitComponent, MsgComponent, OptionsPopupComponent, PullComponent, PushComponent, PushTagsComponent, RenameBranchComponent, - RevisionFilesPopup, SharedOptions, StashMsgComponent, + RevisionFilesPopup, StashMsgComponent, SubmodulesListComponent, TagCommitComponent, TagListComponent, }, input::{Input, InputEvent, InputState}, keys::{key_match, KeyConfig, SharedKeyConfig}, + options::{Options, SharedOptions}, popup_stack::PopupStack, queue::{ Action, InternalEvent, NeedsUpdate, Queue, StackablePopupOpen, @@ -92,6 +93,7 @@ pub struct App { key_config: SharedKeyConfig, input: Input, popup_stack: PopupStack, + options: SharedOptions, // "Flags" requires_redraw: Cell, @@ -109,15 +111,17 @@ impl App { input: Input, theme: Theme, key_config: KeyConfig, - ) -> Self { + ) -> Result { log::trace!("open repo at: {:?}", &repo); let queue = Queue::new(); let theme = Rc::new(theme); let key_config = Rc::new(key_config); - let options = SharedOptions::default(); + let options = Options::new(repo.clone()); - Self { + let tab = options.borrow().current_tab(); + + let mut app = Self { input, reset: ConfirmComponent::new( queue.clone(), @@ -263,7 +267,6 @@ impl App { key_config.clone(), ), msg: MsgComponent::new(theme.clone(), key_config.clone()), - tab: 0, revlog: Revlog::new( &repo, &queue, @@ -277,7 +280,7 @@ impl App { sender, theme.clone(), key_config.clone(), - options, + options.clone(), ), stashing_tab: Stashing::new( &repo, @@ -299,14 +302,20 @@ impl App { theme.clone(), key_config.clone(), ), + tab: 0, queue, theme, + options, key_config, requires_redraw: Cell::new(false), file_to_open: None, repo, popup_stack: PopupStack::default(), - } + }; + + app.set_tab(tab)?; + + Ok(app) } /// @@ -678,6 +687,7 @@ impl App { } self.tab = tab; + self.options.borrow_mut().set_current_tab(tab); Ok(()) } diff --git a/src/components/changes.rs b/src/components/changes.rs index ca3df2991f..92fa0262b9 100644 --- a/src/components/changes.rs +++ b/src/components/changes.rs @@ -1,11 +1,12 @@ use super::{ status_tree::StatusTreeComponent, utils::filetree::{FileTreeItem, FileTreeItemKind}, - CommandBlocking, DrawableComponent, SharedOptions, + CommandBlocking, DrawableComponent, }; use crate::{ components::{CommandInfo, Component, EventState}, keys::{key_match, SharedKeyConfig}, + options::SharedOptions, queue::{Action, InternalEvent, NeedsUpdate, Queue, ResetItem}, strings, try_or_popup, ui::style::SharedTheme, diff --git a/src/components/file_revlog.rs b/src/components/file_revlog.rs index 20af109652..563ee04dbb 100644 --- a/src/components/file_revlog.rs +++ b/src/components/file_revlog.rs @@ -1,6 +1,7 @@ -use super::{utils::logitems::ItemBatch, SharedOptions}; +use super::utils::logitems::ItemBatch; use super::{visibility_blocking, BlameFileOpen, InspectCommitOpen}; use crate::keys::key_match; +use crate::options::SharedOptions; use crate::queue::StackablePopupOpen; use crate::{ components::{ @@ -191,7 +192,7 @@ impl FileRevlogComponent { let diff_params = DiffParams { path: open_request.file_path.clone(), diff_type: DiffType::Commit(commit_id), - options: self.options.borrow().diff, + options: self.options.borrow().diff_options(), }; if let Some((params, last)) = diff --git a/src/components/mod.rs b/src/components/mod.rs index 9628684d32..fb42dbec93 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -51,9 +51,7 @@ pub use file_revlog::{FileRevOpen, FileRevlogComponent}; pub use help::HelpComponent; pub use inspect_commit::{InspectCommitComponent, InspectCommitOpen}; pub use msg::MsgComponent; -pub use options_popup::{ - AppOption, OptionsPopupComponent, SharedOptions, -}; +pub use options_popup::{AppOption, OptionsPopupComponent}; pub use pull::PullComponent; pub use push::PushComponent; pub use push_tags::PushTagsComponent; diff --git a/src/components/options_popup.rs b/src/components/options_popup.rs index 707c9928ec..3e9fd46e69 100644 --- a/src/components/options_popup.rs +++ b/src/components/options_popup.rs @@ -1,5 +1,3 @@ -use std::{cell::RefCell, rc::Rc}; - use super::{ visibility_blocking, CommandBlocking, CommandInfo, Component, DrawableComponent, EventState, @@ -7,12 +5,13 @@ use super::{ use crate::{ components::utils::string_width_align, keys::{key_match, SharedKeyConfig}, + options::SharedOptions, queue::{InternalEvent, Queue}, strings::{self}, ui::{self, style::SharedTheme}, }; use anyhow::Result; -use asyncgit::sync::{diff::DiffOptions, ShowUntrackedFilesConfig}; +use asyncgit::sync::ShowUntrackedFilesConfig; use crossterm::event::Event; use tui::{ backend::Backend, @@ -31,14 +30,6 @@ pub enum AppOption { DiffInterhunkLines, } -#[derive(Default, Copy, Clone)] -pub struct Options { - pub status_show_untracked: Option, - pub diff: DiffOptions, -} - -pub type SharedOptions = Rc>; - pub struct OptionsPopupComponent { selection: AppOption, queue: Queue, @@ -91,26 +82,27 @@ impl OptionsPopupComponent { ); Self::add_header(txt, ""); + let diff = self.options.borrow().diff_options(); Self::add_header(txt, "Diff"); self.add_entry( txt, width, "Ignore whitespaces", - &self.options.borrow().diff.ignore_whitespace.to_string(), + &diff.ignore_whitespace.to_string(), self.is_select(AppOption::DiffIgnoreWhitespaces), ); self.add_entry( txt, width, "Context lines", - &self.options.borrow().diff.context.to_string(), + &diff.context.to_string(), self.is_select(AppOption::DiffContextLines), ); self.add_entry( txt, width, "Inter hunk lines", - &self.options.borrow().diff.interhunk_lines.to_string(), + &diff.interhunk_lines.to_string(), self.is_select(AppOption::DiffInterhunkLines), ); } diff --git a/src/main.rs b/src/main.rs index 3cc81d081e..0c089f2be7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -27,6 +27,7 @@ mod components; mod input; mod keys; mod notify_mutex; +mod options; mod popup_stack; mod profiler; mod queue; @@ -175,7 +176,7 @@ fn run_app( input.clone(), theme, key_config, - ); + )?; let mut spinner = Spinner::default(); let mut first_update = true; diff --git a/src/options.rs b/src/options.rs new file mode 100644 index 0000000000..48005e32f9 --- /dev/null +++ b/src/options.rs @@ -0,0 +1,90 @@ +use anyhow::Result; +use asyncgit::sync::{ + diff::DiffOptions, repo_dir, RepoPathRef, + ShowUntrackedFilesConfig, +}; +use ron::{ + de::from_bytes, + ser::{to_string_pretty, PrettyConfig}, +}; +use serde::{Deserialize, Serialize}; +use std::{ + cell::RefCell, + fs::File, + io::{Read, Write}, + path::PathBuf, + rc::Rc, +}; + +#[derive(Default, Copy, Clone, Serialize, Deserialize)] +struct OptionsData { + pub tab: usize, +} + +#[derive(Clone)] +pub struct Options { + //TODO: un-pub and use getters/setters and move into persisted data + pub status_show_untracked: Option, + pub diff: DiffOptions, + + repo: RepoPathRef, + data: OptionsData, +} + +pub type SharedOptions = Rc>; + +impl Options { + pub fn new(repo: RepoPathRef) -> SharedOptions { + Rc::new(RefCell::new(Self { + data: Self::read(&repo).unwrap_or_default(), + diff: DiffOptions::default(), + status_show_untracked: None, + repo, + })) + } + + pub fn set_current_tab(&mut self, tab: usize) { + self.data.tab = tab; + self.save(); + } + + pub const fn current_tab(&self) -> usize { + self.data.tab + } + + pub const fn diff_options(&self) -> DiffOptions { + self.diff + } + + fn save(&self) { + if let Err(e) = self.save_failable() { + log::error!("options save error: {}", e); + } + } + + fn read(repo: &RepoPathRef) -> Result { + let dir = Self::options_file(repo)?; + + let mut f = File::open(dir)?; + let mut buffer = Vec::new(); + f.read_to_end(&mut buffer)?; + Ok(from_bytes(&buffer)?) + } + + fn save_failable(&self) -> Result<()> { + let dir = Self::options_file(&self.repo)?; + + let mut file = File::create(&dir)?; + let data = + to_string_pretty(&self.data, PrettyConfig::default())?; + file.write_all(data.as_bytes())?; + + Ok(()) + } + + fn options_file(repo: &RepoPathRef) -> Result { + let dir = repo_dir(&repo.borrow())?; + let dir = dir.join("gitui"); + Ok(dir) + } +} diff --git a/src/tabs/status.rs b/src/tabs/status.rs index de25ffd53f..117883db6d 100644 --- a/src/tabs/status.rs +++ b/src/tabs/status.rs @@ -4,9 +4,10 @@ use crate::{ command_pump, event_pump, visibility_blocking, ChangesComponent, CommandBlocking, CommandInfo, Component, DiffComponent, DrawableComponent, EventState, - FileTreeItemKind, SharedOptions, + FileTreeItemKind, }, keys::{key_match, SharedKeyConfig}, + options::SharedOptions, queue::{Action, InternalEvent, NeedsUpdate, Queue, ResetItem}, strings, try_or_popup, ui::style::SharedTheme, @@ -490,7 +491,7 @@ impl Status { let diff_params = DiffParams { path: path.clone(), diff_type, - options: self.options.borrow().diff, + options: self.options.borrow().diff_options(), }; if self.diff.current() == (path.clone(), is_stage) {