尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Windows Terminal 文本搜索功能设计:从 Spec 605 到 SearchBoxControl 的完整实现

Windows Terminal 文本搜索功能设计:从 Spec 605 到 SearchBoxControl 的完整实现 Windows Terminal 文本搜索功能设计从 Spec #605 到 SearchBoxControl 的完整实现【免费下载链接】terminalThe new Windows Terminal and the original Windows console host, all in the same place!项目地址: https://gitcode.com/GitHub_Trending/term/terminal本篇围绕 Windows TerminalOpenConsole 仓库的搜索功能设计文档 doc/specs/#605 - Search/spec.md 展开完整讲解该功能从需求动机、组件拆分、搜索流程到 UI/UX 交互的设计决策并结合当前仓库中的 SearchBoxControl、TermControl 等源码还原在终端文本缓冲区中查找文本这一能力是如何落地的。读完后你将掌握 Terminal 搜索框SearchBoxControl的组件边界、搜索请求/结果的数据结构、匹配与高亮的实现链路以及规格书中规划的未来演进方向。![SearchBox 在深色与浅色主题下的整体样式](https://gitcode.com/GitHub_Trending/term/terminal/blob/20588130d8ef2ba40eb56bdae88e04cce7fc5b5d/doc/specs/?utm_sourcegitcode_repo_files#605 - Search/images/SearchBoxControl.png)一、需求背景为什么终端需要内容搜索搜索功能的起点是功能请求 issue #605 Search。设计文档指出iTerm2 的内容搜索是其优点之一它提供两种形态从当前标签页搜索和从所有标签页搜索几乎所有编辑器都有等效的字符串查找。Terminal 希望复刻这种体验同样支持单标签页内搜索与跨多标签页搜索两种变体但先从单标签页搜索开始实现。文档明确了设计目标的分层终极目标是同时提供单标签页搜索与全标签页搜索而第一版Version 1只做单标签页内的精确文本匹配。![点击向上箭头按钮后方向按钮进入选中样式](https://gitcode.com/GitHub_Trending/term/terminal/blob/20588130d8ef2ba40eb56bdae88e04cce7fc5b5d/doc/specs/?utm_sourcegitcode_repo_files#605 - Search/images/SearchBoxUpSelected.png)二、总体设计六条设计准则规格书对搜索体验提出了六条硬性要求构成了整个功能的骨架按键触发搜索由 KeyBindings 触发。Json 配置文件中启用一个名为find的设置属性用户可以为搜索自定义按键绑定默认值为CtrlShiftF。搜索框载体用户在一个 XAMLTextBox中键入搜索内容该 TextBox 包含在自定义SearchBoxControl中。搜索框默认出现在窗口的右上角。多种匹配方式最简单的匹配是精确文本匹配其他方式还包括大小写敏感的精确匹配与正则表达式匹配。第一阶段聚焦大小写敏感/不敏感的精确文本匹配。搜索起点规则当前没有活动选区时搜索从mutableViewport的最后一行开始存在活动选区时则从选中文本的前一个或后一个位置开始。到达搜索起点后自动环绕wrap-around继续搜索。不阻塞终端交互搜索框在屏时用户必须能与终端完整交互输入、滚动等。可访问性搜索框获得焦点后用户应能通过键盘 Tab 在搜索框的所有可交互元素间导航搜索框可由按键绑定打开和关闭关闭通常绑定Esc。三、底层复用把 Conhost 的搜索模块变成共享组件设计文档中一个关键的架构决策是复用 conhost 已有的搜索模块。conhost 中已存在一个搜索模块实现了大小写敏感/不敏感的精确文本匹配并提供了选中命中词的方法。但当时它位于 Conhost 内部依赖BufferOut以及SCREEN_INFORMATION等 ConHost 私有类型。为了将 Search 做成Terminal 与 Console Host 共享的组件需要剥离它对 ConHost 类型的依赖——BufferOut本身已是共享组件只需确保没有其他 Conhost 依赖。搜索算法本身采用暴力brute-force方式从文本缓冲区中的每个位置开始将待搜索字符串的 span 与缓冲区字符逐一比较一旦当前缓冲区文本与整个搜索串匹配就记录该文本在缓冲区中的位置并返回。记录的位置信息随后被用于执行选区。向上/向下搜索方向、大小写敏感与否都由搜索模块内部的一个布尔标志控制——默认向上搜索、默认不区分大小写。四、SearchBoxControl组件边界与放置位置搜索框被实现为一个 XAMLUserControl元素SearchBoxControl。搜索流程开始时创建一个SearchBoxControl对象并挂接到TermControl的根网格上即每个TermControl各自持有一个 SearchBox。文档给出了三点理由每个TermControl对象是一个终端窗口拥有独立的文本缓冲区第一版就搜索当前终端的文本缓冲区。如果把搜索框放在 TerminalApp 层级搜索只能发生在当前聚焦的终端上反而限制了灵活性。如果社区不喜欢当前设计可以把 SearchBox 提升到更高层级——架构上保留了调整空间。在当前仓库中该组件对应 SearchBoxControl.h、SearchBoxControl.cpp 与 SearchBoxControl.xaml。从源码结构看实现相比规格书已进一步演进头文件中除了规格书描述的GoForward()方向、CaseSensitive()大小写之外还增加了RegularExpression()与SetStatus(totalMatches, currentMatch, searchRegexInvalid)等成员说明现在的搜索框支持正则模式并显示当前命中/总命中数状态。五、搜索流程实现七步规格书把搜索流程拆成了清晰的七步用户按下CtrlShiftF或自定义按键时创建新的SearchBoxControl对象并作为TermControl的子元素挂接焦点转移到其中的 TextBox。用户按 Enter 或点击上/下箭头按钮后从当前视口最后一行或当前选区开始在文本缓冲区中查找精确文本最近的命中被选中随后搜索起点被设置为该选中文本下一次搜索从其之前或之后继续。复用 conhost 的 Search 模块执行暴力匹配见上一节。搜索方向由一个布尔标志决定默认向上。大小写敏感/不敏感同样由布尔标志控制默认不敏感。Tab 导航由 XAML 实现只需在SearchBoxControl上设置TabNavigationCycle。用户点击 X 按钮或按Esc时搜索框消失对象被析构并从TermControl的 XAML 树中摘除第一版不保存任何状态。第 5 条保证搜索框打开时终端可完整交互的实现手段是搜索框与终端输入在键盘焦点上隔离。当前键盘焦点在搜索框上时keydown 事件在搜索框层级处理焦点回到终端时按键则正常流向终端。在当前代码中TermControl.cpp 的CreateSearchBoxControl()负责查找并初始化SearchBox控件SearchMatch(goForward)TermControl.cpp#L711在用户按 Enter/点击方向按钮时发起一次查找_Search与_SearchChangedTermControl.cpp#L758分别处理执行搜索与文本变化时刷新二者都以SearchRequest结构调用_core.Search(...)_CloseSearchBoxControl则在关闭时调用_core.ClearSearch()清理状态。搜索请求与结果的数据契约定义在 ControlCore.idlstruct SearchRequest { String Text; // 搜索文本 Boolean GoForward; // 搜索方向true 向下false 向上 Boolean CaseSensitive; // 是否区分大小写 Boolean RegularExpression; // 是否按正则解析 Boolean ExecuteSearch; // true执行一次查找false仅刷新高亮/计数 Boolean ScrollIntoView; // 是否需要把命中滚动到可视区域 Int32 ScrollOffset; // 滚动偏移 }; struct SearchResults { Int32 TotalMatches; // 总命中数 Int32 CurrentMatch; // 当前命中的序号 Boolean SearchInvalidated; Boolean SearchRegexInvalid; // 正则表达式非法时置位 };可以看到当前实现把规格书中方向/大小写两个布尔标志扩展成了结构化的请求/结果对象并额外承载了高亮刷新ExecuteSearchfalse与命中计数TotalMatches/CurrentMatch这些能力正是规格书Future considerations中第 5 条输入时高亮与状态展示的落地。六、UI/UX 设计细节搜索框默认位于终端窗口右上角如果当前标签页被分割为多个 pane每个 pane 各自拥有一个独立的搜索框。控件的组成元素两个带上/下箭头的按钮控制搜索方向被选中的方向按钮会以不同样式标示当前方向带 Aa 图标的按钮按下即表示启用区分大小写的搜索关闭按钮 X。样式上所有元素——X 按钮、文本框、搜索控制按钮——被排在同一行。这保证了SearchBoxControl不会太高而遮挡终端文本类似 VS Code 的做法。文档还讨论了另一种多层布局占更多行但搜索框更窄由于元素不多最终选择了单行布局。完整的用户体验流程规格书 UI/UX 一节的十步按CtrlShiftF或自定义绑定打开搜索框焦点移到 TextBox。按 Enter 或点击上/下箭头开始搜索命中文本被选中下一次搜索从当前选区开始朝所选方向继续。通过点击上/下箭头按钮选择方向所选按钮显示选中样式不点击时默认方向为向上。通过勾选方式选择区分大小写或不区分默认不区分。搜索框获得焦点时可用 Tab 在其内部元素间导航选中后按 Enter 等效于点击。点击 X 或按Esc结束搜索搜索框消失焦点移回终端。搜索框关闭退出搜索模式后选区仍然保留——这与 VS Code 和 cmd 的现有体验一致想清除选区可点击窗口其他区域。搜索框打开时点击终端焦点从搜索框移回终端但搜索框保持打开。搜索框打开时用户可以与终端交互滚动终端内容或在焦点位于终端控件时输入文本。搜索框打开时切换标签页焦点会移回终端。七、能力清单与非功能要求第一版能力Capabilities用户可以在终端屏幕的文本缓冲区中搜索精确匹配的文本可选择区分/不区分大小写可向上或向下搜索命中的文本会被选中存在活动选区时从选区含开始搜索否则从已写入文本的末尾开始到达起点后自动环绕可用 Tab 在搜索框所有元素间导航可用Shift Enter向相反方向搜索。可访问性、安全、可靠性、兼容性与性能可访问性搜索必须可以仅用键盘完成搜索框聚焦后 Tab 导航、Enter点击。安全该功能不引入新的安全问题。可靠性终端命令行输入与搜索框的键入必须隔离搜索框打开时不能阻塞命令行交互搜索框只占一行不会大量遮挡终端输出。兼容性不破坏 Terminal 现有功能。性能/功耗功能按需启动不影响 Terminal 整体性能。八、已知的边界问题窗口尺寸不足时的表现规格书明确记录了两个窗口尺寸相关的边界行为并给出了截图佐证窗口不够宽TextBox右侧的按钮会变不可见但TextBox本身仍可见且窗口不能比TextBox更窄。这与其它编辑器的行为类似![窗口宽度不足以完整显示搜索框时的表现](https://gitcode.com/GitHub_Trending/term/terminal/blob/20588130d8ef2ba40eb56bdae88e04cce7fc5b5d/doc/specs/?utm_sourcegitcode_repo_files#605 - Search/images/SearchBoxControlNoEnoughWidth.png)窗口不够高整个终端屏幕包括SearchBoxControl可能消失同样类似其它编辑器的行为。九、未来演进规格书规划的六项后续工作规格书把 Version 2 的候选工作列为六条并解释了每条被推迟的理由下拉菜单中的 Find 按钮让搜索可以纯鼠标操作。但由于可访问性并不强制要求第一阶段不做。从所有标签页搜索社区有此需求但可能要求对搜索算法做较大改动且不是高频场景放到后续阶段。实现思路是让 TerminalPage 或 App 持有SearchBoxControl并向其提供当前聚焦终端的文本缓冲区同时改造搜索算法。正则表达式匹配编辑器中常用的搜索模式但使用频率低于精确文本搜索放到后续。从源码看当前仓库的 SearchBoxControl.h 中已出现RegularExpression()、RegexButtonClicked以及ControlCore.idl中SearchRequest.RegularExpression字段说明这一项已经从未来计划走向了实现。搜索历史用户常重复相同搜索保存历史很有价值VS Code 尚未实现此能力未来可作为差异化亮点。输入时高亮Highlight while you type用描边或另一种颜色的选区标出缓冲区中所有其它命中提供被搜索文本的更清晰视图由于需要改动搜索与选区算法而推迟。从 Terminal.hpp 中的GetSearchHighlights()、GetSearchHighlightFocused()、SetSearchHighlights()与ScrollToSearchHighlight()等接口可以推断当前 TerminalCore 已具备维护全部命中 当前命中高亮集合的基础设施。尺寸手柄size handle部分编辑器允许用户调整搜索框大小搜索框左侧有手柄方便搜索长文本若社区有需要可加入。规格书还指出搜索功能分阶段的特性追踪由上游 open issue #3920 承担。十、在仓库中继续深入关键文件索引如果你想从本文继续深入源码建议按以下路径阅读关注点文件搜索框组件接口与事件Search/SearchChanged/Closedsrc/cascadia/TerminalControl/SearchBoxControl.h搜索框逻辑实现src/cascadia/TerminalControl/SearchBoxControl.cpp搜索框布局与样式src/cascadia/TerminalControl/SearchBoxControl.xamlCreateSearchBoxControl、SearchMatch、_handleSearchResults等调用链src/cascadia/TerminalControl/TermControl.cpp#L674-L830SearchRequest/SearchResults数据契约src/cascadia/TerminalControl/ControlCore.idl#L52-L69TerminalCore 侧的高亮与滚动接口src/cascadia/TerminalCore/Terminal.hpp#L216-L243原始设计文档doc/specs/#605 - Search/spec.md需要说明的是规格书写于 2019 年描述的是第一版单标签页、精确匹配的设计意图当前仓库中的实现已在其基础上扩展了正则匹配、命中计数状态与全量高亮等能力。以当前仓库实际代码为准上述规格书内容是理解为什么这样设计的最佳入口而TerminalControl与TerminalCore源码则是实际如何做到的证据。【免费下载链接】terminalThe new Windows Terminal and the original Windows console host, all in the same place!项目地址: https://gitcode.com/GitHub_Trending/term/terminal创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表