// nixos-config - My current NixOS configuration // // Copyright (C) 2025 Benedikt Peetz // 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 . use std::{fs::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; impl Project { pub(super) fn get_sessionstore(&self) -> Result { let path = dirs::data_local_dir() .context("Failed to get data dir")? .join("qutebrowser") .join(self.to_project_display()) // NOTE(@bpeetz): We could use another real session name, but this file should // always exist. <2025-06-03> .join("data/sessions/_autosave.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 { 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())) .ok_or(anyhow!("Missing tab history active"))? .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())) .ok_or(anyhow!("Missing tab history zoom"))? .as_f64() .ok_or(anyhow!("tab history zoom not 64"))?, }) }) .collect::, _>>()?, active: hash .get(&Yaml::String("active".to_owned())) .unwrap_or(&Yaml::Boolean(false)) .as_bool() .ok_or(anyhow!("active not bool"))?, }) }) .collect::, _>>()?, }) }) .collect::, _>>()?, }) } #[derive(Debug)] pub struct SessionStore { pub windows: Vec, } #[derive(Debug)] pub struct Window { pub geometry: String, pub tabs: Vec, } #[derive(Debug)] pub struct Tab { pub history: Vec, 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, }