109 lines · 4.0 KB · Rust
RawDownload
use crate::slash_command::file_command::{FileCommandMetadata, FileSlashCommand};use anyhow::Result;use assistant_slash_command::{    ArgumentCompletion, SlashCommand, SlashCommandOutput, SlashCommandOutputSection,};use collections::HashSet;use futures::future;use gpui::{Task, WeakView, WindowContext};use language::{BufferSnapshot, LspAdapterDelegate};use std::sync::{atomic::AtomicBool, Arc};use text::OffsetRangeExt;use workspace::Workspace; pub(crate) struct DeltaSlashCommand; impl SlashCommand for DeltaSlashCommand {    fn name(&self) -> String {        "delta".into()    }     fn description(&self) -> String {        "re-insert changed files".into()    }     fn menu_text(&self) -> String {        "Re-insert Changed Files".into()    }     fn requires_argument(&self) -> bool {        false    }     fn complete_argument(        self: Arc<Self>,        _arguments: &[String],        _cancellation_flag: Arc<AtomicBool>,        _workspace: Option<WeakView<Workspace>>,        _cx: &mut WindowContext,    ) -> Task<Result<Vec<ArgumentCompletion>>> {        unimplemented!()    }     fn run(        self: Arc<Self>,        _arguments: &[String],        context_slash_command_output_sections: &[SlashCommandOutputSection<language::Anchor>],        context_buffer: BufferSnapshot,        workspace: WeakView<Workspace>,        delegate: Option<Arc<dyn LspAdapterDelegate>>,        cx: &mut WindowContext,    ) -> Task<Result<SlashCommandOutput>> {        let mut paths = HashSet::default();        let mut file_command_old_outputs = Vec::new();        let mut file_command_new_outputs = Vec::new();        for section in context_slash_command_output_sections.iter().rev() {            if let Some(metadata) = section                .metadata                .as_ref()                .and_then(|value| serde_json::from_value::<FileCommandMetadata>(value.clone()).ok())            {                if paths.insert(metadata.path.clone()) {                    file_command_old_outputs.push(                        context_buffer                            .as_rope()                            .slice(section.range.to_offset(&context_buffer)),                    );                    file_command_new_outputs.push(Arc::new(FileSlashCommand).run(                        &[metadata.path.clone()],                        context_slash_command_output_sections,                        context_buffer.clone(),                        workspace.clone(),                        delegate.clone(),                        cx,                    ));                }            }        }         cx.background_executor().spawn(async move {            let mut output = SlashCommandOutput::default();             let file_command_new_outputs = future::join_all(file_command_new_outputs).await;            for (old_text, new_output) in file_command_old_outputs                .into_iter()                .zip(file_command_new_outputs)            {                if let Ok(new_output) = new_output {                    if let Some(file_command_range) = new_output.sections.first() {                        let new_text = &new_output.text[file_command_range.range.clone()];                        if old_text.chars().ne(new_text.chars()) {                            output.sections.extend(new_output.sections.into_iter().map(                                |section| SlashCommandOutputSection {                                    range: output.text.len() + section.range.start                                        ..output.text.len() + section.range.end,                                    icon: section.icon,                                    label: section.label,                                    metadata: section.metadata,                                },                            ));                            output.text.push_str(&new_output.text);                        }                    }                }            }             Ok(output)        })    }}