Chapter 176 · XUI 专业控件

CodeEdit 查找替换

内置查找/替换面板:正则表达式、大小写敏感、全部替换、FindScope 范围限定。

176

概念

CodeEdit 内置完整的查找替换系统:
• Find 面板:OpenFind 打开内嵌查找栏
• Replace 面板:OpenReplace 打开带替换的查找栏
• xui_find_options_t:模式/大小写/正则/全词匹配
• FindScope:限定查找范围(全文/选区/当前行)
• 快捷替换:ReplaceAllPlain / ReplaceAllRegex 无需 UI

API 速查

函数说明
int xuiCodeEditOpenFind(xui_widget pW)打开查找面板
int xuiCodeEditOpenReplace(xui_widget pW)打开替换面板
int xuiCodeEditFindAll(pW, pOptions, pResultCount)查找全部
int xuiCodeEditFindNext(pW, pOptions)查找下一个
int xuiCodeEditFindPrevious(pW, pOptions)查找上一个
int xuiCodeEditReplaceCurrent(pW, pOptions)替换当前
int xuiCodeEditReplaceAll(pW, pOptions, pReplaceCount)全部替换
int xuiCodeEditReplaceAllPlain(pW, sPattern, sReplace, iFlags, pCount)纯文本替换
int xuiCodeEditReplaceAllRegex(pW, sPattern, sReplace, iFlags, pCount)正则替换
int xuiCodeEditSetFindScope(pW, pScope)限定范围
int xuiCodeEditGetFindResultCount(pW)结果数量

编译本章示例

gcc -O2 -I. -o ch176.exe ch176_main.c src\xui_*.c build\xge.lib -lm -lws2_32 -liphlpapi -lgdi32 -luser32 -lshell32 -lopengl32 -lole32 -lwinmm -lavrt
.\ch176.exe

示例:正则查找与批量替换

// 打开查找面板(用户交互)
xuiCodeEditOpenFind(pEditor);

// 编程式:正则替换所有 foo( → bar(
int iReplaced = 0;
xuiCodeEditReplaceAllRegex(pEditor,
    "foo\\(", "bar(", 0, &iReplaced);
printf("替换了 %d 处\n", iReplaced);

// 使用 FindOptions 精细控制
xui_find_options_t opt = { 0 };
opt.sPattern = "TODO";
opt.bCaseSensitive = 1;
opt.bWholeWord = 1;

int iCount = 0;
xuiCodeEditFindAll(pEditor, &opt, &iCount);
printf("找到 %d 个 TODO\n", iCount);

// 遍历结果
for (int i = 0; i < iCount; i++) {
    xui_code_find_result_t r;
    xuiCodeEditGetFindResult(pEditor, i, &r);
}

完整代码

将以下代码保存为 ch176_main.c,编译后运行即可看到正则查找与批量替换效果:

#include "xge.h"
#include "xui.h"
#include <stdio.h>

static xui_context g_pCtx;
static xui_widget g_pEditor;
static int g_bDone = 0;

static int onFrame(void* pUser) {
    (void)pUser;
    xgeClear(0x1E1E1EFF);
    xui_vec2_t pos;
    xgeMouseGet(&pos.x, &pos.y);
    xuiInputPointerMove(g_pCtx, pos.x, pos.y);
    if (xgeMouseDown(XGE_MOUSE_LEFT))
        xuiInputPointerDown(g_pCtx, pos.x, pos.y, 0);
    else
        xuiInputPointerUp(g_pCtx, pos.x, pos.y, 0);

    if (!g_bDone) {
        g_bDone = 1;
        // 正则替换所有 foo( → bar(
        int iReplaced = 0;
        xuiCodeEditReplaceAllRegex(g_pEditor,
            "foo\\(", "bar(", 0, &iReplaced);
        printf("Replaced %d\n", iReplaced);

        // 查找所有 TODO
        xui_find_options_t opt = { 0 };
        opt.sPattern = "TODO";
        opt.bCaseSensitive = 1;
        opt.bWholeWord = 1;
        int iCount = 0;
        xuiCodeEditFindAll(g_pEditor, &opt, &iCount);
        printf("Found %d TODOs\n", iCount);
    }

    xuiUpdate(g_pCtx, xgeGetDelta());
    xuiLayout(g_pCtx);
    xuiRender(g_pCtx, NULL, NULL, 0);
    return XGE_OK;
}

int main(void) {
    xge_desc_t d = { 0 };
    d.iWidth = 900; d.iHeight = 640;
    d.sTitle = "ch176 - Find Replace";
    d.iFlags = XGE_INIT_VSYNC;
    xgeInit(&d);

    xuiCreate(&g_pCtx);
    extern const xui_proxy_t tXgeProxy;
    xui_proxy_t tXgeProxy = xuiProxyXge();
xuiSetProxy(g_pCtx, &tXgeProxy);
    xuiSetViewportSize(g_pCtx, 900, 640);

    xui_code_edit_desc_t desc = { 0 };
    xuiCodeEditCreate(g_pCtx, &g_pEditor, &desc);
    xuiCodeEditSetLanguage(g_pEditor, "c");
    xuiCodeEditSetDefaultMargins(g_pEditor, 1, 0, 0, 0);

    const char* sCode =
        "// TODO: refactor\n"
        "void foo_init(void) {}\n"
        "void foo_run(void) {}\n"
        "// TODO: cleanup\n"
        "void foo_shutdown(void) {}\n";
    xuiCodeEditSetText(g_pEditor, sCode);

    xui_widget pRoot = xuiGetRootWidget(g_pCtx);
    xuiWidgetAddChild(pRoot, g_pEditor);
    xuiWidgetSetRect(g_pEditor, (xui_rect_t){0, 0, 900, 640});

    xgeRun(onFrame, NULL);
    xuiDestroy(g_pCtx);
    xgeUnit();
    return 0;
}

代码讲解

  • ReplaceAllRegex:正则批量替换,C 字符串中反斜杠需双写("foo\\(")。
  • xui_find_options_t:配置查找模式、大小写敏感、全字匹配等选项。
  • FindAll:执行全文查找,返回匹配数量,可用 GetFindResult 遍历结果。
  • 首帧执行:用 g_bDone 标志确保查找替换只执行一次。

要点与陷阱

  • FindScope:默认全文搜索;设为选区范围可仅搜索选中部分。
  • 正则转义:ReplaceAllRegex 中反斜杠需双写(C 字符串)。
  • ClearFind:替换完成后调用 ClearFind 清除高亮标记。
  • FindWindow:GetFindWindow 获取查找面板 Widget 可自定义布局。

进阶练习

  1. 多文件查找:遍历文件列表,对每个 CodeEdit 执行 FindAll。
  2. 查找结果面板:ListView 展示所有匹配,点击跳转。
CodeEdit 查找替换效果
图:CodeEdit 查找替换渲染效果