[[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");
});
});
}
```