migrate ui components to gpui-kit
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Phase A fix-up: route gpui_kit::component imports to their real module paths,
|
||||
rewrite font-weight helpers. Run from repo root. Idempotent."""
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
# item -> full module path under gpui_kit::component (None = keep at root)
|
||||
MODULE_PATHS = {
|
||||
"Avatar": "avatar",
|
||||
"Button": "button",
|
||||
"ButtonVariants": "button",
|
||||
"ButtonVariant": "button",
|
||||
"ButtonCustomVariant": "button",
|
||||
"ButtonGroup": "button",
|
||||
"DropdownButton": "button",
|
||||
"Toggle": "button",
|
||||
"Notification": "notification",
|
||||
"NotificationType": "notification",
|
||||
"Switch": "switch",
|
||||
"GroupBox": "group_box",
|
||||
"GroupBoxVariants": "group_box",
|
||||
"GroupBoxVariant": "group_box",
|
||||
"Tab": "tab",
|
||||
"TabBar": "tab",
|
||||
"Scrollbar": "scroll",
|
||||
"ScrollableElement": "scroll",
|
||||
"Input": "input",
|
||||
"InputState": "input",
|
||||
"Textarea": "textarea" if False else "input",
|
||||
"TextareaState": "input",
|
||||
"InputEvent": "input",
|
||||
"PopupMenu": "menu",
|
||||
"PopupMenuItem": "menu",
|
||||
"DropdownMenu": "menu",
|
||||
"ContextMenu": "menu",
|
||||
"Dialog": "dialog",
|
||||
"DialogButtonProps": "dialog",
|
||||
"AlertDialog": "dialog",
|
||||
"DockArea": "dock",
|
||||
"DockLayout": "dock",
|
||||
"DockPlacement": "dock",
|
||||
"Panel": "dock",
|
||||
"PanelEvent": "dock",
|
||||
"PanelHandle": "dock",
|
||||
"ClosePanel": "dock",
|
||||
"DockSkin": "dock",
|
||||
"Spinner": "spinner",
|
||||
"Tooltip": "tooltip",
|
||||
"Badge": "badge",
|
||||
"Marker": "marker",
|
||||
"Kbd": "kbd",
|
||||
"Sidebar": "sidebar",
|
||||
"SidebarMenu": "sidebar",
|
||||
"SidebarMenuItem": "sidebar",
|
||||
"SidebarGroup": "sidebar",
|
||||
"SidebarHeader": "sidebar",
|
||||
"SidebarFooter": "sidebar",
|
||||
"SidebarItem": "sidebar",
|
||||
}
|
||||
|
||||
FILES = list(Path("crates").rglob("*.rs"))
|
||||
|
||||
kit_re = re.compile(r"^use gpui_kit::component::\{([^}]*)\};")
|
||||
|
||||
for f in FILES:
|
||||
src = f.read_text()
|
||||
lines = src.split("\n")
|
||||
buckets = {}
|
||||
keep = []
|
||||
for line in lines:
|
||||
m = kit_re.match(line.strip())
|
||||
if m:
|
||||
for item in [i.strip() for i in m.group(1).split(",") if i.strip()]:
|
||||
base = item.split(" as ")[0].strip()
|
||||
mod = MODULE_PATHS.get(base)
|
||||
buckets.setdefault(mod, []).append(item)
|
||||
else:
|
||||
keep.append(line)
|
||||
if buckets:
|
||||
imports = []
|
||||
for mod, items in sorted(buckets.items(), key=lambda kv: kv[0] or ""):
|
||||
uniq = sorted(set(items))
|
||||
if mod is None:
|
||||
imports.append(f"use gpui_kit::component::{{{', '.join(uniq)}}};")
|
||||
else:
|
||||
imports.append(f"use gpui_kit::component::{mod}::{{{', '.join(uniq)}}};")
|
||||
# insert after the last existing `use` at top or just append imports where first import was
|
||||
keep[0:0] = imports
|
||||
src = "\n".join(keep)
|
||||
|
||||
# font weight helpers (gpui_base::StyledExt has none)
|
||||
src = src.replace(".font_semibold()", ".font_weight(gpui::FontWeight::SEMIBOLD)")
|
||||
src = src.replace(".font_medium()", ".font_weight(gpui::FontWeight::MEDIUM)")
|
||||
src = src.replace(".font_normal()", ".font_weight(gpui::FontWeight::NORMAL)")
|
||||
|
||||
if src != f.read_text():
|
||||
f.write_text(src)
|
||||
print("fixed", f)
|
||||
@@ -0,0 +1,189 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Phase A sweep: mechanical import + token rewrites toward gpui-kit.
|
||||
|
||||
Run from repo root: python3 script/migration/sweep.py
|
||||
Idempotent; only touches consumer crates.
|
||||
"""
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
FILES = [
|
||||
"crates/settings/src/lib.rs",
|
||||
"crates/nip4e/src/lib.rs",
|
||||
"crates/nip29_ui/src/lib.rs",
|
||||
"crates/nip29_ui/src/message.rs",
|
||||
"crates/nip29_ui/src/details.rs",
|
||||
"crates/nip29_ui/src/invite.rs",
|
||||
"crates/nip29_ui/src/metadata.rs",
|
||||
"crates/nip29_ui/src/util.rs",
|
||||
"crates/chat_ui/src/lib.rs",
|
||||
"crates/chat_ui/src/text.rs",
|
||||
"crates/chat_ui/src/actions.rs",
|
||||
"crates/chat_ui/src/file.rs",
|
||||
"crates/workspace/src/lib.rs",
|
||||
"crates/workspace/src/dialogs/import.rs",
|
||||
"crates/workspace/src/dialogs/join_group.rs",
|
||||
"crates/workspace/src/dialogs/new_chat.rs",
|
||||
"crates/workspace/src/dialogs/new_group.rs",
|
||||
"crates/workspace/src/dialogs/profile.rs",
|
||||
"crates/workspace/src/dialogs/relays.rs",
|
||||
"crates/workspace/src/dialogs/restore.rs",
|
||||
"crates/workspace/src/dialogs/screening.rs",
|
||||
"crates/workspace/src/dialogs/settings.rs",
|
||||
"crates/workspace/src/panels/backup.rs",
|
||||
"crates/workspace/src/panels/browse.rs",
|
||||
"crates/workspace/src/panels/contact_list.rs",
|
||||
"crates/workspace/src/panels/greeter.rs",
|
||||
"crates/workspace/src/panels/inbox.rs",
|
||||
"crates/workspace/src/sidebar/group_view.rs",
|
||||
"crates/workspace/src/sidebar/header.rs",
|
||||
"crates/workspace/src/sidebar/inbox.rs",
|
||||
"crates/workspace/src/sidebar/list.rs",
|
||||
"crates/workspace/src/sidebar/mod.rs",
|
||||
"crates/workspace/src/sidebar/onboarding.rs",
|
||||
"crates/workspace/src/sidebar/rows.rs",
|
||||
"crates/workspace/src/sidebar/search.rs",
|
||||
]
|
||||
|
||||
KIT = "gpui_kit::component"
|
||||
|
||||
# ui:: items that move to the kit's component root
|
||||
KIT_ITEMS = {
|
||||
"Icon", "IconName", "Sizable", "Size", "Disableable", "Selectable",
|
||||
"StyledExt", "h_flex", "v_flex", "WindowExt",
|
||||
"Notification", "NotificationType",
|
||||
"Button", "ButtonVariants", "ButtonVariant", "ButtonCustomVariant", "IconPosition",
|
||||
"Switch", "Avatar", "GroupBox", "GroupBoxVariants", "GroupBoxVariant",
|
||||
"Tab", "TabBar", "Scrollbar", "ScrollableElement", "Tooltip",
|
||||
"Input", "InputState", "Textarea", "TextareaState", "InputEvent",
|
||||
"PopupMenu", "PopupMenuItem", "DropdownMenu", "ContextMenu",
|
||||
"Dialog", "DialogButtonProps", "AlertDialog",
|
||||
"ActiveTheme", "Theme", "ThemeMode",
|
||||
"Spinner", "Kbd", "TitleBar",
|
||||
"DockArea", "DockLayout", "DockPlacement", "Panel", "PanelEvent",
|
||||
"PanelHandle", "ClosePanel",
|
||||
"Divider", "Separator",
|
||||
}
|
||||
|
||||
# ui:: items that stay in the coop ui crate (utilities)
|
||||
UI_ITEMS = {
|
||||
"TextStyle", "Typeset", "Metrics", "base_text_size", "DEFAULT_BASE_TEXT_SIZE",
|
||||
"SPACE", "CONTENT_MARGIN", "EDGE", "BUTTON_HEIGHT", "CONTROL_HEIGHT_SMALL",
|
||||
"BASE_RADIUS", "bubble_radius", "surface_radius", "panel_radius", "button_radius",
|
||||
"control_radius", "inset_radius",
|
||||
"TABBAR_HEIGHT", "SIDEBAR_WIDTH", "TRAFFIC_LIGHT_PADDING",
|
||||
"CLIENT_SIDE_DECORATION_ROUNDING", "CLIENT_SIDE_DECORATION_SHADOW",
|
||||
"CLIENT_SIDE_DECORATION_BORDER",
|
||||
"title_bar_drag_handlers",
|
||||
}
|
||||
|
||||
TOKEN_RENAMES = [
|
||||
# order matters: longest first
|
||||
("surface_raised_hover", "secondary_hover"),
|
||||
("surface_raised", "secondary"),
|
||||
("surface_dialog", "popover"),
|
||||
("surface_overlay", "popover"),
|
||||
("surface_card", "muted"),
|
||||
("surface", "sidebar"),
|
||||
("element_hover", "accent"),
|
||||
("element_active", "list_active"),
|
||||
("border_faint", "border"),
|
||||
("border_strong", "border"),
|
||||
("text_muted", "muted_foreground"),
|
||||
("text_faint", "muted_foreground"),
|
||||
("text_dim", "muted_foreground"),
|
||||
("on_solid", "primary_foreground"),
|
||||
("solid", "primary"),
|
||||
("accent_strong", "primary"),
|
||||
("accent", "primary"),
|
||||
("danger_strong", "button_danger"),
|
||||
("danger_muted", "danger"),
|
||||
("warning_muted", "warning.opacity(0.15)"),
|
||||
("drop_line", "drag_border"),
|
||||
("input_bg", "input"),
|
||||
("bg", "background"),
|
||||
("text", "foreground"),
|
||||
]
|
||||
|
||||
def rewrite_use(line: str):
|
||||
"""Rewrite one `use ui::...;` or `use theme::...;` line. Returns new lines."""
|
||||
s = line.strip()
|
||||
if s.startswith("use ui::{") and s.endswith(";"):
|
||||
inner = s[len("use ui::{"):-2]
|
||||
items = [i.strip() for i in inner.split(",") if i.strip()]
|
||||
kit, ui = [], []
|
||||
for item in items:
|
||||
name = item.split(" as ")[0].strip()
|
||||
(ui if name in UI_ITEMS else kit).append(item)
|
||||
out = []
|
||||
if kit:
|
||||
out.append(f"use {KIT}::{{{', '.join(sorted(set(kit)))}}};")
|
||||
if ui:
|
||||
out.append(f"use ui::{{{', '.join(sorted(set(ui)))}}};")
|
||||
return out
|
||||
if s.startswith("use ui::") and s.endswith(";"):
|
||||
path = s[4:-1]
|
||||
item = path.split("::")[-1]
|
||||
if item in UI_ITEMS:
|
||||
return [f"use ui::{item};"]
|
||||
return [f"use {KIT}::{{{item}}};"]
|
||||
if s.startswith("use theme::{") and s.endswith(";"):
|
||||
inner = s[len("use theme::{"):-2]
|
||||
items = [i.strip() for i in inner.split(",") if i.strip()]
|
||||
kit, ui = [], []
|
||||
for item in items:
|
||||
name = item.split("::")[-1]
|
||||
if name == "ActiveTheme" or name in KIT_ITEMS:
|
||||
kit.append(name)
|
||||
else:
|
||||
ui.append(name)
|
||||
out = []
|
||||
if kit:
|
||||
out.append(f"use {KIT}::{{{', '.join(sorted(set(kit)))}}};")
|
||||
if ui:
|
||||
out.append(f"use ui::{{{', '.join(sorted(set(ui)))}}};")
|
||||
return out
|
||||
if s.startswith("use theme::") and s.endswith(";"):
|
||||
name = s[11:-1].split("::")[-1]
|
||||
if name == "ActiveTheme" or name in KIT_ITEMS:
|
||||
return [f"use {KIT}::{name};"]
|
||||
return [f"use ui::{name};"]
|
||||
return [line]
|
||||
|
||||
def process(path: Path):
|
||||
src = path.read_text()
|
||||
lines = src.split("\n")
|
||||
out = []
|
||||
for line in lines:
|
||||
s = line.strip()
|
||||
if s.startswith("use ui::") or s.startswith("use theme::"):
|
||||
out.extend(rewrite_use(line))
|
||||
else:
|
||||
out.append(line)
|
||||
src = "\n".join(out)
|
||||
|
||||
# theme token renames, applied to `theme().x` reads only
|
||||
for old, new in TOKEN_RENAMES:
|
||||
src = re.sub(
|
||||
re.escape("theme()." + old) + r"(?![a-z_0-9])",
|
||||
"theme()." + new,
|
||||
src,
|
||||
)
|
||||
|
||||
# method/type renames
|
||||
src = src.replace("WindowExtension", "WindowExt")
|
||||
src = src.replace(".clear_notification_by_id::<", ".remove_notification::<")
|
||||
src = src.replace(".clear_notification::<", ".remove_notification::<")
|
||||
src = src.replace("with_kind(NotificationKind::", "with_type(NotificationType::")
|
||||
src = src.replace("NotificationKind", "NotificationType")
|
||||
|
||||
path.write_text(src)
|
||||
|
||||
for f in FILES:
|
||||
p = Path(f)
|
||||
if p.exists():
|
||||
process(p)
|
||||
print("swept", f)
|
||||
else:
|
||||
print("MISSING", f, file=sys.stderr)
|
||||
Reference in New Issue
Block a user