Merge Zed task context providing logic (#10544)
Before, `tasks_ui` set most of the context with `SymbolContextProvider` providing the symbol data part of the context. Now, there's a `BasicContextProvider` that forms all standard Zed context and it automatically serves as a base, with no need for other providers like `RustContextProvider` to call it as before. Also, stop adding `SelectedText` task variable into the context for blank text selection. Release Notes: - N/A
This commit is contained in:
parent
97c5cffbe3
commit
573ba83034
5 changed files with 173 additions and 124 deletions
|
@ -1,12 +1,16 @@
|
|||
use std::{path::PathBuf, sync::Arc};
|
||||
use std::{
|
||||
path::{Path, PathBuf},
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use ::settings::Settings;
|
||||
use anyhow::Context;
|
||||
use editor::Editor;
|
||||
use gpui::{AppContext, ViewContext, WindowContext};
|
||||
use language::{Language, Point};
|
||||
use language::{BasicContextProvider, ContextProvider, Language};
|
||||
use modal::{Spawn, TasksModal};
|
||||
use project::{Location, TaskSourceKind, WorktreeId};
|
||||
use task::{ResolvedTask, TaskContext, TaskTemplate, TaskVariables, VariableName};
|
||||
use task::{ResolvedTask, TaskContext, TaskTemplate, TaskVariables};
|
||||
use util::ResultExt;
|
||||
use workspace::Workspace;
|
||||
|
||||
|
@ -146,100 +150,88 @@ fn active_item_selection_properties(
|
|||
}
|
||||
|
||||
fn task_context(workspace: &Workspace, cx: &mut WindowContext<'_>) -> TaskContext {
|
||||
let cwd = task_cwd(workspace, cx).log_err().flatten();
|
||||
let current_editor = workspace
|
||||
.active_item(cx)
|
||||
.and_then(|item| item.act_as::<Editor>(cx));
|
||||
if let Some(current_editor) = current_editor {
|
||||
(|| {
|
||||
let editor = current_editor.read(cx);
|
||||
fn task_context_impl(workspace: &Workspace, cx: &mut WindowContext<'_>) -> Option<TaskContext> {
|
||||
let cwd = task_cwd(workspace, cx).log_err().flatten();
|
||||
let editor = workspace
|
||||
.active_item(cx)
|
||||
.and_then(|item| item.act_as::<Editor>(cx))?;
|
||||
|
||||
let (selection, buffer, editor_snapshot) = editor.update(cx, |editor, cx| {
|
||||
let selection = editor.selections.newest::<usize>(cx);
|
||||
let (buffer, _, _) = editor
|
||||
.buffer()
|
||||
.read(cx)
|
||||
.point_to_buffer_offset(selection.start, cx)?;
|
||||
let snapshot = editor.snapshot(cx);
|
||||
Some((selection, buffer, snapshot))
|
||||
})?;
|
||||
let language_context_provider = buffer
|
||||
.read(cx)
|
||||
.language()
|
||||
.and_then(|language| language.context_provider())?;
|
||||
|
||||
current_editor.update(cx, |editor, cx| {
|
||||
let snapshot = editor.snapshot(cx);
|
||||
let selection_range = selection.range();
|
||||
let start = snapshot
|
||||
.display_snapshot
|
||||
.buffer_snapshot
|
||||
.anchor_after(selection_range.start)
|
||||
.text_anchor;
|
||||
let end = snapshot
|
||||
.display_snapshot
|
||||
.buffer_snapshot
|
||||
.anchor_after(selection_range.end)
|
||||
.text_anchor;
|
||||
let Point { row, column } = snapshot
|
||||
.display_snapshot
|
||||
.buffer_snapshot
|
||||
.offset_to_point(selection_range.start);
|
||||
let row = row + 1;
|
||||
let column = column + 1;
|
||||
let location = Location {
|
||||
buffer: buffer.clone(),
|
||||
range: start..end,
|
||||
};
|
||||
|
||||
let current_file = location
|
||||
.buffer
|
||||
let selection_range = selection.range();
|
||||
let start = editor_snapshot
|
||||
.display_snapshot
|
||||
.buffer_snapshot
|
||||
.anchor_after(selection_range.start)
|
||||
.text_anchor;
|
||||
let end = editor_snapshot
|
||||
.display_snapshot
|
||||
.buffer_snapshot
|
||||
.anchor_after(selection_range.end)
|
||||
.text_anchor;
|
||||
let worktree_abs_path = buffer
|
||||
.read(cx)
|
||||
.file()
|
||||
.map(|file| WorktreeId::from_usize(file.worktree_id()))
|
||||
.and_then(|worktree_id| {
|
||||
workspace
|
||||
.project()
|
||||
.read(cx)
|
||||
.file()
|
||||
.and_then(|file| file.as_local())
|
||||
.map(|file| file.abs_path(cx).to_string_lossy().to_string());
|
||||
let worktree_id = location
|
||||
.buffer
|
||||
.read(cx)
|
||||
.file()
|
||||
.map(|file| WorktreeId::from_usize(file.worktree_id()));
|
||||
let context = buffer
|
||||
.read(cx)
|
||||
.language()
|
||||
.and_then(|language| language.context_provider())
|
||||
.and_then(|provider| provider.build_context(location, cx).ok());
|
||||
|
||||
let worktree_path = worktree_id.and_then(|worktree_id| {
|
||||
workspace
|
||||
.project()
|
||||
.read(cx)
|
||||
.worktree_for_id(worktree_id, cx)
|
||||
.map(|worktree| worktree.read(cx).abs_path().to_string_lossy().to_string())
|
||||
});
|
||||
|
||||
let selected_text = buffer.read(cx).chars_for_range(selection_range).collect();
|
||||
|
||||
let mut task_variables = TaskVariables::from_iter([
|
||||
(VariableName::Row, row.to_string()),
|
||||
(VariableName::Column, column.to_string()),
|
||||
(VariableName::SelectedText, selected_text),
|
||||
]);
|
||||
if let Some(path) = current_file {
|
||||
task_variables.insert(VariableName::File, path);
|
||||
}
|
||||
if let Some(worktree_path) = worktree_path {
|
||||
task_variables.insert(VariableName::WorktreeRoot, worktree_path);
|
||||
}
|
||||
if let Some(language_context) = context {
|
||||
task_variables.extend(language_context);
|
||||
}
|
||||
|
||||
Some(TaskContext {
|
||||
cwd: cwd.clone(),
|
||||
task_variables,
|
||||
})
|
||||
})
|
||||
})()
|
||||
.unwrap_or_else(|| TaskContext {
|
||||
.worktree_for_id(worktree_id, cx)
|
||||
.map(|worktree| worktree.read(cx).abs_path())
|
||||
});
|
||||
let location = Location {
|
||||
buffer,
|
||||
range: start..end,
|
||||
};
|
||||
let task_variables = combine_task_variables(
|
||||
worktree_abs_path.as_deref(),
|
||||
location,
|
||||
language_context_provider.as_ref(),
|
||||
cx,
|
||||
)
|
||||
.log_err()?;
|
||||
Some(TaskContext {
|
||||
cwd,
|
||||
task_variables: Default::default(),
|
||||
task_variables,
|
||||
})
|
||||
}
|
||||
|
||||
task_context_impl(workspace, cx).unwrap_or_default()
|
||||
}
|
||||
|
||||
fn combine_task_variables(
|
||||
worktree_abs_path: Option<&Path>,
|
||||
location: Location,
|
||||
context_provider: &dyn ContextProvider,
|
||||
cx: &mut WindowContext<'_>,
|
||||
) -> anyhow::Result<TaskVariables> {
|
||||
if context_provider.is_basic() {
|
||||
context_provider
|
||||
.build_context(worktree_abs_path, &location, cx)
|
||||
.context("building basic provider context")
|
||||
} else {
|
||||
TaskContext {
|
||||
cwd,
|
||||
task_variables: Default::default(),
|
||||
}
|
||||
let mut basic_context = BasicContextProvider
|
||||
.build_context(worktree_abs_path, &location, cx)
|
||||
.context("building basic default context")?;
|
||||
basic_context.extend(
|
||||
context_provider
|
||||
.build_context(worktree_abs_path, &location, cx)
|
||||
.context("building provider context ")?,
|
||||
);
|
||||
Ok(basic_context)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -325,7 +317,7 @@ mod tests {
|
|||
|
||||
use editor::Editor;
|
||||
use gpui::{Entity, TestAppContext};
|
||||
use language::{Language, LanguageConfig, SymbolContextProvider};
|
||||
use language::{BasicContextProvider, Language, LanguageConfig};
|
||||
use project::{FakeFs, Project};
|
||||
use serde_json::json;
|
||||
use task::{TaskContext, TaskVariables, VariableName};
|
||||
|
@ -375,7 +367,7 @@ mod tests {
|
|||
name: (_) @name) @item"#,
|
||||
)
|
||||
.unwrap()
|
||||
.with_context_provider(Some(Arc::new(SymbolContextProvider))),
|
||||
.with_context_provider(Some(Arc::new(BasicContextProvider))),
|
||||
);
|
||||
|
||||
let typescript_language = Arc::new(
|
||||
|
@ -393,7 +385,7 @@ mod tests {
|
|||
")" @context)) @item"#,
|
||||
)
|
||||
.unwrap()
|
||||
.with_context_provider(Some(Arc::new(SymbolContextProvider))),
|
||||
.with_context_provider(Some(Arc::new(BasicContextProvider))),
|
||||
);
|
||||
let project = Project::test(fs, ["/dir".as_ref()], cx).await;
|
||||
let worktree_id = project.update(cx, |project, cx| {
|
||||
|
@ -435,7 +427,6 @@ mod tests {
|
|||
(VariableName::WorktreeRoot, "/dir".into()),
|
||||
(VariableName::Row, "1".into()),
|
||||
(VariableName::Column, "1".into()),
|
||||
(VariableName::SelectedText, "".into())
|
||||
])
|
||||
}
|
||||
);
|
||||
|
@ -469,7 +460,6 @@ mod tests {
|
|||
(VariableName::WorktreeRoot, "/dir".into()),
|
||||
(VariableName::Row, "1".into()),
|
||||
(VariableName::Column, "1".into()),
|
||||
(VariableName::SelectedText, "".into()),
|
||||
(VariableName::Symbol, "this_is_a_test".into()),
|
||||
])
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue