ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Clay 如何接入终端 ANSI 渲染器输出字符界面?

Clay 如何接入终端 ANSI 渲染器输出字符界面? Clay 如何接入终端 ANSI 渲染器输出字符界面【免费下载链接】clayHigh performance UI layout library in C.项目地址: https://gitcode.com/GitHub_Trending/clay9/clayClay 是一个纯布局库它只输出排序好的渲染指令数组Clay_RenderCommandArray不负责把指令画到任何平台上。这篇文章的任务是把这些指令接进终端用 ANSI 转义序列输出一个字符界面。仓库提供了完整的可运行示例 examples/terminal-example/main.c 和渲染器实现 renderers/terminal/clay_renderer_terminal_ansi.c按下面的顺序照做即可得到同一个效果初始化 Clay 内存、注册文本测量函数、每帧调用Clay_Terminal_Render把布局绘制到终端。渲染器提供了哪些接入点ANSI 渲染器是一个可以直接#include的.c文件对主程序暴露两个函数见 renderers/terminal/clay_renderer_terminal_ansi.cClay_SetMeasureTextFunction注册用的测量函数Console_MeasureText按字符数估算文本尺寸并把结果乘以columnWidth放大到 Clay 的布局坐标系。userData参数传一个int指针指向columnWidth的值。Clay_Terminal_Render(Clay_RenderCommandArray renderCommands, int width, int height, int columnWidth)每帧调用一次把一帧渲染指令画到终端。渲染器内部用 ANSI 转义序列工作每帧开头输出\033[H\033[J清屏通过printf(\033[%d;%dH, y 1, x 1)移动光标定位字符矩形和边框不画像素而是把颜色四个通道的平均值换算成四个挡位的块状字符█平均值 0.75、▓ 0.5、▒ 0.25、░其余。它处理的渲染指令类型只有五类CLAY_RENDER_COMMAND_TYPE_TEXT、CLAY_RENDER_COMMAND_TYPE_SCISSOR_START、CLAY_RENDER_COMMAND_TYPE_SCISSOR_END、CLAY_RENDER_COMMAND_TYPE_RECTANGLE、CLAY_RENDER_COMMAND_TYPE_BORDER。遇到其他指令类型例如图片指令时程序会输出Error: unhandled render command.并以退出码 1 结束定义了CLAY_OVERFLOW_TRAP时先触发SIGTRAP。所以接入这个渲染器的布局里不要使用图片类元素。columnWidth是像素与字符格之间的换算系数布局坐标除以它还原成字符坐标文本测量结果乘以它放大成布局坐标。示例中取 16。准备工作一个支持 C99 的编译器构建系统若走 CMake仓库要求的版本是 3.27见 CMakeLists.txt 的cmake_minimum_required(VERSION 3.27)。终端示例只在非 MSVC 环境下参与构建根目录 CMakeLists.txt 中add_subdirectory(examples/terminal-example)包在if (NOT MSVC)里且由CLAY_INCLUDE_ALL_EXAMPLES默认 ON或CLAY_INCLUDE_DEMOS默认 OFF控制是否构建。示例 examples/terminal-example/CMakeLists.txt 将标准设为 C99Linux 下额外链接m库。接入步骤主程序只需要一个 C 文件。以 examples/terminal-example/main.c 为模板结构如下// Must be defined in one file, _before_ #include clay.h #define CLAY_IMPLEMENTATION #include unistd.h #include clay.h #include renderers/terminal/clay_renderer_terminal_ansi.c #include examples/shared-layouts/clay-video-demo.c void HandleClayErrors(Clay_ErrorData errorData) { printf(%s, errorData.errorText.chars); } int main() { const int width 145; // 终端布局宽度字符格 const int height 41; // 终端布局高度字符格 int columnWidth 16; // 每字符格对应的布局坐标尺寸 uint64_t totalMemorySize Clay_MinMemorySize(); Clay_Arena arena Clay_CreateArenaWithCapacityAndMemory(totalMemorySize, malloc(totalMemorySize)); Clay_Initialize(arena, (Clay_Dimensions) {.width (float) width * columnWidth, .height (float) height * columnWidth}, (Clay_ErrorHandler) {HandleClayErrors}); // Tell clay how to measure text Clay_SetMeasureTextFunction(Console_MeasureText, columnWidth); ClayVideoDemo_Data demoData ClayVideoDemo_Initialize(); while (true) { Clay_RenderCommandArray renderCommands ClayVideoDemo_CreateLayout(demoData); Clay_Terminal_Render(renderCommands, width, height, columnWidth); fflush(stdout); sleep(1); } }上面代码与示例文件一致唯一差别是#include路径示例中用相对路径../../clay.h这里按仓库根目录书写。width、height、columnWidth就是示例使用的数值 145、41、16换成你自己的终端尺寸时三个值要一起改且Clay_Initialize里的布局尺寸始终写成width * columnWidth、height * columnWidth。各步骤的用途CLAY_IMPLEMENTATION必须先于clay.h定义且整个工程只能在一个文件里定义。随后#include渲染器的.c文件而不是链接它。初始化顺序按 README.md 中 Lifecycle for public functions 一节执行Clay_MinMemorySize-Clay_CreateArenaWithCapacityAndMemory-Clay_Initialize-Clay_SetMeasureTextFunction。Clay_MinMemorySize返回当前配置所需的字节数示例用malloc分配README 说明这里用malloc只是示例任何能提供对应大小地址空间的分配器都可以。注册文本测量函数是必做项布局里用了CLAY_TEXT却没调用Clay_SetMeasureTextFunction或传了空指针时Clay 会报CLAY_ERROR_TYPE_TEXT_MEASUREMENT_FUNCTION_NOT_PROVIDED由错误处理器HandleClayErrors输出。渲染循环每帧用 examples/shared-layouts/clay-video-demo.c 里的ClayVideoDemo_CreateLayout生成布局再交给Clay_Terminal_Render。这个 demo 内部自己调用了Clay_BeginLayout到Clay_EndLayout如果你换成自己的布局代码就要按 README 的每帧流程自己写Clay_BeginLayout/CLAY(...)/Clay_EndLayout。fflush(stdout)保证转义序列立刻输出sleep(1)让界面每秒刷新一次。构建并验证结果在仓库根目录构建全部示例CLAY_INCLUDE_ALL_EXAMPLES默认开启cmake -S . -B build cmake --build build ./build/examples/terminal-example/clay_examples_terminal运行后终端会持续输出 Clay 视频 demo 的字符界面顶部是标题栏左侧是文档列表右侧是内容区矩形底色显示为不同密度的块状字符内容每帧重新绘制。判断是否跑通就看两点终端每秒刷新一次布局且width、height之外的区域没有乱码光标残留——渲染器每帧开头的\033[H\033[J负责清屏程序没有打印Error: unhandled render command.。一旦出现这条信息说明布局里出现了该渲染器不处理的指令类型进程会以退出码 1 结束CLAY_OVERFLOW_TRAP下先触发SIGTRAP需要回到布局定义里检查元素类型。已知限制文本测量是近似值。Console_MeasureText按字符数计宽源文件中标注this function is very wrong, it measures in characters, I have no idea what is the size in pixels所以它适合等宽字符格场景不适合做精确排版。只能画文本、矩形和边框。图片等其他指令类型会走default分支导致进程退出前面已说明。仅支持非 MSVC 平台参与构建根目录 CMake 对NOT MSVC之外不添加这个示例。Clay 不管终端窗口本身。README 明确 Clay doesnt handle window related tasks示例直接写死了 145x41 的布局尺寸如果要在真实窗口尺寸下自适应需要自己从终端环境取尺寸并调用Clay_SetLayoutDimensions更新。布局里用了CLAY_TEXT却没注册测量函数、或 arena 容量不足CLAY_ERROR_TYPE_ARENA_CAPACITY_EXCEEDED这类错误都会通过Clay_Initialize传入的HandleClayErrors打印到终端排查时先看它输出的错误文本。【免费下载链接】clayHigh performance UI layout library in C.项目地址: https://gitcode.com/GitHub_Trending/clay9/clay创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进