feat(config): json schema support

This PR includes the necessary code changes, CI changes and documentation to generate and deploy a full JSON schema for each release and the master branch, which can be used within config files for autocomplete and type checking.
This commit is contained in:
Jake Stanger 2024-05-10 22:40:00 +01:00
parent a47ef0c763
commit 36d724f148
No known key found for this signature in database
GPG Key ID: C51FC8F9CB0BEA61
36 changed files with 230 additions and 15 deletions

View File

@ -6,20 +6,13 @@ on:
- v[0-9]+.[0-9]+.[0-9]+ - v[0-9]+.[0-9]+.[0-9]+
jobs: jobs:
deploy: release:
name: 'Create Release'
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
override: true
- name: Install build deps
run: ./.github/scripts/ubuntu_setup.sh
- name: Update CHANGELOG - name: Update CHANGELOG
id: changelog id: changelog
uses: Requarks/changelog-action@v1 uses: Requarks/changelog-action@v1
@ -41,9 +34,54 @@ jobs:
uses: stefanzweifel/git-auto-commit-action@v4 uses: stefanzweifel/git-auto-commit-action@v4
with: with:
branch: master branch: master
commit_message: 'docs: update CHANGELOG.md for ${{ github.ref_name }} [skip ci]' commit_message: 'chore: update CHANGELOG.md for ${{ github.ref_name }} [skip ci]'
file_pattern: CHANGELOG.md file_pattern: CHANGELOG.md
- uses: katyo/publish-crates@v1
publish-crate:
name: 'Publish Crate'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
override: true
- name: Install build deps
run: ./.github/scripts/ubuntu_setup.sh
- name: Publish crate
uses: katyo/publish-crates@v1
with: with:
registry-token: ${{ secrets.CARGO_REGISTRY_TOKEN }} registry-token: ${{ secrets.CARGO_REGISTRY_TOKEN }}
publish-schema:
name: 'Publish Schema'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: Swatinem/rust-cache@v2
name: Cache dependencies
- name: Install build deps
run: ./.github/scripts/ubuntu_setup.sh
- name: Build schema
run: cargo build --features schema -- --print-schema > target/schema-${{ github.ref_name }}.json
- name: Copy file via SSH
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.SSH_HOST }}
port: ${{ secrets.SSH_PORT }}
username: ${{ secrets.SSH_USERNAME }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
source: "target/schema-${{ github.ref_name }}.json"
target: /storage/Public/github/ironbar
strip_components: 1

41
.github/workflows/schema.yml vendored Normal file
View File

@ -0,0 +1,41 @@
name: Publish Schema
on:
workflow_dispatch:
push:
branches: [ "master" ]
env:
CARGO_TERM_COLOR: always
RUSTFLAGS: '-Dwarnings'
jobs:
publish-schema:
name: 'Publish Schema'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: Swatinem/rust-cache@v2
name: Cache dependencies
- name: Install build deps
run: ./.github/scripts/ubuntu_setup.sh
- name: Build
run: cargo build --features schema
- name: Print schema
run: cargo run --features schema -- --print-schema > target/schema.json
- name: Copy file via SSH
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.SSH_HOST }}
port: ${{ secrets.SSH_PORT }}
username: ${{ secrets.SSH_USERNAME }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
source: "target/schema.json"
target: /storage/Public/github/ironbar
strip_components: 1

42
Cargo.lock generated
View File

@ -755,6 +755,12 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650"
[[package]]
name = "dyn-clone"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125"
[[package]] [[package]]
name = "either" name = "either"
version = "1.8.1" version = "1.8.1"
@ -1606,6 +1612,7 @@ dependencies = [
"notify", "notify",
"regex", "regex",
"reqwest", "reqwest",
"schemars",
"serde", "serde",
"serde_json", "serde_json",
"smithay-client-toolkit", "smithay-client-toolkit",
@ -2637,6 +2644,30 @@ dependencies = [
"windows-sys 0.42.0", "windows-sys 0.42.0",
] ]
[[package]]
name = "schemars"
version = "0.8.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc6e7ed6919cb46507fb01ff1654309219f62b4d603822501b0b80d42f6f21ef"
dependencies = [
"dyn-clone",
"schemars_derive",
"serde",
"serde_json",
]
[[package]]
name = "schemars_derive"
version = "0.8.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "185f2b7aa7e02d418e453790dde16890256bbd2bcd04b7dc5348811052b53f49"
dependencies = [
"proc-macro2",
"quote 1.0.35",
"serde_derive_internals",
"syn 2.0.48",
]
[[package]] [[package]]
name = "scoped-tls" name = "scoped-tls"
version = "1.0.1" version = "1.0.1"
@ -2698,6 +2729,17 @@ dependencies = [
"syn 2.0.48", "syn 2.0.48",
] ]
[[package]]
name = "serde_derive_internals"
version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "330f01ce65a3a5fe59a60c82f3c9a024b573b8a6e875bd233fe5f934e71d54e3"
dependencies = [
"proc-macro2",
"quote 1.0.35",
"syn 2.0.48",
]
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.117" version = "1.0.117"

View File

@ -76,6 +76,8 @@ workspaces = ["futures-lite"]
"workspaces+sway" = ["workspaces", "swayipc-async"] "workspaces+sway" = ["workspaces", "swayipc-async"]
"workspaces+hyprland" = ["workspaces", "hyprland"] "workspaces+hyprland" = ["workspaces", "hyprland"]
schema = ["dep:schemars"]
[dependencies] [dependencies]
# core # core
gtk = "0.18.1" gtk = "0.18.1"
@ -157,3 +159,6 @@ regex = { version = "1.10.4", default-features = false, features = [
"std", "std",
], optional = true } # music, sys_info ], optional = true } # music, sys_info
zbus = { version = "3.15.2", default-features = false, features = ["tokio"], optional = true } # notifications, upower zbus = { version = "3.15.2", default-features = false, features = ["tokio"], optional = true } # notifications, upower
# schema
schemars = { version = "0.8.19", optional = true }

View File

@ -101,6 +101,9 @@ cargo build --release --no-default-features \
| workspaces+all | Enables the `workspaces` module with support for all compositors. | | workspaces+all | Enables the `workspaces` module with support for all compositors. |
| workspaces+sway | Enables the `workspaces` module with support for Sway. | | workspaces+sway | Enables the `workspaces` module with support for Sway. |
| workspaces+hyprland | Enables the `workspaces` module with support for Hyprland. | | workspaces+hyprland | Enables the `workspaces` module with support for Hyprland. |
| **Other** | |
| schema | Enables JSON schema support and the CLI `--print-schema` flag. |
## Speeding up compiling ## Speeding up compiling

View File

@ -20,11 +20,18 @@ Ironbar supports a range of configuration formats, so you can pick your favourit
- `config.json` - `config.json`
- `config.toml` - `config.toml`
- `config.yaml` - `config.yaml`
- `config.corn` (Experimental, includes variable support for re-using blocks. - `config.corn` (Includes variable support for re-using blocks.
See [here](https://github.com/jakestanger/corn) for info) See [here](https://github.com/jakestanger/corn) for info)
You can also override the default config path using the `IRONBAR_CONFIG` environment variable. You can also override the default config path using the `IRONBAR_CONFIG` environment variable.
A hosted schema is available for the latest Git version ~~and each versioned release~~.
JSON and YAML both support schema checking by adding the `$schema` key
to the top level of your config.
- master: `https://f.jstanger.dev/github/ironbar/schema.json`
- ~~release: `https://f.jstanger.dev/github/ironbar/schema-v0.16.0.json`~~ *(Not released yet)*
## 2. Pick your use-case ## 2. Pick your use-case
Ironbar gives you a few ways to configure the bar to suit your needs. Ironbar gives you a few ways to configure the bar to suit your needs.

View File

@ -1,4 +1,5 @@
{ {
"$schema": "https://f.jstanger.dev/github/ironbar/schema.json",
"anchor_to_edges": true, "anchor_to_edges": true,
"position": "bottom", "position": "bottom",
"icon_theme": "Paper", "icon_theme": "Paper",

View File

@ -1,3 +1,4 @@
$schema: https://f.jstanger.dev/github/ironbar/schema.json
anchor_to_edges: true anchor_to_edges: true
position: bottom position: bottom
icon_theme: Paper icon_theme: Paper

View File

@ -9,6 +9,12 @@ pub struct Args {
#[command(subcommand)] #[command(subcommand)]
pub command: Option<Command>, pub command: Option<Command>,
/// Prints the config JSON schema to `stdout`
/// and exits.
#[cfg(feature = "schema")]
#[arg(long("print-schema"))]
pub print_schema: bool,
/// `bar_id` argument passed by `swaybar_command`. /// `bar_id` argument passed by `swaybar_command`.
/// Not used. /// Not used.
#[arg(short('b'), hide(true))] #[arg(short('b'), hide(true))]

View File

@ -16,6 +16,7 @@ use tracing::trace;
/// see [here](script). /// see [here](script).
/// For information on styling, please see the [styling guide](styling-guide). /// For information on styling, please see the [styling guide](styling-guide).
#[derive(Debug, Default, Deserialize, Clone)] #[derive(Debug, Default, Deserialize, Clone)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct CommonConfig { pub struct CommonConfig {
/// Sets the unique widget name, /// Sets the unique widget name,
/// allowing you to target it in CSS using `#name`. /// allowing you to target it in CSS using `#name`.
@ -160,6 +161,7 @@ pub struct CommonConfig {
#[derive(Debug, Deserialize, Clone)] #[derive(Debug, Deserialize, Clone)]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub enum TransitionType { pub enum TransitionType {
None, None,
Crossfade, Crossfade,
@ -169,6 +171,7 @@ pub enum TransitionType {
#[derive(Debug, Default, Deserialize, Clone, Copy)] #[derive(Debug, Default, Deserialize, Clone, Copy)]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub enum ModuleOrientation { pub enum ModuleOrientation {
#[default] #[default]
#[serde(alias = "h")] #[serde(alias = "h")]

View File

@ -36,11 +36,15 @@ use color_eyre::Result;
use serde::Deserialize; use serde::Deserialize;
use std::collections::HashMap; use std::collections::HashMap;
#[cfg(feature = "schema")]
use schemars::JsonSchema;
pub use self::common::{CommonConfig, ModuleOrientation, TransitionType}; pub use self::common::{CommonConfig, ModuleOrientation, TransitionType};
pub use self::truncate::TruncateMode; pub use self::truncate::TruncateMode;
#[derive(Debug, Deserialize, Clone)] #[derive(Debug, Deserialize, Clone)]
#[serde(tag = "type", rename_all = "snake_case")] #[serde(tag = "type", rename_all = "snake_case")]
#[cfg_attr(feature = "schema", derive(JsonSchema))]
pub enum ModuleConfig { pub enum ModuleConfig {
#[cfg(feature = "cairo")] #[cfg(feature = "cairo")]
Cairo(Box<CairoModule>), Cairo(Box<CairoModule>),
@ -117,6 +121,7 @@ impl ModuleConfig {
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
#[cfg_attr(feature = "schema", derive(JsonSchema))]
pub enum MonitorConfig { pub enum MonitorConfig {
Single(BarConfig), Single(BarConfig),
Multiple(Vec<BarConfig>), Multiple(Vec<BarConfig>),
@ -124,6 +129,7 @@ pub enum MonitorConfig {
#[derive(Debug, Deserialize, Copy, Clone, PartialEq, Eq)] #[derive(Debug, Deserialize, Copy, Clone, PartialEq, Eq)]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
#[cfg_attr(feature = "schema", derive(JsonSchema))]
pub enum BarPosition { pub enum BarPosition {
Top, Top,
Bottom, Bottom,
@ -138,6 +144,7 @@ impl Default for BarPosition {
} }
#[derive(Debug, Default, Deserialize, Copy, Clone, PartialEq, Eq)] #[derive(Debug, Default, Deserialize, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "schema", derive(JsonSchema))]
pub struct MarginConfig { pub struct MarginConfig {
#[serde(default)] #[serde(default)]
pub bottom: i32, pub bottom: i32,
@ -156,6 +163,7 @@ pub struct MarginConfig {
/// depending on your [use-case](#2-pick-your-use-case). /// depending on your [use-case](#2-pick-your-use-case).
/// ///
#[derive(Debug, Deserialize, Clone)] #[derive(Debug, Deserialize, Clone)]
#[cfg_attr(feature = "schema", derive(JsonSchema))]
pub struct BarConfig { pub struct BarConfig {
/// A unique identifier for the bar, used for controlling it over IPC. /// A unique identifier for the bar, used for controlling it over IPC.
/// If not set, uses a generated integer suffix. /// If not set, uses a generated integer suffix.
@ -292,6 +300,7 @@ impl Default for BarConfig {
} }
#[derive(Debug, Deserialize, Clone, Default)] #[derive(Debug, Deserialize, Clone, Default)]
#[cfg_attr(feature = "schema", derive(JsonSchema))]
pub struct Config { pub struct Config {
/// A map of [ironvar](ironvar) keys and values /// A map of [ironvar](ironvar) keys and values
/// to initialize Ironbar with on startup. /// to initialize Ironbar with on startup.

View File

@ -4,6 +4,7 @@ use serde::Deserialize;
#[derive(Debug, Deserialize, Clone, Copy)] #[derive(Debug, Deserialize, Clone, Copy)]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub enum EllipsizeMode { pub enum EllipsizeMode {
Start, Start,
Middle, Middle,
@ -28,6 +29,7 @@ impl From<EllipsizeMode> for GtkEllipsizeMode {
/// ///
#[derive(Debug, Deserialize, Clone, Copy)] #[derive(Debug, Deserialize, Clone, Copy)]
#[serde(untagged)] #[serde(untagged)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub enum TruncateMode { pub enum TruncateMode {
/// Auto mode lets GTK decide when to ellipsize. /// Auto mode lets GTK decide when to ellipsize.
/// ///

View File

@ -8,6 +8,7 @@ use tokio::sync::mpsc;
#[derive(Debug, Deserialize, Clone)] #[derive(Debug, Deserialize, Clone)]
#[serde(untagged)] #[serde(untagged)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub enum DynamicBool { pub enum DynamicBool {
/// Either a script or variable, to be determined. /// Either a script or variable, to be determined.
Unknown(String), Unknown(String),

View File

@ -76,6 +76,13 @@ fn main() {
fn run_with_args() { fn run_with_args() {
let args = cli::Args::parse(); let args = cli::Args::parse();
#[cfg(feature = "schema")]
if args.print_schema {
let schema = schemars::schema_for!(Config);
println!("{}", serde_json::to_string_pretty(&schema).unwrap());
return;
}
match args.command { match args.command {
Some(command) => { Some(command) => {
let rt = create_runtime(); let rt = create_runtime();

View File

@ -18,6 +18,7 @@ use tokio::time::sleep;
use tracing::{debug, error}; use tracing::{debug, error};
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct CairoModule { pub struct CairoModule {
/// The path to the Lua script to load. /// The path to the Lua script to load.
/// This can be absolute, or relative to the working directory. /// This can be absolute, or relative to the working directory.

View File

@ -17,6 +17,7 @@ use tokio::sync::{broadcast, mpsc};
use tracing::{debug, error}; use tracing::{debug, error};
#[derive(Debug, Deserialize, Clone)] #[derive(Debug, Deserialize, Clone)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct ClipboardModule { pub struct ClipboardModule {
/// The icon to show on the bar widget button. /// The icon to show on the bar widget button.
/// Supports [image](images) icons. /// Supports [image](images) icons.

View File

@ -16,6 +16,7 @@ use crate::modules::{
use crate::{glib_recv, module_impl, send_async, spawn, try_send}; use crate::{glib_recv, module_impl, send_async, spawn, try_send};
#[derive(Debug, Deserialize, Clone)] #[derive(Debug, Deserialize, Clone)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct ClockModule { pub struct ClockModule {
/// The format string to use for the date/time shown on the bar. /// The format string to use for the date/time shown on the bar.
/// Pango markup is supported. /// Pango markup is supported.

View File

@ -6,6 +6,7 @@ use gtk::prelude::*;
use serde::Deserialize; use serde::Deserialize;
#[derive(Debug, Deserialize, Clone)] #[derive(Debug, Deserialize, Clone)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct BoxWidget { pub struct BoxWidget {
/// Widget name. /// Widget name.
/// ///

View File

@ -10,6 +10,7 @@ use crate::{build, try_send};
use super::{CustomWidget, CustomWidgetContext, ExecEvent, WidgetConfig}; use super::{CustomWidget, CustomWidgetContext, ExecEvent, WidgetConfig};
#[derive(Debug, Deserialize, Clone)] #[derive(Debug, Deserialize, Clone)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct ButtonWidget { pub struct ButtonWidget {
/// Widget name. /// Widget name.
/// ///

View File

@ -9,6 +9,7 @@ use crate::image::ImageProvider;
use super::{CustomWidget, CustomWidgetContext}; use super::{CustomWidget, CustomWidgetContext};
#[derive(Debug, Deserialize, Clone)] #[derive(Debug, Deserialize, Clone)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct ImageWidget { pub struct ImageWidget {
/// Widget name. /// Widget name.
/// ///

View File

@ -9,6 +9,7 @@ use crate::dynamic_value::dynamic_string;
use super::{CustomWidget, CustomWidgetContext}; use super::{CustomWidget, CustomWidgetContext};
#[derive(Debug, Deserialize, Clone)] #[derive(Debug, Deserialize, Clone)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct LabelWidget { pub struct LabelWidget {
/// Widget name. /// Widget name.
/// ///

View File

@ -28,6 +28,7 @@ use tokio::sync::{broadcast, mpsc};
use tracing::{debug, error}; use tracing::{debug, error};
#[derive(Debug, Deserialize, Clone)] #[derive(Debug, Deserialize, Clone)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct CustomModule { pub struct CustomModule {
/// Modules and widgets to add to the bar container. /// Modules and widgets to add to the bar container.
/// ///
@ -45,6 +46,7 @@ pub struct CustomModule {
} }
#[derive(Debug, Deserialize, Clone)] #[derive(Debug, Deserialize, Clone)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct WidgetConfig { pub struct WidgetConfig {
/// One of a custom module native Ironbar module. /// One of a custom module native Ironbar module.
#[serde(flatten)] #[serde(flatten)]
@ -57,6 +59,7 @@ pub struct WidgetConfig {
#[derive(Debug, Deserialize, Clone)] #[derive(Debug, Deserialize, Clone)]
#[serde(untagged)] #[serde(untagged)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub enum WidgetOrModule { pub enum WidgetOrModule {
/// A custom-module specific basic widget /// A custom-module specific basic widget
Widget(Widget), Widget(Widget),
@ -67,6 +70,7 @@ pub enum WidgetOrModule {
#[derive(Debug, Deserialize, Clone)] #[derive(Debug, Deserialize, Clone)]
#[serde(tag = "type", rename_all = "snake_case")] #[serde(tag = "type", rename_all = "snake_case")]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub enum Widget { pub enum Widget {
/// A container to place nested widgets inside. /// A container to place nested widgets inside.
Box(BoxWidget), Box(BoxWidget),

View File

@ -13,6 +13,7 @@ use crate::{build, glib_recv_mpsc, spawn, try_send};
use super::{CustomWidget, CustomWidgetContext}; use super::{CustomWidget, CustomWidgetContext};
#[derive(Debug, Deserialize, Clone)] #[derive(Debug, Deserialize, Clone)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct ProgressWidget { pub struct ProgressWidget {
/// Widget name. /// Widget name.
/// ///

View File

@ -16,6 +16,7 @@ use crate::{build, glib_recv_mpsc, spawn, try_send};
use super::{CustomWidget, CustomWidgetContext, ExecEvent}; use super::{CustomWidget, CustomWidgetContext, ExecEvent};
#[derive(Debug, Deserialize, Clone)] #[derive(Debug, Deserialize, Clone)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct SliderWidget { pub struct SliderWidget {
/// Widget name. /// Widget name.
/// ///

View File

@ -12,6 +12,7 @@ use tokio::sync::mpsc;
use tracing::debug; use tracing::debug;
#[derive(Debug, Deserialize, Clone)] #[derive(Debug, Deserialize, Clone)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct FocusedModule { pub struct FocusedModule {
/// Whether to show icon on the bar. /// Whether to show icon on the bar.
/// ///

View File

@ -9,6 +9,7 @@ use serde::Deserialize;
use tokio::sync::mpsc; use tokio::sync::mpsc;
#[derive(Debug, Deserialize, Clone)] #[derive(Debug, Deserialize, Clone)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct LabelModule { pub struct LabelModule {
/// The text to show on the label. /// The text to show on the label.
/// This is a [Dynamic String](dynamic-values#dynamic-string). /// This is a [Dynamic String](dynamic-values#dynamic-string).

View File

@ -19,6 +19,7 @@ use tokio::sync::{broadcast, mpsc};
use tracing::{debug, error, trace}; use tracing::{debug, error, trace};
#[derive(Debug, Deserialize, Clone)] #[derive(Debug, Deserialize, Clone)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct LauncherModule { pub struct LauncherModule {
/// List of app IDs (or classes) to always show regardless of open state, /// List of app IDs (or classes) to always show regardless of open state,
/// in the order specified. /// in the order specified.

View File

@ -4,6 +4,7 @@ use serde::Deserialize;
use std::path::PathBuf; use std::path::PathBuf;
#[derive(Debug, Deserialize, Clone)] #[derive(Debug, Deserialize, Clone)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct Icons { pub struct Icons {
/// Icon to display when playing. /// Icon to display when playing.
/// ///
@ -71,6 +72,7 @@ impl Default for Icons {
#[derive(Debug, Deserialize, Clone, Copy)] #[derive(Debug, Deserialize, Clone, Copy)]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub enum PlayerType { pub enum PlayerType {
Mpd, Mpd,
Mpris, Mpris,
@ -83,6 +85,7 @@ impl Default for PlayerType {
} }
#[derive(Debug, Deserialize, Clone)] #[derive(Debug, Deserialize, Clone)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct MusicModule { pub struct MusicModule {
/// Type of player to connect to /// Type of player to connect to
#[serde(default)] #[serde(default)]

View File

@ -10,6 +10,7 @@ use tokio::sync::mpsc::Receiver;
use tracing::error; use tracing::error;
#[derive(Debug, Deserialize, Clone)] #[derive(Debug, Deserialize, Clone)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct NotificationsModule { pub struct NotificationsModule {
/// Whether to show the current notification count. /// Whether to show the current notification count.
/// ///
@ -29,6 +30,7 @@ pub struct NotificationsModule {
} }
#[derive(Debug, Deserialize, Clone)] #[derive(Debug, Deserialize, Clone)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
struct Icons { struct Icons {
/// Icon to show when the panel is closed, with no notifications. /// Icon to show when the panel is closed, with no notifications.
/// ///

View File

@ -10,6 +10,7 @@ use tokio::sync::mpsc;
use tracing::error; use tracing::error;
#[derive(Debug, Deserialize, Clone)] #[derive(Debug, Deserialize, Clone)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct ScriptModule { pub struct ScriptModule {
/// Path to script to execute. /// Path to script to execute.
/// ///

View File

@ -14,6 +14,7 @@ use tokio::sync::mpsc;
use tokio::time::sleep; use tokio::time::sleep;
#[derive(Debug, Deserialize, Clone)] #[derive(Debug, Deserialize, Clone)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct SysInfoModule { pub struct SysInfoModule {
/// List of strings including formatting tokens. /// List of strings including formatting tokens.
/// For available tokens, see [below](#formatting-tokens). /// For available tokens, see [below](#formatting-tokens).
@ -51,6 +52,7 @@ pub struct SysInfoModule {
} }
#[derive(Debug, Deserialize, Copy, Clone)] #[derive(Debug, Deserialize, Copy, Clone)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct Intervals { pub struct Intervals {
/// The number of seconds between refreshing memory data. /// The number of seconds between refreshing memory data.
/// ///
@ -91,6 +93,7 @@ pub struct Intervals {
#[derive(Debug, Deserialize, Copy, Clone)] #[derive(Debug, Deserialize, Copy, Clone)]
#[serde(untagged)] #[serde(untagged)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub enum Interval { pub enum Interval {
All(u64), All(u64),
Individual(Intervals), Individual(Intervals),

View File

@ -19,6 +19,7 @@ use tokio::sync::mpsc;
use tracing::{debug, error, warn}; use tracing::{debug, error, warn};
#[derive(Debug, Deserialize, Clone)] #[derive(Debug, Deserialize, Clone)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct TrayModule { pub struct TrayModule {
/// Requests that icons from the theme be used over the item-provided item. /// Requests that icons from the theme be used over the item-provided item.
/// Most items only provide one or the other so this will have no effect in most circumstances. /// Most items only provide one or the other so this will have no effect in most circumstances.
@ -38,7 +39,8 @@ pub struct TrayModule {
/// **Valid options**: `top_to_bottom`, `bottom_to_top`, `left_to_right`, `right_to_left` /// **Valid options**: `top_to_bottom`, `bottom_to_top`, `left_to_right`, `right_to_left`
/// <br> /// <br>
/// **Default**: `left_to_right` if bar is horizontal, `top_to_bottom` if bar is vertical /// **Default**: `left_to_right` if bar is horizontal, `top_to_bottom` if bar is vertical
#[serde(default, deserialize_with = "deserialize_orientation")] #[serde(default, deserialize_with = "deserialize_pack_direction")]
#[cfg_attr(feature = "schema", schemars(schema_with = "schema_pack_direction"))]
direction: Option<PackDirection>, direction: Option<PackDirection>,
/// See [common options](module-level-options#common-options). /// See [common options](module-level-options#common-options).
@ -50,7 +52,7 @@ const fn default_icon_size() -> u32 {
16 16
} }
fn deserialize_orientation<'de, D>(deserializer: D) -> Result<Option<PackDirection>, D::Error> fn deserialize_pack_direction<'de, D>(deserializer: D) -> Result<Option<PackDirection>, D::Error>
where where
D: serde::Deserializer<'de>, D: serde::Deserializer<'de>,
{ {
@ -61,11 +63,24 @@ where
"right_to_left" => Ok(PackDirection::Rtl), "right_to_left" => Ok(PackDirection::Rtl),
"top_to_bottom" => Ok(PackDirection::Ttb), "top_to_bottom" => Ok(PackDirection::Ttb),
"bottom_to_top" => Ok(PackDirection::Btt), "bottom_to_top" => Ok(PackDirection::Btt),
_ => Err(serde::de::Error::custom("invalid value for orientation")), _ => Err(serde::de::Error::custom("invalid value for direction")),
}) })
.transpose() .transpose()
} }
#[cfg(feature = "schema")]
fn schema_pack_direction(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
use schemars::JsonSchema;
let mut schema: schemars::schema::SchemaObject = <String>::json_schema(gen).into();
schema.enum_values = Some(vec![
"top_to_bottom".into(),
"bottom_to_top".into(),
"left_to_right".into(),
"right_to_left".into(),
]);
schema.into()
}
impl Module<MenuBar> for TrayModule { impl Module<MenuBar> for TrayModule {
type SendMessage = Event; type SendMessage = Event;
type ReceiveMessage = ActivateRequest; type ReceiveMessage = ActivateRequest;

View File

@ -22,6 +22,7 @@ const HOUR: i64 = 60 * 60;
const MINUTE: i64 = 60; const MINUTE: i64 = 60;
#[derive(Debug, Deserialize, Clone)] #[derive(Debug, Deserialize, Clone)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct UpowerModule { pub struct UpowerModule {
/// The format string to use for the widget button label. /// The format string to use for the widget button label.
/// For available tokens, see [below](#formatting-tokens). /// For available tokens, see [below](#formatting-tokens).

View File

@ -14,6 +14,7 @@ use std::collections::HashMap;
use tokio::sync::mpsc; use tokio::sync::mpsc;
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct VolumeModule { pub struct VolumeModule {
/// The format string to use for the widget button label. /// The format string to use for the widget button label.
/// For available tokens, see [below](#formatting-tokens). /// For available tokens, see [below](#formatting-tokens).
@ -45,6 +46,7 @@ fn default_format() -> String {
} }
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct Icons { pub struct Icons {
/// Icon to show for high volume levels. /// Icon to show for high volume levels.
/// ///

View File

@ -15,6 +15,7 @@ use tracing::{debug, trace, warn};
#[derive(Debug, Deserialize, Clone, Copy, Eq, PartialEq)] #[derive(Debug, Deserialize, Clone, Copy, Eq, PartialEq)]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub enum SortOrder { pub enum SortOrder {
/// Shows workspaces in the order they're added /// Shows workspaces in the order they're added
Added, Added,
@ -31,6 +32,7 @@ impl Default for SortOrder {
#[derive(Debug, Deserialize, Clone)] #[derive(Debug, Deserialize, Clone)]
#[serde(untagged)] #[serde(untagged)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub enum Favorites { pub enum Favorites {
ByMonitor(HashMap<String, Vec<String>>), ByMonitor(HashMap<String, Vec<String>>),
Global(Vec<String>), Global(Vec<String>),
@ -43,6 +45,7 @@ impl Default for Favorites {
} }
#[derive(Debug, Deserialize, Clone)] #[derive(Debug, Deserialize, Clone)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct WorkspacesModule { pub struct WorkspacesModule {
/// Map of actual workspace names to custom names. /// Map of actual workspace names to custom names.
/// ///

View File

@ -14,6 +14,7 @@ use tracing::{debug, error, trace, warn};
#[derive(Debug, Deserialize, Clone)] #[derive(Debug, Deserialize, Clone)]
#[serde(untagged)] #[serde(untagged)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub enum ScriptInput { pub enum ScriptInput {
String(String), String(String),
Struct(Script), Struct(Script),
@ -21,6 +22,7 @@ pub enum ScriptInput {
#[derive(Debug, Deserialize, Clone, Copy, Eq, PartialEq)] #[derive(Debug, Deserialize, Clone, Copy, Eq, PartialEq)]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub enum ScriptMode { pub enum ScriptMode {
Poll, Poll,
Watch, Watch,
@ -75,6 +77,7 @@ impl ScriptMode {
} }
#[derive(Debug, Deserialize, Clone)] #[derive(Debug, Deserialize, Clone)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct Script { pub struct Script {
#[serde(default = "ScriptMode::default")] #[serde(default = "ScriptMode::default")]
pub(crate) mode: ScriptMode, pub(crate) mode: ScriptMode,