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
15294 "schemars 1.0.4",15294 "schemars 1.0.4",
15295 "search",15295 "search",
15296 "serde",15296 "serde",
15297 "serde_json",
15297 "session",15298 "session",
15298 "settings",15299 "settings",
15299 "strum 0.27.2",15300 "strum 0.27.2",
crates/settings_ui/Cargo.toml+2−0
@@ -30,6 +30,7 @@ project.workspace = true · 29 unmodified lines
30schemars.workspace = true30schemars.workspace = true
31search.workspace = true31search.workspace = true
32serde.workspace = true32serde.workspace = true
33serde_json.workspace = true
33settings.workspace = true34settings.workspace = true
34strum.workspace = true35strum.workspace = true
35theme.workspace = true36theme.workspace = true
@@ -51,5 +52,6 @@ node_runtime.workspace = true · 15 unmodified lines
51paths.workspace = true52paths.workspace = true
52session.workspace = true53session.workspace = true
53settings.workspace = true54settings.workspace = true
55workspace = { workspace = true, features = ["test-support"] }
54zlog.workspace = true56zlog.workspace = true
55pretty_assertions.workspace = true57pretty_assertions.workspace = true
crates/settings_ui/src/settings_ui.rs+107−1
@@ -222,6 +222,81 @@ struct SettingFieldRenderer { · 221 unmodified lines
222 222
223impl Global for SettingFieldRenderer {}223impl Global for SettingFieldRenderer {}
224 224
225#[derive(Default, Clone)]
226struct SettingsJsonKeyFinder {
227 key_finders: Rc<RefCell<HashMap<TypeId, Box<dyn Fn(SettingsContent) -> Option<String>>>>>,
228}
229
230impl Global for SettingsJsonKeyFinder {}
231
232impl 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.
264fn 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
225impl SettingFieldRenderer {300impl SettingFieldRenderer {
226 fn add_basic_renderer<T: 'static>(301 fn add_basic_renderer<T: 'static>(
227 &mut self,302 &mut self,
@@ -343,6 +418,7 @@ impl FeatureFlag for SettingsUiFeatureFlag { · 115 unmodified lines
343 418
344pub fn init(cx: &mut App) {419pub fn init(cx: &mut App) {
345 init_renderers(cx);420 init_renderers(cx);
421 init_json_key_finders(cx);
346 422
347 cx.observe_new(|workspace: &mut workspace::Workspace, _, _| {423 cx.observe_new(|workspace: &mut workspace::Workspace, _, _| {
348 workspace.register_action(|workspace, _: &OpenSettings, window, cx| {424 workspace.register_action(|workspace, _: &OpenSettings, window, cx| {
@@ -356,6 +432,14 @@ pub fn init(cx: &mut App) { · 7 unmodified lines
356 .detach();432 .detach();
357}433}
358 434
435fn 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
359fn init_renderers(cx: &mut App) {443fn init_renderers(cx: &mut App) {
360 cx.default_global::<SettingFieldRenderer>()444 cx.default_global::<SettingFieldRenderer>()
361 .add_basic_renderer::<UnimplementedSettingField>(|_, _, _, _, _| {445 .add_basic_renderer::<UnimplementedSettingField>(|_, _, _, _, _| {
@@ -3114,8 +3198,25 @@ fn render_icon_theme_picker( · 2752 unmodified lines
3114#[cfg(test)]3198#[cfg(test)]
3115mod test {3199mod test {
3116 3200
3201 use gpui::TestAppContext;
3202 use workspace::AppState;
3203
3117 use super::*;3204 use super::*;
3118 3205
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
3119 impl SettingsWindow {3220 impl SettingsWindow {
3120 fn navbar_entry(&self) -> usize {3221 fn navbar_entry(&self) -> usize {
3121 self.navbar_entry3222 self.navbar_entry
@@ -3134,9 +3235,14 @@ mod test { · 12 unmodified lines
3134 }3235 }
3135 3236
3136 fn register_settings(cx: &mut App) {3237 fn register_settings(cx: &mut App) {
3238 let app_state = workspace::AppState::test(cx);
3239
3137 settings::init(cx);3240 settings::init(cx);
3138 theme::init(theme::LoadThemes::JustBase, cx);3241 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
3140 project::Project::init_settings(cx);3246 project::Project::init_settings(cx);
3141 language::init(cx);3247 language::init(cx);
3142 editor::init(cx);3248 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>