Polish prompt library UX (#12647)

This could still use some improvement UI-wise but the user experience
should be a lot better.

- [x] Show in "Window" application menu
- [x] Load prompt as it's selected in the picker
- [x] Refocus picker on `esc`
- [x] When creating a new prompt, if a new prompt already exists and is
unedited, activate it instead
- [x] Add `/default` command
- [x] Evaluate /commands on prompt insertion
- [x] Autocomplete /commands (but don't evaluate) during prompt editing
- [x] Show token count using the settings model, right-aligned in the
editor
- [x] Picker 
- [x] Sorted alpha
- [x] 2 sublists
    - Default
        - Empty state: Star a prompt to add it to your default prompt
        - Otherwise show prompts with star on hover
    - All
        - Move prompts with star on hover

Release Notes:

- N/A
This commit is contained in:
Antonio Scandurra 2024-06-04 18:36:54 +02:00 committed by GitHub
parent e4bb666eab
commit c5b22eee2d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
22 changed files with 716 additions and 358 deletions

View file

@ -8,15 +8,7 @@ use std::sync::{atomic::AtomicBool, Arc};
use ui::{prelude::*, ButtonLike, ElevationIndex};
use workspace::Workspace;
pub(crate) struct PromptSlashCommand {
store: Arc<PromptStore>,
}
impl PromptSlashCommand {
pub fn new(store: Arc<PromptStore>) -> Self {
Self { store }
}
}
pub(crate) struct PromptSlashCommand;
impl SlashCommand for PromptSlashCommand {
fn name(&self) -> String {
@ -42,9 +34,9 @@ impl SlashCommand for PromptSlashCommand {
_workspace: WeakView<Workspace>,
cx: &mut AppContext,
) -> Task<Result<Vec<String>>> {
let store = self.store.clone();
let store = PromptStore::global(cx);
cx.background_executor().spawn(async move {
let prompts = store.search(query).await;
let prompts = store.await?.search(query).await;
Ok(prompts
.into_iter()
.filter_map(|prompt| Some(prompt.title?.to_string()))
@ -63,11 +55,12 @@ impl SlashCommand for PromptSlashCommand {
return Task::ready(Err(anyhow!("missing prompt name")));
};
let store = self.store.clone();
let store = PromptStore::global(cx);
let title = SharedString::from(title.to_string());
let prompt = cx.background_executor().spawn({
let title = title.clone();
async move {
let store = store.await?;
let prompt_id = store
.id_for_title(&title)
.with_context(|| format!("no prompt found with title {:?}", title))?;
@ -91,6 +84,7 @@ impl SlashCommand for PromptSlashCommand {
.into_any_element()
}),
}],
run_commands_in_text: true,
})
})
}