1use std::sync::Arc;
2
3use futures::StreamExt;
4use gpui::AppContext as _;
5use settings::{DEFAULT_KEYMAP_PATH, KeymapFile, SettingsStore, watch_config_file};
6use settings_ui::open_settings_editor;
7use ui::BorrowAppContext;
8
9fn merge_paths(a: &std::path::Path, b: &std::path::Path) -> std::path::PathBuf {
10 let a_parts: Vec<_> = a.components().collect();
11 let b_parts: Vec<_> = b.components().collect();
12
13 let mut overlap = 0;
14 for i in 0..=a_parts.len().min(b_parts.len()) {
15 if a_parts[a_parts.len() - i..] == b_parts[..i] {
16 overlap = i;
17 }
18 }
19
20 let mut result = std::path::PathBuf::new();
21 for part in &a_parts {
22 result.push(part.as_os_str());
23 }
24 for part in &b_parts[overlap..] {
25 result.push(part.as_os_str());
26 }
27 result
28}
29
30fn main() {
31 zlog::init();
32 zlog::init_output_stderr();
33
34 let [crate_path, file_path] = [env!("CARGO_MANIFEST_DIR"), file!()].map(std::path::Path::new);
35 let example_dir_abs_path = merge_paths(crate_path, file_path)
36 .parent()
37 .unwrap()
38 .to_path_buf();
39
40 let app = gpui::Application::new().with_assets(assets::Assets);
41
42 let fs = Arc::new(fs::RealFs::new(None, app.background_executor()));
43 let mut user_settings_file_rx = watch_config_file(
44 &app.background_executor(),
45 fs.clone(),
46 paths::settings_file().clone(),
47 );
48
49 app.run(move |cx| {
50 <dyn fs::Fs>::set_global(fs.clone(), cx);
51 settings::init(cx);
52 settings_ui::init(cx);
53 theme::init(theme::LoadThemes::JustBase, cx);
54 client::init_settings(cx);
55 workspace::init_settings(cx);
56 // production client because fake client requires gpui/test-support
57 // and that causes issues with the real stuff we want to do
58 let client = client::Client::production(cx);
59 let user_store = cx.new(|cx| client::UserStore::new(client.clone(), cx));
60 let languages = Arc::new(language::LanguageRegistry::new(
61 cx.background_executor().clone(),
62 ));
63
64 client::init(&client, cx);
65
66 project::Project::init(&client, cx);
67
68 zlog::info!(
69 "Creating fake worktree in {}",
70 example_dir_abs_path.display(),
71 );
72 let project = project::Project::local(
73 client.clone(),
74 node_runtime::NodeRuntime::unavailable(),
75 user_store,
76 languages,
77 fs.clone(),
78 Some(Default::default()), // WARN: if None is passed here, prepare to be process bombed
79 cx,
80 );
81 let worktree_task = project.update(cx, |project, cx| {
82 project.create_worktree(example_dir_abs_path, true, cx)
83 });
84 cx.spawn(async move |_| {
85 let worktree = worktree_task.await.unwrap();
86 std::mem::forget(worktree);
87 })
88 .detach();
89 std::mem::forget(project);
90
91 language::init(cx);
92 editor::init(cx);
93 menu::init();
94
95 let keybindings =
96 KeymapFile::load_asset_allow_partial_failure(DEFAULT_KEYMAP_PATH, cx).unwrap();
97 cx.bind_keys(keybindings);
98 cx.spawn(async move |cx| {
99 while let Some(content) = user_settings_file_rx.next().await {
100 cx.update(|cx| {
101 cx.update_global(|store: &mut SettingsStore, cx| {
102 store.set_user_settings(&content, cx).unwrap()
103 })
104 })
105 .ok();
106 }
107 })
108 .detach();
109
110 open_settings_editor(cx).unwrap();
111 cx.activate(true);
112 });
113}