feat: [preview] config section
This commit is contained in:
1 parent
04aedc810f
commit
acbf9f74db
2 files changed
+48
-7
No files matched your search
+45
-7
@@ -1,6 +1,6 @@
|
|||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result, bail};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
use crate::error::HintExt;
|
use crate::error::HintExt;
|
||||||
@@ -10,6 +10,7 @@ use crate::error::HintExt;
|
|||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub save: Save,
|
pub save: Save,
|
||||||
pub capture: Capture,
|
pub capture: Capture,
|
||||||
|
pub preview: Preview,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Deserialize)]
|
||||||
@@ -26,6 +27,22 @@ pub struct Capture {
|
|||||||
pub show_cursor: bool,
|
pub show_cursor: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Deserialize)]
|
||||||
|
#[serde(default)]
|
||||||
|
pub struct Preview {
|
||||||
|
pub enabled: bool,
|
||||||
|
pub timeout_secs: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Preview {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
enabled: true,
|
||||||
|
timeout_secs: 5,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Default for Save {
|
impl Default for Save {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
@@ -77,7 +94,10 @@ pub fn load(path: &Path) -> Result<Config> {
|
|||||||
pub fn parse(text: &str) -> Result<(Config, Vec<String>)> {
|
pub fn parse(text: &str) -> Result<(Config, Vec<String>)> {
|
||||||
let de = toml::Deserializer::parse(text)?;
|
let de = toml::Deserializer::parse(text)?;
|
||||||
let mut unknown = Vec::new();
|
let mut unknown = Vec::new();
|
||||||
let config = serde_ignored::deserialize(de, |path| unknown.push(path.to_string()))?;
|
let config: Config = serde_ignored::deserialize(de, |path| unknown.push(path.to_string()))?;
|
||||||
|
if config.preview.timeout_secs == 0 {
|
||||||
|
bail!("preview.timeout_secs must be at least 1");
|
||||||
|
}
|
||||||
Ok((config, unknown))
|
Ok((config, unknown))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,13 +134,10 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn unknown_keys_are_reported_not_rejected() {
|
fn unknown_keys_are_reported_not_rejected() {
|
||||||
let text = "[preview]\nenabled = true\n\n[save]\nfolder = \"x\"\n";
|
let text = "[zoom]\nscroll_step = 1.15\n\n[save]\nfolder = \"x\"\n";
|
||||||
let (config, unknown) = parse(text).unwrap();
|
let (config, unknown) = parse(text).unwrap();
|
||||||
assert_eq!(config, Config::default());
|
assert_eq!(config, Config::default());
|
||||||
assert_eq!(
|
assert_eq!(unknown, vec!["save.folder".to_string(), "zoom".to_string()]);
|
||||||
unknown,
|
|
||||||
vec!["preview".to_string(), "save.folder".to_string()]
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -134,6 +151,27 @@ mod tests {
|
|||||||
assert!(parse("[capture]\nshow_cursor = \"yes\"\n").is_err());
|
assert!(parse("[capture]\nshow_cursor = \"yes\"\n").is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn preview_defaults_and_overrides() {
|
||||||
|
assert_eq!(
|
||||||
|
Config::default().preview,
|
||||||
|
Preview {
|
||||||
|
enabled: true,
|
||||||
|
timeout_secs: 5
|
||||||
|
}
|
||||||
|
);
|
||||||
|
let (config, _) = parse("[preview]\ntimeout_secs = 2\n").unwrap();
|
||||||
|
assert!(config.preview.enabled);
|
||||||
|
assert_eq!(config.preview.timeout_secs, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn preview_timeout_must_be_positive() {
|
||||||
|
let err = parse("[preview]\ntimeout_secs = 0\n").unwrap_err();
|
||||||
|
assert_eq!(err.to_string(), "preview.timeout_secs must be at least 1");
|
||||||
|
assert!(parse("[preview]\ntimeout_secs = -3\n").is_err());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn missing_file_gives_defaults() {
|
fn missing_file_gives_defaults() {
|
||||||
let dir = tempfile::tempdir().unwrap();
|
let dir = tempfile::tempdir().unwrap();
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
// Phase 2 modules land before the CLI uses them; Task 6 removes this.
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
mod capture;
|
mod capture;
|
||||||
mod config;
|
mod config;
|
||||||
mod detach;
|
mod detach;
|
||||||
|
|||||||
Reference in new issue
Block a user