1use crate::Editor;
2
3use gpui::{Task as AsyncTask, WindowContext};
4use project::Location;
5use task::{TaskContext, TaskVariables, VariableName};
6use text::{ToOffset, ToPoint};
7use workspace::Workspace;
8
9fn task_context_with_editor(
10 editor: &mut Editor,
11 cx: &mut WindowContext,
12) -> AsyncTask<Option<TaskContext>> {
13 let Some(project) = editor.project.clone() else {
14 return AsyncTask::ready(None);
15 };
16 let (selection, buffer, editor_snapshot) = {
17 let selection = editor.selections.newest_adjusted(cx);
18 let Some((buffer, _, _)) = editor
19 .buffer()
20 .read(cx)
21 .point_to_buffer_offset(selection.start, cx)
22 else {
23 return AsyncTask::ready(None);
24 };
25 let snapshot = editor.snapshot(cx);
26 (selection, buffer, snapshot)
27 };
28 let selection_range = selection.range();
29 let start = editor_snapshot
30 .display_snapshot
31 .buffer_snapshot
32 .anchor_after(selection_range.start)
33 .text_anchor;
34 let end = editor_snapshot
35 .display_snapshot
36 .buffer_snapshot
37 .anchor_after(selection_range.end)
38 .text_anchor;
39 let location = Location {
40 buffer,
41 range: start..end,
42 };
43 let captured_variables = {
44 let mut variables = TaskVariables::default();
45 let buffer = location.buffer.read(cx);
46 let buffer_id = buffer.remote_id();
47 let snapshot = buffer.snapshot();
48 let starting_point = location.range.start.to_point(&snapshot);
49 let starting_offset = starting_point.to_offset(&snapshot);
50 for (_, tasks) in editor
51 .tasks
52 .range((buffer_id, 0)..(buffer_id, starting_point.row + 1))
53 {
54 if !tasks
55 .context_range
56 .contains(&crate::BufferOffset(starting_offset))
57 {
58 continue;
59 }
60 for (capture_name, value) in tasks.extra_variables.iter() {
61 variables.insert(
62 VariableName::Custom(capture_name.to_owned().into()),
63 value.clone(),
64 );
65 }
66 }
67 variables
68 };
69
70 project.update(cx, |project, cx| {
71 project.task_store().update(cx, |task_store, cx| {
72 task_store.task_context_for_location(captured_variables, location, cx)
73 })
74 })
75}
76
77pub fn task_context(workspace: &Workspace, cx: &mut WindowContext) -> AsyncTask<TaskContext> {
78 let Some(editor) = workspace
79 .active_item(cx)
80 .and_then(|item| item.act_as::<Editor>(cx))
81 else {
82 return AsyncTask::ready(TaskContext::default());
83 };
84 editor.update(cx, |editor, cx| {
85 let context_task = task_context_with_editor(editor, cx);
86 cx.background_executor()
87 .spawn(async move { context_task.await.unwrap_or_default() })
88 })
89}