diff options
Diffstat (limited to 'pkgs/by-name/ts/tskm/src/interface/open/mod.rs')
-rw-r--r-- | pkgs/by-name/ts/tskm/src/interface/open/mod.rs | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/pkgs/by-name/ts/tskm/src/interface/open/mod.rs b/pkgs/by-name/ts/tskm/src/interface/open/mod.rs new file mode 100644 index 00000000..e403b4a8 --- /dev/null +++ b/pkgs/by-name/ts/tskm/src/interface/open/mod.rs @@ -0,0 +1,198 @@ +// nixos-config - My current NixOS configuration +// +// Copyright (C) 2025 Benedikt Peetz <benedikt.peetz@b-peetz.de> +// SPDX-License-Identifier: GPL-3.0-or-later +// +// This file is part of my nixos-config. +// +// You should have received a copy of the License along with this program. +// If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>. + +use std::{ + fs::{self, File}, + io::Read, + str::FromStr, +}; + +use anyhow::{anyhow, Context, Result}; +use taskchampion::chrono::NaiveDateTime; +use url::Url; +use yaml_rust2::Yaml; + +use crate::task::Project; + +pub mod handle; +pub use handle::handle; + +/// An Url that also accepts file paths +#[derive(Debug, Clone)] +pub struct UrlLike(Url); + +impl FromStr for UrlLike { + type Err = url::ParseError; + + fn from_str(s: &str) -> std::result::Result<Self, Self::Err> { + if let Ok(u) = fs::canonicalize(s) { + Ok(Self(Url::from_file_path(u).expect( + "The path could be canonicalized, as such it is valid for this", + ))) + } else { + Url::from_str(s).map(Self) + } + } +} + +impl From<UrlLike> for Url { + fn from(value: UrlLike) -> Self { + value.0 + } +} + +impl Project { + pub(super) fn get_sessionstore(&self) -> Result<SessionStore> { + let path = dirs::data_local_dir() + .context("Failed to get data dir")? + .join("qutebrowser") + .join(self.to_project_display()) + .join("data/sessions/default.yml"); + + let mut file = File::open(&path) + .with_context(|| format!("Failed to open path '{}'", path.display()))?; + + let mut yaml_str = String::new(); + file.read_to_string(&mut yaml_str) + .context("Failed to read _autosave.yml path")?; + let yaml = yaml_rust2::YamlLoader::load_from_str(&yaml_str)?; + + let store = qute_store_from_yaml(&yaml).context("Failed to read yaml store")?; + + Ok(store) + } +} + +fn qute_store_from_yaml(yaml: &[Yaml]) -> Result<SessionStore> { + assert_eq!(yaml.len(), 1); + let doc = &yaml[0]; + + let hash = doc.as_hash().context("Invalid yaml")?; + let windows = hash + .get(&Yaml::String("windows".to_owned())) + .ok_or(anyhow!("Missing windows"))? + .as_vec() + .ok_or(anyhow!("Windows not vector"))?; + + Ok(SessionStore { + windows: windows + .iter() + .map(|window| { + let hash = window.as_hash().ok_or(anyhow!("Windows not hashmap"))?; + + Ok::<_, anyhow::Error>(Window { + geometry: hash + .get(&Yaml::String("geometry".to_owned())) + .ok_or(anyhow!("Missing window geometry"))? + .as_str() + .ok_or(anyhow!("geometry not string"))? + .to_owned(), + tabs: hash + .get(&Yaml::String("tabs".to_owned())) + .ok_or(anyhow!("Missing window tabs"))? + .as_vec() + .ok_or(anyhow!("Tabs not vec"))? + .iter() + .map(|tab| { + let hash = tab.as_hash().ok_or(anyhow!("Tab not hashmap"))?; + + Ok::<_, anyhow::Error>(Tab { + history: hash + .get(&Yaml::String("history".to_owned())) + .ok_or(anyhow!("Missing tab history"))? + .as_vec() + .ok_or(anyhow!("tab history not vec"))? + .iter() + .map(|history| { + let hash = history + .as_hash() + .ok_or(anyhow!("Tab history not hashmap"))?; + + Ok::<_, anyhow::Error>(TabHistory { + active: hash + .get(&Yaml::String("active".to_owned())) + .unwrap_or(&Yaml::Boolean(false)) + .as_bool() + .ok_or(anyhow!("tab history active not bool"))?, + last_visited: NaiveDateTime::from_str( + hash.get(&Yaml::String("last_visited".to_owned())) + .ok_or(anyhow!( + "Missing tab history last_visited" + ))? + .as_str() + .ok_or(anyhow!( + "tab history last_visited not string" + ))?, + ) + .context("Failed to parse last_visited")?, + pinned: hash + .get(&Yaml::String("pinned".to_owned())) + .ok_or(anyhow!("Missing tab history pinned"))? + .as_bool() + .ok_or(anyhow!("tab history pinned not bool"))?, + title: hash + .get(&Yaml::String("title".to_owned())) + .ok_or(anyhow!("Missing tab history title"))? + .as_str() + .ok_or(anyhow!("tab history title not string"))? + .to_owned(), + url: Url::parse( + hash.get(&Yaml::String("url".to_owned())) + .ok_or(anyhow!("Missing tab history url"))? + .as_str() + .ok_or(anyhow!("tab history url not string"))?, + ) + .context("Failed to parse url")?, + zoom: hash + .get(&Yaml::String("zoom".to_owned())) + .unwrap_or(&Yaml::Real("1.0".to_owned())) + .as_f64() + .ok_or(anyhow!("tab history zoom not 64"))?, + }) + }) + .collect::<Result<Vec<_>, _>>()?, + active: hash + .get(&Yaml::String("active".to_owned())) + .unwrap_or(&Yaml::Boolean(false)) + .as_bool() + .ok_or(anyhow!("active not bool"))?, + }) + }) + .collect::<Result<Vec<_>, _>>()?, + }) + }) + .collect::<Result<Vec<_>, _>>()?, + }) +} + +#[derive(Debug)] +pub struct SessionStore { + pub windows: Vec<Window>, +} +#[derive(Debug)] +pub struct Window { + pub geometry: String, + pub tabs: Vec<Tab>, +} +#[derive(Debug)] +pub struct Tab { + pub history: Vec<TabHistory>, + pub active: bool, +} +#[derive(Debug)] +pub struct TabHistory { + pub active: bool, + pub last_visited: NaiveDateTime, + pub pinned: bool, + // pub scroll-pos: + pub title: String, + pub url: Url, + pub zoom: f64, +} |