tasks: Add editor: Spawn Nearest Task
action (#19901)
This spawns the runnable task that that's closest to the cursor. One thing missing right now is that it doesn't find tasks that are attached to non-outline symbols, such as subtests in Go. Release Notes: - Added a new reveal option for tasks: `"no_focus"`. If used, the tasks terminal panel will be opened and shown, but not focused. - Added a new `editor: spawn nearest task` action that spawns the task with a run indicator icon nearest to the cursor. It can be configured to also use a `reveal` strategy. Example: ```json { "context": "EmptyPane || SharedScreen || vim_mode == normal", "bindings": { ", r t": ["editor::SpawnNearestTask", { "reveal": "no_focus" }], } } ``` Demo: https://github.com/user-attachments/assets/0d1818f0-7ae4-4200-8c3e-0ed47550c298 --------- Co-authored-by: Bennet <bennet@zed.dev>
This commit is contained in:
parent
633b665379
commit
293e080f03
8 changed files with 259 additions and 38 deletions
|
@ -13330,6 +13330,89 @@ async fn test_goto_definition_with_find_all_references_fallback(cx: &mut gpui::T
|
|||
});
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_find_enclosing_node_with_task(cx: &mut gpui::TestAppContext) {
|
||||
init_test(cx, |_| {});
|
||||
|
||||
let language = Arc::new(Language::new(
|
||||
LanguageConfig::default(),
|
||||
Some(tree_sitter_rust::LANGUAGE.into()),
|
||||
));
|
||||
|
||||
let text = r#"
|
||||
#[cfg(test)]
|
||||
mod tests() {
|
||||
#[test]
|
||||
fn runnable_1() {
|
||||
let a = 1;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn runnable_2() {
|
||||
let a = 1;
|
||||
let b = 2;
|
||||
}
|
||||
}
|
||||
"#
|
||||
.unindent();
|
||||
|
||||
let fs = FakeFs::new(cx.executor());
|
||||
fs.insert_file("/file.rs", Default::default()).await;
|
||||
|
||||
let project = Project::test(fs, ["/a".as_ref()], cx).await;
|
||||
let workspace = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
|
||||
let cx = &mut VisualTestContext::from_window(*workspace.deref(), cx);
|
||||
let buffer = cx.new_model(|cx| Buffer::local(text, cx).with_language(language, cx));
|
||||
let multi_buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer.clone(), cx));
|
||||
|
||||
let editor = cx.new_view(|cx| {
|
||||
Editor::new(
|
||||
EditorMode::Full,
|
||||
multi_buffer,
|
||||
Some(project.clone()),
|
||||
true,
|
||||
cx,
|
||||
)
|
||||
});
|
||||
|
||||
editor.update(cx, |editor, cx| {
|
||||
editor.tasks.insert(
|
||||
(buffer.read(cx).remote_id(), 3),
|
||||
RunnableTasks {
|
||||
templates: vec![],
|
||||
offset: MultiBufferOffset(43),
|
||||
column: 0,
|
||||
extra_variables: HashMap::default(),
|
||||
context_range: BufferOffset(43)..BufferOffset(85),
|
||||
},
|
||||
);
|
||||
editor.tasks.insert(
|
||||
(buffer.read(cx).remote_id(), 8),
|
||||
RunnableTasks {
|
||||
templates: vec![],
|
||||
offset: MultiBufferOffset(86),
|
||||
column: 0,
|
||||
extra_variables: HashMap::default(),
|
||||
context_range: BufferOffset(86)..BufferOffset(191),
|
||||
},
|
||||
);
|
||||
|
||||
// Test finding task when cursor is inside function body
|
||||
editor.change_selections(None, cx, |s| {
|
||||
s.select_ranges([Point::new(4, 5)..Point::new(4, 5)])
|
||||
});
|
||||
let (_, row, _) = editor.find_enclosing_node_task(cx).unwrap();
|
||||
assert_eq!(row, 3, "Should find task for cursor inside runnable_1");
|
||||
|
||||
// Test finding task when cursor is on function name
|
||||
editor.change_selections(None, cx, |s| {
|
||||
s.select_ranges([Point::new(8, 4)..Point::new(8, 4)])
|
||||
});
|
||||
let (_, row, _) = editor.find_enclosing_node_task(cx).unwrap();
|
||||
assert_eq!(row, 8, "Should find task when cursor is on function name");
|
||||
});
|
||||
}
|
||||
|
||||
fn empty_range(row: usize, column: usize) -> Range<DisplayPoint> {
|
||||
let point = DisplayPoint::new(DisplayRow(row as u32), column as u32);
|
||||
point..point
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue