feat: 支持模糊搜索指令 - #573
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces a new word token search feature (分词搜索) that supports cross-word abbreviation matching. It includes a new tokenizer, a token search engine, a setting toggle in the general settings UI, and updated highlighting and sorting logic. The review feedback highlights several critical improvements: ensuring Vue's reactivity tracks the search setting correctly, resolving a highlighting misalignment bug for mixed pinyin/number queries by including digits in character position mapping, preventing a potential infinite loop in pinyin segmentation when encountering empty syllables, and adding defensive checks in the character classification function to handle undefined inputs.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| // 合并去重后仍居前,无需在此重复处理),然后按 token 档位排序。 | ||
| // 同档位内 tiebreaker:系统应用软加权 → 频率。 | ||
| // 开关 OFF: 旧比较器(完全匹配 → 前缀 → 系统应用 → 频率) | ||
| if (wordTokenEnabled) { |
There was a problem hiding this comment.
| function getChineseCharPositions(text: string): number[] { | ||
| const positions: number[] = [] | ||
| for (let i = 0; i < text.length; i++) { | ||
| const code = text.charCodeAt(i) | ||
| if ( | ||
| (code >= 0x4e00 && code <= 0x9fff) || | ||
| (code >= 0x3400 && code <= 0x4dbf) || | ||
| (code >= 0xf900 && code <= 0xfaff) | ||
| ) { | ||
| positions.push(i) | ||
| } | ||
| } | ||
| return positions | ||
| } |
There was a problem hiding this comment.
🔴 Critical Highlighting Alignment Bug\n\nIssue:\nThe getChineseCharPositions function only extracts the indices of Chinese characters. However, buildPinyinFields in commandDataStore.ts includes digits 0-9 in pinyinTokens to support mixed pinyin/number queries (e.g., "360极速" -> ['3', '6', '0', 'ji', 'su']).\n\nBecause digits are omitted from getChineseCharPositions, the mapped indices for pinyin matches containing numbers will be completely misaligned, leading to incorrect characters being highlighted (e.g., searching "360" on "360极速" highlights "极速" instead of "360").\n\nResolution:\nUpdate getChineseCharPositions to also include digits 0-9 (ASCII range 0x30 to 0x39) so that it aligns perfectly with the characters processed in pinyinTokens.
| function getChineseCharPositions(text: string): number[] { | |
| const positions: number[] = [] | |
| for (let i = 0; i < text.length; i++) { | |
| const code = text.charCodeAt(i) | |
| if ( | |
| (code >= 0x4e00 && code <= 0x9fff) || | |
| (code >= 0x3400 && code <= 0x4dbf) || | |
| (code >= 0xf900 && code <= 0xfaff) | |
| ) { | |
| positions.push(i) | |
| } | |
| } | |
| return positions | |
| } | |
| function getChineseCharPositions(text: string): number[] { | |
| const positions: number[] = [] | |
| for (let i = 0; i < text.length; i++) { | |
| const code = text.charCodeAt(i) | |
| if ( | |
| (code >= 0x4e00 && code <= 0x9fff) || | |
| (code >= 0x3400 && code <= 0x4dbf) || | |
| (code >= 0xf900 && code <= 0xfaff) || | |
| (code >= 0x30 && code <= 0x39) | |
| ) { | |
| positions.push(i) | |
| } | |
| } | |
| return positions | |
| } |
| for (let i = cursor; i < syllables.length; i++) { | ||
| const syl = syllables[i] |
There was a problem hiding this comment.
⚠️ Potential App-Freezing Infinite Loop\n\nIssue:\nIn segmentPinyin, if any element in syllables is empty or falsy, rest.startsWith(syl) will evaluate to true (since any string starts with ""), and qStart will be incremented by syl.length (which is 0). This results in an infinite loop that freezes the entire Electron application.\n\nResolution:\nAdd a defensive check if (!syl) continue at the beginning of the loop to skip empty syllables.
| for (let i = cursor; i < syllables.length; i++) { | |
| const syl = syllables[i] | |
| for (let i = cursor; i < syllables.length; i++) { | |
| const syl = syllables[i] | |
| if (!syl) continue |
| function classifyChar(ch: string): CharKind { | ||
| if (ch === ' ' || ch === '\t' || ch === '\n' || ch === '\r' || ch === '_' || ch === '-') | ||
| return 'separator' |
There was a problem hiding this comment.
Issue: If classifyChar is ever called with undefined or an empty string, ch.codePointAt(0) will throw a TypeError: Cannot read properties of undefined (reading 'codePointAt'). Adding a defensive check at the beginning of the function makes it robust against unexpected inputs.
| function classifyChar(ch: string): CharKind { | |
| if (ch === ' ' || ch === '\t' || ch === '\n' || ch === '\r' || ch === '_' || ch === '-') | |
| return 'separator' | |
| function classifyChar(ch: string | undefined): CharKind { | |
| if (!ch || ch === ' ' || ch === '\\t' || ch === '\\n' || ch === '\\r' || ch === '_' || ch === '-') | |
| return 'separator' |
|
|
3b6dd14 to
433330d
Compare
Issues
Closes #495
Related #462 #352
Changed
tas ma可以匹配Task Manager通用设置->搜索->分词模式:默认禁用。是否聚合模式使用分词搜索、列表模式二次排序使用分词算法。禁用则回退原算法通用设置->搜索->匹配单词内部:默认禁用,避免噪音。仅在分词算法启用时才显示。是否允许从非词首匹配,例如ps或shop命中Photoshop