diff --git a/crates/acp_thread/src/mention.rs b/crates/acp_thread/src/mention.rs index 0f9c8ad36b..2c7c1ba437 100644 --- a/crates/acp_thread/src/mention.rs +++ b/crates/acp_thread/src/mention.rs @@ -180,7 +180,7 @@ pub struct MentionLink<'a>(&'a MentionUri); impl fmt::Display for MentionLink<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "[{}]({})", self.0.name(), self.0.to_uri()) + write!(f, "[@{}]({})", self.0.name(), self.0.to_uri()) } } diff --git a/crates/agent_ui/src/acp/completion_provider.rs b/crates/agent_ui/src/acp/completion_provider.rs index 519be85b0a..4259d53b50 100644 --- a/crates/agent_ui/src/acp/completion_provider.rs +++ b/crates/agent_ui/src/acp/completion_provider.rs @@ -1034,438 +1034,428 @@ impl MentionCompletion { } } -// #[cfg(test)] -// mod tests { -// use super::*; -// use editor::AnchorRangeExt; -// use gpui::{EventEmitter, FocusHandle, Focusable, TestAppContext, VisualTestContext}; -// use project::{Project, ProjectPath}; -// use serde_json::json; -// use settings::SettingsStore; -// use std::{ops::Deref, rc::Rc}; -// use util::path; -// use workspace::{AppState, Item}; +#[cfg(test)] +mod tests { + use super::*; + use editor::AnchorRangeExt; + use gpui::{EventEmitter, FocusHandle, Focusable, TestAppContext, VisualTestContext}; + use project::{Project, ProjectPath}; + use serde_json::json; + use settings::SettingsStore; + use std::{ops::Deref, rc::Rc}; + use util::path; + use workspace::{AppState, Item}; -// #[test] -// fn test_mention_completion_parse() { -// assert_eq!(MentionCompletion::try_parse("Lorem Ipsum", 0), None); + #[test] + fn test_mention_completion_parse() { + assert_eq!(MentionCompletion::try_parse("Lorem Ipsum", 0), None); -// assert_eq!( -// MentionCompletion::try_parse("Lorem @", 0), -// Some(MentionCompletion { -// source_range: 6..7, -// mode: None, -// argument: None, -// }) -// ); + assert_eq!( + MentionCompletion::try_parse("Lorem @", 0), + Some(MentionCompletion { + source_range: 6..7, + mode: None, + argument: None, + }) + ); -// assert_eq!( -// MentionCompletion::try_parse("Lorem @file", 0), -// Some(MentionCompletion { -// source_range: 6..11, -// mode: Some(ContextPickerMode::File), -// argument: None, -// }) -// ); + assert_eq!( + MentionCompletion::try_parse("Lorem @file", 0), + Some(MentionCompletion { + source_range: 6..11, + mode: Some(ContextPickerMode::File), + argument: None, + }) + ); -// assert_eq!( -// MentionCompletion::try_parse("Lorem @file ", 0), -// Some(MentionCompletion { -// source_range: 6..12, -// mode: Some(ContextPickerMode::File), -// argument: None, -// }) -// ); + assert_eq!( + MentionCompletion::try_parse("Lorem @file ", 0), + Some(MentionCompletion { + source_range: 6..12, + mode: Some(ContextPickerMode::File), + argument: None, + }) + ); -// assert_eq!( -// MentionCompletion::try_parse("Lorem @file main.rs", 0), -// Some(MentionCompletion { -// source_range: 6..19, -// mode: Some(ContextPickerMode::File), -// argument: Some("main.rs".to_string()), -// }) -// ); + assert_eq!( + MentionCompletion::try_parse("Lorem @file main.rs", 0), + Some(MentionCompletion { + source_range: 6..19, + mode: Some(ContextPickerMode::File), + argument: Some("main.rs".to_string()), + }) + ); -// assert_eq!( -// MentionCompletion::try_parse("Lorem @file main.rs ", 0), -// Some(MentionCompletion { -// source_range: 6..19, -// mode: Some(ContextPickerMode::File), -// argument: Some("main.rs".to_string()), -// }) -// ); + assert_eq!( + MentionCompletion::try_parse("Lorem @file main.rs ", 0), + Some(MentionCompletion { + source_range: 6..19, + mode: Some(ContextPickerMode::File), + argument: Some("main.rs".to_string()), + }) + ); -// assert_eq!( -// MentionCompletion::try_parse("Lorem @file main.rs Ipsum", 0), -// Some(MentionCompletion { -// source_range: 6..19, -// mode: Some(ContextPickerMode::File), -// argument: Some("main.rs".to_string()), -// }) -// ); + assert_eq!( + MentionCompletion::try_parse("Lorem @file main.rs Ipsum", 0), + Some(MentionCompletion { + source_range: 6..19, + mode: Some(ContextPickerMode::File), + argument: Some("main.rs".to_string()), + }) + ); -// assert_eq!( -// MentionCompletion::try_parse("Lorem @main", 0), -// Some(MentionCompletion { -// source_range: 6..11, -// mode: None, -// argument: Some("main".to_string()), -// }) -// ); + assert_eq!( + MentionCompletion::try_parse("Lorem @main", 0), + Some(MentionCompletion { + source_range: 6..11, + mode: None, + argument: Some("main".to_string()), + }) + ); -// assert_eq!(MentionCompletion::try_parse("test@", 0), None); -// } + assert_eq!(MentionCompletion::try_parse("test@", 0), None); + } -// struct AtMentionEditor(Entity); + struct AtMentionEditor(Entity); -// impl Item for AtMentionEditor { -// type Event = (); + impl Item for AtMentionEditor { + type Event = (); -// fn include_in_nav_history() -> bool { -// false -// } + fn include_in_nav_history() -> bool { + false + } -// fn tab_content_text(&self, _detail: usize, _cx: &App) -> SharedString { -// "Test".into() -// } -// } + fn tab_content_text(&self, _detail: usize, _cx: &App) -> SharedString { + "Test".into() + } + } -// impl EventEmitter<()> for AtMentionEditor {} + impl EventEmitter<()> for AtMentionEditor {} -// impl Focusable for AtMentionEditor { -// fn focus_handle(&self, cx: &App) -> FocusHandle { -// self.0.read(cx).focus_handle(cx).clone() -// } -// } + impl Focusable for AtMentionEditor { + fn focus_handle(&self, cx: &App) -> FocusHandle { + self.0.read(cx).focus_handle(cx).clone() + } + } -// impl Render for AtMentionEditor { -// fn render(&mut self, _window: &mut Window, _cx: &mut Context) -> impl IntoElement { -// self.0.clone().into_any_element() -// } -// } + impl Render for AtMentionEditor { + fn render(&mut self, _window: &mut Window, _cx: &mut Context) -> impl IntoElement { + self.0.clone().into_any_element() + } + } -// #[gpui::test] -// async fn test_context_completion_provider(cx: &mut TestAppContext) { -// init_test(cx); + #[gpui::test] + async fn test_context_completion_provider(cx: &mut TestAppContext) { + init_test(cx); -// let app_state = cx.update(AppState::test); + let app_state = cx.update(AppState::test); -// cx.update(|cx| { -// language::init(cx); -// editor::init(cx); -// workspace::init(app_state.clone(), cx); -// Project::init_settings(cx); -// }); + cx.update(|cx| { + language::init(cx); + editor::init(cx); + workspace::init(app_state.clone(), cx); + Project::init_settings(cx); + }); -// app_state -// .fs -// .as_fake() -// .insert_tree( -// path!("/dir"), -// json!({ -// "editor": "", -// "a": { -// "one.txt": "", -// "two.txt": "", -// "three.txt": "", -// "four.txt": "" -// }, -// "b": { -// "five.txt": "", -// "six.txt": "", -// "seven.txt": "", -// "eight.txt": "", -// } -// }), -// ) -// .await; + app_state + .fs + .as_fake() + .insert_tree( + path!("/dir"), + json!({ + "editor": "", + "a": { + "one.txt": "", + "two.txt": "", + "three.txt": "", + "four.txt": "" + }, + "b": { + "five.txt": "", + "six.txt": "", + "seven.txt": "", + "eight.txt": "", + } + }), + ) + .await; -// let project = Project::test(app_state.fs.clone(), [path!("/dir").as_ref()], cx).await; -// let window = cx.add_window(|window, cx| Workspace::test_new(project.clone(), window, cx)); -// let workspace = window.root(cx).unwrap(); + let project = Project::test(app_state.fs.clone(), [path!("/dir").as_ref()], cx).await; + let window = cx.add_window(|window, cx| Workspace::test_new(project.clone(), window, cx)); + let workspace = window.root(cx).unwrap(); -// let worktree = project.update(cx, |project, cx| { -// let mut worktrees = project.worktrees(cx).collect::>(); -// assert_eq!(worktrees.len(), 1); -// worktrees.pop().unwrap() -// }); -// let worktree_id = worktree.read_with(cx, |worktree, _| worktree.id()); + let worktree = project.update(cx, |project, cx| { + let mut worktrees = project.worktrees(cx).collect::>(); + assert_eq!(worktrees.len(), 1); + worktrees.pop().unwrap() + }); + let worktree_id = worktree.read_with(cx, |worktree, _| worktree.id()); -// let mut cx = VisualTestContext::from_window(*window.deref(), cx); + let mut cx = VisualTestContext::from_window(*window.deref(), cx); -// let paths = vec![ -// path!("a/one.txt"), -// path!("a/two.txt"), -// path!("a/three.txt"), -// path!("a/four.txt"), -// path!("b/five.txt"), -// path!("b/six.txt"), -// path!("b/seven.txt"), -// path!("b/eight.txt"), -// ]; + let paths = vec![ + path!("a/one.txt"), + path!("a/two.txt"), + path!("a/three.txt"), + path!("a/four.txt"), + path!("b/five.txt"), + path!("b/six.txt"), + path!("b/seven.txt"), + path!("b/eight.txt"), + ]; -// let mut opened_editors = Vec::new(); -// for path in paths { -// let buffer = workspace -// .update_in(&mut cx, |workspace, window, cx| { -// workspace.open_path( -// ProjectPath { -// worktree_id, -// path: Path::new(path).into(), -// }, -// None, -// false, -// window, -// cx, -// ) -// }) -// .await -// .unwrap(); -// opened_editors.push(buffer); -// } + let mut opened_editors = Vec::new(); + for path in paths { + let buffer = workspace + .update_in(&mut cx, |workspace, window, cx| { + workspace.open_path( + ProjectPath { + worktree_id, + path: Path::new(path).into(), + }, + None, + false, + window, + cx, + ) + }) + .await + .unwrap(); + opened_editors.push(buffer); + } -// let editor = workspace.update_in(&mut cx, |workspace, window, cx| { -// let editor = cx.new(|cx| { -// Editor::new( -// editor::EditorMode::full(), -// multi_buffer::MultiBuffer::build_simple("", cx), -// None, -// window, -// cx, -// ) -// }); -// workspace.active_pane().update(cx, |pane, cx| { -// pane.add_item( -// Box::new(cx.new(|_| AtMentionEditor(editor.clone()))), -// true, -// true, -// None, -// window, -// cx, -// ); -// }); -// editor -// }); + let editor = workspace.update_in(&mut cx, |workspace, window, cx| { + let editor = cx.new(|cx| { + Editor::new( + editor::EditorMode::full(), + multi_buffer::MultiBuffer::build_simple("", cx), + None, + window, + cx, + ) + }); + workspace.active_pane().update(cx, |pane, cx| { + pane.add_item( + Box::new(cx.new(|_| AtMentionEditor(editor.clone()))), + true, + true, + None, + window, + cx, + ); + }); + editor + }); -// let context_store = cx.new(|_| ContextStore::new(project.downgrade(), None)); + let mention_set = Arc::new(Mutex::new(MentionSet::default())); -// let editor_entity = editor.downgrade(); -// editor.update_in(&mut cx, |editor, window, cx| { -// let last_opened_buffer = opened_editors.last().and_then(|editor| { -// editor -// .downcast::()? -// .read(cx) -// .buffer() -// .read(cx) -// .as_singleton() -// .as_ref() -// .map(Entity::downgrade) -// }); -// window.focus(&editor.focus_handle(cx)); -// editor.set_completion_provider(Some(Rc::new(ContextPickerCompletionProvider::new( -// workspace.downgrade(), -// context_store.downgrade(), -// None, -// None, -// editor_entity, -// last_opened_buffer, -// )))); -// }); + let editor_entity = editor.downgrade(); + editor.update_in(&mut cx, |editor, window, cx| { + window.focus(&editor.focus_handle(cx)); + editor.set_completion_provider(Some(Rc::new(ContextPickerCompletionProvider::new( + mention_set.clone(), + workspace.downgrade(), + WeakEntity::new_invalid(), + WeakEntity::new_invalid(), + editor_entity, + )))); + }); -// cx.simulate_input("Lorem "); + cx.simulate_input("Lorem "); -// editor.update(&mut cx, |editor, cx| { -// assert_eq!(editor.text(cx), "Lorem "); -// assert!(!editor.has_visible_completions_menu()); -// }); + editor.update(&mut cx, |editor, cx| { + assert_eq!(editor.text(cx), "Lorem "); + assert!(!editor.has_visible_completions_menu()); + }); -// cx.simulate_input("@"); + cx.simulate_input("@"); -// editor.update(&mut cx, |editor, cx| { -// assert_eq!(editor.text(cx), "Lorem @"); -// assert!(editor.has_visible_completions_menu()); -// assert_eq!( -// current_completion_labels(editor), -// &[ -// "seven.txt dir/b/", -// "six.txt dir/b/", -// "five.txt dir/b/", -// "four.txt dir/a/", -// "Files & Directories", -// "Symbols", -// "Fetch" -// ] -// ); -// }); + editor.update(&mut cx, |editor, cx| { + assert_eq!(editor.text(cx), "Lorem @"); + assert!(editor.has_visible_completions_menu()); + assert_eq!( + current_completion_labels(editor), + &[ + "eight.txt dir/b/", + "seven.txt dir/b/", + "six.txt dir/b/", + "five.txt dir/b/", + "Files & Directories", + "Symbols", + "Threads", + "Fetch" + ] + ); + }); -// // Select and confirm "File" -// editor.update_in(&mut cx, |editor, window, cx| { -// assert!(editor.has_visible_completions_menu()); -// editor.context_menu_next(&editor::actions::ContextMenuNext, window, cx); -// editor.context_menu_next(&editor::actions::ContextMenuNext, window, cx); -// editor.context_menu_next(&editor::actions::ContextMenuNext, window, cx); -// editor.context_menu_next(&editor::actions::ContextMenuNext, window, cx); -// editor.confirm_completion(&editor::actions::ConfirmCompletion::default(), window, cx); -// }); + // Select and confirm "File" + editor.update_in(&mut cx, |editor, window, cx| { + assert!(editor.has_visible_completions_menu()); + editor.context_menu_next(&editor::actions::ContextMenuNext, window, cx); + editor.context_menu_next(&editor::actions::ContextMenuNext, window, cx); + editor.context_menu_next(&editor::actions::ContextMenuNext, window, cx); + editor.context_menu_next(&editor::actions::ContextMenuNext, window, cx); + editor.confirm_completion(&editor::actions::ConfirmCompletion::default(), window, cx); + }); -// cx.run_until_parked(); + cx.run_until_parked(); -// editor.update(&mut cx, |editor, cx| { -// assert_eq!(editor.text(cx), "Lorem @file "); -// assert!(editor.has_visible_completions_menu()); -// }); + editor.update(&mut cx, |editor, cx| { + assert_eq!(editor.text(cx), "Lorem @file "); + assert!(editor.has_visible_completions_menu()); + }); -// cx.simulate_input("one"); + cx.simulate_input("one"); -// editor.update(&mut cx, |editor, cx| { -// assert_eq!(editor.text(cx), "Lorem @file one"); -// assert!(editor.has_visible_completions_menu()); -// assert_eq!(current_completion_labels(editor), vec!["one.txt dir/a/"]); -// }); + editor.update(&mut cx, |editor, cx| { + assert_eq!(editor.text(cx), "Lorem @file one"); + assert!(editor.has_visible_completions_menu()); + assert_eq!(current_completion_labels(editor), vec!["one.txt dir/a/"]); + }); -// editor.update_in(&mut cx, |editor, window, cx| { -// assert!(editor.has_visible_completions_menu()); -// editor.confirm_completion(&editor::actions::ConfirmCompletion::default(), window, cx); -// }); + editor.update_in(&mut cx, |editor, window, cx| { + assert!(editor.has_visible_completions_menu()); + editor.confirm_completion(&editor::actions::ConfirmCompletion::default(), window, cx); + }); -// editor.update(&mut cx, |editor, cx| { -// assert_eq!(editor.text(cx), "Lorem [@one.txt](@file:dir/a/one.txt) "); -// assert!(!editor.has_visible_completions_menu()); -// assert_eq!( -// fold_ranges(editor, cx), -// vec![Point::new(0, 6)..Point::new(0, 37)] -// ); -// }); + editor.update(&mut cx, |editor, cx| { + assert_eq!(editor.text(cx), "Lorem [@one.txt](file:///dir/a/one.txt) "); + assert!(!editor.has_visible_completions_menu()); + assert_eq!( + fold_ranges(editor, cx), + vec![Point::new(0, 6)..Point::new(0, 39)] + ); + }); -// cx.simulate_input(" "); + cx.simulate_input(" "); -// editor.update(&mut cx, |editor, cx| { -// assert_eq!(editor.text(cx), "Lorem [@one.txt](@file:dir/a/one.txt) "); -// assert!(!editor.has_visible_completions_menu()); -// assert_eq!( -// fold_ranges(editor, cx), -// vec![Point::new(0, 6)..Point::new(0, 37)] -// ); -// }); + editor.update(&mut cx, |editor, cx| { + assert_eq!(editor.text(cx), "Lorem [@one.txt](file:///dir/a/one.txt) "); + assert!(!editor.has_visible_completions_menu()); + assert_eq!( + fold_ranges(editor, cx), + vec![Point::new(0, 6)..Point::new(0, 39)] + ); + }); -// cx.simulate_input("Ipsum "); + cx.simulate_input("Ipsum "); -// editor.update(&mut cx, |editor, cx| { -// assert_eq!( -// editor.text(cx), -// "Lorem [@one.txt](@file:dir/a/one.txt) Ipsum ", -// ); -// assert!(!editor.has_visible_completions_menu()); -// assert_eq!( -// fold_ranges(editor, cx), -// vec![Point::new(0, 6)..Point::new(0, 37)] -// ); -// }); + editor.update(&mut cx, |editor, cx| { + assert_eq!( + editor.text(cx), + "Lorem [@one.txt](file:///dir/a/one.txt) Ipsum ", + ); + assert!(!editor.has_visible_completions_menu()); + assert_eq!( + fold_ranges(editor, cx), + vec![Point::new(0, 6)..Point::new(0, 39)] + ); + }); -// cx.simulate_input("@file "); + cx.simulate_input("@file "); -// editor.update(&mut cx, |editor, cx| { -// assert_eq!( -// editor.text(cx), -// "Lorem [@one.txt](@file:dir/a/one.txt) Ipsum @file ", -// ); -// assert!(editor.has_visible_completions_menu()); -// assert_eq!( -// fold_ranges(editor, cx), -// vec![Point::new(0, 6)..Point::new(0, 37)] -// ); -// }); + editor.update(&mut cx, |editor, cx| { + assert_eq!( + editor.text(cx), + "Lorem [@one.txt](file:///dir/a/one.txt) Ipsum @file ", + ); + assert!(editor.has_visible_completions_menu()); + assert_eq!( + fold_ranges(editor, cx), + vec![Point::new(0, 6)..Point::new(0, 39)] + ); + }); -// editor.update_in(&mut cx, |editor, window, cx| { -// editor.confirm_completion(&editor::actions::ConfirmCompletion::default(), window, cx); -// }); + editor.update_in(&mut cx, |editor, window, cx| { + editor.confirm_completion(&editor::actions::ConfirmCompletion::default(), window, cx); + }); -// cx.run_until_parked(); + cx.run_until_parked(); -// editor.update(&mut cx, |editor, cx| { -// assert_eq!( -// editor.text(cx), -// "Lorem [@one.txt](@file:dir/a/one.txt) Ipsum [@seven.txt](@file:dir/b/seven.txt) " -// ); -// assert!(!editor.has_visible_completions_menu()); -// assert_eq!( -// fold_ranges(editor, cx), -// vec![ -// Point::new(0, 6)..Point::new(0, 37), -// Point::new(0, 45)..Point::new(0, 80) -// ] -// ); -// }); + editor.update(&mut cx, |editor, cx| { + assert_eq!( + editor.text(cx), + "Lorem [@one.txt](file:///dir/a/one.txt) Ipsum [@eight.txt](file:///dir/b/eight.txt) " + ); + assert!(!editor.has_visible_completions_menu()); + assert_eq!( + fold_ranges(editor, cx), + vec![ + Point::new(0, 6)..Point::new(0, 39), + Point::new(0, 47)..Point::new(0, 84) + ] + ); + }); -// cx.simulate_input("\n@"); + cx.simulate_input("\n@"); -// editor.update(&mut cx, |editor, cx| { -// assert_eq!( -// editor.text(cx), -// "Lorem [@one.txt](@file:dir/a/one.txt) Ipsum [@seven.txt](@file:dir/b/seven.txt) \n@" -// ); -// assert!(editor.has_visible_completions_menu()); -// assert_eq!( -// fold_ranges(editor, cx), -// vec![ -// Point::new(0, 6)..Point::new(0, 37), -// Point::new(0, 45)..Point::new(0, 80) -// ] -// ); -// }); + editor.update(&mut cx, |editor, cx| { + assert_eq!( + editor.text(cx), + "Lorem [@one.txt](file:///dir/a/one.txt) Ipsum [@eight.txt](file:///dir/b/eight.txt) \n@" + ); + assert!(editor.has_visible_completions_menu()); + assert_eq!( + fold_ranges(editor, cx), + vec![ + Point::new(0, 6)..Point::new(0, 39), + Point::new(0, 47)..Point::new(0, 84) + ] + ); + }); -// editor.update_in(&mut cx, |editor, window, cx| { -// editor.confirm_completion(&editor::actions::ConfirmCompletion::default(), window, cx); -// }); + editor.update_in(&mut cx, |editor, window, cx| { + editor.confirm_completion(&editor::actions::ConfirmCompletion::default(), window, cx); + }); -// cx.run_until_parked(); + cx.run_until_parked(); -// editor.update(&mut cx, |editor, cx| { -// assert_eq!( -// editor.text(cx), -// "Lorem [@one.txt](@file:dir/a/one.txt) Ipsum [@seven.txt](@file:dir/b/seven.txt) \n[@six.txt](@file:dir/b/six.txt) " -// ); -// assert!(!editor.has_visible_completions_menu()); -// assert_eq!( -// fold_ranges(editor, cx), -// vec![ -// Point::new(0, 6)..Point::new(0, 37), -// Point::new(0, 45)..Point::new(0, 80), -// Point::new(1, 0)..Point::new(1, 31) -// ] -// ); -// }); -// } + editor.update(&mut cx, |editor, cx| { + assert_eq!( + editor.text(cx), + "Lorem [@one.txt](file:///dir/a/one.txt) Ipsum [@eight.txt](file:///dir/b/eight.txt) \n[@seven.txt](file:///dir/b/seven.txt) " + ); + assert!(!editor.has_visible_completions_menu()); + assert_eq!( + fold_ranges(editor, cx), + vec![ + Point::new(0, 6)..Point::new(0, 39), + Point::new(0, 47)..Point::new(0, 84), + Point::new(1, 0)..Point::new(1, 37) + ] + ); + }); + } -// fn fold_ranges(editor: &Editor, cx: &mut App) -> Vec> { -// let snapshot = editor.buffer().read(cx).snapshot(cx); -// editor.display_map.update(cx, |display_map, cx| { -// display_map -// .snapshot(cx) -// .folds_in_range(0..snapshot.len()) -// .map(|fold| fold.range.to_point(&snapshot)) -// .collect() -// }) -// } + fn fold_ranges(editor: &Editor, cx: &mut App) -> Vec> { + let snapshot = editor.buffer().read(cx).snapshot(cx); + editor.display_map.update(cx, |display_map, cx| { + display_map + .snapshot(cx) + .folds_in_range(0..snapshot.len()) + .map(|fold| fold.range.to_point(&snapshot)) + .collect() + }) + } -// fn current_completion_labels(editor: &Editor) -> Vec { -// let completions = editor.current_completions().expect("Missing completions"); -// completions -// .into_iter() -// .map(|completion| completion.label.text.to_string()) -// .collect::>() -// } + fn current_completion_labels(editor: &Editor) -> Vec { + let completions = editor.current_completions().expect("Missing completions"); + completions + .into_iter() + .map(|completion| completion.label.text.to_string()) + .collect::>() + } -// pub(crate) fn init_test(cx: &mut TestAppContext) { -// cx.update(|cx| { -// let store = SettingsStore::test(cx); -// cx.set_global(store); -// theme::init(theme::LoadThemes::JustBase, cx); -// client::init_settings(cx); -// language::init(cx); -// Project::init_settings(cx); -// workspace::init_settings(cx); -// editor::init_settings(cx); -// }); -// } -// } + pub(crate) fn init_test(cx: &mut TestAppContext) { + cx.update(|cx| { + let store = SettingsStore::test(cx); + cx.set_global(store); + theme::init(theme::LoadThemes::JustBase, cx); + client::init_settings(cx); + language::init(cx); + Project::init_settings(cx); + workspace::init_settings(cx); + editor::init_settings(cx); + }); + } +}