mirror of
https://github.com/l0ng-ai/tty7.git
synced 2026-09-21 16:02:20 +00:00
fix(settings): a row you can see is a row search can find
The two halves of settings search did not agree on what matching means.
`row_matches_query` accepts a bare label match, so a row highlights on
its own title; `section_match_count` counts only `settings_search_entries`,
and that count is what drives the nav badges, `best_matching_section`,
and the "nothing matches" note.
Eleven rendered rows were missing from that index, and the result was not
merely that they failed to highlight. Typing a row's own title into the
box made the page answer that nothing matches it, with the row sitting
right there on screen — measured, not inferred:
"Interface font size" -> 0 matches
"Zoom with the wheel" -> 0 matches
"Skip banner" -> 0 matches
"Shell integration" -> 0 matches
"Import aliases" -> 0 matches
"Custom path" -> 0 matches
"Give each pane its own shell history" -> 0 matches
All eleven are indexed now, with keywords in the three locales. The SSH
profile form's distinctive rows are among them — someone searching for
"x11" or "proxyjump" is better served by landing on the SSH page than by
being told the feature does not exist. Its four bare field labels
("Name", "Host", "User", "Auth") stay out: each is one common word, and
a one-word entry would put a match on the SSH badge for half the queries
anyone types.
The guard is the durable half. It reads the rows out of this file's own
source, because a hand-kept list would need exactly the discipline the
index needs and would drift the same way — it could not catch the index
doing it. A second test holds the four exemptions to naming rows that
still exist, so renaming one cannot quietly widen the exemption to
nothing.
A label may resolve to more than one key: the blur row is "Background
material" on Windows and "Blur" elsewhere, and the index is `cfg`-gated
to match. So the guard asks whether *any* of a row's keys is indexed
rather than picking the branch the test binary was built for.
This commit is contained in:
@@ -118,6 +118,18 @@ pub fn translate_en(key: L10nKey) -> &'static str {
|
||||
L10nKey::SettingsLanguageEnglish => "English",
|
||||
L10nKey::SettingsLanguageChinese => "简体中文",
|
||||
L10nKey::SettingsLanguageJapanese => "日本語",
|
||||
L10nKey::SettingsSearchAgentForwardingKeywords => {
|
||||
"ssh agent forwarding key auth forward ForwardAgent"
|
||||
}
|
||||
L10nKey::SettingsSearchCustomShellPathKeywords => {
|
||||
"shell binary path executable custom login program"
|
||||
}
|
||||
L10nKey::SettingsSearchImportAliasesKeywords => {
|
||||
"ssh config alias host import openssh known hosts"
|
||||
}
|
||||
L10nKey::SettingsSearchJumpHostKeywords => {
|
||||
"ssh bastion proxyjump jump host tunnel gateway hop"
|
||||
}
|
||||
L10nKey::SettingsSearchLanguageKeywords => "language, locale, english, chinese",
|
||||
L10nKey::SettingsTransparency => "Transparency",
|
||||
L10nKey::SettingsOpacity => "Opacity",
|
||||
@@ -798,6 +810,9 @@ pub fn translate_en(key: L10nKey) -> &'static str {
|
||||
}
|
||||
L10nKey::SettingsSearchKeybindingsTitle => "Keybindings",
|
||||
L10nKey::SettingsSearchLineHeightKeywords => "typography leading spacing",
|
||||
L10nKey::SettingsSearchMouseZoomKeywords => {
|
||||
"wheel scroll zoom font size ctrl cmd modifier mouse"
|
||||
}
|
||||
L10nKey::SettingsSearchNewTabPositionKeywords => "tabs order end after current",
|
||||
L10nKey::SettingsSearchNotifyOnCommandFinishKeywords => {
|
||||
"notification alert done osc desktop banner long command"
|
||||
@@ -808,6 +823,9 @@ pub fn translate_en(key: L10nKey) -> &'static str {
|
||||
L10nKey::SettingsSearchOpacityKeywords => {
|
||||
"transparency translucent see through window alpha"
|
||||
}
|
||||
L10nKey::SettingsSearchOpenFilesCommandKeywords => {
|
||||
"link file open editor command external application click"
|
||||
}
|
||||
L10nKey::SettingsSearchOpenFilesWithKeywords => {
|
||||
"links file editor command external app path line column"
|
||||
}
|
||||
@@ -818,6 +836,9 @@ pub fn translate_en(key: L10nKey) -> &'static str {
|
||||
L10nKey::SettingsSearchOhMyPiKeywords => "agent integration extension install omp oh my pi",
|
||||
L10nKey::SettingsSearchGeminiKeywords => "agent integration hooks install gemini google",
|
||||
L10nKey::SettingsSearchDroidKeywords => "agent integration hooks install droid factory",
|
||||
L10nKey::SettingsSearchPerPaneHistoryKeywords => {
|
||||
"shell history per pane separate up arrow recall bash zsh"
|
||||
}
|
||||
L10nKey::SettingsSearchQwenCodeKeywords => {
|
||||
"agent integration hooks install qwen code qwen-code"
|
||||
}
|
||||
@@ -842,9 +863,18 @@ pub fn translate_en(key: L10nKey) -> &'static str {
|
||||
"restore session previous tabs splits reopen launch startup layout"
|
||||
}
|
||||
L10nKey::SettingsSearchScrollSpeedKeywords => "mouse wheel multiplier scrolling",
|
||||
L10nKey::SettingsSearchShellIntegrationKeywords => {
|
||||
"ssh remote shell integration rc bashrc zshrc prompt marks"
|
||||
}
|
||||
L10nKey::SettingsSearchSkipBannerKeywords => {
|
||||
"ssh login banner motd suppress quiet message of the day"
|
||||
}
|
||||
L10nKey::SettingsSearchSmoothScrollKeywords => {
|
||||
"smooth animation ease wheel notch trackpad scrolling"
|
||||
}
|
||||
L10nKey::SettingsSearchUiFontSizeKeywords => {
|
||||
"interface ui chrome sidebar tab settings text bigger smaller zoom scale"
|
||||
}
|
||||
L10nKey::SettingsSearchUpdateChannelKeywords => {
|
||||
"update channel stable nightly release prerelease build"
|
||||
}
|
||||
@@ -896,6 +926,9 @@ pub fn translate_en(key: L10nKey) -> &'static str {
|
||||
"ssh confirm close tab pane live session security"
|
||||
}
|
||||
L10nKey::SettingsSearchStartupWindowKeywords => "launch open maximized fullscreen normal",
|
||||
L10nKey::SettingsSearchX11ForwardingKeywords => {
|
||||
"ssh x11 forwarding display gui xquartz ForwardX11"
|
||||
}
|
||||
L10nKey::SwitcherNoMatch => "No workspace or machine matches.",
|
||||
L10nKey::AddSshHost => "Add SSH Host…",
|
||||
L10nKey::ClickForNewWindow => "click for a new window",
|
||||
|
||||
@@ -123,6 +123,18 @@ pub fn translate_ja(key: L10nKey) -> Option<&'static str> {
|
||||
L10nKey::SettingsLanguageEnglish => "English",
|
||||
L10nKey::SettingsLanguageChinese => "简体中文",
|
||||
L10nKey::SettingsLanguageJapanese => "日本語",
|
||||
L10nKey::SettingsSearchAgentForwardingKeywords => {
|
||||
"SSH エージェント転送 鍵転送 ssh agent forwarding key forward"
|
||||
}
|
||||
L10nKey::SettingsSearchCustomShellPathKeywords => {
|
||||
"シェル パス 実行ファイル ログインシェル shell binary path executable custom"
|
||||
}
|
||||
L10nKey::SettingsSearchImportAliasesKeywords => {
|
||||
"エイリアス取り込み SSH 設定 ホスト ssh config alias host import openssh"
|
||||
}
|
||||
L10nKey::SettingsSearchJumpHostKeywords => {
|
||||
"踏み台 ジャンプホスト 中継 ssh bastion proxyjump jump host gateway"
|
||||
}
|
||||
L10nKey::SettingsSearchLanguageKeywords => {
|
||||
"言語 ロケール 英語 中国語 language locale english chinese"
|
||||
}
|
||||
@@ -837,6 +849,9 @@ pub fn translate_ja(key: L10nKey) -> Option<&'static str> {
|
||||
L10nKey::SettingsSearchLineHeightKeywords => {
|
||||
"タイポグラフィ リーディング 行間 line height typography leading spacing"
|
||||
}
|
||||
L10nKey::SettingsSearchMouseZoomKeywords => {
|
||||
"ホイール ズーム 拡大 縮小 修飾キー wheel scroll zoom mouse font size modifier"
|
||||
}
|
||||
L10nKey::SettingsSearchNewTabPositionKeywords => {
|
||||
"タブ 順序 末尾 現在のタブの隣 new tab position tabs order end after current"
|
||||
}
|
||||
@@ -849,6 +864,9 @@ pub fn translate_ja(key: L10nKey) -> Option<&'static str> {
|
||||
L10nKey::SettingsSearchOpacityKeywords => {
|
||||
"透明度 半透明 透ける ウィンドウ alpha opacity transparency translucent window"
|
||||
}
|
||||
L10nKey::SettingsSearchOpenFilesCommandKeywords => {
|
||||
"ファイルを開く コマンド エディタ 外部アプリ リンク open file command editor external link"
|
||||
}
|
||||
L10nKey::SettingsSearchOpenFilesWithKeywords => {
|
||||
"リンク ファイル エディタ コマンド 外部アプリ パス 行 列 open files with editor external app path line column"
|
||||
}
|
||||
@@ -867,6 +885,9 @@ pub fn translate_ja(key: L10nKey) -> Option<&'static str> {
|
||||
L10nKey::SettingsSearchDroidKeywords => {
|
||||
"エージェント 統合 フック インストール droid factory agent integration hooks install"
|
||||
}
|
||||
L10nKey::SettingsSearchPerPaneHistoryKeywords => {
|
||||
"ペインごとの履歴 コマンド履歴 上矢印 bash zsh shell history per pane"
|
||||
}
|
||||
L10nKey::SettingsSearchQwenCodeKeywords => {
|
||||
"エージェント 統合 フック インストール qwen code agent integration hooks install"
|
||||
}
|
||||
@@ -897,9 +918,18 @@ pub fn translate_ja(key: L10nKey) -> Option<&'static str> {
|
||||
L10nKey::SettingsSearchScrollSpeedKeywords => {
|
||||
"マウス ホイール 倍率 スクロール scroll speed mouse wheel multiplier scrolling"
|
||||
}
|
||||
L10nKey::SettingsSearchShellIntegrationKeywords => {
|
||||
"シェル統合 リモート rc bashrc zshrc プロンプト shell integration remote"
|
||||
}
|
||||
L10nKey::SettingsSearchSkipBannerKeywords => {
|
||||
"バナー抑制 motd ログインメッセージ ssh login banner suppress quiet"
|
||||
}
|
||||
L10nKey::SettingsSearchSmoothScrollKeywords => {
|
||||
"スムーズ スクロール アニメーション ホイール トラックパッド smooth animation ease wheel trackpad"
|
||||
}
|
||||
L10nKey::SettingsSearchUiFontSizeKeywords => {
|
||||
"UI フォントサイズ インターフェイス 文字サイズ サイドバー タブ 拡大 縮小 interface ui font size text zoom"
|
||||
}
|
||||
L10nKey::SettingsSearchUpdateChannelKeywords => {
|
||||
"更新 チャンネル 安定版 ナイトリー リリース update channel stable nightly release"
|
||||
}
|
||||
@@ -957,6 +987,9 @@ pub fn translate_ja(key: L10nKey) -> Option<&'static str> {
|
||||
L10nKey::SettingsSearchStartupWindowKeywords => {
|
||||
"起動 開く 最大化 全画面 通常 startup window launch maximized fullscreen normal"
|
||||
}
|
||||
L10nKey::SettingsSearchX11ForwardingKeywords => {
|
||||
"X11 転送 GUI 転送 ディスプレイ ssh x11 forwarding display gui xquartz"
|
||||
}
|
||||
L10nKey::SwitcherNoMatch => "一致するワークスペースまたはマシンがありません",
|
||||
L10nKey::AddSshHost => "SSH ホストを追加…",
|
||||
L10nKey::ClickForNewWindow => "クリックで新しいウィンドウを開く",
|
||||
|
||||
@@ -179,6 +179,10 @@ l10n_keys! {
|
||||
SettingsLanguageEnglish,
|
||||
SettingsLanguageChinese,
|
||||
SettingsLanguageJapanese,
|
||||
SettingsSearchAgentForwardingKeywords,
|
||||
SettingsSearchCustomShellPathKeywords,
|
||||
SettingsSearchImportAliasesKeywords,
|
||||
SettingsSearchJumpHostKeywords,
|
||||
SettingsSearchLanguageKeywords,
|
||||
SettingsTransparency,
|
||||
SettingsOpacity,
|
||||
@@ -585,6 +589,12 @@ l10n_keys! {
|
||||
SettingsSearchAboutKeywords,
|
||||
SettingsSearchAutoDownloadKeywords,
|
||||
SettingsSearchCheckUpdatesOnLaunchKeywords,
|
||||
SettingsSearchMouseZoomKeywords,
|
||||
SettingsSearchOpenFilesCommandKeywords,
|
||||
SettingsSearchPerPaneHistoryKeywords,
|
||||
SettingsSearchShellIntegrationKeywords,
|
||||
SettingsSearchSkipBannerKeywords,
|
||||
SettingsSearchUiFontSizeKeywords,
|
||||
SettingsSearchUpdateChannelKeywords,
|
||||
SettingsSearchAnsiColorsKeywords,
|
||||
SettingsSearchBackgroundImageKeywords,
|
||||
@@ -652,6 +662,7 @@ l10n_keys! {
|
||||
SettingsSearchVerifyHostKeysKeywords,
|
||||
SettingsSearchWarnBeforeClosingKeywords,
|
||||
SettingsSearchStartupWindowKeywords,
|
||||
SettingsSearchX11ForwardingKeywords,
|
||||
SwitcherNoMatch,
|
||||
AddSshHost,
|
||||
ClickForNewWindow,
|
||||
|
||||
@@ -105,6 +105,18 @@ pub fn translate_zh(key: L10nKey) -> Option<&'static str> {
|
||||
L10nKey::SettingsLanguageEnglish => "English",
|
||||
L10nKey::SettingsLanguageChinese => "简体中文",
|
||||
L10nKey::SettingsLanguageJapanese => "日本語",
|
||||
L10nKey::SettingsSearchAgentForwardingKeywords => {
|
||||
"SSH agent 转发 密钥转发 代理转发 ssh agent forwarding key forward"
|
||||
}
|
||||
L10nKey::SettingsSearchCustomShellPathKeywords => {
|
||||
"自定义 shell 路径 可执行文件 登录程序 shell binary path executable custom"
|
||||
}
|
||||
L10nKey::SettingsSearchImportAliasesKeywords => {
|
||||
"导入别名 SSH 配置 主机别名 ssh config alias host import openssh"
|
||||
}
|
||||
L10nKey::SettingsSearchJumpHostKeywords => {
|
||||
"跳板机 堡垒机 中转 ssh bastion proxyjump jump host gateway"
|
||||
}
|
||||
L10nKey::SettingsSearchLanguageKeywords => {
|
||||
"语言 区域设置 英文 中文 language locale english chinese"
|
||||
}
|
||||
@@ -744,6 +756,9 @@ pub fn translate_zh(key: L10nKey) -> Option<&'static str> {
|
||||
L10nKey::SettingsSearchLineHeightKeywords => {
|
||||
"行高 行间距 行距 typography line height spacing leading"
|
||||
}
|
||||
L10nKey::SettingsSearchMouseZoomKeywords => {
|
||||
"滚轮缩放 鼠标缩放 字号 修饰键 wheel scroll zoom mouse font size modifier"
|
||||
}
|
||||
L10nKey::SettingsSearchNewTabPositionKeywords => {
|
||||
"新标签页位置 标签页 顺序 末尾 当前之后 new tab position tabs order end after current"
|
||||
}
|
||||
@@ -756,6 +771,9 @@ pub fn translate_zh(key: L10nKey) -> Option<&'static str> {
|
||||
L10nKey::SettingsSearchOpacityKeywords => {
|
||||
"不透明度 透明度 窗口 半透明 alpha opacity transparency translucent window"
|
||||
}
|
||||
L10nKey::SettingsSearchOpenFilesCommandKeywords => {
|
||||
"打开文件 命令 编辑器 外部程序 链接 open file command editor external link"
|
||||
}
|
||||
L10nKey::SettingsSearchOpenFilesWithKeywords => {
|
||||
"打开文件 链接 编辑器 命令 外部应用 路径 行号 列号 open files editor command path line column"
|
||||
}
|
||||
@@ -774,6 +792,9 @@ pub fn translate_zh(key: L10nKey) -> Option<&'static str> {
|
||||
L10nKey::SettingsSearchDroidKeywords => {
|
||||
"Droid agent 集成 钩子 安装 droid factory agent integration hooks install"
|
||||
}
|
||||
L10nKey::SettingsSearchPerPaneHistoryKeywords => {
|
||||
"每个窗格独立历史 命令历史 上方向键 bash zsh shell history per pane"
|
||||
}
|
||||
L10nKey::SettingsSearchQwenCodeKeywords => {
|
||||
"Qwen Code 通义千问 agent 集成 钩子 安装 qwen code agent integration hooks install"
|
||||
}
|
||||
@@ -804,9 +825,18 @@ pub fn translate_zh(key: L10nKey) -> Option<&'static str> {
|
||||
L10nKey::SettingsSearchScrollSpeedKeywords => {
|
||||
"滚动速度 鼠标滚轮 滚动倍率 scroll speed mouse wheel multiplier scrolling"
|
||||
}
|
||||
L10nKey::SettingsSearchShellIntegrationKeywords => {
|
||||
"Shell 集成 远程 rc 文件 bashrc zshrc 提示符标记 shell integration remote"
|
||||
}
|
||||
L10nKey::SettingsSearchSkipBannerKeywords => {
|
||||
"跳过登录横幅 motd 登录消息 静默 ssh login banner suppress quiet"
|
||||
}
|
||||
L10nKey::SettingsSearchSmoothScrollKeywords => {
|
||||
"平滑滚动 动画 缓动 滚轮 触控板 smooth animation ease wheel trackpad scrolling"
|
||||
}
|
||||
L10nKey::SettingsSearchUiFontSizeKeywords => {
|
||||
"界面字号 界面文字大小 侧边栏 标签页 缩放 interface ui font size text bigger smaller zoom"
|
||||
}
|
||||
L10nKey::SettingsSearchUpdateChannelKeywords => {
|
||||
"更新通道 稳定版 每夜构建 预发布 版本 update channel stable nightly release"
|
||||
}
|
||||
@@ -864,6 +894,9 @@ pub fn translate_zh(key: L10nKey) -> Option<&'static str> {
|
||||
L10nKey::SettingsSearchStartupWindowKeywords => {
|
||||
"启动窗口 启动 最大化 全屏 普通 startup window launch maximized fullscreen normal"
|
||||
}
|
||||
L10nKey::SettingsSearchX11ForwardingKeywords => {
|
||||
"X11 转发 图形转发 显示 ssh x11 forwarding display gui xquartz"
|
||||
}
|
||||
L10nKey::SwitcherNoMatch => "没有匹配的工作区或机器。",
|
||||
L10nKey::AddSshHost => "添加 SSH 主机…",
|
||||
L10nKey::ClickForNewWindow => "点击打开新窗口",
|
||||
|
||||
@@ -718,6 +718,61 @@ fn settings_search_entries() -> &'static [SearchEntry] {
|
||||
title: SettingsInstallCliOnPath,
|
||||
keywords: SettingsSearchCommandLineToolKeywords,
|
||||
},
|
||||
SearchEntry {
|
||||
section: Appearance,
|
||||
title: SettingsUiFontSize,
|
||||
keywords: SettingsSearchUiFontSizeKeywords,
|
||||
},
|
||||
SearchEntry {
|
||||
section: Terminal,
|
||||
title: SettingsCustomPath,
|
||||
keywords: SettingsSearchCustomShellPathKeywords,
|
||||
},
|
||||
SearchEntry {
|
||||
section: Terminal,
|
||||
title: SettingsMouseZoom,
|
||||
keywords: SettingsSearchMouseZoomKeywords,
|
||||
},
|
||||
SearchEntry {
|
||||
section: Terminal,
|
||||
title: SettingsOpenFilesCommand,
|
||||
keywords: SettingsSearchOpenFilesCommandKeywords,
|
||||
},
|
||||
SearchEntry {
|
||||
section: Input,
|
||||
title: SettingsPerPaneHistory,
|
||||
keywords: SettingsSearchPerPaneHistoryKeywords,
|
||||
},
|
||||
SearchEntry {
|
||||
section: Ssh,
|
||||
title: SettingsImportAliases,
|
||||
keywords: SettingsSearchImportAliasesKeywords,
|
||||
},
|
||||
SearchEntry {
|
||||
section: Ssh,
|
||||
title: SettingsJumpHost,
|
||||
keywords: SettingsSearchJumpHostKeywords,
|
||||
},
|
||||
SearchEntry {
|
||||
section: Ssh,
|
||||
title: SettingsAgentForwarding,
|
||||
keywords: SettingsSearchAgentForwardingKeywords,
|
||||
},
|
||||
SearchEntry {
|
||||
section: Ssh,
|
||||
title: SettingsX11Forwarding,
|
||||
keywords: SettingsSearchX11ForwardingKeywords,
|
||||
},
|
||||
SearchEntry {
|
||||
section: Ssh,
|
||||
title: SettingsShellIntegration,
|
||||
keywords: SettingsSearchShellIntegrationKeywords,
|
||||
},
|
||||
SearchEntry {
|
||||
section: Ssh,
|
||||
title: SettingsSkipBanner,
|
||||
keywords: SettingsSearchSkipBannerKeywords,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
@@ -8247,3 +8302,150 @@ mod gpui_tests {
|
||||
assert!(tab_completion, "the completion menu comes back with it");
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod search_index_tests {
|
||||
use super::*;
|
||||
|
||||
/// The label key of every row `settings.rs` can render, read out of its own
|
||||
/// source.
|
||||
///
|
||||
/// Reading the source rather than keeping a list by hand is the point: a
|
||||
/// list would need exactly the discipline the search index needs, and would
|
||||
/// fall out of date the same way, so it could not catch the index doing it.
|
||||
/// The label keys of every row `settings.rs` can render, read out of its
|
||||
/// own source — one entry per row, holding every key that row's label can
|
||||
/// resolve to.
|
||||
///
|
||||
/// Reading the source rather than keeping a list by hand is the point: a
|
||||
/// list would need exactly the discipline the search index needs, and would
|
||||
/// fall out of date the same way, so it could not catch the index doing it.
|
||||
///
|
||||
/// A label can name more than one key, because a few are chosen by
|
||||
/// `cfg!(target_os = ...)` — the blur row is "Background material" on
|
||||
/// Windows and "Blur" everywhere else. The index is gated the same way, so
|
||||
/// the caller asks whether *any* of a row's keys is indexed rather than
|
||||
/// picking the branch this build happens to be on.
|
||||
fn rendered_row_label_keys() -> Vec<Vec<String>> {
|
||||
const SOURCE: &str = include_str!("settings.rs");
|
||||
|
||||
fn keys_in(text: &str) -> Vec<String> {
|
||||
let mut out = Vec::new();
|
||||
let mut rest = text;
|
||||
while let Some(at) = rest.find("L10nKey::") {
|
||||
rest = &rest[at + "L10nKey::".len()..];
|
||||
let end = rest
|
||||
.find(|c: char| !c.is_alphanumeric() && c != '_')
|
||||
.unwrap_or(rest.len());
|
||||
out.push(rest[..end].to_string());
|
||||
rest = &rest[end..];
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
let mut rows = Vec::new();
|
||||
for call in ["self.settings_row(", "self.settings_row_gated_when("] {
|
||||
let mut from = 0;
|
||||
while let Some(at) = SOURCE[from..].find(call) {
|
||||
let start = from + at + call.len();
|
||||
from = start;
|
||||
// The label is the first argument. Stop at the comma that ends
|
||||
// it so the description's key cannot be read as the label's.
|
||||
let arg = &SOURCE[start..SOURCE.len().min(start + 400)];
|
||||
let arg = match arg.find(',') {
|
||||
Some(end) => &arg[..end],
|
||||
None => arg,
|
||||
};
|
||||
let keys = keys_in(arg);
|
||||
if keys.is_empty() {
|
||||
// A row labelled by a runtime string (an agent's display
|
||||
// name, a caller's `label`). Nothing static to index.
|
||||
continue;
|
||||
}
|
||||
rows.push(keys);
|
||||
}
|
||||
}
|
||||
assert!(
|
||||
rows.len() > 50,
|
||||
"the source scan found only {} rows, so it has stopped matching how \
|
||||
a row is written",
|
||||
rows.len()
|
||||
);
|
||||
rows
|
||||
}
|
||||
|
||||
/// Every settings row is reachable from the search box.
|
||||
///
|
||||
/// The two halves of search do not agree on their own: [`row_matches_query`]
|
||||
/// accepts a bare label match, while [`section_match_count`] — which drives
|
||||
/// the nav badges, [`best_matching_section`] and the "nothing matches" note
|
||||
/// — counts only the index. A row missing from the index is therefore not
|
||||
/// merely unhighlighted: typing its own title into the box makes the page
|
||||
/// answer that nothing matches, while the row sits there on screen. Seven
|
||||
/// rows did, including "Zoom with the wheel" and "Skip banner".
|
||||
///
|
||||
/// The fix is the index, not the count: a row's label is written for a
|
||||
/// reader, and the keywords are what carry the words they would actually
|
||||
/// reach for.
|
||||
#[test]
|
||||
fn every_rendered_settings_row_is_findable_by_its_own_label() {
|
||||
// Bare field labels inside the SSH profile form — "Name", "Host",
|
||||
// "User", "Auth". They are indexed nowhere on purpose: each is one
|
||||
// common word, and a one-word entry puts a match on the SSH badge for
|
||||
// half the queries anyone types. The distinctive rows of that same form
|
||||
// (jump host, agent forwarding, X11, shell integration, skip banner)
|
||||
// *are* indexed, so the form is reachable by the things it is actually
|
||||
// searched for.
|
||||
const BARE_FIELD_LABELS: &[&str] = &[
|
||||
"SettingsName",
|
||||
"SettingsHost",
|
||||
"SettingsUser",
|
||||
"SettingsAuth",
|
||||
];
|
||||
|
||||
// `L10nKey` is not `Hash`, and its `Debug` name is what the source scan
|
||||
// yields, so the index is compared as those names.
|
||||
let indexed: std::collections::HashSet<String> = settings_search_entries()
|
||||
.iter()
|
||||
.map(|e| format!("{:?}", e.title))
|
||||
.collect();
|
||||
|
||||
let mut missing: Vec<String> = rendered_row_label_keys()
|
||||
.into_iter()
|
||||
.filter(|keys| {
|
||||
!keys
|
||||
.iter()
|
||||
.any(|k| BARE_FIELD_LABELS.contains(&k.as_str()) || indexed.contains(k))
|
||||
})
|
||||
.map(|keys| keys.join(" or "))
|
||||
.collect();
|
||||
missing.sort();
|
||||
missing.dedup();
|
||||
|
||||
assert!(
|
||||
missing.is_empty(),
|
||||
"these settings rows are rendered but not in the search index, so \
|
||||
searching for one by name answers that nothing matches: {missing:?}"
|
||||
);
|
||||
}
|
||||
|
||||
/// The exemptions above name rows that exist.
|
||||
///
|
||||
/// Without this, renaming one of those keys would silently widen the
|
||||
/// exemption to nothing and take a row out of the guard with it.
|
||||
#[test]
|
||||
fn the_search_index_exemptions_still_name_rendered_rows() {
|
||||
let rendered = rendered_row_label_keys();
|
||||
for key in [
|
||||
"SettingsName",
|
||||
"SettingsHost",
|
||||
"SettingsUser",
|
||||
"SettingsAuth",
|
||||
] {
|
||||
assert!(
|
||||
rendered.iter().any(|keys| keys.iter().any(|k| k == key)),
|
||||
"{key} is exempt from the search index but no longer names a row"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user