English: themebuilder.en.md
tools/themebuilder/ 是给 TyControls 写 .tycss 主题用的桌面程序。左边写主题,右边的预览马上换上它;写错的地方在问题列表里标出行号。也可以接一个大模型,用一句话说想要什么样的主题,让它起草或修改,改了什么在对比窗口里看清楚再决定要不要。
它是仓库里的一个工具,不是库的一部分,不对外承诺接口。
不用先在 IDE 里装包,工程直接引用 source/ 与 designtime/ 下的源码:
lazbuild -B tools/themebuilder/themebuilder.lpiLinux 上按需要的 widgetset 加参数,例如 --ws=gtk2、--ws=qt6;macOS 加 --ws=cocoa。编出来的程序在 tools/themebuilder/lib/<CPU>-<系统>/ 下。
界面跟随系统语言,中文系统下是中文。
图标:Windows 上图标编进了程序(tools/themebuilder/themebuilder.ico,任务栏、标题栏左边都是它)。Linux / macOS 的程序文件不带图标,要的话用 tools/themebuilder/icon/themebuilder-256.png:Linux 在 .desktop 文件里写 Icon=<这张图的路径>;macOS 打成 .app 时用它做 .icns(工具没有现成的 .icns)。图标由 scripts/gen-themebuilder-icon.ps1 生成,改了图标重跑它再重编工具。
单击标题栏左边的图标,或者在标题栏上点右键,会弹出窗口菜单(还原、最小化、最大化、关闭);双击图标关闭窗口。
- 左边是侧栏,三页:种子、问题、AI。「视图」菜单里的同名项可以切到对应页,再点一次收起侧栏。
- 中间是编辑区,带
.tycss高亮和补全。 - 右边是预览,按控件家族分了八页,顶上一排开关:暗色、密度(经典 / 现代)、全部禁用。「窗体外框」页里可以打开一个真窗体看标题栏和阴影。
编辑器自己的配色在「视图 → 编辑器外观」里选,和正在写的主题无关。预览挂在自己的样式控制器上,主题写坏了只会坏预览,不会把编辑器本身弄乱。
停手 0.3 秒,编辑器的内容就会被解析、检查,然后载入预览。解析不了或者预览画不出来时,预览保留上一版能用的样子,原因写在问题列表里。
新建:「文件 → 新建」可以选极简主题(只有亮、暗两套种子,其余全靠底层),也可以复制任何一个内置主题的全文。
种子页:六个种子(--accent、--surface、--on-surface、--border、--danger、--radius)是大部分颜色的来源,改它们最省事。文件有 @mode light / @mode dark 两块时分两列显示;只有一块 :root 时一列,可以一键拆成亮暗两套。点色块换颜色,改的只是文件里那一个值,别的字节都不动。值原来是表达式(var()、darken() 之类)时会先问一句。
问题页:解析错误、不认识的属性、未定义的变量、对比度太低等,带行号列出来,双击跳过去。底层主题已经定义的变量不算未定义。
Ctrl+点击预览里的控件(macOS 上是 Cmd+点击):编辑器跳到这个控件的规则;文件里还没有就在合适的位置加一条。没有变体的控件加的是底层规则的副本,而不是空规则——空规则会让底层对这个控件整个让位,控件就没了样式。
覆盖检查(「视图 → 覆盖检查」):列出主题写了、预览里却没有摆出来的控件,以及预览里有、但主题和底层都没专门写的控件。
.tycss 怎么写见 tycss-reference.md。
「编辑」菜单在「文件」与「视图」之间。撤销、剪切、复制、粘贴、删除、全选作用在有焦点的那个文字框上:编辑区,或者查找框、AI 页的描述框这类 Ty 输入框;焦点在按钮、列表上时,用快捷键什么都不做(键照常交给那个控件),从菜单里点则作用在编辑区。没有选中文字时剪切、复制、删除是灰的,没有可撤销的改动时撤销是灰的。格式化与查找总是作用在编辑区。
格式化文档 / 格式化选中部分:一行一条声明、写成 名字: 值;,每层缩进两个空格,右花括号单独一行,几个空行并成一个。选择器(TyButton:hover 的冒号)、注释(含多行的文件头注释)、引号里的字符串原样不动。「格式化选中部分」整理选中的那几行,按它们所在的层级缩进。两者都是一步撤销。
查找条:Ctrl+F 在编辑区顶上打开(选中了一段单行文字时自动填进查找框),Ctrl+H 打开时多一行替换。有区分大小写、全字匹配;上一个 / 下一个找到头会绕回另一端;找不到时右边写「找不到」。「替换」换掉选中的那一处再找下一个,「全部替换」一次换完、一步撤销,右边写换了几处。在查找框里按 Enter 找下一个、Shift+Enter 找上一个,Esc 关掉查找条、回到编辑区。
| 操作 | 快捷键 |
|---|---|
| 撤销 / 重做 | Ctrl+Z / Ctrl+Shift+Z |
| 剪切 / 复制 / 粘贴 | Ctrl+X / Ctrl+C / Ctrl+V |
| 删除选中的文字 | Del |
| 全选 | Ctrl+A |
| 格式化文档 | Ctrl+Shift+F |
| 格式化选中部分 | (菜单) |
| 查找 / 替换 | Ctrl+F / Ctrl+H |
| 查找下一个 / 上一个 | F3 / Shift+F3 |
| 补全 | Ctrl+Space |
编辑区还有 SynEdit 自带的键:Ctrl+Y 删除一行、Ctrl+I / Ctrl+U 整块缩进 / 反缩进、Ctrl+Shift+数字 设书签、Ctrl+数字 跳到书签。
保存时换行符、BOM、文末换行都照读入时的样子写回,没改过的行一个字节都不变。打开仓库里的内置主题文件可以直接保存,状态栏会提醒重跑对应的生成脚本。
导出主题包(「文件 → 导出主题包」):导出成文件夹包(theme.tycss + theme.json + 主题引用的文件),或者在主题没有引用任何文件时导出成 zip。导出后会读回来试加载一遍,失败就不留下任何东西。
在程序里怎么用(同一菜单):给出三种加载方式的代码片段——从文件、从主题包、把文本注册成命名主题,可以直接复制。
「视图 → AI 设置」或 AI 页右上角的齿轮。点「添加」从预置里选一个:
| 预置 | 格式 | 地址 | 模型 |
|---|---|---|---|
| OpenAI | OpenAI 兼容 | https://api.openai.com/v1 |
gpt-5 |
| DeepSeek | OpenAI 兼容 | https://api.deepseek.com/v1 |
deepseek-chat |
| Anthropic | Anthropic | https://api.anthropic.com/v1 |
claude-sonnet-5 |
| 本地(Ollama) | OpenAI 兼容 | http://localhost:11434/v1 |
qwen2.5-coder:7b |
| 自定义 | OpenAI 兼容 | (自己填) | (自己填) |
预置只是帮你填好地址和模型名,填好后都能改。模型名会过时,「测试连接」报「地址或模型名不对(404)」时多半是它。
- 密钥:本地模型不需要。Windows 上用当前用户的 DPAPI 加密后存进配置文件;Linux / macOS 上存在一个只有你能读的文件里(权限 0600)。密钥不会出现在任何提示、错误信息里。
- 最大输出:0 表示不发送这一项,由服务自己决定。OpenAI 的新模型不接受旧的写法,所以默认是 0;DeepSeek 的
deepseek-chat最多 8192;Anthropic 必须大于 0,默认 32000。 - 超时:多少秒收不到任何数据算超时。生成一整份主题要一两分钟是正常的,所以没有总时长限制,随时可以点「停止」。
- 测试连接:发一个最小的请求,一收到回答就停,然后说一句结果。
设置页底下写着:主题文本和你的描述会发给这里配置的服务。用本地模型,它们就不会离开这台电脑。
地址是 http://(不是 https://)、又不在这台电脑上时(比如内网里的服务、局域网里另一台机器上的 Ollama),设置页和 AI 页都会出一条「未加密」的警告:这个地址用 http,密钥和主题文本会明文经过网络。只是提醒,照样能用、也可以填密钥——网络可不可信只有你知道。服务把请求重定向到别的地址时,工具不跟过去(密钥会被一起带走),只告诉你它指向哪台主机,确认是对的地址就在设置里改过去。
装好 Ollama,ollama pull qwen2.5-coder:7b(或别的 7–8B 代码模型),先设好上下文长度再启动 Ollama:
OLLAMA_CONTEXT_LENGTH=32768 ollama serveOllama 默认的上下文只有几千 token,请求太长时它会悄悄截掉开头——每次请求都带着一份几千 token 的语法参考,截掉的正是它,模型就会乱写。地址填本机时,设置页也会提示这一点。
在 AI 页写一句描述(比如「暖色调,圆角大一点」),点「生成」:
- 回答一段段出现在下面的输出框里,可以随时「停止」。用的是带思考的模型时,先会显示「模型在思考……」。
- 结束后,工具从回答里取出
tycss代码块,用和编辑器一样的标准检查:能不能解析、属性认不认识、变量有没有定义、亮暗两种模式下预览能不能画出来。有错就把问题发回去请模型改,最多两次;对比度低这类只是提示,不发回去。 - 对比窗口自动打开(这时若有别的对话框开着,就不弹,状态行提示用「查看对比…」):左边是编辑器现在的文本,右边是模型的版本,改动的行标了颜色,两边一起滚动。剩下的问题列在底下。勾上「在预览里试看」,预览就换成模型的版本;去掉勾或关掉窗口就换回来。
- 「接受」把编辑器换成模型的版本,Ctrl+Z 一次就能撤回;「放弃」什么都不变。关掉之后,AI 页的「查看对比…」可以再打开。
生成之后又在编辑器里改过,接受时会先问一句:接受会把这些改动一起替换掉。
勾上「附上问题列表」时,编辑器当前的问题会一起发过去。文件有错误时它会自动勾上,没错误时自动去掉;你自己点过之后,在这份文档里就不再自动改。
同一份文档里,工具会记住你之前的每句描述,以及那次的结果有没有被接受,所以「再暗一点」能接上。之前的回答不会再发,每次只发当前的文件,请求不会越来越长。新建或打开另一份文档时,对话从头开始;也可以点「新对话」。
发给模型的规则和语法参考是英文的(模型对英文规则遵守得最好);你的描述原样发送,模型写在代码块前面的那句说明会用你的语言。
| 状态行 | 意思 |
|---|---|
| 连不上 …。服务开着吗?或者需要代理? | 地址对,但没有服务在听,或者网络不通 |
| 找不到主机 … | 主机名解析不了 |
| 密钥被拒绝(401) | 密钥不对或者过期 |
| 地址或模型名不对(404) | 地址多了或少了一段,或者模型名写错 |
| 请求太多(429) | 服务限流了,等一会儿再试 |
| … 已经 N 秒没有回应 | 超过了设置里的超时 |
| 回答到了最大输出长度,被截断了 | 把设置里的最大输出调大 |
| 回答的格式不对 | 地址指向的不是这种格式的服务 |
| 回答里没有 tycss 代码块 | 模型没照规矩回答,原文留在输出框里 |
| 回答不完整:在代码块中间就结束了 | 服务说完了,代码块却没写完 |
| 服务返回了重定向,指向 … | 地址变了;工具不跟过去,确认后在设置里改 |
| 代理要求用户名和密码(407) | 在系统的代理设置里填上 |
出什么错编辑器都不受影响。
AI 用系统的 libcurl,运行时加载。找不到时 AI 页会说试过哪些库名,生成按钮变灰,其余功能照常。Debian / Ubuntu 上装 libcurl4 包即可;库名特别的发行版可以用环境变量指定:
THEMEBUILDER_LIBCURL=/usr/lib64/libcurl.so.4 ./themebuilderWindows 上跟随系统的代理设置。Linux / macOS 上读 https_proxy、http_proxy、no_proxy 这几个环境变量。连本机地址(本地模型)时不走代理。
工具的设置、最近文件和 AI 配置都在用户配置目录里:
| 系统 | 目录 |
|---|---|
| Windows | %LOCALAPPDATA%\themebuilder\ |
| Linux / macOS | ~/.config/themebuilder/ |
themebuilder.ini 是工具自己的设置,themebuilder-ai.ini 是 AI 服务,Linux / macOS 上另有存密钥的 themebuilder-ai.keys。想从头来,删掉它们就行。
- 编辑器和对比窗口用的是 SynEdit,它的边框和滚动条是系统原生的,不跟随编辑器外观。
- AI 每次都交回整份文件,改一个颜色也一样。
- macOS(Apple 芯片)上调用 libcurl 的方式还没在真机上验过。
- Linux / macOS 上,正在解析主机名(DNS)时点「停止」不会立刻生效:libcurl 查名字时不回头看停止,要等查完或连接超时(15 秒)。
- 同样的原因,Linux / macOS 上正在解析主机名时关掉工具(或关掉正在「测试连接」的 AI 设置窗口),窗口最长要等约 15 秒才关上:关闭要等那次请求结束。
- Linux / macOS 上系统的 libcurl 太旧、不认 AI 需要的某个选项时,生成不会发出,状态行说是哪个选项,换新一点的 libcurl 即可。