tasks.rs

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