docs(schema): ensure every enum variant has a renderable title

This commit is contained in:
LGUG2Z
2025-12-27 20:28:08 -08:00
parent 3a81f7babb
commit f77a303b30
14 changed files with 163 additions and 30 deletions

View File

@@ -5,8 +5,9 @@ Check schema.json and schema.bar.json for missing docstrings and map them to Rus
This script analyzes the generated JSON schemas and identifies:
1. Type definitions ($defs) missing top-level descriptions
2. Enum variants missing descriptions (in oneOf/anyOf)
3. Struct properties missing descriptions
4. Top-level schema properties missing descriptions
3. Enum variants missing titles (object variants in oneOf/anyOf)
4. Struct properties missing descriptions
5. Top-level schema properties missing descriptions
For each missing docstring, it attempts to find the corresponding Rust source
file and line number where the docstring should be added.
@@ -23,7 +24,7 @@ from typing import Optional
@dataclass
class MissingDoc:
type_name: str
kind: str # "type", "variant", "property"
kind: str # "type", "variant", "property", "variant_title"
item_name: Optional[str] # variant or property name
rust_file: Optional[str] = None
rust_line: Optional[int] = None
@@ -39,6 +40,8 @@ class MissingDoc:
return f"[TYPE] {self.type_name}{location}"
elif self.kind == "variant":
return f"[VARIANT] {self.type_name}::{self.item_name}{location}"
elif self.kind == "variant_title":
return f"[VARIANT_TITLE] {self.type_name}::{self.item_name}{location}"
else:
return f"[PROPERTY] {self.type_name}.{self.item_name}{location}"
@@ -62,7 +65,7 @@ def find_rust_definition(
rf"pub\s+enum\s+{type_name}\b",
rf"pub\s+struct\s+{type_name}\b",
]
elif kind == "variant":
elif kind in ("variant", "variant_title"):
patterns = [
rf"^\s*{re.escape(item_name)}\s*[,\(\{{]",
rf"^\s*{re.escape(item_name)}\s*$",
@@ -83,7 +86,7 @@ def find_rust_definition(
if re.search(pattern, line):
return str(rust_file), i + 1
elif kind in ("variant", "property"):
elif kind in ("variant", "variant_title", "property"):
parent_pattern = rf"pub\s+(?:enum|struct)\s+{type_name}\b"
in_type = False
brace_count = 0
@@ -112,6 +115,39 @@ def find_rust_definition(
return None, None
def _get_variant_identifier(variant: dict) -> str:
"""Extract a meaningful identifier for a variant.
Tries to find the best identifier by checking:
1. A top-level const value (e.g., {"const": "Linear"})
2. A property with a const value (e.g., {"kind": {"const": "Bar"}})
3. The first required property name
4. The type field
5. Falls back to "unknown"
"""
# Check for top-level const value (simple enum variant)
if "const" in variant:
return str(variant["const"])
properties = variant.get("properties", {})
# Check for a property with a const value (common pattern for tagged enums)
for prop_name, prop_def in properties.items():
if isinstance(prop_def, dict) and "const" in prop_def:
return str(prop_def["const"])
# Fall back to first required property name
required = variant.get("required", [])
if required:
return str(required[0])
# Fall back to type
if "type" in variant:
return str(variant["type"])
return "unknown"
def check_type_description(type_name: str, type_def: dict) -> list[MissingDoc]:
"""Check if a type definition has proper documentation."""
missing = []
@@ -150,6 +186,19 @@ def check_type_description(type_name: str, type_def: dict) -> list[MissingDoc]:
MissingDoc(type_name, "variant", str(prop_name), None, None)
)
# Case 4: Object variant missing title (needed for schema UI display)
# Object variants should have a title or const for proper display in editors
if (
"properties" in variant
and "title" not in variant
and "const" not in variant
):
# Try to find a good identifier for the variant (for display only)
variant_id = _get_variant_identifier(variant)
missing.append(
MissingDoc(type_name, "variant_title", str(variant_id), None, None)
)
# Check anyOf variants - check each variant individually
elif "anyOf" in type_def:
# anyOf types should have a top-level description
@@ -180,6 +229,17 @@ def check_type_description(type_name: str, type_def: dict) -> list[MissingDoc]:
MissingDoc(type_name, "variant", str(variant_id), None, None)
)
# Check for missing title on object variants in anyOf
if (
"properties" in variant
and "title" not in variant
and "const" not in variant
):
variant_id = _get_variant_identifier(variant)
missing.append(
MissingDoc(type_name, "variant_title", str(variant_id), None, None)
)
# Check simple string enums (no oneOf means no variant descriptions possible in schema)
elif "enum" in type_def:
if not has_top_description:
@@ -285,11 +345,13 @@ def print_results(all_missing: list[MissingDoc], display_name: str) -> None:
type_count = sum(1 for d in all_missing if d.kind == "type")
variant_count = sum(1 for d in all_missing if d.kind == "variant")
variant_title_count = sum(1 for d in all_missing if d.kind == "variant_title")
prop_count = sum(1 for d in all_missing if d.kind == "property")
print(f"\nTotal: {len(all_missing)} missing docstrings")
print(f"\nTotal: {len(all_missing)} missing docstrings/titles")
print(f" - {type_count} types")
print(f" - {variant_count} variants")
print(f" - {variant_title_count} variant titles")
print(f" - {prop_count} properties")
# Print by file
@@ -311,8 +373,7 @@ def print_results(all_missing: list[MissingDoc], display_name: str) -> None:
def main():
script_dir = Path(__file__).parent
project_root = script_dir.parent
project_root = Path.cwd()
# Define schemas to check with their respective search paths
schemas = [

View File

@@ -78,8 +78,8 @@ deadlock $RUST_LOG="trace":
docgen starlight:
rm {{ starlight }}/src/data/cli/windows/*.md
cargo run --package komorebic -- docgen --output {{ starlight }}/src/data/cli/windows
schemars-docgen ./schema.json --output {{ starlight }}/src/content/docs/reference/komorebi-windows.mdx --format mdx --title "komorebi.json (Windows)" --description "komorebi for Windows configuration schema reference"
schemars-docgen ./schema.bar.json --output {{ starlight }}/src/content/docs/reference/bar-windows.mdx --format mdx --title "komorebi.bar.json (Windows)" --description "komorebi-bar for Windows configuration schema reference"
schemars-docgen ./schema.json --output {{ starlight }}/src/content/docs/reference/komorebi-windows.mdx --title "komorebi.json (Windows)" --description "komorebi for Windows configuration schema reference"
schemars-docgen ./schema.bar.json --output {{ starlight }}/src/content/docs/reference/bar-windows.mdx --title "komorebi.bar.json (Windows)" --description "komorebi-bar for Windows configuration schema reference"
jsonschema:
cargo run --package komorebic -- static-config-schema > schema.json

View File

@@ -571,6 +571,7 @@ impl From<Position> for Pos2 {
/// Komorebi bar theme
pub enum KomobarTheme {
/// Theme from catppuccin-egui
#[cfg_attr(feature = "schemars", schemars(title = "Catppuccin"))]
Catppuccin {
/// Name of the Catppuccin theme (theme previews: https://github.com/catppuccin/catppuccin)
name: komorebi_themes::Catppuccin,
@@ -582,6 +583,7 @@ pub enum KomobarTheme {
auto_select_text: Option<komorebi_themes::CatppuccinValue>,
},
/// Theme from base16-egui-themes
#[cfg_attr(feature = "schemars", schemars(title = "Base16"))]
Base16 {
/// Name of the Base16 theme (theme previews: https://tinted-theming.github.io/tinted-gallery/)
name: komorebi_themes::Base16,
@@ -593,6 +595,7 @@ pub enum KomobarTheme {
auto_select_text: Option<komorebi_themes::Base16Value>,
},
/// Custom Base16 theme
#[cfg_attr(feature = "schemars", schemars(title = "Custom"))]
Custom {
/// Colours of the custom Base16 theme palette
colours: Box<komorebi_themes::Base16ColourPalette>,
@@ -669,9 +672,10 @@ pub enum DisplayFormat {
}
macro_rules! extend_enum {
($existing_enum:ident, $new_enum:ident, { $($(#[$meta:meta])* $variant:ident),* $(,)? }) => {
($(#[$type_meta:meta])* $existing_enum:ident, $new_enum:ident, { $($(#[$meta:meta])* $variant:ident),* $(,)? }) => {
#[derive(Copy, Clone, Debug, serde::Serialize, serde::Deserialize, PartialEq)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
$(#[$type_meta])*
pub enum $new_enum {
// Add new variants
$(
@@ -692,7 +696,9 @@ macro_rules! extend_enum {
};
}
extend_enum!(DisplayFormat, WorkspacesDisplayFormat, {
extend_enum!(
/// Workspaces display format
DisplayFormat, WorkspacesDisplayFormat, {
/// Show all icons only
AllIcons,
/// Show both all icons and text

View File

@@ -30,12 +30,16 @@ static SHOW_KOMOREBI_LAYOUT_OPTIONS: AtomicUsize = AtomicUsize::new(0);
/// Grouping
pub enum Grouping {
/// No grouping is applied
#[cfg_attr(feature = "schemars", schemars(title = "None"))]
None,
/// Widgets are grouped as a whole
#[cfg_attr(feature = "schemars", schemars(title = "Bar"))]
Bar(GroupingConfig),
/// Widgets are grouped by alignment
#[cfg_attr(feature = "schemars", schemars(title = "Alignment"))]
Alignment(GroupingConfig),
/// Widgets are grouped individually
#[cfg_attr(feature = "schemars", schemars(title = "Widget"))]
Widget(GroupingConfig),
}

View File

@@ -116,8 +116,10 @@ pub enum DateFormat {
/// Day Date Month Year format (8 September 2024)
DayDateMonthYear,
/// Custom format (https://docs.rs/chrono/latest/chrono/format/strftime/index.html)
#[cfg_attr(feature = "schemars", schemars(title = "Custom"))]
Custom(String),
/// Custom format with modifiers
#[cfg_attr(feature = "schemars", schemars(title = "CustomModifiers"))]
CustomModifiers(CustomModifiers),
}

View File

@@ -29,6 +29,7 @@ use std::fmt::Formatter;
/// Komorebi layout kind
pub enum KomorebiLayout {
/// Predefined layout
#[cfg_attr(feature = "schemars", schemars(title = "Default"))]
Default(komorebi_client::DefaultLayout),
/// Monocle mode
Monocle,

View File

@@ -135,6 +135,7 @@ pub enum TimeFormat {
/// Twenty-four-hour format displayed as a binary clock with rectangles (with seconds) (https://en.wikipedia.org/wiki/Binary_clock)
BinaryRectangle,
/// Custom format (https://docs.rs/chrono/latest/chrono/format/strftime/index.html)
#[cfg_attr(feature = "schemars", schemars(title = "Custom"))]
Custom(String),
}

View File

@@ -37,28 +37,40 @@ pub trait BarWidget {
/// Widget configuration
pub enum WidgetConfig {
/// Applications widget configuration
#[cfg_attr(feature = "schemars", schemars(title = "Applications"))]
Applications(ApplicationsConfig),
/// Battery widget configuration
#[cfg_attr(feature = "schemars", schemars(title = "Battery"))]
Battery(BatteryConfig),
/// CPU widget configuration
#[cfg_attr(feature = "schemars", schemars(title = "Cpu"))]
Cpu(CpuConfig),
/// Date widget configuration
#[cfg_attr(feature = "schemars", schemars(title = "Date"))]
Date(DateConfig),
/// Keyboard widget configuration
#[cfg_attr(feature = "schemars", schemars(title = "Keyboard"))]
Keyboard(KeyboardConfig),
/// Komorebi widget configuration
#[cfg_attr(feature = "schemars", schemars(title = "Komorebi"))]
Komorebi(KomorebiConfig),
/// Media widget configuration
#[cfg_attr(feature = "schemars", schemars(title = "Media"))]
Media(MediaConfig),
/// Memory widget configuration
#[cfg_attr(feature = "schemars", schemars(title = "Memory"))]
Memory(MemoryConfig),
/// Network widget configuration
#[cfg_attr(feature = "schemars", schemars(title = "Network"))]
Network(NetworkConfig),
/// Storage widget configuration
#[cfg_attr(feature = "schemars", schemars(title = "Storage"))]
Storage(StorageConfig),
/// Time widget configuration
#[cfg_attr(feature = "schemars", schemars(title = "Time"))]
Time(TimeConfig),
/// Update widget configuration
#[cfg_attr(feature = "schemars", schemars(title = "Update"))]
Update(UpdateConfig),
}

View File

@@ -308,13 +308,13 @@ impl Base16Value {
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, Display, PartialEq)]
/// Catppuccin palette
pub enum Catppuccin {
/// Frappe
/// Frappe (https://catppuccin.com/palette#flavor-frappe)
Frappe,
/// Latte
/// Latte (https://catppuccin.com/palette#flavor-latte)
Latte,
/// Macchiato
/// Macchiato (https://catppuccin.com/palette#flavor-macchiato)
Macchiato,
/// Mocha
/// Mocha (https://catppuccin.com/palette#flavor-mocha)
Mocha,
}

View File

@@ -72,6 +72,7 @@ pub enum AnimationStyle {
EaseOutBounce,
/// Ease in out bounce
EaseInOutBounce,
#[cfg_attr(feature = "schemars", schemars(title = "CubicBezier"))]
#[value(skip)]
/// Custom Cubic Bézier function
CubicBezier(f64, f64, f64, f64),

View File

@@ -663,12 +663,15 @@ pub struct StaticConfig {
/// Animations configuration options
pub struct AnimationsConfig {
/// Enable or disable animations
#[cfg_attr(feature = "schemars", schemars(extend("default" = PerAnimationPrefixConfig::Global(false))))]
pub enabled: PerAnimationPrefixConfig<bool>,
/// Set the animation duration in ms
#[serde(skip_serializing_if = "Option::is_none")]
#[cfg_attr(feature = "schemars", schemars(extend("default" = PerAnimationPrefixConfig::Global(250))))]
pub duration: Option<PerAnimationPrefixConfig<u64>>,
/// Set the animation style
#[serde(skip_serializing_if = "Option::is_none")]
#[cfg_attr(feature = "schemars", schemars(extend("default" = PerAnimationPrefixConfig::Global(AnimationStyle::Linear))))]
pub style: Option<PerAnimationPrefixConfig<AnimationStyle>>,
/// Set the animation FPS
#[serde(skip_serializing_if = "Option::is_none")]
@@ -682,6 +685,7 @@ pub struct AnimationsConfig {
/// Komorebi theme
pub enum KomorebiTheme {
/// A theme from catppuccin-egui
#[cfg_attr(feature = "schemars", schemars(title = "Catppuccin"))]
Catppuccin {
/// Name of the Catppuccin theme (theme previews: https://github.com/catppuccin/catppuccin)
name: komorebi_themes::Catppuccin,
@@ -727,6 +731,7 @@ pub enum KomorebiTheme {
bar_accent: Option<komorebi_themes::CatppuccinValue>,
},
/// A theme from base16-egui-themes
#[cfg_attr(feature = "schemars", schemars(title = "Base16"))]
Base16 {
/// Name of the Base16 theme (theme previews: https://tinted-theming.github.io/tinted-gallery/)
name: komorebi_themes::Base16,
@@ -772,6 +777,7 @@ pub enum KomorebiTheme {
bar_accent: Option<komorebi_themes::Base16Value>,
},
/// A custom Base16 theme
#[cfg_attr(feature = "schemars", schemars(title = "Custom"))]
Custom {
/// Colours of the custom Base16 theme palette
colours: Box<komorebi_themes::Base16ColourPalette>,

View File

@@ -305,8 +305,10 @@ impl RenderDispatcher for TransparencyRenderDispatcher {
/// Aspect ratio for temporarily floating windows
pub enum AspectRatio {
/// Predefined aspect ratio
#[cfg_attr(feature = "schemars", schemars(title = "Predefined"))]
Predefined(PredefinedAspectRatio),
/// Custom W:H aspect ratio
#[cfg_attr(feature = "schemars", schemars(title = "Custom"))]
Custom(i32, i32),
}

View File

@@ -345,6 +345,7 @@
"const": "EaseInOutBounce"
},
{
"title": "CubicBezier",
"description": "Custom Cubic Bézier function",
"type": "object",
"properties": {
@@ -2154,22 +2155,22 @@
"description": "Catppuccin palette",
"oneOf": [
{
"description": "Frappe",
"description": "Frappe (https://catppuccin.com/palette#flavor-frappe)",
"type": "string",
"const": "Frappe"
},
{
"description": "Latte",
"description": "Latte (https://catppuccin.com/palette#flavor-latte)",
"type": "string",
"const": "Latte"
},
{
"description": "Macchiato",
"description": "Macchiato (https://catppuccin.com/palette#flavor-macchiato)",
"type": "string",
"const": "Macchiato"
},
{
"description": "Mocha",
"description": "Mocha (https://catppuccin.com/palette#flavor-mocha)",
"type": "string",
"const": "Mocha"
}
@@ -2456,6 +2457,7 @@
"const": "DayDateMonthYear"
},
{
"title": "Custom",
"description": "Custom format (https://docs.rs/chrono/latest/chrono/format/strftime/index.html)",
"type": "object",
"properties": {
@@ -2469,6 +2471,7 @@
]
},
{
"title": "CustomModifiers",
"description": "Custom format with modifiers",
"type": "object",
"properties": {
@@ -2649,6 +2652,7 @@
"description": "Grouping",
"oneOf": [
{
"title": "None",
"description": "No grouping is applied",
"type": "object",
"properties": {
@@ -2662,6 +2666,7 @@
]
},
{
"title": "Bar",
"description": "Widgets are grouped as a whole",
"type": "object",
"properties": {
@@ -2676,6 +2681,7 @@
]
},
{
"title": "Alignment",
"description": "Widgets are grouped by alignment",
"type": "object",
"properties": {
@@ -2690,6 +2696,7 @@
]
},
{
"title": "Widget",
"description": "Widgets are grouped individually",
"type": "object",
"properties": {
@@ -2879,6 +2886,7 @@
"description": "Komorebi bar theme",
"oneOf": [
{
"title": "Catppuccin",
"description": "Theme from catppuccin-egui",
"type": "object",
"properties": {
@@ -2930,6 +2938,7 @@
]
},
{
"title": "Base16",
"description": "Theme from base16-egui-themes",
"type": "object",
"properties": {
@@ -2981,6 +2990,7 @@
]
},
{
"title": "Custom",
"description": "Custom Base16 theme",
"type": "object",
"properties": {
@@ -3162,6 +3172,7 @@
"description": "Komorebi layout kind",
"anyOf": [
{
"title": "Default",
"description": "Predefined layout",
"$ref": "#/$defs/DefaultLayout"
},
@@ -3281,6 +3292,7 @@
"description": "Komorebi theme",
"oneOf": [
{
"title": "Catppuccin",
"description": "A theme from catppuccin-egui",
"type": "object",
"properties": {
@@ -3419,6 +3431,7 @@
]
},
{
"title": "Base16",
"description": "A theme from base16-egui-themes",
"type": "object",
"properties": {
@@ -3557,6 +3570,7 @@
]
},
{
"title": "Custom",
"description": "A custom Base16 theme",
"type": "object",
"properties": {
@@ -8055,6 +8069,7 @@
"const": "BinaryRectangle"
},
{
"title": "Custom",
"description": "Custom format (https://docs.rs/chrono/latest/chrono/format/strftime/index.html)",
"type": "object",
"properties": {
@@ -8107,6 +8122,7 @@
"description": "Widget configuration",
"oneOf": [
{
"title": "Applications",
"description": "Applications widget configuration",
"type": "object",
"properties": {
@@ -8120,6 +8136,7 @@
]
},
{
"title": "Battery",
"description": "Battery widget configuration",
"type": "object",
"properties": {
@@ -8133,6 +8150,7 @@
]
},
{
"title": "Cpu",
"description": "CPU widget configuration",
"type": "object",
"properties": {
@@ -8146,6 +8164,7 @@
]
},
{
"title": "Date",
"description": "Date widget configuration",
"type": "object",
"properties": {
@@ -8159,6 +8178,7 @@
]
},
{
"title": "Keyboard",
"description": "Keyboard widget configuration",
"type": "object",
"properties": {
@@ -8172,6 +8192,7 @@
]
},
{
"title": "Komorebi",
"description": "Komorebi widget configuration",
"type": "object",
"properties": {
@@ -8185,6 +8206,7 @@
]
},
{
"title": "Media",
"description": "Media widget configuration",
"type": "object",
"properties": {
@@ -8198,6 +8220,7 @@
]
},
{
"title": "Memory",
"description": "Memory widget configuration",
"type": "object",
"properties": {
@@ -8211,6 +8234,7 @@
]
},
{
"title": "Network",
"description": "Network widget configuration",
"type": "object",
"properties": {
@@ -8224,6 +8248,7 @@
]
},
{
"title": "Storage",
"description": "Storage widget configuration",
"type": "object",
"properties": {
@@ -8237,6 +8262,7 @@
]
},
{
"title": "Time",
"description": "Time widget configuration",
"type": "object",
"properties": {
@@ -8250,6 +8276,7 @@
]
},
{
"title": "Update",
"description": "Update widget configuration",
"type": "object",
"properties": {
@@ -8300,6 +8327,7 @@
]
},
"WorkspacesDisplayFormat": {
"description": "Workspaces display format",
"anyOf": [
{
"description": "Show all icons only",

View File

@@ -702,6 +702,7 @@
"const": "EaseInOutBounce"
},
{
"title": "CubicBezier",
"description": "Custom Cubic Bézier function",
"type": "object",
"properties": {
@@ -749,11 +750,13 @@
{
"type": "null"
}
]
],
"default": 250
},
"enabled": {
"description": "Enable or disable animations",
"$ref": "#/$defs/PerAnimationPrefixConfig"
"$ref": "#/$defs/PerAnimationPrefixConfig",
"default": false
},
"fps": {
"description": "Set the animation FPS",
@@ -774,7 +777,8 @@
{
"type": "null"
}
]
],
"default": "Linear"
}
},
"required": [
@@ -826,10 +830,12 @@
"description": "Aspect ratio for temporarily floating windows",
"anyOf": [
{
"title": "Predefined",
"description": "Predefined aspect ratio",
"$ref": "#/$defs/PredefinedAspectRatio"
},
{
"title": "Custom",
"description": "Custom W:H aspect ratio",
"type": "array",
"maxItems": 2,
@@ -2501,22 +2507,22 @@
"description": "Catppuccin palette",
"oneOf": [
{
"description": "Frappe",
"description": "Frappe (https://catppuccin.com/palette#flavor-frappe)",
"type": "string",
"const": "Frappe"
},
{
"description": "Latte",
"description": "Latte (https://catppuccin.com/palette#flavor-latte)",
"type": "string",
"const": "Latte"
},
{
"description": "Macchiato",
"description": "Macchiato (https://catppuccin.com/palette#flavor-macchiato)",
"type": "string",
"const": "Macchiato"
},
{
"description": "Mocha",
"description": "Mocha (https://catppuccin.com/palette#flavor-mocha)",
"type": "string",
"const": "Mocha"
}
@@ -2839,6 +2845,7 @@
"description": "Komorebi theme",
"oneOf": [
{
"title": "Catppuccin",
"description": "A theme from catppuccin-egui",
"type": "object",
"properties": {
@@ -2977,6 +2984,7 @@
]
},
{
"title": "Base16",
"description": "A theme from base16-egui-themes",
"type": "object",
"properties": {
@@ -3115,6 +3123,7 @@
]
},
{
"title": "Custom",
"description": "A custom Base16 theme",
"type": "object",
"properties": {