## Issue
- [In file fuzzy search · Issue \#209 · tadashi\-aikawa/obsidian\-another\-quick\-switcher](https://github.com/tadashi-aikawa/obsidian-another-quick-switcher/issues/209)
## 先の展開
- 最終的には現在ファイル以外のファイルもターゲットに検索したい
- イメージとしては[[2 hop link]]や2世代先までの検索みたいな..
- 検索対象って大体今の[[ノート]]を起点に近しい箇所がいいからね
- ファイルの中身を読み込む必要があるから、ファイル数が増えるとfileio的な厳しさはありそう
- [[Backlink search]]が既にそんな感じだし...
- fileioなしで取得できるデータがあればいいんだけどなあ...
- core searchが持ってたりしそうだけど...
## TODO
- [x] 基本
- [x] コマンドをつくる
- [x] `In file search`
- [x] Noticeを一旦表示
- [x] showInFileFuzzyDialog
- [x] `InFileDialog`を作成する
- [x] suggestionItemを全部表示する
- [x] 入力で絞り込めるようにする
- [x] 前後2行くらいもあわせて表示できるようにする
- [x] ハイライトを追加する
- [x] hotkey設定を追加する
- [x] CSSを専用に置き換える
- [x] 枠線で区切った方がよさそう
- [x] タイトルは一回消す
- [x] 行番号の追加
- [x] 未入力のときのガイド
- [x] ブラッシュアップ
- [x] 検索ワードを残す
- [x] 前後表示行の設定
- [x] floatingを任意にする
- [x] 最後に選択したindexを記憶してカーソル位置を復元させる
- [-] setSelectedItemでscrollさせる
- scrollIntoViewだった
- [x] Minervaにかく
- [x] 第3引数のscrollは不要?
- [x] プレビューはショートカットキーでなく自動プレビュー切り替えのON/OFFにする
- [x] trimの設定を分離
- [x] 不具合?
- [x] ハイライトされた文字が出現しないことの調査
- [x] 前後の行がtrimされない
- [x] 正規表現のエスケープ
- [x] モバイルだとクリックしてもスクロールされない
- [x] モバイルでauto previewするとコマンドパレットのレイアウトが崩れる
- [*] プレビューしたあとに選択して移動するとスクロールしないことがある
- この件に限った話ではない気が.. プレビューと同じあたりだとスクロール不要と見なされてしまうのかな... (スクロールのstateが齟齬ある?)
- [-] より高い要求
- [-] 決定しなかったら元のスクロール位置に戻す
- 同一ファイル内ならそこまで難しくない気がする
- header searchはそれをやっていないから今はいらんかな...
- [-] ハイライトを単語単位にする
- 難しそう...
## offsetの調査
```
- [In file fuzzy search · Issue \#209 · tadashi\-aikawa/obsidian\-another\-quick\-switcher](https://github.com/tadashi-aikawa/obsidian-another-quick-switcher/issues/209)
```
```ts
.forEach(({ index, text }) => {
// index = 5, offset = 0
const before = restLine.slice(0, index - offset);
descriptionDiv.createSpan({
text: trimLineByEllipsis(
before,
this.settings.maxDisplayLengthAroundMatchedWord
),
});
descriptionDiv.createSpan({
text,
cls: "another-quick-switcher__hit_word",
});
// offset = 5 - 0 + 2 = 7
offset = index - offset + text.length;
// restLineの先頭7つを削除
restLine = restLine.slice(offset);
console.log(offset, restLine);
});
```
## 2回検索されてしまう問題
#2024/01/21 にデバッグONにしたら発覚。`Get suggestions`が2回表示される。
### 流れを追ってみる
`AnotherQuickSwitcherModal.ts`にログを仕込んで...
```ts
onOpen() {
console.log("👺super.onOpen start");
super.onOpen();
console.log("👺onOpen start");
if (this.command.floating) {
this.enableFloating();
}
this.inputEl.value = this.command.restoreLastInput
? this.initialInputQuery ?? globalInternalStorage.query
: this.initialInputQuery ?? "";
// Necessary to rerender suggestions
this.inputEl.dispatchEvent(new Event("input"));
this.inputEl.select();
if (this.stackHistory) {
this.navigationHistories.push({
inputQuery: this.inputEl.value,
command: { ...this.command },
originFile: this.originFile,
});
}
this.opened = true;
console.log("👺onOpen end");
}
```
```console
👺super.onOpen start
plugin:obsidian-another-quick-switcher:2891 Get suggestions: (File name search): 40[ms]
plugin:obsidian-another-quick-switcher:2963 👺onOpen start
plugin:obsidian-another-quick-switcher:2891 Get suggestions: (File name search): 6[ms]
plugin:obsidian-another-quick-switcher:2978 👺onOpen end
```
となるので
1. `super.onOpen` で一度検索が実行されている (おそらく初期値)
2. `onOpen` の `this.inputEl`に関する処理で二度目の検索が実行されている
もし `this.inputEl` が `super.onOpen` より前に生成されているなら、手前で実行してしまえば解決しそう。
```ts
onOpen() {
this.inputEl.value = this.command.restoreLastInput
? this.initialInputQuery ?? globalInternalStorage.query
: this.initialInputQuery ?? "";
super.onOpen();
```
これはダメだった... そこまで甘くはない。
### super.onOpenを呼び出さない
`onOpen`で`super.onOpen`の呼び出しをやめたところ、期待通り動作した... がこれはかなり危険な実装。リスクを承知で入れるべきは悩ましい。
`super.onOpen`の実装を少し見てみる。
```js
t.prototype.onOpen = function() {
var e = this.inputEl;
this.isOpen = !0,
e.value = "",
e.focus(),
this.updateSuggestions()
}
```
やっていることは
1. `this.isOpen = true`
2. `inputEl`の要素を **空にして** フォーカス
3. `this.updateSuggestions()` の呼び出し
この実装では外側で1度目の検索を制御できないはずだ。だが、この処理であれば多少のリスクの上、自前実装は可能。具体的には。
1. `super.isOpen = true`
2. `inputEl`の要素を **いい感じに入れて** セレクト
3. `super.updateSuggestions()` の呼び出し
でよい。すなわち
```ts
onOpen() {
// super.onOpen();
// WARN: Instead of super.onOpen()
this.isOpen = true;
this.inputEl.value = this.command.restoreLastInput
? this.initialInputQuery ?? globalInternalStorage.query
: this.initialInputQuery ?? "";
this.inputEl.select();
this.updateSuggestions();
```
### 速度比較
60~70秒が20~30秒になった。
![[Pasted image 20240121174402.png]]
*対応前*
![[Pasted image 20240121174505.png]]
*対応後*