1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-01-24 13:32:50 -05:00

settings: add index extractor script for search

This commit is contained in:
bbedward
2025-12-26 22:21:20 -05:00
parent 6611dfbe05
commit 9fc0d5efff
13 changed files with 4361 additions and 580 deletions

View File

@@ -0,0 +1,370 @@
#!/usr/bin/env python3
import os
import re
import json
from pathlib import Path
ABBREVIATIONS = {
"on-screen displays": ["osd"],
"on-screen display": ["osd"],
"do not disturb": ["dnd"],
"keyboard shortcuts": ["keybinds", "hotkeys", "bindings", "keys"],
"notifications": ["notif", "notifs", "alerts"],
"notification": ["notif", "alert"],
"wallpaper": ["background", "bg", "image", "picture", "desktop"],
"transparency": ["opacity", "alpha", "translucent", "transparent"],
"visibility": ["visible", "hide", "show", "hidden", "autohide", "auto-hide"],
"temperature": ["temp", "celsius", "fahrenheit"],
"configuration": ["config", "configure", "setup"],
"applications": ["apps", "programs"],
"application": ["app", "program"],
"animation": ["motion", "transition", "animate", "animations"],
"typography": ["font", "fonts", "text", "typeface"],
"workspaces": ["workspace", "desktops", "virtual"],
"workspace": ["desktop", "virtual"],
"bluetooth": ["bt"],
"network": ["wifi", "wi-fi", "ethernet", "internet", "connection", "wireless"],
"display": ["monitor", "screen", "output"],
"displays": ["monitors", "screens", "outputs"],
"brightness": ["bright", "dim", "backlight"],
"volume": ["audio", "sound", "speaker", "loudness"],
"battery": ["power", "charge", "charging"],
"clock": ["time", "watch"],
"calendar": ["date", "day", "month", "year"],
"launcher": ["app drawer", "app menu", "start menu", "applications"],
"dock": ["taskbar", "panel"],
"bar": ["panel", "taskbar", "topbar", "statusbar"],
"theme": ["appearance", "look", "style", "colors", "colour"],
"color": ["colour", "hue", "tint"],
"colors": ["colours", "palette"],
"dark": ["night", "dark mode"],
"light": ["day", "light mode"],
"lock screen": ["lockscreen", "login", "security"],
"power": ["shutdown", "reboot", "restart", "suspend", "hibernate", "sleep"],
"idle": ["afk", "inactive", "timeout", "screensaver"],
"gamma": ["color temperature", "night light", "blue light", "redshift"],
"media player": ["mpris", "music", "audio", "playback"],
"clipboard": ["copy", "paste", "cliphist", "history"],
"updater": ["updates", "upgrade", "packages"],
"plugins": ["extensions", "addons", "widgets"],
"spacing": ["gap", "gaps", "margin", "margins", "padding"],
"corner": ["corners", "rounded", "radius", "round"],
"matugen": ["dynamic", "wallpaper colors", "material"],
"running apps": ["taskbar", "windows", "active", "open"],
"weather": ["forecast", "temperature", "climate"],
"sounds": ["audio", "effects", "sfx"],
"printers": ["print", "cups", "printing"],
"widgets": ["components", "modules"],
}
CATEGORY_KEYWORDS = {
"Personalization": ["customize", "custom", "personal", "appearance"],
"Time & Weather": ["clock", "forecast", "date"],
"Keyboard Shortcuts": ["keys", "bindings", "hotkey"],
"Dank Bar": ["panel", "topbar", "statusbar"],
"Workspaces": ["virtual desktops", "spaces"],
"Dock": ["taskbar", "launcher bar"],
"Network": ["connectivity", "online"],
"System": ["os", "linux"],
"Launcher": ["start", "menu", "drawer"],
"Theme & Colors": ["appearance", "look", "style", "scheme"],
"Lock Screen": ["security", "login", "password"],
"Plugins": ["extend", "addon"],
"About": ["info", "version", "credits", "help"],
"Typography & Motion": ["fonts", "animation", "text"],
"Sounds": ["audio", "sfx", "effects"],
"Media Player": ["music", "spotify", "mpris"],
"Notifications": ["alerts", "messages", "toast"],
"On-screen Displays": ["osd", "indicator", "popup"],
"Running Apps": ["windows", "tasks", "active"],
"System Updater": ["packages", "upgrade"],
"Power & Sleep": ["shutdown", "suspend", "energy"],
"Displays": ["monitor", "screen", "resolution"],
"Desktop Widgets": ["conky", "desktop clock"],
}
TAB_INDEX_MAP = {
"WallpaperTab.qml": 0,
"TimeWeatherTab.qml": 1,
"KeybindsTab.qml": 2,
"DankBarTab.qml": 3,
"WorkspacesTab.qml": 4,
"DockTab.qml": 5,
"NetworkTab.qml": 7,
"PrinterTab.qml": 8,
"LauncherTab.qml": 9,
"ThemeColorsTab.qml": 10,
"LockScreenTab.qml": 11,
"PluginsTab.qml": 12,
"AboutTab.qml": 13,
"TypographyMotionTab.qml": 14,
"SoundsTab.qml": 15,
"MediaPlayerTab.qml": 16,
"NotificationsTab.qml": 17,
"OSDTab.qml": 18,
"RunningAppsTab.qml": 19,
"SystemUpdaterTab.qml": 20,
"PowerSleepTab.qml": 21,
"WidgetsTab.qml": 22,
"ClipboardTab.qml": 23,
"DisplayConfigTab.qml": 24,
"GammaControlTab.qml": 25,
"DisplayWidgetsTab.qml": 26,
"DesktopWidgetsTab.qml": 27,
}
TAB_CATEGORY_MAP = {
0: "Personalization",
1: "Time & Weather",
2: "Keyboard Shortcuts",
3: "Dank Bar",
4: "Workspaces",
5: "Dock",
7: "Network",
8: "System",
9: "Launcher",
10: "Theme & Colors",
11: "Lock Screen",
12: "Plugins",
13: "About",
14: "Typography & Motion",
15: "Sounds",
16: "Media Player",
17: "Notifications",
18: "On-screen Displays",
19: "Running Apps",
20: "System Updater",
21: "Power & Sleep",
22: "Dank Bar",
23: "System",
24: "Displays",
25: "Displays",
26: "Displays",
27: "Desktop Widgets",
}
SEARCHABLE_COMPONENTS = [
"SettingsCard",
"SettingsToggleRow",
"SettingsSliderCard",
"SettingsDropdownRow",
"SettingsButtonGroupRow",
"SettingsSliderRow",
"SettingsToggleCard",
]
def enrich_keywords(label, description, category, existing_tags):
keywords = set(existing_tags)
label_lower = label.lower()
label_words = re.split(r'[\s\-_&/]+', label_lower)
keywords.update(w for w in label_words if len(w) > 2)
for term, aliases in ABBREVIATIONS.items():
if term in label_lower:
keywords.update(aliases)
if description:
desc_lower = description.lower()
desc_words = re.split(r'[\s\-_&/,.]+', desc_lower)
keywords.update(w for w in desc_words if len(w) > 3 and w.isalpha())
for term, aliases in ABBREVIATIONS.items():
if term in desc_lower:
keywords.update(aliases)
if category in CATEGORY_KEYWORDS:
keywords.update(CATEGORY_KEYWORDS[category])
cat_lower = category.lower()
cat_words = re.split(r'[\s\-_&/]+', cat_lower)
keywords.update(w for w in cat_words if len(w) > 2)
stopwords = {'the', 'and', 'for', 'with', 'from', 'this', 'that', 'are', 'was',
'will', 'can', 'has', 'have', 'been', 'when', 'your', 'use', 'used',
'using', 'instead', 'like', 'such', 'also', 'only', 'which', 'each',
'other', 'some', 'into', 'than', 'then', 'them', 'these', 'those'}
keywords = {k for k in keywords if k not in stopwords and len(k) > 1}
return sorted(keywords)
def extract_i18n_string(value):
match = re.search(r'I18n\.tr\(["\']([^"\']+)["\']', value)
if match:
return match.group(1)
match = re.search(r'^["\']([^"\']+)["\']$', value.strip())
if match:
return match.group(1)
return None
def extract_tags(value):
match = re.search(r'\[([^\]]+)\]', value)
if not match:
return []
content = match.group(1)
tags = re.findall(r'["\']([^"\']+)["\']', content)
return tags
def parse_component_block(content, start_pos, component_name):
brace_count = 0
started = False
block_start = start_pos
for i in range(start_pos, len(content)):
if content[i] == '{':
if not started:
block_start = i
started = True
brace_count += 1
elif content[i] == '}':
brace_count -= 1
if started and brace_count == 0:
return content[block_start:i+1]
return ""
def extract_property(block, prop_name):
pattern = rf'{prop_name}\s*:\s*([^\n]+)'
match = re.search(pattern, block)
if match:
return match.group(1).strip()
return None
def find_settings_components(content, filename):
results = []
tab_index = TAB_INDEX_MAP.get(filename, -1)
if tab_index == -1:
return results
for component in SEARCHABLE_COMPONENTS:
pattern = rf'\b{component}\s*\{{'
for match in re.finditer(pattern, content):
block = parse_component_block(content, match.start(), component)
if not block:
continue
setting_key = extract_property(block, "settingKey")
if setting_key:
setting_key = setting_key.strip('"\'')
if not setting_key:
continue
title_raw = extract_property(block, "title")
text_raw = extract_property(block, "text")
label = None
if title_raw:
label = extract_i18n_string(title_raw)
if not label and text_raw:
label = extract_i18n_string(text_raw)
if not label:
continue
icon_raw = extract_property(block, "iconName")
icon = None
if icon_raw:
icon = icon_raw.strip('"\'')
if icon.startswith("{") or "?" in icon:
icon = None
tags_raw = extract_property(block, "tags")
tags = []
if tags_raw:
tags = extract_tags(tags_raw)
desc_raw = extract_property(block, "description")
description = None
if desc_raw:
description = extract_i18n_string(desc_raw)
visible_raw = extract_property(block, "visible")
condition_key = None
if visible_raw:
if "CompositorService.isNiri" in visible_raw:
condition_key = "isNiri"
elif "CompositorService.isHyprland" in visible_raw:
condition_key = "isHyprland"
elif "KeybindsService.available" in visible_raw:
condition_key = "keybindsAvailable"
elif "AudioService.soundsAvailable" in visible_raw:
condition_key = "soundsAvailable"
elif "CupsService.cupsAvailable" in visible_raw:
condition_key = "cupsAvailable"
elif "NetworkService.usingLegacy" in visible_raw:
condition_key = "networkNotLegacy"
elif "DMSService.isConnected" in visible_raw:
condition_key = "dmsConnected"
elif "Theme.matugenAvailable" in visible_raw:
condition_key = "matugenAvailable"
elif "CompositorService.isDwl" in visible_raw:
condition_key = "isDwl"
category = TAB_CATEGORY_MAP.get(tab_index, "Settings")
enriched_keywords = enrich_keywords(label, description, category, tags)
entry = {
"section": setting_key,
"label": label,
"tabIndex": tab_index,
"category": category,
"keywords": enriched_keywords,
}
if icon:
entry["icon"] = icon
if description:
entry["description"] = description
if condition_key:
entry["conditionKey"] = condition_key
results.append(entry)
return results
def extract_settings_index(root_dir):
settings_dir = Path(root_dir) / "Modules" / "Settings"
all_entries = []
seen_keys = set()
for qml_file in settings_dir.glob("*.qml"):
if not qml_file.name.endswith("Tab.qml"):
continue
with open(qml_file, 'r', encoding='utf-8') as f:
content = f.read()
entries = find_settings_components(content, qml_file.name)
for entry in entries:
key = entry["section"]
if key not in seen_keys:
seen_keys.add(key)
all_entries.append(entry)
return all_entries
def main():
script_dir = Path(__file__).parent
root_dir = script_dir.parent
print("Extracting settings search index...")
entries = extract_settings_index(root_dir)
entries.sort(key=lambda x: (x["tabIndex"], x["label"]))
output_path = script_dir / "settings_search_index.json"
with open(output_path, 'w', encoding='utf-8') as f:
json.dump(entries, f, indent=2, ensure_ascii=False)
print(f"Found {len(entries)} searchable settings")
print(f"Output: {output_path}")
conditions = set()
for entry in entries:
if "conditionKey" in entry:
conditions.add(entry["conditionKey"])
if conditions:
print(f"Condition keys found: {', '.join(sorted(conditions))}")
if __name__ == '__main__':
main()

File diff suppressed because it is too large Load Diff