[[Customizable search commands]]を実装する。 ## 要件 - [ ] ユーザーは設定から独自コマンドを追加できる - [x] 可変長 (最大数はあってもいい) - 最大数はとりあえず未設定 - [x] 名前を設定できる - [x] 追加されたら裏側ではコマンドが追加される - 明示的にSaveボタンを使う - [ ] コマンドのHotkeysへジャンプできるコマンドを追加 - [x] コマンドを削除するボタンがある - [ ] ユーザーは独自コマンドに初期入力内容を指定できる - [x] 名前と並行して設定欄を設ける - [ ] ユーザーは独自コマンドにソート優先度を設定できる - [ ] 名前と並行して設定欄を設ける - まずは雑なUIでいいかも (複数行入力のフリーテキスト etc) ## 関連Issue [\[Feature Request\] User can create search command with predefined condition · Issue \#19](https://github.com/tadashi-aikawa/obsidian-another-quick-switcher/issues/19) ## メモ [[Templater]]の実装が参考になる。 https://github.com/SilentVoid13/Templater/blob/master/src/settings/Settings.ts#L73 - `addSearch`で設定に検索項目を追加できる - `addSearch((cb) => { new XXXSuggest(app, cb.inputEl) })`でサジェストを制御できる - 詳細は[FolderSuggester.ts](https://github.com/SilentVoid13/Templater/blob/097c7c0c99dc9f6932af6d44df9ebccfd995c4b3/src/settings/suggesters/FolderSuggester.ts#L6)の実装を参考に ### 設定の残骸 ```ts this.plugin.settings.searchCommands.forEach((command, i) => { const inputsDiv = createDiv(); const prioritiesDiv = createDiv(); const wrapperDiv = createDiv({ attr: { style: "display: flex" }, }); wrapperDiv.appendChild(inputsDiv); wrapperDiv.appendChild(prioritiesDiv); containerEl.appendChild(wrapperDiv); new Setting(inputsDiv).addText((tc) => { const el = tc .setPlaceholder("Command name") .setValue(command.name) .onChange(async (value) => { this.plugin.settings.searchCommands[i].name = value; }); el.inputEl.setAttribute("style", "text-align: left"); return el; }); new Setting(inputsDiv).addText((tc) => { const el = tc .setPlaceholder("Default input") .setValue(command.defaultInput) .onChange(async (value) => { this.plugin.settings.searchCommands[i].defaultInput = value; }); return el; }); new Setting(prioritiesDiv) .addTextArea((tc) => { const el = tc .setPlaceholder("Sort priority") .setValue(command.sortPriority.join("\n")) .onChange(async (value) => { const priorities = value.split("\n"); this.plugin.settings.searchCommands[i].sortPriority = priorities as SortPriority[]; }); el.inputEl.setAttribute("style", "height: 200px"); return el; }) .addExtraButton((btn) => { btn .setTooltip("Delete a command") .setIcon("cross") .onClick(() => { this.plugin.settings.searchCommands.remove(command); this.display(); }); }); containerEl.createEl("hr"); }); new Setting(containerEl) .addButton((btn) => { btn .setButtonText("Add a command") .setCta() .onClick(async (ev) => { this.plugin.settings.searchCommands.push({ name: "", defaultInput: "", sortPriority: [], }); this.display(); }); }) .addButton((btn) => { btn .setButtonText("Save") .setCta() .onClick(async (_) => { this.plugin.settings.searchCommands = this.plugin.settings.searchCommands.filter((x) => x.name); const invalidValues = this.plugin.settings.searchCommands .flatMap((x) => x.sortPriority) .filter((x) => !sortPriorityList.includes(x as SortPriority)); if (invalidValues.length > 0) { new Notice( ` Invalid sort priorities: ${invalidValues.map((x) => `- ${x}`).join("\n")} `.trim(), 0 ); return; } await this.plugin.saveSettings(); this.display(); this.plugin.reloadCommands(); new Notice("Save and reload commands"); }); }); } ```