History

Basic proof of concept

Anthony committed 1 year ago

Commit f623ea51 parent 4b489f44 files · +138 −1Browse files

Unified · Split

4 files
  1. Cargo.lock +1 −0
  2. crates/settings_ui/Cargo.toml +2 −0
  3. crates/settings_ui/src/settings_ui.rs +107 −1
  4. crates/zed/resources/zed-debug.entitlements +28 −0
Cargo.lock+1−0
@@ -15294,6 +15294,7 @@ dependencies = [ · 15293 unmodified lines
1529415294 "schemars 1.0.4",
1529515295 "search",
1529615296 "serde",
15297+ "serde_json",
1529715298 "session",
1529815299 "settings",
1529915300 "strum 0.27.2",
crates/settings_ui/Cargo.toml+2−0
@@ -30,6 +30,7 @@ project.workspace = true · 29 unmodified lines
3030 schemars.workspace = true
3131 search.workspace = true
3232 serde.workspace = true
33+serde_json.workspace = true
3334 settings.workspace = true
3435 strum.workspace = true
3536 theme.workspace = true
@@ -51,5 +52,6 @@ node_runtime.workspace = true · 15 unmodified lines
5152 paths.workspace = true
5253 session.workspace = true
5354 settings.workspace = true
55+workspace = { workspace = true, features = ["test-support"] }
5456 zlog.workspace = true
5557 pretty_assertions.workspace = true
crates/settings_ui/src/settings_ui.rs+107−1
@@ -222,6 +222,81 @@ struct SettingFieldRenderer { · 221 unmodified lines
222222
223223 impl Global for SettingFieldRenderer {}
224224
225+#[derive(Default, Clone)]
226+struct SettingsJsonKeyFinder {
227+ key_finders: Rc<RefCell<HashMap<TypeId, Box<dyn Fn(SettingsContent) -> Option<String>>>>>,
228+}
229+
230+impl Global for SettingsJsonKeyFinder {}
231+
232+impl SettingsJsonKeyFinder {
233+ fn add_basic_json_key_finder<T: 'static + Default + serde::Serialize>(
234+ &mut self,
235+ field: SettingField<T>,
236+ ) -> &mut Self {
237+ let key = TypeId::of::<T>();
238+ let key_finder = Box::new(move |mut content: SettingsContent| {
239+ // Write the field with a default value
240+ (field.write)(&mut content, Some(T::default()));
241+
242+ // Serialize to a pretty-printed JSON string
243+ let json_string = serde_json::to_string_pretty(&content)
244+ .expect("Failed to serialize SettingsContent");
245+
246+ // Extract the JSON path from the string (should only have one entry)
247+ extract_json_path_from_string(&json_string)
248+ });
249+ self.key_finders.borrow_mut().insert(key, key_finder);
250+ self
251+ }
252+
253+ fn find_json_path<T: 'static>(&self) -> Option<String> {
254+ let key = TypeId::of::<T>();
255+ let key_finders = self.key_finders.borrow();
256+ let key_finder = key_finders.get(&key)?;
257+ let content = SettingsContent::default();
258+ key_finder(content)
259+ }
260+}
261+
262+/// Extracts the JSON key path from a serialized settings string.
263+/// Assumes only one field is set in the JSON.
264+fn extract_json_path_from_string(json: &str) -> Option<String> {
265+ use serde_json::Value;
266+
267+ let value: Value = serde_json::from_str(json).ok()?;
268+
269+ fn find_non_empty_path(value: &Value, prefix: &str) -> Option<String> {
270+ match value {
271+ Value::Object(map) => {
272+ for (key, val) in map {
273+ let new_prefix = if prefix.is_empty() {
274+ key.clone()
275+ } else {
276+ format!("{}.{}", prefix, key)
277+ };
278+
279+ match val {
280+ Value::Null => continue,
281+ Value::Object(inner_map) if inner_map.is_empty() => continue,
282+ Value::Array(arr) if arr.is_empty() => continue,
283+ Value::Object(_) => {
284+ if let Some(path) = find_non_empty_path(val, &new_prefix) {
285+ return Some(path);
286+ }
287+ }
288+ _ => return Some(new_prefix),
289+ }
290+ }
291+ None
292+ }
293+ _ => None,
294+ }
295+ }
296+
297+ find_non_empty_path(&value, "")
298+}
299+
225300 impl SettingFieldRenderer {
226301 fn add_basic_renderer<T: 'static>(
227302 &mut self,
@@ -343,6 +418,7 @@ impl FeatureFlag for SettingsUiFeatureFlag { · 115 unmodified lines
343418
344419 pub fn init(cx: &mut App) {
345420 init_renderers(cx);
421+ init_json_key_finders(cx);
346422
347423 cx.observe_new(|workspace: &mut workspace::Workspace, _, _| {
348424 workspace.register_action(|workspace, _: &OpenSettings, window, cx| {
@@ -356,6 +432,14 @@ pub fn init(cx: &mut App) { · 7 unmodified lines
356432 .detach();
357433 }
358434
435+fn init_json_key_finders(cx: &mut App) {
436+ cx.default_global::<SettingsJsonKeyFinder>()
437+ .add_basic_json_key_finder(SettingField::<bool> {
438+ pick: |content| content.vim_mode.as_ref(),
439+ write: |content, value| content.vim_mode = value,
440+ });
441+}
442+
359443 fn init_renderers(cx: &mut App) {
360444 cx.default_global::<SettingFieldRenderer>()
361445 .add_basic_renderer::<UnimplementedSettingField>(|_, _, _, _, _| {
@@ -3114,8 +3198,25 @@ fn render_icon_theme_picker( · 2752 unmodified lines
31143198 #[cfg(test)]
31153199 mod test {
31163200
3201+ use gpui::TestAppContext;
3202+ use workspace::AppState;
3203+
31173204 use super::*;
31183205
3206+ #[gpui::test]
3207+ fn test_json_path(cx: &mut TestAppContext) {
3208+ cx.update(|cx| {
3209+ register_settings(cx);
3210+ init_json_key_finders(cx);
3211+
3212+ let json_key_finder = cx.global::<SettingsJsonKeyFinder>();
3213+ let path = json_key_finder.find_json_path::<bool>();
3214+ dbg!(&path);
3215+
3216+ assert_eq!(path, Some("vim_mode".to_string()));
3217+ });
3218+ }
3219+
31193220 impl SettingsWindow {
31203221 fn navbar_entry(&self) -> usize {
31213222 self.navbar_entry
@@ -3134,9 +3235,14 @@ mod test { · 12 unmodified lines
31343235 }
31353236
31363237 fn register_settings(cx: &mut App) {
3238+ let app_state = workspace::AppState::test(cx);
3239+
31373240 settings::init(cx);
31383241 theme::init(theme::LoadThemes::JustBase, cx);
3139− workspace::init_settings(cx);
3242+ // workspace::init_settings(cx);
3243+ workspace::init(app_state.clone(), cx);
3244+ AppState::set_global(Arc::downgrade(&app_state), cx);
3245+
31403246 project::Project::init_settings(cx);
31413247 language::init(cx);
31423248 editor::init(cx);
crates/zed/resources/zed-debug.entitlements+28−0
@@ -0,0 +1,28 @@
1+<?xml version="1.0" encoding="UTF-8"?>
2+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+<plist version="1.0">
4+<dict>
5+ <key>com.apple.security.get-task-allow</key>
6+ <true/>
7+ <key>com.apple.security.automation.apple-events</key>
8+ <true/>
9+ <key>com.apple.security.cs.allow-jit</key>
10+ <true/>
11+ <key>com.apple.security.cs.allow-unsigned-executable-memory</key>
12+ <true/>
13+ <!-- <key>com.apple.security.cs.disable-library-validation</key>
14+ <true/> -->
15+ <key>com.apple.security.device.audio-input</key>
16+ <true/>
17+ <key>com.apple.security.device.camera</key>
18+ <true/>
19+ <key>com.apple.security.personal-information.addressbook</key>
20+ <true/>
21+ <key>com.apple.security.personal-information.calendars</key>
22+ <true/>
23+ <key>com.apple.security.personal-information.location</key>
24+ <true/>
25+ <key>com.apple.security.personal-information.photos-library</key>
26+ <true/>
27+</dict>
28+</plist>