summaryrefslogtreecommitdiffstats
path: root/src/app/session.rs
diff options
context:
space:
mode:
authorqkzk <qu3nt1n@gmail.com>2023-12-10 22:44:17 +0100
committerqkzk <qu3nt1n@gmail.com>2023-12-10 22:44:17 +0100
commit273627ad94ddb0e3df5ebaa3a8a711b6d021ee69 (patch)
treea4d3559f9cbf43fa81819e5bab906c1d223d103c /src/app/session.rs
parent7a07091f9819b54a1ed66db017e065bf7b8f5b58 (diff)
documentation & session refactoring
Diffstat (limited to 'src/app/session.rs')
-rw-r--r--src/app/session.rs143
1 files changed, 143 insertions, 0 deletions
diff --git a/src/app/session.rs b/src/app/session.rs
new file mode 100644
index 0000000..659b89b
--- /dev/null
+++ b/src/app/session.rs
@@ -0,0 +1,143 @@
+use std::fs::File;
+
+use serde::Serialize;
+use serde_yaml::{Error as YamlError, Value as YamlValue};
+
+use crate::common::SESSION_PATH;
+use crate::io::MIN_WIDTH_FOR_DUAL_PANE;
+use crate::log_info;
+
+/// Everything about the current session.
+/// We keep track of display settings (metadata, dual pane, second pane as preview).
+/// Display hidden files is read from args or set to false by default.
+/// Since it's specific to a tab, it's not stored here.
+///
+/// Reads its display values from a session file and updates them when modified.
+/// The file is stored at [`crate::common::SESSION_PATH`] which points to `~/.config/fm/session.yaml`.
+/// Unreachable or unreadable files are ignored.
+///
+/// Holds settings about display :
+/// - do we display one or two tabs ? Default to true.
+/// - do we display files metadata ? Default to true.
+/// - do we use to second pane to preview files ? Default to false.
+#[derive(Debug, Serialize)]
+pub struct Session {
+ /// do we display one or two tabs ?
+ pub dual: bool,
+ /// do we display all info or only the filenames ?
+ pub metadata: bool,
+ /// use the second pane to preview
+ pub preview: bool,
+ /// session filepath
+ #[serde(skip_serializing)]
+ filepath: String,
+}
+
+impl Default for Session {
+ fn default() -> Self {
+ Self {
+ dual: true,
+ metadata: true,
+ preview: false,
+ filepath: shellexpand::tilde(SESSION_PATH).to_string(),
+ }
+ }
+}
+
+impl Session {
+ /// Creates a new instance of `DisplaySettings`.
+ /// Tries to read them from the session file.
+ /// Use default value if the file can't be read.
+ pub fn new(width: usize) -> Self {
+ Self::default().update_from_config(width)
+ }
+
+ fn update_from_config(mut self, width: usize) -> Self {
+ let Ok(file) = File::open(&self.filepath) else {
+ log_info!("Couldn't open file {file}", file = self.filepath);
+ return self;
+ };
+ let Ok(yaml): Result<YamlValue, YamlError> = serde_yaml::from_reader(file) else {
+ log_info!(
+ "Couldn't parse session from file {file}",
+ file = self.filepath
+ );
+ return self;
+ };
+ match yaml["dual"] {
+ YamlValue::Bool(value) => self.dual = Self::parse_dual_pane(value, width),
+ _ => self.dual = true,
+ }
+ match yaml["metadata"] {
+ YamlValue::Bool(value) => self.metadata = value,
+ _ => self.metadata = true,
+ }
+ match yaml["preview"] {
+ YamlValue::Bool(value) => self.preview = value,
+ _ => self.preview = false,
+ }
+ self
+ }
+
+ fn parse_dual_pane(session_bool: bool, width: usize) -> bool {
+ if !Self::display_wide_enough(width) {
+ return false;
+ }
+ session_bool
+ }
+
+ /// True iff the terminal is wide enough to display two panes
+ pub fn display_wide_enough(width: usize) -> bool {
+ width >= MIN_WIDTH_FOR_DUAL_PANE
+ }
+
+ /// True if we display 2 tabs.
+ /// It requires two conditions:
+ /// 1. The display should be wide enough, bigger than [`crate::io::MIN_WIDTH_FOR_DUAL_PANE`].
+ /// 2. The `dual_tab` setting must be true.
+ pub fn use_dual_tab(&self, width: usize) -> bool {
+ self.dual && Self::display_wide_enough(width)
+ }
+
+ pub fn set_dual(&mut self, dual: bool) {
+ self.dual = dual;
+ self.update_yaml_file();
+ }
+
+ pub fn toggle_dual(&mut self) {
+ self.dual = !self.dual;
+ self.update_yaml_file();
+ }
+
+ pub fn toggle_metadata(&mut self) {
+ self.metadata = !self.metadata;
+ self.update_yaml_file();
+ }
+
+ pub fn toggle_preview(&mut self) {
+ self.preview = !self.preview;
+ self.update_yaml_file();
+ }
+
+ /// Writes itself to the session file.
+ /// Does nothing if an error is encountered while creating or writing to the session file.
+ fn update_yaml_file(&self) {
+ let mut file = match File::create(&self.filepath) {
+ Ok(file) => file,
+ Err(error) => {
+ log_info!(
+ "Couldn't create session {file}. Error: {error:?}",
+ file = self.filepath
+ );
+ return;
+ }
+ };
+ match serde_yaml::to_writer(&mut file, &self) {
+ Ok(()) => (),
+ Err(e) => log_info!(
+ "Couldn't write config to session {file}. Error: {e:?}",
+ file = self.filepath
+ ),
+ }
+ }
+}