Skip to content

Commit

Permalink
Add JSON and YAML support; add option serialisation
Browse files Browse the repository at this point in the history
  • Loading branch information
dhardy committed Feb 5, 2021
1 parent d53a6ab commit 3ca235a
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 2 deletions.
8 changes: 8 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ markdown = ["kas-text/markdown"]
# For now, this does work with nightly Cargo and -Z namespaced-features -Z weak-dep-features
# serde = ["dep:serde", "winit?/serde"]

# Enable support for YAML (de)serialisation
yaml = ["serde", "serde_yaml"]

# Enable support for JSON (de)serialisation
json = ["serde", "serde_json"]

[dependencies]
log = "0.4"
smallvec = "1.4"
Expand All @@ -53,6 +59,8 @@ unicode-segmentation = "1.7"
linear-map = "1.2.0"
thiserror = "1.0.23"
serde = { version = "1.0.123", features = ["derive"], optional = true }
serde_json = { version = "1.0.61", optional = true }
serde_yaml = { version = "0.8.16", optional = true }

[dependencies.kas-macros]
version = "0.6.0"
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ The `kas` crate has the following feature flags:
- `winit`: adds compatibility code for winit's event and geometry types.
This is currently the only functional windowing/event library.
- `serde`: adds (de)serialisation support to various types
- `json`: adds config (de)serialisation using JSON (implies `serde`)
- `yaml`: adds config (de)serialisation using YAML (implies `serde`)
- `stack_dst`: some compatibility impls (see `kas-theme`'s documentation)


Expand Down
2 changes: 1 addition & 1 deletion kas-wgpu/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ optional = true
[dev-dependencies]
chrono = "0.4"
env_logger = "0.7"
kas = { path = "..", features = ["markdown", "winit"] }
kas = { path = "..", features = ["markdown", "winit", "json", "yaml"] }

[build-dependencies]
glob = "0.3"
32 changes: 31 additions & 1 deletion src/event/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ use thiserror::Error;

#[derive(Error, Debug)]
pub enum ConfigError {
#[cfg(feature = "yaml")]
#[error("config (de)serialisation to YAML failed")]
Yaml(#[from] serde_yaml::Error),
#[cfg(feature = "json")]
#[error("config (de)serialisation to JSON failed")]
Json(#[from] serde_json::Error),
#[error("error reading / writing config file")]
IoError(#[from] std::io::Error),
#[error("format not supported: {0}")]
Expand All @@ -24,9 +30,15 @@ pub enum ConfigFormat {
/// Not specified: guess from the path
#[error("no format")]
None,
/// JSON
#[error("JSON")]
Json,
/// TOML
#[error("TOML")]
Toml,
/// YAML
#[error("YAML")]
Yaml,
/// Error: unable to guess format
#[error("(unknown format)")]
Unknown,
Expand All @@ -40,6 +52,7 @@ impl Default for ConfigFormat {

/// Event handling configuration
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct Config {
pub shortcuts: Shortcuts,
}
Expand All @@ -56,8 +69,12 @@ impl Config {
fn guess_format(path: &Path) -> ConfigFormat {
// use == since there is no OsStr literal
if let Some(ext) = path.extension() {
if ext == "toml" {
if ext == "json" {
ConfigFormat::Json
} else if ext == "toml" {
ConfigFormat::Toml
} else if ext == "yaml" {
ConfigFormat::Yaml
} else {
ConfigFormat::Unknown
}
Expand All @@ -84,6 +101,19 @@ impl Config {
}

match format {
#[cfg(feature = "json")]
ConfigFormat::Json => {
let w = std::io::BufWriter::new(std::fs::File::create(path)?);
serde_json::to_writer_pretty(w, self)?;
Ok(())
}
#[cfg(feature = "yaml")]
ConfigFormat::Yaml => {
let w = std::io::BufWriter::new(std::fs::File::create(path)?);
serde_yaml::to_writer(w, self)?;
Ok(())
}
// NOTE: Toml is not supported since the `toml` crate does not support enums as map keys
_ => Err(ConfigError::UnsupportedFormat(format)),
}
}
Expand Down
58 changes: 58 additions & 0 deletions src/event/shortcuts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
use super::{Command, ModifiersState, VirtualKeyCode};
use linear_map::LinearMap;
#[cfg(feature = "serde")]
use serde::ser::{Serialize, SerializeMap, Serializer};
use std::collections::HashMap;

/// Shortcut manager
Expand Down Expand Up @@ -195,3 +197,59 @@ impl Shortcuts {
None
}
}

#[cfg(feature = "serde")]
fn state_to_string(state: ModifiersState) -> &'static str {
const SHIFT: ModifiersState = ModifiersState::SHIFT;
const CTRL: ModifiersState = ModifiersState::CTRL;
const ALT: ModifiersState = ModifiersState::ALT;
const SUPER: ModifiersState = ModifiersState::LOGO;
// we can't use match since OR patterns are unstable (rust#54883)
if state == ModifiersState::empty() {
"none"
} else if state == SUPER {
"super"
} else if state == ALT {
"alt"
} else if state == ALT | SUPER {
"alt-super"
} else if state == CTRL {
"ctrl"
} else if state == CTRL | SUPER {
"ctrl-super"
} else if state == CTRL | ALT {
"ctrl-alt"
} else if state == CTRL | ALT | SUPER {
"ctrl-alt-super"
} else if state == SHIFT {
"shift"
} else if state == SHIFT | SUPER {
"shift-super"
} else if state == SHIFT | ALT {
"alt-shift"
} else if state == SHIFT | ALT | SUPER {
"alt-shift-super"
} else if state == SHIFT | CTRL {
"ctrl-shift"
} else if state == SHIFT | CTRL | SUPER {
"ctrl-shift-super"
} else if state == SHIFT | CTRL | ALT {
"ctrl-alt-shift"
} else {
"ctrl-alt-shift-super"
}
}

#[cfg(feature = "serde")]
impl Serialize for Shortcuts {
fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut map = s.serialize_map(Some(self.map.len()))?;
for (k, v) in &self.map {
map.serialize_entry(state_to_string(*k), v)?;
}
map.end()
}
}

0 comments on commit 3ca235a

Please sign in to comment.