# 主题 `theme/` 加载、编辑并保存为 TUI 宿主着色的主题 `.dft` 文件 —— 这些 文件正是宿主在启动时扫描、stdext 在 `src/themes/` 下随附的那些。相关 函数操作普通映射,因此读取是一次深层 `get`,编辑返回一个新的映射,由你 重新绑定。该命名空间在每个宿主和脚本二进制中都可用;在 TUI 宿主中 将它与 `tui/theme-reload` 和 `tui/set-theme` 搭配,可形成 实时编辑 → 保存 → 应用的循环。 ## 函数 | 函数 | 用途 | |---|---| | `theme/load name-or-path` | 词干、显示名称或 `.dft` 路径 → 完整主题映射;记录来源信息供 `theme/save` 使用 | | `theme/current` | 当前工作区的活动主题映射;未应用宿主主题时为 `nil` | | `theme/get $t path...` | 按关键字路径深层读取;任一层级缺失时返回 `nil` | | `theme/set $t path... value` | 深层更新并返回新映射;缺失的中间层级会变成空映射 | | `theme/unset $t path...` | 移除路径上的键,返回新映射 | | `theme/save $t ?path` | 规范写入;返回写入的路径,失败时返回 `nil` | | `theme/list` | 可见主题词干(关键字)的排序向量 | 说明: - 搜索链。 `theme/load` 和 `theme/list` 按顺序查找,每个词干以 先命中者为准:项目 `.deft/local/themes/`、用户主目录 `local/themes/`、预置文件 `:themes :dir`(字符串或路径 向量)、stdext 挂载点的 `themes/`,以及旧版 `./themes/` 回退。 - 名称形式。 `theme/load` 接受文件词干(关键字或字符串, `:dracula` → `dracula.dft`)、与文件 `:name` 字段匹配的显示名称 (`"Dracula"`),或显式的 `.dft` 路径。`theme/get` 和编辑函数会把字符串路径段强制转换为关键字,因此 `[theme/get $t "ui" "accent"]` 与 `[theme/get $t :ui :accent]` 读取同一个槽位。 - 编辑语义。 `theme/set` 和 `theme/unset` 从不修改 输入映射 —— 请绑定返回的映射。`theme/set` 具有 assoc-in 语义, 因此 `[theme/set $t :markdown :code-fg "#00ff00"]` 会在 `:markdown` 段尚不存在时创建它。 - 保存目标。 没有显式路径时,`theme/save` 遵循 `theme/load` 记录的来源。可写来源(项目 `.deft/local/themes`、用户主目录、预置文件 `:themes :dir`、旧版 `./themes`)会被就地覆盖。随 stdext 附带的默认值从不 修改:它会在 `<project` .deft>/local/themes/<stem>.dft` 写入一个覆盖影子文件。在 Deft 中构建` 而非加载的映射,会以 `:name` 的 slug 保存到该影子目录 (`"Catppuccin Mocha"` → `catppuccin-mocha.dft`),当 `:name` 缺失时报错。显式的 `path` 参数优先于以上所有行为。 - 规范格式。 保存的文件带有 `# <name>` 头、4 空格 缩进的嵌套映射,段按 `name → ui → syntax → help →` markdown` 排序后跟附加段,键按字母排序,并采用` 先写后重命名的原子写入 —— 因此主题往返后 diff 稳定。 - 当前主题。 `theme/current` 是宿主已应用的完整解析映射, 与 TUI 宿主中的 `[tui/theme]` 和 `[draw/theme $ctx]` 相同;各包的 `theme.dft` 默认值合并在各自的 app 键下。它在独立的 `deft` 二进制中返回 `nil` —— 在那里回退到 `theme/load` 加上你自己的默认值。它 每次调用都会解析,因此请缓存结果并在主题变更后重新读取 (stdext 的 `theme/on-change` 封装了脏检查模式)。 ## 示例
# Load by stem, display name, or explicit path
set t [theme/load :dracula]
set t [theme/load "Dracula"]
set t [theme/load "themes/my-theme.dft"]

# Deep read
[theme/get $t :ui :accent]          # => "#7a64a1"
[theme/get $t :help]                # => the whole :help sub-map
[theme/get $t :ui :nope]            # => nil

# Deep edits return a new map; rebind it
set t [theme/set $t :ui :accent "#ffffff"]
set t [theme/set $t :markdown :code-fg "#00ff00"]   # section auto-created
set t [theme/unset $t :markdown]

# Save, then apply in a running TUI host
[theme/save $t]                     # => ".deft/local/themes/dracula.dft"
[tui/theme-reload]                  # rescan + re-apply; panels repaint
[tui/set-theme "Nord"]              # switch to another loaded theme

# Discover what is installed
[theme/list]                        # => @{ :catppuccin-mocha :dracula ... }
[in? [theme/list] :dracula]         # => true
在 TUI 宿主之外没有活动主题,因此脚本会回退到具名主题:
if [nil? [theme/current]] {
    set t [theme/load :dracula]
}
## 另见 - TUI 概览 —— 宿主如何扫描并应用主题 - 图形 —— 主题颜色如何到达 `draw/*` - 文件系统 —— 定位并读取主题 `.dft` 文件