create_buffer.rs

  1use anyhow::Result;
  2use assistant_tooling::{LanguageModelTool, ProjectContext, ToolOutput};
  3use editor::Editor;
  4use gpui::{prelude::*, Model, Task, View, WeakView};
  5use project::Project;
  6use schemars::JsonSchema;
  7use serde::Deserialize;
  8use ui::prelude::*;
  9use util::ResultExt;
 10use workspace::Workspace;
 11
 12pub struct CreateBufferTool {
 13    workspace: WeakView<Workspace>,
 14    project: Model<Project>,
 15}
 16
 17impl CreateBufferTool {
 18    pub fn new(workspace: WeakView<Workspace>, project: Model<Project>) -> Self {
 19        Self { workspace, project }
 20    }
 21}
 22
 23#[derive(Debug, Deserialize, JsonSchema)]
 24pub struct CreateBufferInput {
 25    /// The contents of the buffer.
 26    text: String,
 27
 28    /// The name of the language to use for the buffer.
 29    ///
 30    /// This should be a human-readable name, like "Rust", "JavaScript", or "Python".
 31    language: String,
 32}
 33
 34impl LanguageModelTool for CreateBufferTool {
 35    type Input = CreateBufferInput;
 36    type Output = ();
 37    type View = CreateBufferView;
 38
 39    fn name(&self) -> String {
 40        "create_buffer".to_string()
 41    }
 42
 43    fn description(&self) -> String {
 44        "Create a new buffer in the current codebase".to_string()
 45    }
 46
 47    fn execute(&self, input: &Self::Input, cx: &mut WindowContext) -> Task<Result<Self::Output>> {
 48        cx.spawn({
 49            let workspace = self.workspace.clone();
 50            let project = self.project.clone();
 51            let text = input.text.clone();
 52            let language_name = input.language.clone();
 53            |mut cx| async move {
 54                let language = cx
 55                    .update(|cx| {
 56                        project
 57                            .read(cx)
 58                            .languages()
 59                            .language_for_name(&language_name)
 60                    })?
 61                    .await?;
 62
 63                let buffer = cx
 64                    .update(|cx| project.update(cx, |project, cx| project.create_buffer(cx)))?
 65                    .await?;
 66
 67                buffer.update(&mut cx, |buffer, cx| {
 68                    buffer.edit([(0..0, text)], None, cx);
 69                    buffer.set_language(Some(language), cx)
 70                })?;
 71
 72                workspace
 73                    .update(&mut cx, |workspace, cx| {
 74                        workspace.add_item_to_active_pane(
 75                            Box::new(
 76                                cx.new_view(|cx| Editor::for_buffer(buffer, Some(project), cx)),
 77                            ),
 78                            None,
 79                            cx,
 80                        );
 81                    })
 82                    .log_err();
 83
 84                Ok(())
 85            }
 86        })
 87    }
 88
 89    fn view(
 90        &self,
 91        input: Self::Input,
 92        output: Result<Self::Output>,
 93        cx: &mut WindowContext,
 94    ) -> View<Self::View> {
 95        cx.new_view(|_cx| CreateBufferView {
 96            language: input.language,
 97            output,
 98        })
 99    }
100}
101
102pub struct CreateBufferView {
103    language: String,
104    output: Result<()>,
105}
106
107impl Render for CreateBufferView {
108    fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
109        div().child("Opening a buffer")
110    }
111}
112
113impl ToolOutput for CreateBufferView {
114    fn generate(&self, _: &mut ProjectContext, _: &mut WindowContext) -> String {
115        match &self.output {
116            Ok(_) => format!("Created a new {} buffer", self.language),
117            Err(err) => format!("Failed to create buffer: {err:?}"),
118        }
119    }
120}