
From now on, only top-level captures are treated as runnable tags and the rest is appended to task context as custom environmental variables (unless the name is prefixed with _, in which case the capture is ignored). This is most likely gonna help with Pest-like test runners. Release Notes: - N/A --------- Co-authored-by: Remco <djsmits12@gmail.com>
132 lines
3.9 KiB
Rust
132 lines
3.9 KiB
Rust
use crate::Editor;
|
|
|
|
use std::{path::Path, sync::Arc};
|
|
|
|
use anyhow::Context;
|
|
use gpui::WindowContext;
|
|
use language::{BasicContextProvider, ContextProvider};
|
|
use project::{Location, WorktreeId};
|
|
use task::{TaskContext, TaskVariables, VariableName};
|
|
use util::ResultExt;
|
|
use workspace::Workspace;
|
|
|
|
pub(crate) fn task_context_for_location(
|
|
workspace: &Workspace,
|
|
location: Location,
|
|
cx: &mut WindowContext<'_>,
|
|
) -> Option<TaskContext> {
|
|
let cwd = workspace::tasks::task_cwd(workspace, cx)
|
|
.log_err()
|
|
.flatten();
|
|
|
|
let buffer = location.buffer.clone();
|
|
let language_context_provider = buffer
|
|
.read(cx)
|
|
.language()
|
|
.and_then(|language| language.context_provider())
|
|
.unwrap_or_else(|| Arc::new(BasicContextProvider));
|
|
|
|
let worktree_abs_path = buffer
|
|
.read(cx)
|
|
.file()
|
|
.map(|file| WorktreeId::from_usize(file.worktree_id()))
|
|
.and_then(|worktree_id| {
|
|
workspace
|
|
.project()
|
|
.read(cx)
|
|
.worktree_for_id(worktree_id, cx)
|
|
.map(|worktree| worktree.read(cx).abs_path())
|
|
});
|
|
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,
|
|
})
|
|
}
|
|
|
|
pub(crate) fn task_context_with_editor(
|
|
workspace: &Workspace,
|
|
editor: &mut Editor,
|
|
cx: &mut WindowContext<'_>,
|
|
) -> Option<TaskContext> {
|
|
let (selection, buffer, editor_snapshot) = {
|
|
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 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 location = Location {
|
|
buffer,
|
|
range: start..end,
|
|
};
|
|
task_context_for_location(workspace, location.clone(), cx).map(|mut task_context| {
|
|
for range in location
|
|
.buffer
|
|
.read(cx)
|
|
.snapshot()
|
|
.runnable_ranges(location.range)
|
|
{
|
|
for (capture_name, value) in range.extra_captures {
|
|
task_context
|
|
.task_variables
|
|
.insert(VariableName::Custom(capture_name.into()), value);
|
|
}
|
|
}
|
|
task_context
|
|
})
|
|
}
|
|
|
|
pub fn task_context(workspace: &Workspace, cx: &mut WindowContext<'_>) -> TaskContext {
|
|
let Some(editor) = workspace
|
|
.active_item(cx)
|
|
.and_then(|item| item.act_as::<Editor>(cx))
|
|
else {
|
|
return Default::default();
|
|
};
|
|
editor.update(cx, |editor, cx| {
|
|
task_context_with_editor(workspace, editor, 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 {
|
|
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)
|
|
}
|
|
}
|