tasks.rs

 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}