From 9f6f27f305056e85a352f304781eca043728fc61 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 7 Apr 2021 21:54:05 -0600 Subject: [PATCH] Order debug JSON and allow elements to be named; copy to clipboard --- Cargo.lock | 17 +++++++++++ gpui/src/app.rs | 4 +++ gpui/src/elements/align.rs | 2 +- gpui/src/elements/container.rs | 2 +- gpui/src/elements/flex.rs | 2 +- gpui/src/elements/label.rs | 6 ++-- gpui/src/elements/line_box.rs | 2 +- gpui/src/elements/new.rs | 47 +++++++++++++++++++++++------ gpui/src/platform/mac/app.rs | 21 +++++++++++-- gpui/src/platform/mod.rs | 1 + gpui/src/platform/test.rs | 2 ++ zed/Cargo.toml | 4 +-- zed/src/file_finder.rs | 8 ++--- zed/src/workspace/pane.rs | 10 +++--- zed/src/workspace/workspace_view.rs | 8 +++-- 15 files changed, 104 insertions(+), 32 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b6d5b045e2..07e3c4e13d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -940,6 +940,12 @@ dependencies = [ "usvg", ] +[[package]] +name = "hashbrown" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" + [[package]] name = "hermit-abi" version = "0.1.18" @@ -973,6 +979,16 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "indexmap" +version = "1.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3" +dependencies = [ + "autocfg", + "hashbrown", +] + [[package]] name = "instant" version = "0.1.9" @@ -1703,6 +1719,7 @@ version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79" dependencies = [ + "indexmap", "itoa", "ryu", "serde", diff --git a/gpui/src/app.rs b/gpui/src/app.rs index b65e631e96..d6996e0fee 100644 --- a/gpui/src/app.rs +++ b/gpui/src/app.rs @@ -1120,6 +1120,10 @@ impl MutableAppContext { } } } + + pub fn copy(&self, text: &str) { + self.platform.copy(text); + } } impl ModelAsRef for MutableAppContext { diff --git a/gpui/src/elements/align.rs b/gpui/src/elements/align.rs index 9d5c905eb5..a879870cab 100644 --- a/gpui/src/elements/align.rs +++ b/gpui/src/elements/align.rs @@ -91,8 +91,8 @@ impl Element for Align { ) -> json::Value { json!({ "type": "Align", - "alignment": self.alignment.to_json(), "bounds": bounds.to_json(), + "alignment": self.alignment.to_json(), "child": self.child.debug(ctx), }) } diff --git a/gpui/src/elements/container.rs b/gpui/src/elements/container.rs index dcded86f38..9554f3b353 100644 --- a/gpui/src/elements/container.rs +++ b/gpui/src/elements/container.rs @@ -201,6 +201,7 @@ impl Element for Container { ) -> serde_json::Value { json!({ "type": "Container", + "bounds": bounds.to_json(), "details": { "margin": self.margin.to_json(), "padding": self.padding.to_json(), @@ -209,7 +210,6 @@ impl Element for Container { "corner_radius": self.corner_radius, "shadow": self.shadow.to_json(), }, - "bounds": bounds.to_json(), "child": self.child.debug(ctx), }) } diff --git a/gpui/src/elements/flex.rs b/gpui/src/elements/flex.rs index abed2aabc5..db87a80dbf 100644 --- a/gpui/src/elements/flex.rs +++ b/gpui/src/elements/flex.rs @@ -173,8 +173,8 @@ impl Element for Flex { ) -> json::Value { json!({ "type": "Flex", - "axis": self.axis.to_json(), "bounds": bounds.to_json(), + "axis": self.axis.to_json(), "children": self.children.iter().map(|child| child.debug(ctx)).collect::>() }) } diff --git a/gpui/src/elements/label.rs b/gpui/src/elements/label.rs index 952bc0eab0..2ef66bcc9d 100644 --- a/gpui/src/elements/label.rs +++ b/gpui/src/elements/label.rs @@ -166,11 +166,11 @@ impl Element for Label { ) -> Value { json!({ "type": "Label", - "font_size": self.font_size, "bounds": bounds.to_json(), - "text": &self.text, - "family_id": ctx.font_cache.family_name(self.family_id).unwrap(), + "font_family": ctx.font_cache.family_name(self.family_id).unwrap(), + "font_size": self.font_size, "font_properties": self.font_properties.to_json(), + "text": &self.text, "highlights": self.highlights.to_json(), }) } diff --git a/gpui/src/elements/line_box.rs b/gpui/src/elements/line_box.rs index eec76cbeb4..83f58feea5 100644 --- a/gpui/src/elements/line_box.rs +++ b/gpui/src/elements/line_box.rs @@ -99,7 +99,7 @@ impl Element for LineBox { ) -> serde_json::Value { json!({ "bounds": bounds.to_json(), - "family_id": ctx.font_cache.family_name(self.family_id).unwrap(), + "font_family": ctx.font_cache.family_name(self.family_id).unwrap(), "font_size": self.font_size, "font_properties": self.font_properties.to_json(), "child": self.child.debug(ctx), diff --git a/gpui/src/elements/new.rs b/gpui/src/elements/new.rs index 446948e3cc..3521a5fab0 100644 --- a/gpui/src/elements/new.rs +++ b/gpui/src/elements/new.rs @@ -5,7 +5,7 @@ use crate::{ }; use core::panic; use replace_with::replace_with_or_abort; -use std::any::Any; +use std::{any::Any, borrow::Cow}; trait AnyElement { fn layout(&mut self, constraint: SizeConstraint, ctx: &mut LayoutContext) -> Vector2F; @@ -67,7 +67,20 @@ pub trait Element { where Self: 'static + Sized, { - ElementBox(Box::new(Lifecycle::Init { element: self })) + ElementBox { + name: None, + element: Box::new(Lifecycle::Init { element: self }), + } + } + + fn named(self, name: impl Into>) -> ElementBox + where + Self: 'static + Sized, + { + ElementBox { + name: Some(name.into()), + element: Box::new(Lifecycle::Init { element: self }), + } } } @@ -87,7 +100,10 @@ pub enum Lifecycle { paint: T::PaintState, }, } -pub struct ElementBox(Box); +pub struct ElementBox { + name: Option>, + element: Box, +} impl AnyElement for Lifecycle { fn layout(&mut self, constraint: SizeConstraint, ctx: &mut LayoutContext) -> Vector2F { @@ -191,30 +207,41 @@ impl AnyElement for Lifecycle { impl ElementBox { pub fn layout(&mut self, constraint: SizeConstraint, ctx: &mut LayoutContext) -> Vector2F { - self.0.layout(constraint, ctx) + self.element.layout(constraint, ctx) } pub fn after_layout(&mut self, ctx: &mut AfterLayoutContext) { - self.0.after_layout(ctx); + self.element.after_layout(ctx); } pub fn paint(&mut self, origin: Vector2F, ctx: &mut PaintContext) { - self.0.paint(origin, ctx); + self.element.paint(origin, ctx); } pub fn dispatch_event(&mut self, event: &Event, ctx: &mut EventContext) -> bool { - self.0.dispatch_event(event, ctx) + self.element.dispatch_event(event, ctx) } pub fn size(&self) -> Vector2F { - self.0.size() + self.element.size() } pub fn metadata(&self) -> Option<&dyn Any> { - self.0.metadata() + self.element.metadata() } pub fn debug(&self, ctx: &DebugContext) -> json::Value { - self.0.debug(ctx) + let mut value = self.element.debug(ctx); + + if let Some(name) = &self.name { + if let json::Value::Object(map) = &mut value { + let mut new_map: crate::json::Map = Default::default(); + new_map.insert("name".into(), json::Value::String(name.to_string())); + new_map.append(map); + return json::Value::Object(new_map); + } + } + + value } } diff --git a/gpui/src/platform/mac/app.rs b/gpui/src/platform/mac/app.rs index daf8335f60..792639e9d2 100644 --- a/gpui/src/platform/mac/app.rs +++ b/gpui/src/platform/mac/app.rs @@ -1,9 +1,13 @@ use super::{BoolExt as _, Dispatcher, FontSystem, Window}; use crate::{executor, platform}; use anyhow::Result; -use cocoa::base::id; +use cocoa::{ + appkit::{NSPasteboard, NSPasteboardTypeString}, + base::{id, nil}, + foundation::NSData, +}; use objc::{class, msg_send, sel, sel_impl}; -use std::{rc::Rc, sync::Arc}; +use std::{ffi::c_void, rc::Rc, sync::Arc}; pub struct App { dispatcher: Arc, @@ -42,4 +46,17 @@ impl platform::App for App { fn fonts(&self) -> Arc { self.fonts.clone() } + + fn copy(&self, text: &str) { + unsafe { + let data = NSData::dataWithBytes_length_( + nil, + text.as_ptr() as *const c_void, + text.len() as u64, + ); + let pasteboard = NSPasteboard::generalPasteboard(nil); + pasteboard.clearContents(); + pasteboard.setData_forType(data, NSPasteboardTypeString); + } + } } diff --git a/gpui/src/platform/mod.rs b/gpui/src/platform/mod.rs index 5bd7e4659e..ce4c27f923 100644 --- a/gpui/src/platform/mod.rs +++ b/gpui/src/platform/mod.rs @@ -40,6 +40,7 @@ pub trait App { executor: Rc, ) -> Result>; fn fonts(&self) -> Arc; + fn copy(&self, text: &str); } pub trait Dispatcher: Send + Sync { diff --git a/gpui/src/platform/test.rs b/gpui/src/platform/test.rs index 545ab10e34..c42b94628a 100644 --- a/gpui/src/platform/test.rs +++ b/gpui/src/platform/test.rs @@ -46,6 +46,8 @@ impl super::App for App { fn fonts(&self) -> std::sync::Arc { self.fonts.clone() } + + fn copy(&self, _: &str) {} } impl Window { diff --git a/zed/Cargo.toml b/zed/Cargo.toml index b1cecf1ae0..61864372cd 100644 --- a/zed/Cargo.toml +++ b/zed/Cargo.toml @@ -18,9 +18,9 @@ arrayvec = "0.5.2" crossbeam-channel = "0.5.0" dirs = "3.0" easy-parallel = "3.1.0" +futures-core = "0.3" gpui = {path = "../gpui"} ignore = {git = "https://github.com/zed-industries/ripgrep", rev = "1d152118f35b3e3590216709b86277062d79b8a0"} -futures-core = "0.3" lazy_static = "1.4.0" libc = "0.2" log = "0.4" @@ -33,6 +33,6 @@ smallvec = "1.6.1" smol = "1.2.5" [dev-dependencies] -serde_json = "1.0.64" +serde_json = {version = "1.0.64", features = ["preserve_order"]} tempdir = "0.3.7" unindent = "0.1.7" diff --git a/zed/src/file_finder.rs b/zed/src/file_finder.rs index 39b497f5c8..c951d12934 100644 --- a/zed/src/file_finder.rs +++ b/zed/src/file_finder.rs @@ -78,7 +78,7 @@ impl View for FileFinder { .boxed(), ) .top_center() - .boxed() + .named("file finder") } fn on_focus(&mut self, ctx: &mut ViewContext) { @@ -105,7 +105,7 @@ impl FileFinder { .boxed(), ) .with_margin_top(6.0) - .boxed(); + .named("empty matches"); } let handle = self.handle.clone(); @@ -127,7 +127,7 @@ impl FileFinder { .with_background_color(ColorU::from_u32(0xf7f7f7ff)) .with_border(Border::all(1.0, ColorU::from_u32(0xdbdbdcff))) .with_margin_top(6.0) - .boxed() + .named("matches") } fn render_match( @@ -226,7 +226,7 @@ impl FileFinder { ctx.dispatch_action("file_finder:select", (tree_id, entry_id)); true }) - .boxed() + .named("match") }) } diff --git a/zed/src/workspace/pane.rs b/zed/src/workspace/pane.rs index 845fa0c4a7..fad299aa8b 100644 --- a/zed/src/workspace/pane.rs +++ b/zed/src/workspace/pane.rs @@ -244,7 +244,7 @@ impl Pane { .with_max_width(264.0) .boxed(), ) - .boxed(), + .named("tab"), ); } @@ -263,10 +263,10 @@ impl Pane { .with_border(Border::bottom(1.0, border_color)) .boxed(), ) - .boxed(), + .named("filler"), ); - row.boxed() + row.named("tabs") } fn render_modified_icon(is_modified: bool) -> ElementBox { @@ -304,9 +304,9 @@ impl View for Pane { Flex::column() .with_child(self.render_tabs(app)) .with_child(Expanded::new(1.0, ChildView::new(active_item.id()).boxed()).boxed()) - .boxed() + .named("pane") } else { - Empty::new().boxed() + Empty::new().named("pane") } } diff --git a/zed/src/workspace/workspace_view.rs b/zed/src/workspace/workspace_view.rs index 7cb9fd8b64..5810245be4 100644 --- a/zed/src/workspace/workspace_view.rs +++ b/zed/src/workspace/workspace_view.rs @@ -258,7 +258,11 @@ impl WorkspaceView { pub fn debug_elements(&mut self, _: &(), ctx: &mut ViewContext) { match to_string_pretty(&ctx.debug_elements()) { Ok(json) => { - log::info!("{}", json); + ctx.app_mut().copy(&json); + log::info!( + "copied {:.1} KiB of element debug JSON to the clipboard", + json.len() as f32 / 1024. + ); } Err(error) => { log::error!("error debugging elements: {}", error); @@ -373,7 +377,7 @@ impl View for WorkspaceView { .boxed(), ) .with_background_color(rgbu(0xea, 0xea, 0xeb)) - .boxed() + .named("workspace") } fn on_focus(&mut self, ctx: &mut ViewContext) {