## 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]] *対応後*