Skip to content

Commit

Permalink
feat: add settings for case sensitivity, prefix matching and characte…
Browse files Browse the repository at this point in the history
…r fuzziness
  • Loading branch information
yan42685 committed Oct 26, 2024
1 parent 3d3c913 commit e052a19
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 6 deletions.
6 changes: 6 additions & 0 deletions src/globals/plugin-setting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ export class OuterSetting {
followObsidianExcludedFiles: boolean;
excludedPaths: string[]; // NOTE: can't use Set() or it will be a non-iterable object after deserialization
logLevel: LogLevel;
isCaseSensitive: boolean;
isPrefixMatch: boolean;
isCharacterFuzzyAllowed: boolean;
enableStopWordsEn: boolean;
enableChinesePatch: boolean;
enableStopWordsZh: boolean;
Expand All @@ -25,6 +28,9 @@ export const DEFAULT_OUTER_SETTING: OuterSetting = {
followObsidianExcludedFiles: true,
excludedPaths: [],
logLevel: isDevEnvironment ? "trace" : "info",
isCaseSensitive: false,
isPrefixMatch: true,
isCharacterFuzzyAllowed: true,
enableStopWordsEn: true,
// TODO: 繁体中文
enableChinesePatch: isChineseUser ? true : false,
Expand Down
22 changes: 22 additions & 0 deletions src/services/obsidian/setting-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,28 @@ class GeneralTab extends PluginSettingTab {
),
);

new Setting(containerEl).setName(t("Case sensitive")).addToggle((t) =>
t.setValue(this.setting.isCaseSensitive).onChange((v) => {
this.setting.isCaseSensitive = v;
this.settingManager.shouldReload = true;
}),
);
new Setting(containerEl)
.setName(t("Prefix match"))
.addToggle((t) =>
t
.setValue(this.setting.isPrefixMatch)
.onChange((v) => (this.setting.isPrefixMatch = v)),
);

new Setting(containerEl)
.setName(t("Character fuzzy allowed"))
.addToggle((t) =>
t
.setValue(this.setting.isCharacterFuzzyAllowed)
.onChange((v) => (this.setting.isCharacterFuzzyAllowed = v)),
);

new Setting(containerEl)
.setName(t("English word blacklist"))
.setDesc(t("English word blacklist desc"))
Expand Down
4 changes: 4 additions & 0 deletions src/services/obsidian/translations/locale/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ export default {
"Floating window for in-file search": "Floating window for in-file search",
"Floating window for in-file search desc": "Execute 'in-file search' command again will close the existing floating window. Disable this option to use classic modal UI",

"Case sensitive": "Case sensitive",
"Prefix match":"Prefix match",
"Character fuzzy allowed": "Character fuzzy allowed",

"English word blacklist": "English word blacklist",
"English word blacklist desc": `Exclude some meaningless English words like "do", "and", "them" from indexing, enhancing search and indexing speed. Modify the file at ${stopWordsEnTargetUrl} to tailor the list to your needs.`,
"Chinese patch": "Chinese patch",
Expand Down
4 changes: 4 additions & 0 deletions src/services/obsidian/translations/locale/zh-cn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ export default {
"Floating window for in-file search": "文件内搜索使用悬浮窗口 UI",
"Floating window for in-file search desc": "再次执行 '文件内搜索' 命令会关闭已有的悬浮窗口。关闭这个选项将使用模态框 UI",

"Case sensitive": "区分大小写",
"Prefix match":"单词前缀匹配",
"Character fuzzy allowed": "允许字符模糊",

"English word blacklist": "英文单词黑名单",
"English word blacklist desc": `建立索引时,忽略一些含义模糊的单词,比如 "do", "and", "them", 可以加快索引和搜索速度,但是这些单词不会被搜索到. 可以在 ${stopWordsEnTargetUrl} 按需修改单词黑名单`,
"Chinese patch": "中文搜索优化",
Expand Down
32 changes: 26 additions & 6 deletions src/services/search/lexical-engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import { TruncateOption, type TruncateType } from "./truncate-option";
@singleton()
export class LexicalEngine {
private option = getInstance(LexicalOptions);
private pluginSetting = getInstance(OuterSetting);
private outerSetting = getInstance(OuterSetting);
public filesIndex = new MiniSearch(this.option.fileIndexOption);
private linesIndex = new MiniSearch(this.option.lineIndexOption);
private tokenizer = getInstance(Tokenizer);
Expand Down Expand Up @@ -90,7 +90,7 @@ export class LexicalEngine {
selector: (item) => item.text,
});
return (await fzf.find(queryText))
.slice(0, this.pluginSetting.ui.maxItemResults)
.slice(0, this.outerSetting.ui.maxItemResults)
.map((entry: FzfResultItem<Line>) => {
return {
text: entry.item.text,
Expand All @@ -116,9 +116,9 @@ export class LexicalEngine {
query.text,
this.option.getFileSearchOption(combinationMode),
);
logger.debug(`maxFileItems: ${this.pluginSetting.ui.maxItemResults}`);
logger.debug(`maxFileItems: ${this.outerSetting.ui.maxItemResults}`);
return minisearchResult
.slice(0, this.pluginSetting.ui.maxItemResults)
.slice(0, this.outerSetting.ui.maxItemResults)
.map((item) => {
return {
path: item.id,
Expand Down Expand Up @@ -233,6 +233,7 @@ export class LexicalEngine {
@singleton()
class LexicalOptions {
// private readonly setting: SearchSetting = getInstance(OuterSetting).search;
private readonly outerSetting = getInstance(OuterSetting);
private readonly inSetting = innerSetting.search;
private readonly tokenizer = getInstance(Tokenizer);
private readonly tokenizeIndex = (text: string) =>
Expand All @@ -254,6 +255,9 @@ class LexicalOptions {
"content",
] as DocumentFields,
storeFields: ["tags"] as DocumentFields,
// will be applied when indexing and searching
processTerm: (term) =>
this.outerSetting.isCaseSensitive ? term : term.toLocaleLowerCase(),
};
readonly lineIndexOption: Options = {
tokenize: this.tokenizeIndex,
Expand All @@ -273,10 +277,16 @@ class LexicalOptions {
// TODO: for autosuggestion, we can choose to do a prefix match only when the term is
// at the last index of the query terms
prefix: (term) =>
term.length >= this.inSetting.minTermLengthForPrefixSearch,
this.outerSetting.isPrefixMatch
? term.length >= this.inSetting.minTermLengthForPrefixSearch
: false,
// TODO: fuzziness based on language
fuzzy: (term) =>
term.length <= 3 ? 0 : this.inSetting.fuzzyProportion,
this.outerSetting.isCharacterFuzzyAllowed
? term.length <= 3
? 0
: this.inSetting.fuzzyProportion
: false,
// if `fields` are omitted, all fields will be search with weight 1
boost: {
basename: this.inSetting.weightFilename,
Expand Down Expand Up @@ -504,3 +514,13 @@ class LinesMatcher {
});
}
}

class UserSearchOption {
public readonly isPrefixMatch: boolean;
public readonly isCharacterFuzzyAllowed: boolean;

constructor(isPrefixMatch: boolean, isCharacterFuzzyAllowed: boolean) {
this.isPrefixMatch = isPrefixMatch;
this.isCharacterFuzzyAllowed = isCharacterFuzzyAllowed;
}
}

0 comments on commit e052a19

Please sign in to comment.