diff --git a/.github/workflows/publish_collab_image.yml b/.github/workflows/publish_collab_image.yml index 3421409287..b012e65841 100644 --- a/.github/workflows/publish_collab_image.yml +++ b/.github/workflows/publish_collab_image.yml @@ -11,7 +11,7 @@ env: jobs: publish: - name: Publish collab server image + name: Publish collab server image runs-on: - self-hosted - deploy @@ -22,6 +22,9 @@ jobs: - name: Sign into DigitalOcean docker registry run: doctl registry login + - name: Prune Docker system + run: docker system prune + - name: Checkout repo uses: actions/checkout@v3 with: @@ -41,6 +44,6 @@ jobs: - name: Build docker image run: docker build . --tag registry.digitalocean.com/zed/collab:v${COLLAB_VERSION} - + - name: Publish docker image run: docker push registry.digitalocean.com/zed/collab:v${COLLAB_VERSION} diff --git a/Cargo.lock b/Cargo.lock index 0081626cab..101a495b6e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1312,12 +1312,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" -[[package]] -name = "claxon" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bfbf56724aa9eca8afa4fcfadeb479e722935bb2a0900c2d37e0cc477af0688" - [[package]] name = "cli" version = "0.1.0" @@ -1415,7 +1409,7 @@ dependencies = [ [[package]] name = "collab" -version = "0.17.0" +version = "0.18.0" dependencies = [ "anyhow", "async-tungstenite", @@ -2104,6 +2098,15 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "derive_refineable" +version = "0.1.0" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "dhat" version = "0.3.2" @@ -3086,6 +3089,7 @@ dependencies = [ "png", "postage", "rand 0.8.5", + "refineable", "resvg", "schemars", "seahash", @@ -3097,6 +3101,7 @@ dependencies = [ "smol", "sqlez", "sum_tree", + "taffy", "time 0.3.24", "tiny-skia", "usvg", @@ -3109,11 +3114,18 @@ dependencies = [ name = "gpui_macros" version = "0.1.0" dependencies = [ + "lazy_static", "proc-macro2", "quote", "syn 1.0.109", ] +[[package]] +name = "grid" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eec1c01eb1de97451ee0d60de7d81cf1e72aabefb021616027f3d1c3ec1c723c" + [[package]] name = "h2" version = "0.3.20" @@ -3903,17 +3915,6 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" -[[package]] -name = "lewton" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "777b48df9aaab155475a83a7df3070395ea1ac6902f5cd062b8f2b028075c030" -dependencies = [ - "byteorder", - "ogg", - "tinyvec", -] - [[package]] name = "libc" version = "0.2.147" @@ -4767,15 +4768,6 @@ dependencies = [ "cc", ] -[[package]] -name = "ogg" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6951b4e8bf21c8193da321bcce9c9dd2e13c858fe078bf9054a288b419ae5d6e" -dependencies = [ - "byteorder", -] - [[package]] name = "once_cell" version = "1.18.0" @@ -5126,6 +5118,33 @@ version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +[[package]] +name = "playground" +version = "0.1.0" +dependencies = [ + "anyhow", + "derive_more", + "gpui", + "log", + "parking_lot 0.11.2", + "playground_macros", + "refineable", + "serde", + "simplelog", + "smallvec", + "taffy", + "util", +] + +[[package]] +name = "playground_macros" +version = "0.1.0" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "plist" version = "1.5.0" @@ -5803,6 +5822,16 @@ dependencies = [ "thiserror", ] +[[package]] +name = "refineable" +version = "0.1.0" +dependencies = [ + "derive_refineable", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "regalloc2" version = "0.2.3" @@ -6021,11 +6050,8 @@ version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bdf1d4dea18dff2e9eb6dca123724f8b60ef44ad74a9ad283cdfe025df7e73fa" dependencies = [ - "claxon", "cpal", "hound", - "lewton", - "symphonia", ] [[package]] @@ -6117,9 +6143,9 @@ dependencies = [ [[package]] name = "rust-embed" -version = "6.8.1" +version = "8.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a36224c3276f8c4ebc8c20f158eca7ca4359c8db89991c4925132aaaf6702661" +checksum = "b1e7d90385b59f0a6bf3d3b757f3ca4ece2048265d70db20a2016043d4509a40" dependencies = [ "rust-embed-impl", "rust-embed-utils", @@ -6128,9 +6154,9 @@ dependencies = [ [[package]] name = "rust-embed-impl" -version = "6.8.1" +version = "8.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49b94b81e5b2c284684141a2fb9e2a31be90638caf040bf9afbc5a0416afe1ac" +checksum = "3c3d8c6fd84090ae348e63a84336b112b5c3918b3bf0493a581f7bd8ee623c29" dependencies = [ "proc-macro2", "quote", @@ -6141,9 +6167,9 @@ dependencies = [ [[package]] name = "rust-embed-utils" -version = "7.8.1" +version = "8.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d38ff6bf570dc3bb7100fce9f7b60c33fa71d80e88da3f2580df4ff2bdded74" +checksum = "873feff8cb7bf86fdf0a71bb21c95159f4e4a37dd7a4bd1855a940909b583ada" dependencies = [ "globset", "sha2 0.10.7", @@ -6971,6 +6997,15 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7" +[[package]] +name = "slotmap" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1e08e261d0e8f5c43123b7adf3e4ca1690d655377ac93a03b2c9d3e98de1342" +dependencies = [ + "version_check", +] + [[package]] name = "sluice" version = "0.5.5" @@ -7341,56 +7376,6 @@ dependencies = [ "siphasher", ] -[[package]] -name = "symphonia" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62e48dba70095f265fdb269b99619b95d04c89e619538138383e63310b14d941" -dependencies = [ - "lazy_static", - "symphonia-bundle-mp3", - "symphonia-core", - "symphonia-metadata", -] - -[[package]] -name = "symphonia-bundle-mp3" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f31d7fece546f1e6973011a9eceae948133bbd18fd3d52f6073b1e38ae6368a" -dependencies = [ - "bitflags 1.3.2", - "lazy_static", - "log", - "symphonia-core", - "symphonia-metadata", -] - -[[package]] -name = "symphonia-core" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7c73eb88fee79705268cc7b742c7bc93a7b76e092ab751d0833866970754142" -dependencies = [ - "arrayvec 0.7.4", - "bitflags 1.3.2", - "bytemuck", - "lazy_static", - "log", -] - -[[package]] -name = "symphonia-metadata" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89c3e1937e31d0e068bbe829f66b2f2bfaa28d056365279e0ef897172c3320c0" -dependencies = [ - "encoding_rs", - "lazy_static", - "log", - "symphonia-core", -] - [[package]] name = "syn" version = "1.0.109" @@ -7460,6 +7445,17 @@ dependencies = [ "winx", ] +[[package]] +name = "taffy" +version = "0.3.11" +source = "git+https://github.com/DioxusLabs/taffy?rev=dab541d6104d58e2e10ce90c4a1dad0b703160cd#dab541d6104d58e2e10ce90c4a1dad0b703160cd" +dependencies = [ + "arrayvec 0.7.4", + "grid", + "num-traits", + "slotmap", +] + [[package]] name = "take-until" version = "0.2.0" @@ -9649,7 +9645,7 @@ dependencies = [ [[package]] name = "zed" -version = "0.101.0" +version = "0.102.0" dependencies = [ "activity_indicator", "ai", diff --git a/Cargo.toml b/Cargo.toml index d434f34773..cd15a72366 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,8 @@ members = [ "crates/copilot", "crates/copilot_button", "crates/db", + "crates/refineable", + "crates/refineable/derive_refineable", "crates/diagnostics", "crates/drag_and_drop", "crates/editor", @@ -29,6 +31,8 @@ members = [ "crates/git", "crates/go_to_line", "crates/gpui", + "crates/gpui/playground", + "crates/gpui/playground_macros", "crates/gpui_macros", "crates/install_cli", "crates/journal", @@ -93,8 +97,9 @@ ordered-float = { version = "2.1.1" } parking_lot = { version = "0.11.1" } postage = { version = "0.5", features = ["futures-traits"] } rand = { version = "0.8.5" } +refineable = { path = "./crates/refineable" } regex = { version = "1.5" } -rust-embed = { version = "6.3", features = ["include-exclude"] } +rust-embed = { version = "8.0", features = ["include-exclude"] } schemars = { version = "0.8" } serde = { version = "1.0", features = ["derive", "rc"] } serde_derive = { version = "1.0", features = ["deserialize_in_place"] } diff --git a/assets/keymaps/default.json b/assets/keymaps/default.json index 83875ab44a..1bd973e83b 100644 --- a/assets/keymaps/default.json +++ b/assets/keymaps/default.json @@ -543,6 +543,8 @@ "bindings": { "left": "project_panel::CollapseSelectedEntry", "right": "project_panel::ExpandSelectedEntry", + "cmd-n": "project_panel::NewFile", + "alt-cmd-n": "project_panel::NewDirectory", "cmd-x": "project_panel::Cut", "cmd-c": "project_panel::Copy", "cmd-v": "project_panel::Paste", diff --git a/assets/keymaps/textmate.json b/assets/keymaps/textmate.json index 90eb090211..dd3e217ae9 100644 --- a/assets/keymaps/textmate.json +++ b/assets/keymaps/textmate.json @@ -2,7 +2,6 @@ { "bindings": { "cmd-shift-o": "projects::OpenRecent", - "cmd-shift-b": "branches::OpenRecent", "cmd-alt-tab": "project_panel::ToggleFocus" } }, @@ -12,8 +11,9 @@ "cmd-l": "go_to_line::Toggle", "ctrl-shift-d": "editor::DuplicateLine", "cmd-b": "editor::GoToDefinition", - "alt-cmd-b": "editor::GoToDefinition", "cmd-j": "editor::ScrollCursorCenter", + "cmd-enter": "editor::NewlineBelow", + "cmd-alt-enter": "editor::NewLineAbove", "cmd-shift-l": "editor::SelectLine", "cmd-shift-t": "outline::Toggle", "alt-backspace": "editor::DeleteToPreviousWordStart", @@ -51,14 +51,17 @@ } ], "ctrl-shift-left": "editor::SelectToPreviousSubwordStart", - "ctrl-shift-right": "editor::SelectToNextSubwordEnd" + "ctrl-shift-right": "editor::SelectToNextSubwordEnd", + "ctrl-w": "editor::SelectNext", + "ctrl-u": "editor::ConvertToUpperCase", + "ctrl-shift-u": "editor::ConvertToLowerCase", + "ctrl-alt-u": "editor::ConvertToUpperCamelCase", + "ctrl-_": "editor::ConvertToSnakeCase" } }, { "context": "Editor && mode == full", - "bindings": { - "cmd-alt-enter": "editor::NewlineAbove" - } + "bindings": {} }, { "context": "BufferSearchBar", @@ -85,5 +88,9 @@ { "context": "ProjectPanel", "bindings": {} + }, + { + "context": "Dock", + "bindings": {} } ] diff --git a/assets/keymaps/vim.json b/assets/keymaps/vim.json index 458232b9b0..c0de3420f2 100644 --- a/assets/keymaps/vim.json +++ b/assets/keymaps/vim.json @@ -287,6 +287,12 @@ "shift-o": "vim::InsertLineAbove", "~": "vim::ChangeCase", "p": "vim::Paste", + "shift-p": [ + "vim::Paste", + { + "before": true + } + ], "u": "editor::Undo", "ctrl-r": "editor::Redo", "/": "vim::Search", @@ -375,7 +381,13 @@ "d": "vim::VisualDelete", "x": "vim::VisualDelete", "y": "vim::VisualYank", - "p": "vim::VisualPaste", + "p": "vim::Paste", + "shift-p": [ + "vim::Paste", + { + "preserveClipboard": true + } + ], "s": "vim::Substitute", "c": "vim::Substitute", "~": "vim::ChangeCase", @@ -421,7 +433,7 @@ } }, { - "context": "Editor && vim_mode == insert", + "context": "Editor && vim_mode == insert && !menu", "bindings": { "escape": "vim::NormalBefore", "ctrl-c": "vim::NormalBefore", diff --git a/assets/settings/default.json b/assets/settings/default.json index 08faedbed6..24412b883b 100644 --- a/assets/settings/default.json +++ b/assets/settings/default.json @@ -138,7 +138,13 @@ // Default width when the assistant is docked to the left or right. "default_width": 640, // Default height when the assistant is docked to the bottom. - "default_height": 320 + "default_height": 320, + // The default OpenAI model to use when starting new conversations. This + // setting can take two values: + // + // 1. "gpt-3.5-turbo-0613"" + // 2. "gpt-4-0613"" + "default_open_ai_model": "gpt-4-0613" }, // Whether the screen sharing icon is shown in the os status bar. "show_call_status_icon": true, diff --git a/crates/ai/src/ai.rs b/crates/ai/src/ai.rs index 7cc5f08f7c..d2be651bd5 100644 --- a/crates/ai/src/ai.rs +++ b/crates/ai/src/ai.rs @@ -3,6 +3,7 @@ mod assistant_settings; use anyhow::Result; pub use assistant::AssistantPanel; +use assistant_settings::OpenAIModel; use chrono::{DateTime, Local}; use collections::HashMap; use fs::Fs; @@ -60,7 +61,7 @@ struct SavedConversation { messages: Vec, message_metadata: HashMap, summary: String, - model: String, + model: OpenAIModel, } impl SavedConversation { diff --git a/crates/ai/src/assistant.rs b/crates/ai/src/assistant.rs index e5026182ed..81299bbdc2 100644 --- a/crates/ai/src/assistant.rs +++ b/crates/ai/src/assistant.rs @@ -1,5 +1,5 @@ use crate::{ - assistant_settings::{AssistantDockPosition, AssistantSettings}, + assistant_settings::{AssistantDockPosition, AssistantSettings, OpenAIModel}, MessageId, MessageMetadata, MessageStatus, OpenAIRequest, OpenAIResponseStreamEvent, RequestMessage, Role, SavedConversation, SavedConversationMetadata, SavedMessage, }; @@ -833,7 +833,7 @@ struct Conversation { pending_summary: Task>, completion_count: usize, pending_completions: Vec, - model: String, + model: OpenAIModel, token_count: Option, max_token_count: usize, pending_token_count: Task>, @@ -853,7 +853,6 @@ impl Conversation { language_registry: Arc, cx: &mut ModelContext, ) -> Self { - let model = "gpt-3.5-turbo-0613"; let markdown = language_registry.language_for_name("Markdown"); let buffer = cx.add_model(|cx| { let mut buffer = Buffer::new(0, "", cx); @@ -872,6 +871,9 @@ impl Conversation { buffer }); + let settings = settings::get::(cx); + let model = settings.default_open_ai_model.clone(); + let mut this = Self { message_anchors: Default::default(), messages_metadata: Default::default(), @@ -881,9 +883,9 @@ impl Conversation { completion_count: Default::default(), pending_completions: Default::default(), token_count: None, - max_token_count: tiktoken_rs::model::get_context_size(model), + max_token_count: tiktoken_rs::model::get_context_size(&model.full_name()), pending_token_count: Task::ready(None), - model: model.into(), + model: model.clone(), _subscriptions: vec![cx.subscribe(&buffer, Self::handle_buffer_event)], pending_save: Task::ready(Ok(())), path: None, @@ -977,7 +979,7 @@ impl Conversation { completion_count: Default::default(), pending_completions: Default::default(), token_count: None, - max_token_count: tiktoken_rs::model::get_context_size(&model), + max_token_count: tiktoken_rs::model::get_context_size(&model.full_name()), pending_token_count: Task::ready(None), model, _subscriptions: vec![cx.subscribe(&buffer, Self::handle_buffer_event)], @@ -1031,13 +1033,16 @@ impl Conversation { cx.background().timer(Duration::from_millis(200)).await; let token_count = cx .background() - .spawn(async move { tiktoken_rs::num_tokens_from_messages(&model, &messages) }) + .spawn(async move { + tiktoken_rs::num_tokens_from_messages(&model.full_name(), &messages) + }) .await?; this.upgrade(&cx) .ok_or_else(|| anyhow!("conversation was dropped"))? .update(&mut cx, |this, cx| { - this.max_token_count = tiktoken_rs::model::get_context_size(&this.model); + this.max_token_count = + tiktoken_rs::model::get_context_size(&this.model.full_name()); this.token_count = Some(token_count); cx.notify() }); @@ -1051,7 +1056,7 @@ impl Conversation { Some(self.max_token_count as isize - self.token_count? as isize) } - fn set_model(&mut self, model: String, cx: &mut ModelContext) { + fn set_model(&mut self, model: OpenAIModel, cx: &mut ModelContext) { self.model = model; self.count_remaining_tokens(cx); cx.notify(); @@ -1093,7 +1098,7 @@ impl Conversation { } } else { let request = OpenAIRequest { - model: self.model.clone(), + model: self.model.full_name().to_string(), messages: self .messages(cx) .filter(|message| matches!(message.status, MessageStatus::Done)) @@ -1419,7 +1424,7 @@ impl Conversation { .into(), })); let request = OpenAIRequest { - model: self.model.clone(), + model: self.model.full_name().to_string(), messages: messages.collect(), stream: true, }; @@ -2023,11 +2028,8 @@ impl ConversationEditor { fn cycle_model(&mut self, cx: &mut ViewContext) { self.conversation.update(cx, |conversation, cx| { - let new_model = match conversation.model.as_str() { - "gpt-4-0613" => "gpt-3.5-turbo-0613", - _ => "gpt-4-0613", - }; - conversation.set_model(new_model.into(), cx); + let new_model = conversation.model.cycle(); + conversation.set_model(new_model, cx); }); } @@ -2049,7 +2051,8 @@ impl ConversationEditor { MouseEventHandler::new::(0, cx, |state, cx| { let style = style.model.style_for(state); - Label::new(self.conversation.read(cx).model.clone(), style.text.clone()) + let model_display_name = self.conversation.read(cx).model.short_name(); + Label::new(model_display_name, style.text.clone()) .contained() .with_style(style.container) }) @@ -2238,6 +2241,8 @@ mod tests { #[gpui::test] fn test_inserting_and_removing_messages(cx: &mut AppContext) { + cx.set_global(SettingsStore::test(cx)); + init(cx); let registry = Arc::new(LanguageRegistry::test()); let conversation = cx.add_model(|cx| Conversation::new(Default::default(), registry, cx)); let buffer = conversation.read(cx).buffer.clone(); @@ -2364,6 +2369,8 @@ mod tests { #[gpui::test] fn test_message_splitting(cx: &mut AppContext) { + cx.set_global(SettingsStore::test(cx)); + init(cx); let registry = Arc::new(LanguageRegistry::test()); let conversation = cx.add_model(|cx| Conversation::new(Default::default(), registry, cx)); let buffer = conversation.read(cx).buffer.clone(); @@ -2458,6 +2465,8 @@ mod tests { #[gpui::test] fn test_messages_for_offsets(cx: &mut AppContext) { + cx.set_global(SettingsStore::test(cx)); + init(cx); let registry = Arc::new(LanguageRegistry::test()); let conversation = cx.add_model(|cx| Conversation::new(Default::default(), registry, cx)); let buffer = conversation.read(cx).buffer.clone(); @@ -2538,6 +2547,8 @@ mod tests { #[gpui::test] fn test_serialization(cx: &mut AppContext) { + cx.set_global(SettingsStore::test(cx)); + init(cx); let registry = Arc::new(LanguageRegistry::test()); let conversation = cx.add_model(|cx| Conversation::new(Default::default(), registry.clone(), cx)); diff --git a/crates/ai/src/assistant_settings.rs b/crates/ai/src/assistant_settings.rs index 04ba8fb946..05d8d9ffeb 100644 --- a/crates/ai/src/assistant_settings.rs +++ b/crates/ai/src/assistant_settings.rs @@ -3,6 +3,37 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use settings::Setting; +#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq)] +pub enum OpenAIModel { + #[serde(rename = "gpt-3.5-turbo-0613")] + ThreePointFiveTurbo, + #[serde(rename = "gpt-4-0613")] + Four, +} + +impl OpenAIModel { + pub fn full_name(&self) -> &'static str { + match self { + OpenAIModel::ThreePointFiveTurbo => "gpt-3.5-turbo-0613", + OpenAIModel::Four => "gpt-4-0613", + } + } + + pub fn short_name(&self) -> &'static str { + match self { + OpenAIModel::ThreePointFiveTurbo => "gpt-3.5-turbo", + OpenAIModel::Four => "gpt-4", + } + } + + pub fn cycle(&self) -> Self { + match self { + OpenAIModel::ThreePointFiveTurbo => OpenAIModel::Four, + OpenAIModel::Four => OpenAIModel::ThreePointFiveTurbo, + } + } +} + #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] #[serde(rename_all = "snake_case")] pub enum AssistantDockPosition { @@ -17,6 +48,7 @@ pub struct AssistantSettings { pub dock: AssistantDockPosition, pub default_width: f32, pub default_height: f32, + pub default_open_ai_model: OpenAIModel, } #[derive(Clone, Default, Serialize, Deserialize, JsonSchema, Debug)] @@ -25,6 +57,7 @@ pub struct AssistantSettingsContent { pub dock: Option, pub default_width: Option, pub default_height: Option, + pub default_open_ai_model: Option, } impl Setting for AssistantSettings { diff --git a/crates/audio/Cargo.toml b/crates/audio/Cargo.toml index 182e421eb8..36135a1e76 100644 --- a/crates/audio/Cargo.toml +++ b/crates/audio/Cargo.toml @@ -13,7 +13,7 @@ gpui = { path = "../gpui" } collections = { path = "../collections" } util = { path = "../util" } -rodio = "0.17.1" +rodio ={version = "0.17.1", default-features=false, features = ["wav"]} log.workspace = true diff --git a/crates/call/src/call.rs b/crates/call/src/call.rs index 3ac29bfc85..5fef53fa81 100644 --- a/crates/call/src/call.rs +++ b/crates/call/src/call.rs @@ -274,7 +274,7 @@ impl ActiveCall { .borrow_mut() .take() .ok_or_else(|| anyhow!("no incoming call"))?; - Self::report_call_event_for_room("decline incoming", call.room_id, &self.client, cx); + Self::report_call_event_for_room("decline incoming", call.room_id, None, &self.client, cx); self.client.send(proto::DeclineCall { room_id: call.room_id, })?; @@ -406,19 +406,31 @@ impl ActiveCall { fn report_call_event(&self, operation: &'static str, cx: &AppContext) { if let Some(room) = self.room() { - Self::report_call_event_for_room(operation, room.read(cx).id(), &self.client, cx) + let room = room.read(cx); + Self::report_call_event_for_room( + operation, + room.id(), + room.channel_id(), + &self.client, + cx, + ) } } pub fn report_call_event_for_room( operation: &'static str, room_id: u64, + channel_id: Option, client: &Arc, cx: &AppContext, ) { let telemetry = client.telemetry(); let telemetry_settings = *settings::get::(cx); - let event = ClickhouseEvent::Call { operation, room_id }; + let event = ClickhouseEvent::Call { + operation, + room_id, + channel_id, + }; telemetry.report_clickhouse_event(event, telemetry_settings); } } diff --git a/crates/client/src/telemetry.rs b/crates/client/src/telemetry.rs index dc5154d96f..48886377ba 100644 --- a/crates/client/src/telemetry.rs +++ b/crates/client/src/telemetry.rs @@ -74,6 +74,7 @@ pub enum ClickhouseEvent { Call { operation: &'static str, room_id: u64, + channel_id: Option, }, } diff --git a/crates/collab/Cargo.toml b/crates/collab/Cargo.toml index fc8c1644cd..b8d0c26960 100644 --- a/crates/collab/Cargo.toml +++ b/crates/collab/Cargo.toml @@ -3,7 +3,7 @@ authors = ["Nathan Sobo "] default-run = "collab" edition = "2021" name = "collab" -version = "0.17.0" +version = "0.18.0" publish = false [[bin]] diff --git a/crates/collab_ui/src/collab_titlebar_item.rs b/crates/collab_ui/src/collab_titlebar_item.rs index e4faa3b9c9..684ddca08d 100644 --- a/crates/collab_ui/src/collab_titlebar_item.rs +++ b/crates/collab_ui/src/collab_titlebar_item.rs @@ -1096,7 +1096,7 @@ impl CollabTitlebarItem { style } - fn render_face( + fn render_face( avatar: Arc, avatar_style: AvatarStyle, background_color: Color, diff --git a/crates/collab_ui/src/collab_ui.rs b/crates/collab_ui/src/collab_ui.rs index 0fed2e0ef9..5420dd1db5 100644 --- a/crates/collab_ui/src/collab_ui.rs +++ b/crates/collab_ui/src/collab_ui.rs @@ -49,6 +49,7 @@ pub fn toggle_screen_sharing(_: &ToggleScreenSharing, cx: &mut AppContext) { ActiveCall::report_call_event_for_room( "disable screen share", room.id(), + room.channel_id(), &client, cx, ); @@ -57,6 +58,7 @@ pub fn toggle_screen_sharing(_: &ToggleScreenSharing, cx: &mut AppContext) { ActiveCall::report_call_event_for_room( "enable screen share", room.id(), + room.channel_id(), &client, cx, ); @@ -73,11 +75,18 @@ pub fn toggle_mute(_: &ToggleMute, cx: &mut AppContext) { let client = call.client(); room.update(cx, |room, cx| { if room.is_muted(cx) { - ActiveCall::report_call_event_for_room("enable microphone", room.id(), &client, cx); + ActiveCall::report_call_event_for_room( + "enable microphone", + room.id(), + room.channel_id(), + &client, + cx, + ); } else { ActiveCall::report_call_event_for_room( "disable microphone", room.id(), + room.channel_id(), &client, cx, ); diff --git a/crates/collab_ui/src/notifications.rs b/crates/collab_ui/src/notifications.rs index 9258ad3ab1..9aff3a3522 100644 --- a/crates/collab_ui/src/notifications.rs +++ b/crates/collab_ui/src/notifications.rs @@ -2,14 +2,14 @@ use client::User; use gpui::{ elements::*, platform::{CursorStyle, MouseButton}, - AnyElement, Element, View, ViewContext, + AnyElement, Element, ViewContext, }; use std::sync::Arc; enum Dismiss {} enum Button {} -pub fn render_user_notification( +pub fn render_user_notification( user: Arc, title: &'static str, body: Option<&'static str>, @@ -19,7 +19,6 @@ pub fn render_user_notification( ) -> AnyElement where F: 'static + Fn(&mut V, &mut ViewContext), - V: View, { let theme = theme::current(cx).clone(); let theme = &theme.contact_notification; diff --git a/crates/component_test/src/component_test.rs b/crates/component_test/src/component_test.rs index 30fd431290..9f6b4918b9 100644 --- a/crates/component_test/src/component_test.rs +++ b/crates/component_test/src/component_test.rs @@ -1,6 +1,5 @@ use gpui::{ actions, - color::Color, elements::{Component, Flex, ParentElement, SafeStylable}, AppContext, Element, Entity, ModelHandle, Task, View, ViewContext, ViewHandle, WeakViewHandle, }; @@ -97,7 +96,7 @@ impl View for ComponentTest { } impl Item for ComponentTest { - fn tab_content( + fn tab_content( &self, _: Option, style: &theme::Tab, diff --git a/crates/diagnostics/src/diagnostics.rs b/crates/diagnostics/src/diagnostics.rs index 16a7340fae..0e5b714f09 100644 --- a/crates/diagnostics/src/diagnostics.rs +++ b/crates/diagnostics/src/diagnostics.rs @@ -538,7 +538,7 @@ impl ProjectDiagnosticsEditor { } impl Item for ProjectDiagnosticsEditor { - fn tab_content( + fn tab_content( &self, _detail: Option, style: &theme::Tab, @@ -735,7 +735,7 @@ fn diagnostic_header_renderer(diagnostic: Diagnostic) -> RenderBlock { }) } -pub(crate) fn render_summary( +pub(crate) fn render_summary( summary: &DiagnosticSummary, text_style: &TextStyle, theme: &theme::ProjectDiagnostics, diff --git a/crates/drag_and_drop/src/drag_and_drop.rs b/crates/drag_and_drop/src/drag_and_drop.rs index 59b0bc89e2..197c9918f5 100644 --- a/crates/drag_and_drop/src/drag_and_drop.rs +++ b/crates/drag_and_drop/src/drag_and_drop.rs @@ -11,7 +11,7 @@ use gpui::{ const DEAD_ZONE: f32 = 4.; -enum State { +enum State { Down { region_offset: Vector2F, region: RectF, @@ -31,7 +31,7 @@ enum State { Canceled, } -impl Clone for State { +impl Clone for State { fn clone(&self) -> Self { match self { &State::Down { @@ -68,12 +68,12 @@ impl Clone for State { } } -pub struct DragAndDrop { +pub struct DragAndDrop { containers: HashSet>, currently_dragged: Option>, } -impl Default for DragAndDrop { +impl Default for DragAndDrop { fn default() -> Self { Self { containers: Default::default(), @@ -82,7 +82,7 @@ impl Default for DragAndDrop { } } -impl DragAndDrop { +impl DragAndDrop { pub fn register_container(&mut self, handle: WeakViewHandle) { self.containers.insert(handle); } @@ -291,7 +291,7 @@ impl DragAndDrop { } } -pub trait Draggable { +pub trait Draggable { fn as_draggable( self, payload: P, @@ -301,7 +301,7 @@ pub trait Draggable { Self: Sized; } -impl Draggable for MouseEventHandler { +impl Draggable for MouseEventHandler { fn as_draggable( self, payload: P, diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index a38145f48c..67279b1ba6 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -1736,6 +1736,31 @@ impl Editor { }); } + pub fn edit_with_block_indent( + &mut self, + edits: I, + original_indent_columns: Vec, + cx: &mut ViewContext, + ) where + I: IntoIterator, T)>, + S: ToOffset, + T: Into>, + { + if self.read_only { + return; + } + + self.buffer.update(cx, |buffer, cx| { + buffer.edit( + edits, + Some(AutoindentMode::Block { + original_indent_columns, + }), + cx, + ) + }); + } + fn select(&mut self, phase: SelectPhase, cx: &mut ViewContext) { self.hide_context_menu(cx); @@ -2667,7 +2692,6 @@ impl Editor { false }); } - fn completion_query(buffer: &MultiBufferSnapshot, position: impl ToOffset) -> Option { let offset = position.to_offset(buffer); let (word_range, kind) = buffer.surrounding_word(offset); @@ -4742,6 +4766,7 @@ impl Editor { let mut clipboard_selections = Vec::with_capacity(selections.len()); { let max_point = buffer.max_point(); + let mut is_first = true; for selection in &mut selections { let is_entire_line = selection.is_empty() || self.selections.line_mode; if is_entire_line { @@ -4749,6 +4774,11 @@ impl Editor { selection.end = cmp::min(max_point, Point::new(selection.end.row + 1, 0)); selection.goal = SelectionGoal::None; } + if is_first { + is_first = false; + } else { + text += "\n"; + } let mut len = 0; for chunk in buffer.text_for_range(selection.start..selection.end) { text.push_str(chunk); @@ -4779,6 +4809,7 @@ impl Editor { let mut clipboard_selections = Vec::with_capacity(selections.len()); { let max_point = buffer.max_point(); + let mut is_first = true; for selection in selections.iter() { let mut start = selection.start; let mut end = selection.end; @@ -4787,6 +4818,11 @@ impl Editor { start = Point::new(start.row, 0); end = cmp::min(max_point, Point::new(end.row + 1, 0)); } + if is_first { + is_first = false; + } else { + text += "\n"; + } let mut len = 0; for chunk in buffer.text_for_range(start..end) { text.push_str(chunk); @@ -4806,7 +4842,7 @@ impl Editor { pub fn paste(&mut self, _: &Paste, cx: &mut ViewContext) { self.transact(cx, |this, cx| { if let Some(item) = cx.read_from_clipboard() { - let mut clipboard_text = Cow::Borrowed(item.text()); + let clipboard_text = Cow::Borrowed(item.text()); if let Some(mut clipboard_selections) = item.metadata::>() { let old_selections = this.selections.all::(cx); let all_selections_were_entire_line = @@ -4814,18 +4850,7 @@ impl Editor { let first_selection_indent_column = clipboard_selections.first().map(|s| s.first_line_indent); if clipboard_selections.len() != old_selections.len() { - let mut newline_separated_text = String::new(); - let mut clipboard_selections = clipboard_selections.drain(..).peekable(); - let mut ix = 0; - while let Some(clipboard_selection) = clipboard_selections.next() { - newline_separated_text - .push_str(&clipboard_text[ix..ix + clipboard_selection.len]); - ix += clipboard_selection.len; - if clipboard_selections.peek().is_some() { - newline_separated_text.push('\n'); - } - } - clipboard_text = Cow::Owned(newline_separated_text); + clipboard_selections.drain(..); } this.buffer.update(cx, |buffer, cx| { @@ -4841,8 +4866,9 @@ impl Editor { if let Some(clipboard_selection) = clipboard_selections.get(ix) { let end_offset = start_offset + clipboard_selection.len; to_insert = &clipboard_text[start_offset..end_offset]; + dbg!(start_offset, end_offset, &clipboard_text, &to_insert); entire_line = clipboard_selection.is_entire_line; - start_offset = end_offset; + start_offset = end_offset + 1; original_indent_column = Some(clipboard_selection.first_line_indent); } else { @@ -8537,6 +8563,7 @@ fn build_style( font_size, font_properties, underline: Default::default(), + soft_wrap: false, }, placeholder_text: None, line_height_scalar, diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index 04f45921d7..0f26e5819c 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -605,7 +605,7 @@ impl EditorElement { visible_bounds: RectF, layout: &mut LayoutState, editor: &mut Editor, - cx: &mut ViewContext, + cx: &mut PaintContext, ) { let line_height = layout.position_map.line_height; @@ -760,7 +760,7 @@ impl EditorElement { visible_bounds: RectF, layout: &mut LayoutState, editor: &mut Editor, - cx: &mut ViewContext, + cx: &mut PaintContext, ) { let style = &self.style; let local_replica_id = editor.replica_id(cx); @@ -1337,7 +1337,7 @@ impl EditorElement { visible_bounds: RectF, layout: &mut LayoutState, editor: &mut Editor, - cx: &mut ViewContext, + cx: &mut PaintContext, ) { let scroll_position = layout.position_map.snapshot.scroll_position(); let scroll_left = scroll_position.x() * layout.position_map.em_width; diff --git a/crates/editor/src/items.rs b/crates/editor/src/items.rs index b99977a60e..668ea48203 100644 --- a/crates/editor/src/items.rs +++ b/crates/editor/src/items.rs @@ -561,7 +561,7 @@ impl Item for Editor { } } - fn tab_content( + fn tab_content( &self, detail: Option, style: &theme::Tab, @@ -1028,7 +1028,7 @@ impl SearchableItem for Editor { if let Some((_, _, excerpt_buffer)) = buffer.as_singleton() { ranges.extend( query - .search(excerpt_buffer.as_rope()) + .search(excerpt_buffer, None) .await .into_iter() .map(|range| { @@ -1038,17 +1038,22 @@ impl SearchableItem for Editor { } else { for excerpt in buffer.excerpt_boundaries_in_range(0..buffer.len()) { let excerpt_range = excerpt.range.context.to_offset(&excerpt.buffer); - let rope = excerpt.buffer.as_rope().slice(excerpt_range.clone()); - ranges.extend(query.search(&rope).await.into_iter().map(|range| { - let start = excerpt - .buffer - .anchor_after(excerpt_range.start + range.start); - let end = excerpt - .buffer - .anchor_before(excerpt_range.start + range.end); - buffer.anchor_in_excerpt(excerpt.id.clone(), start) - ..buffer.anchor_in_excerpt(excerpt.id.clone(), end) - })); + ranges.extend( + query + .search(&excerpt.buffer, Some(excerpt_range.clone())) + .await + .into_iter() + .map(|range| { + let start = excerpt + .buffer + .anchor_after(excerpt_range.start + range.start); + let end = excerpt + .buffer + .anchor_before(excerpt_range.start + range.end); + buffer.anchor_in_excerpt(excerpt.id.clone(), start) + ..buffer.anchor_in_excerpt(excerpt.id.clone(), end) + }), + ); } } ranges diff --git a/crates/editor/src/movement.rs b/crates/editor/src/movement.rs index 4eec92c8eb..6b3032b2a3 100644 --- a/crates/editor/src/movement.rs +++ b/crates/editor/src/movement.rs @@ -176,14 +176,21 @@ pub fn line_end( } pub fn previous_word_start(map: &DisplaySnapshot, point: DisplayPoint) -> DisplayPoint { + let raw_point = point.to_point(map); + let language = map.buffer_snapshot.language_at(raw_point); + find_preceding_boundary(map, point, |left, right| { - (char_kind(left) != char_kind(right) && !right.is_whitespace()) || left == '\n' + (char_kind(language, left) != char_kind(language, right) && !right.is_whitespace()) + || left == '\n' }) } pub fn previous_subword_start(map: &DisplaySnapshot, point: DisplayPoint) -> DisplayPoint { + let raw_point = point.to_point(map); + let language = map.buffer_snapshot.language_at(raw_point); find_preceding_boundary(map, point, |left, right| { - let is_word_start = char_kind(left) != char_kind(right) && !right.is_whitespace(); + let is_word_start = + char_kind(language, left) != char_kind(language, right) && !right.is_whitespace(); let is_subword_start = left == '_' && right != '_' || left.is_lowercase() && right.is_uppercase(); is_word_start || is_subword_start || left == '\n' @@ -191,14 +198,20 @@ pub fn previous_subword_start(map: &DisplaySnapshot, point: DisplayPoint) -> Dis } pub fn next_word_end(map: &DisplaySnapshot, point: DisplayPoint) -> DisplayPoint { + let raw_point = point.to_point(map); + let language = map.buffer_snapshot.language_at(raw_point); find_boundary(map, point, |left, right| { - (char_kind(left) != char_kind(right) && !left.is_whitespace()) || right == '\n' + (char_kind(language, left) != char_kind(language, right) && !left.is_whitespace()) + || right == '\n' }) } pub fn next_subword_end(map: &DisplaySnapshot, point: DisplayPoint) -> DisplayPoint { + let raw_point = point.to_point(map); + let language = map.buffer_snapshot.language_at(raw_point); find_boundary(map, point, |left, right| { - let is_word_end = (char_kind(left) != char_kind(right)) && !left.is_whitespace(); + let is_word_end = + (char_kind(language, left) != char_kind(language, right)) && !left.is_whitespace(); let is_subword_end = left != '_' && right == '_' || left.is_lowercase() && right.is_uppercase(); is_word_end || is_subword_end || right == '\n' @@ -385,10 +398,15 @@ pub fn find_boundary_in_line( } pub fn is_inside_word(map: &DisplaySnapshot, point: DisplayPoint) -> bool { + let raw_point = point.to_point(map); + let language = map.buffer_snapshot.language_at(raw_point); let ix = map.clip_point(point, Bias::Left).to_offset(map, Bias::Left); let text = &map.buffer_snapshot; - let next_char_kind = text.chars_at(ix).next().map(char_kind); - let prev_char_kind = text.reversed_chars_at(ix).next().map(char_kind); + let next_char_kind = text.chars_at(ix).next().map(|c| char_kind(language, c)); + let prev_char_kind = text + .reversed_chars_at(ix) + .next() + .map(|c| char_kind(language, c)); prev_char_kind.zip(next_char_kind) == Some((CharKind::Word, CharKind::Word)) } diff --git a/crates/editor/src/multi_buffer.rs b/crates/editor/src/multi_buffer.rs index 8417c411f2..9dd40af898 100644 --- a/crates/editor/src/multi_buffer.rs +++ b/crates/editor/src/multi_buffer.rs @@ -1346,10 +1346,7 @@ impl MultiBuffer { .map(|state| state.buffer.clone()) } - pub fn is_completion_trigger(&self, position: T, text: &str, cx: &AppContext) -> bool - where - T: ToOffset, - { + pub fn is_completion_trigger(&self, position: Anchor, text: &str, cx: &AppContext) -> bool { let mut chars = text.chars(); let char = if let Some(char) = chars.next() { char @@ -1360,7 +1357,9 @@ impl MultiBuffer { return false; } - if char.is_alphanumeric() || char == '_' { + let language = self.language_at(position.clone(), cx); + + if char_kind(language.as_ref(), char) == CharKind::Word { return true; } @@ -1865,13 +1864,16 @@ impl MultiBufferSnapshot { let mut end = start; let mut next_chars = self.chars_at(start).peekable(); let mut prev_chars = self.reversed_chars_at(start).peekable(); + + let language = self.language_at(start); + let kind = |c| char_kind(language, c); let word_kind = cmp::max( - prev_chars.peek().copied().map(char_kind), - next_chars.peek().copied().map(char_kind), + prev_chars.peek().copied().map(kind), + next_chars.peek().copied().map(kind), ); for ch in prev_chars { - if Some(char_kind(ch)) == word_kind && ch != '\n' { + if Some(kind(ch)) == word_kind && ch != '\n' { start -= ch.len_utf8(); } else { break; @@ -1879,7 +1881,7 @@ impl MultiBufferSnapshot { } for ch in next_chars { - if Some(char_kind(ch)) == word_kind && ch != '\n' { + if Some(kind(ch)) == word_kind && ch != '\n' { end += ch.len_utf8(); } else { break; diff --git a/crates/editor/src/test/editor_lsp_test_context.rs b/crates/editor/src/test/editor_lsp_test_context.rs index 83aaa3b703..668d6abf21 100644 --- a/crates/editor/src/test/editor_lsp_test_context.rs +++ b/crates/editor/src/test/editor_lsp_test_context.rs @@ -6,6 +6,7 @@ use std::{ use anyhow::Result; +use collections::HashSet; use futures::Future; use gpui::{json, ViewContext, ViewHandle}; use indoc::indoc; @@ -154,10 +155,23 @@ impl<'a> EditorLspTestContext<'a> { capabilities: lsp::ServerCapabilities, cx: &'a mut gpui::TestAppContext, ) -> EditorLspTestContext<'a> { + let mut word_characters: HashSet = Default::default(); + word_characters.insert('$'); + word_characters.insert('#'); let language = Language::new( LanguageConfig { name: "Typescript".into(), path_suffixes: vec!["ts".to_string()], + brackets: language::BracketPairConfig { + pairs: vec![language::BracketPair { + start: "{".to_string(), + end: "}".to_string(), + close: true, + newline: true, + }], + disabled_scopes_by_bracket_ix: Default::default(), + }, + word_characters, ..Default::default() }, Some(tree_sitter_typescript::language_typescript()), @@ -169,6 +183,23 @@ impl<'a> EditorLspTestContext<'a> { ("{" @open "}" @close) ("<" @open ">" @close) ("\"" @open "\"" @close)"#})), + indents: Some(Cow::from(indoc! {r#" + [ + (call_expression) + (assignment_expression) + (member_expression) + (lexical_declaration) + (variable_declaration) + (assignment_expression) + (if_statement) + (for_statement) + ] @indent + + (_ "[" "]" @end) @indent + (_ "<" ">" @end) @indent + (_ "{" "}" @end) @indent + (_ "(" ")" @end) @indent + "#})), ..Default::default() }) .expect("Could not parse queries"); diff --git a/crates/feedback/src/feedback_editor.rs b/crates/feedback/src/feedback_editor.rs index 47cb90875a..a717223f6d 100644 --- a/crates/feedback/src/feedback_editor.rs +++ b/crates/feedback/src/feedback_editor.rs @@ -268,7 +268,7 @@ impl Item for FeedbackEditor { Some("Send Feedback".into()) } - fn tab_content( + fn tab_content( &self, _: Option, style: &theme::Tab, diff --git a/crates/gpui/Cargo.toml b/crates/gpui/Cargo.toml index 5bd7d03184..24397f6193 100644 --- a/crates/gpui/Cargo.toml +++ b/crates/gpui/Cargo.toml @@ -39,6 +39,7 @@ pathfinder_color = "0.5" pathfinder_geometry = "0.5" postage.workspace = true rand.workspace = true +refineable.workspace = true resvg = "0.14" schemars = "0.8" seahash = "4.1" @@ -47,6 +48,7 @@ serde_derive.workspace = true serde_json.workspace = true smallvec.workspace = true smol.workspace = true +taffy = { git = "https://github.com/DioxusLabs/taffy", rev = "dab541d6104d58e2e10ce90c4a1dad0b703160cd", features = ["flexbox"] } time.workspace = true tiny-skia = "0.5" usvg = { version = "0.14", features = [] } diff --git a/crates/gpui/examples/text.rs b/crates/gpui/examples/text.rs index a269706cc5..bda70a49dc 100644 --- a/crates/gpui/examples/text.rs +++ b/crates/gpui/examples/text.rs @@ -58,6 +58,7 @@ impl gpui::View for TextView { font_family_id: family, underline: Default::default(), font_properties: Default::default(), + soft_wrap: false, }, ) .with_highlights(vec![(17..26, underline), (34..40, underline)]) diff --git a/crates/gpui/playground/Cargo.lock b/crates/gpui/playground/Cargo.lock new file mode 100644 index 0000000000..95e0b10c62 --- /dev/null +++ b/crates/gpui/playground/Cargo.lock @@ -0,0 +1,2919 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "adler32" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" + +[[package]] +name = "aho-corasick" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" +dependencies = [ + "memchr", +] + +[[package]] +name = "anyhow" +version = "1.0.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" + +[[package]] +name = "arrayref" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" + +[[package]] +name = "arrayvec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" + +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + +[[package]] +name = "async-channel" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" +dependencies = [ + "concurrent-queue", + "event-listener", + "futures-core", +] + +[[package]] +name = "async-executor" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fa3dc5f2a8564f07759c008b9109dc0d39de92a88d5588b8a5036d286383afb" +dependencies = [ + "async-lock", + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "slab", +] + +[[package]] +name = "async-fs" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "279cf904654eeebfa37ac9bb1598880884924aab82e290aa65c9e77a0e142e06" +dependencies = [ + "async-lock", + "autocfg", + "blocking", + "futures-lite", +] + +[[package]] +name = "async-io" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" +dependencies = [ + "async-lock", + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-lite", + "log", + "parking", + "polling", + "rustix", + "slab", + "socket2", + "waker-fn", +] + +[[package]] +name = "async-lock" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa24f727524730b077666307f2734b4a1a1c57acb79193127dcc8914d5242dd7" +dependencies = [ + "event-listener", +] + +[[package]] +name = "async-net" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4051e67316bc7eff608fe723df5d32ed639946adcd69e07df41fd42a7b411f1f" +dependencies = [ + "async-io", + "autocfg", + "blocking", + "futures-lite", +] + +[[package]] +name = "async-process" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a9d28b1d97e08915212e2e45310d47854eafa69600756fc735fb788f75199c9" +dependencies = [ + "async-io", + "async-lock", + "autocfg", + "blocking", + "cfg-if", + "event-listener", + "futures-lite", + "rustix", + "signal-hook", + "windows-sys", +] + +[[package]] +name = "async-task" +version = "4.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc7ab41815b3c653ccd2978ec3255c81349336702dfdf62ee6f7069b12a3aae" + +[[package]] +name = "atomic" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba" + +[[package]] +name = "atomic-waker" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1181e1e0d1fce796a03db1ae795d67167da795f9cf4a39c37589e85ef57f26d3" + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "backtrace" +version = "0.3.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide 0.7.1", + "object", + "rustc-demangle", +] + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "bindgen" +version = "0.65.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfdf7b466f9a4903edc73f95d6d2bcd5baf8ae620638762244d3f60143643cc5" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "lazy_static", + "lazycell", + "log", + "peeking_take_while", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn 2.0.25", + "which", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "blocking" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77231a1c8f801696fc0123ec6150ce92cffb8e164a02afb9c8ddee0e9b65ad65" +dependencies = [ + "async-channel", + "async-lock", + "async-task", + "atomic-waker", + "fastrand", + "futures-lite", + "log", +] + +[[package]] +name = "bstr" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6798148dccfbff0fae41c7574d2fa8f1ef3492fba0face179de5d8d447d67b05" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "bytemuck" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea" + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "bytes" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" + +[[package]] +name = "castaway" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2698f953def977c68f935bb0dfa959375ad4638570e969e2f1e9f433cbf1af6" + +[[package]] +name = "cc" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clang-sys" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f" +dependencies = [ + "glob", + "libc", + "libloading 0.7.4", +] + +[[package]] +name = "cmake" +version = "0.1.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130" +dependencies = [ + "cc", +] + +[[package]] +name = "cocoa" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f425db7937052c684daec3bd6375c8abe2d146dca4b8b143d6db777c39138f3a" +dependencies = [ + "bitflags", + "block", + "cocoa-foundation", + "core-foundation", + "core-graphics", + "foreign-types", + "libc", + "objc", +] + +[[package]] +name = "cocoa-foundation" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "931d3837c286f56e3c58423ce4eba12d08db2374461a785c86f672b08b5650d6" +dependencies = [ + "bitflags", + "block", + "core-foundation", + "core-graphics-types", + "foreign-types", + "libc", + "objc", +] + +[[package]] +name = "collections" +version = "0.1.0" + +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + +[[package]] +name = "concurrent-queue" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62ec6771ecfa0762d24683ee5a32ad78487a3d3afdc0fb8cae19d2c5deb50b7c" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "const-cstr" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3d0b5ff30645a68f35ece8cea4556ca14ef8a1651455f789a099a0513532a6" + +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", + "uuid 0.5.1", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" + +[[package]] +name = "core-graphics" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" +dependencies = [ + "bitflags", + "core-foundation", + "core-graphics-types", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bb142d41022986c1d8ff29103a1411c8a3dfad3552f87a4f8dc50d61d4f4e33" +dependencies = [ + "bitflags", + "core-foundation", + "libc", +] + +[[package]] +name = "core-text" +version = "19.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d74ada66e07c1cefa18f8abfba765b486f250de2e4a999e5727fc0dd4b4a25" +dependencies = [ + "core-foundation", + "core-graphics", + "foreign-types", + "libc", +] + +[[package]] +name = "cpufeatures" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-queue" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "ctor" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "curl" +version = "0.4.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "509bd11746c7ac09ebd19f0b17782eae80aadee26237658a6b4808afb5c11a22" +dependencies = [ + "curl-sys", + "libc", + "openssl-probe", + "openssl-sys", + "schannel", + "socket2", + "winapi", +] + +[[package]] +name = "curl-sys" +version = "0.4.63+curl-8.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aeb0fef7046022a1e2ad67a004978f0e3cacb9e3123dc62ce768f92197b771dc" +dependencies = [ + "cc", + "libc", + "libz-sys", + "openssl-sys", + "pkg-config", + "vcpkg", + "winapi", +] + +[[package]] +name = "data-url" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a30bfce702bcfa94e906ef82421f2c0e61c076ad76030c16ee5d2e9a32fe193" +dependencies = [ + "matches", +] + +[[package]] +name = "deflate" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73770f8e1fe7d64df17ca66ad28994a0a623ea497fa69486e14984e715c5d174" +dependencies = [ + "adler32", + "byteorder", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "dirs" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30baa043103c9d0c2a57cf537cc2f35623889dc0d405e6c3cccfadbc81c71309" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "dlib" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" +dependencies = [ + "libloading 0.8.0", +] + +[[package]] +name = "dwrote" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439a1c2ba5611ad3ed731280541d36d2e9c4ac5e7fb818a27b604bdc5a6aa65b" +dependencies = [ + "lazy_static", + "libc", + "winapi", + "wio", +] + +[[package]] +name = "dyn-clone" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68b0cf012f1230e43cd00ebb729c6bb58707ecfa8ad08b52ef3a4ccd2697fc30" + +[[package]] +name = "either" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" + +[[package]] +name = "encoding_rs" +version = "0.8.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "erased-serde" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f94c0e13118e7d7533271f754a168ae8400e6a1cc043f2bfd53cc7290f1a1de3" +dependencies = [ + "serde", +] + +[[package]] +name = "errno" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +dependencies = [ + "errno-dragonfly", + "libc", + "windows-sys", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "etagere" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcf22f748754352918e082e0039335ee92454a5d62bcaf69b5e8daf5907d9644" +dependencies = [ + "euclid", + "svg_fmt", +] + +[[package]] +name = "euclid" +version = "0.22.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f253bc5c813ca05792837a0ff4b3a580336b224512d48f7eda1d7dd9210787" +dependencies = [ + "num-traits", +] + +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + +[[package]] +name = "flate2" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743" +dependencies = [ + "crc32fast", + "miniz_oxide 0.7.1", +] + +[[package]] +name = "float-cmp" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75224bec9bfe1a65e2d34132933f2de7fe79900c96a0174307554244ece8150e" + +[[package]] +name = "float-ord" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bad48618fdb549078c333a7a8528acb57af271d0433bdecd523eb620628364e" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "font-kit" +version = "0.11.0" +source = "git+https://github.com/zed-industries/font-kit?rev=b2f77d56f450338aa4f7dd2f0197d8c9acb0cf18#b2f77d56f450338aa4f7dd2f0197d8c9acb0cf18" +dependencies = [ + "bitflags", + "byteorder", + "core-foundation", + "core-graphics", + "core-text", + "dirs-next", + "dwrote", + "float-ord", + "freetype", + "lazy_static", + "libc", + "log", + "pathfinder_geometry", + "pathfinder_simd", + "walkdir", + "winapi", + "yeslogic-fontconfig-sys", +] + +[[package]] +name = "fontdb" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e58903f4f8d5b58c7d300908e4ebe5289c1bfdf5587964330f12023b8ff17fd1" +dependencies = [ + "log", + "memmap2", + "ttf-parser 0.12.3", +] + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "freetype" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bee38378a9e3db1cc693b4f88d166ae375338a0ff75cb8263e1c601d51f35dc6" +dependencies = [ + "freetype-sys", + "libc", +] + +[[package]] +name = "freetype-sys" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a37d4011c0cc628dfa766fcc195454f4b068d7afdc2adfd28861191d866e731a" +dependencies = [ + "cmake", + "libc", + "pkg-config", +] + +[[package]] +name = "futures" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" + +[[package]] +name = "futures-executor" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" + +[[package]] +name = "futures-lite" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] + +[[package]] +name = "futures-macro" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.25", +] + +[[package]] +name = "futures-sink" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" + +[[package]] +name = "futures-task" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" + +[[package]] +name = "futures-util" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gif" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3edd93c6756b4dfaf2709eafcc345ba2636565295c198a9cfbf75fa5e3e00b06" +dependencies = [ + "color_quant", + "weezl", +] + +[[package]] +name = "gimli" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "globset" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1391ab1f92ffcc08911957149833e682aa3fe252b9f45f966d2ef972274c97df" +dependencies = [ + "aho-corasick", + "bstr", + "fnv", + "log", + "regex", +] + +[[package]] +name = "gpui" +version = "0.1.0" +dependencies = [ + "anyhow", + "async-task", + "bindgen", + "block", + "cc", + "cocoa", + "collections", + "core-foundation", + "core-graphics", + "core-text", + "ctor", + "etagere", + "font-kit", + "foreign-types", + "futures", + "gpui_macros", + "image", + "itertools", + "lazy_static", + "log", + "media", + "metal", + "num_cpus", + "objc", + "ordered-float", + "parking", + "parking_lot 0.11.2", + "pathfinder_color", + "pathfinder_geometry", + "postage", + "rand", + "resvg", + "schemars", + "seahash", + "serde", + "serde_derive", + "serde_json", + "smallvec", + "smol", + "sqlez", + "sum_tree", + "time", + "tiny-skia", + "usvg", + "util", + "uuid 1.4.0", + "waker-fn", +] + +[[package]] +name = "gpui_macros" +version = "0.1.0" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "hashbrown" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" + +[[package]] +name = "hermit-abi" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" + +[[package]] +name = "http" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "idna" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "image" +version = "0.23.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24ffcb7e7244a9bf19d35bf2883b9c080c4ced3c07a9895572178cdb8f13f6a1" +dependencies = [ + "bytemuck", + "byteorder", + "color_quant", + "gif", + "jpeg-decoder", + "num-iter", + "num-rational", + "num-traits", + "png", + "scoped_threadpool", + "tiff", +] + +[[package]] +name = "indexmap" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "indoc" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa799dd5ed20a7e349f3b4639aa80d74549c81716d9ec4f994c9b5815598306" + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "io-lifetimes" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys", +] + +[[package]] +name = "isahc" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "334e04b4d781f436dc315cb1e7515bd96826426345d498149e4bde36b67f8ee9" +dependencies = [ + "async-channel", + "castaway", + "crossbeam-utils", + "curl", + "curl-sys", + "encoding_rs", + "event-listener", + "futures-lite", + "http", + "log", + "mime", + "once_cell", + "polling", + "slab", + "sluice", + "tracing", + "tracing-futures", + "url", + "waker-fn", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b02a5381cc465bd3041d84623d0fa3b66738b52b8e2fc3bab8ad63ab032f4a" + +[[package]] +name = "jpeg-decoder" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "229d53d58899083193af11e15917b5640cd40b29ff475a1fe4ef725deb02d0f2" +dependencies = [ + "rayon", +] + +[[package]] +name = "kurbo" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a53776d271cfb873b17c618af0298445c88afc52837f3e948fa3fafd131f449" +dependencies = [ + "arrayvec 0.7.4", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + +[[package]] +name = "libc" +version = "0.2.147" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" + +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if", + "winapi", +] + +[[package]] +name = "libloading" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d580318f95776505201b28cf98eb1fa5e4be3b689633ba6a3e6cd880ff22d8cb" +dependencies = [ + "cfg-if", + "windows-sys", +] + +[[package]] +name = "libsqlite3-sys" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "898745e570c7d0453cc1fbc4a701eb6c662ed54e8fec8b7d14be137ebeeb9d14" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "libz-sys" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56ee889ecc9568871456d42f603d6a0ce59ff328d291063a45cbdf0036baf6db" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "linux-raw-sys" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" + +[[package]] +name = "lock_api" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +dependencies = [ + "serde", + "value-bag", +] + +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + +[[package]] +name = "matches" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" + +[[package]] +name = "media" +version = "0.1.0" +dependencies = [ + "anyhow", + "bindgen", + "block", + "bytes", + "core-foundation", + "foreign-types", + "metal", + "objc", +] + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "memmap2" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "723e3ebdcdc5c023db1df315364573789f8857c11b631a2fdfad7c00f5c046b4" +dependencies = [ + "libc", +] + +[[package]] +name = "memoffset" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +dependencies = [ + "autocfg", +] + +[[package]] +name = "metal" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4598d719460ade24c7d91f335daf055bf2a7eec030728ce751814c50cdd6a26c" +dependencies = [ + "bitflags", + "block", + "cocoa-foundation", + "foreign-types", + "log", + "objc", +] + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435" +dependencies = [ + "adler32", +] + +[[package]] +name = "miniz_oxide" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +dependencies = [ + "adler", + "autocfg", +] + +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", + "objc_exception", +] + +[[package]] +name = "objc_exception" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4" +dependencies = [ + "cc", +] + +[[package]] +name = "object" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "374533b0e45f3a7ced10fcaeccca020e66656bc03dac384f852e4e5a7a8104a6" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "ordered-float" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7940cf2ca942593318d07fcf2596cdca60a85c9e7fab408a5e21a4f9dcd40d87" +dependencies = [ + "num-traits", +] + +[[package]] +name = "parking" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14f2252c834a40ed9bb5422029649578e63aa341ac401f74e719dd1afda8394e" + +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core 0.8.6", +] + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core 0.9.8", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall 0.2.16", + "smallvec", + "winapi", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.3.5", + "smallvec", + "windows-targets", +] + +[[package]] +name = "pathfinder_color" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69bdc0d277d559e35e1b374de56df9262a6b71e091ca04a8831a239f8c7f0c62" +dependencies = [ + "pathfinder_simd", +] + +[[package]] +name = "pathfinder_geometry" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b7e7b4ea703700ce73ebf128e1450eb69c3a8329199ffbfb9b2a0418e5ad3" +dependencies = [ + "log", + "pathfinder_simd", +] + +[[package]] +name = "pathfinder_simd" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39fe46acc5503595e5949c17b818714d26fdf9b4920eacf3b2947f0199f4a6ff" +dependencies = [ + "rustc_version", +] + +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + +[[package]] +name = "percent-encoding" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" + +[[package]] +name = "pest" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f73935e4d55e2abf7f130186537b19e7a4abc886a0252380b59248af473a3fc9" +dependencies = [ + "thiserror", + "ucd-trie", +] + +[[package]] +name = "pico-args" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db8bcd96cb740d03149cbad5518db9fd87126a10ab519c011893b1754134c468" + +[[package]] +name = "pin-project" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "030ad2bc4db10a8944cb0d837f158bdfec4d4a4873ab701a95046770d11f8842" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.25", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" + +[[package]] +name = "playground" +version = "0.1.0" +dependencies = [ + "gpui", +] + +[[package]] +name = "png" +version = "0.16.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6" +dependencies = [ + "bitflags", + "crc32fast", + "deflate", + "miniz_oxide 0.3.7", +] + +[[package]] +name = "polling" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" +dependencies = [ + "autocfg", + "bitflags", + "cfg-if", + "concurrent-queue", + "libc", + "log", + "pin-project-lite", + "windows-sys", +] + +[[package]] +name = "pollster" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5da3b0203fd7ee5720aa0b5e790b591aa5d3f41c3ed2c34a3a393382198af2f7" + +[[package]] +name = "postage" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af3fb618632874fb76937c2361a7f22afd393c982a2165595407edc75b06d3c1" +dependencies = [ + "atomic", + "crossbeam-queue", + "futures", + "log", + "parking_lot 0.12.1", + "pin-project", + "pollster", + "static_assertions", + "thiserror", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "prettyplease" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92139198957b410250d43fad93e630d956499a625c527eda65175c8680f83387" +dependencies = [ + "proc-macro2", + "syn 2.0.25", +] + +[[package]] +name = "proc-macro2" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78803b62cbf1f46fde80d7c0e803111524b9877184cfe7c3033659490ac7a7da" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rayon" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "num_cpus", +] + +[[package]] +name = "rctree" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be9e29cb19c8fe84169fcb07f8f11e66bc9e6e0280efd4715c54818296f8a4a8" + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_users" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +dependencies = [ + "getrandom", + "redox_syscall 0.2.16", + "thiserror", +] + +[[package]] +name = "regex" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" + +[[package]] +name = "resvg" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09697862c5c3f940cbaffef91969c62188b5c8ed385b0aef43a5ff01ddc8000f" +dependencies = [ + "jpeg-decoder", + "log", + "pico-args", + "png", + "rgb", + "svgfilters", + "tiny-skia", + "usvg", +] + +[[package]] +name = "rgb" +version = "0.8.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20ec2d3e3fc7a92ced357df9cebd5a10b6fb2aa1ee797bf7e9ce2f17dffc8f59" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "roxmltree" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "921904a62e410e37e215c40381b7117f830d9d89ba60ab5236170541dd25646b" +dependencies = [ + "xmlparser", +] + +[[package]] +name = "rust-embed" +version = "6.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a36224c3276f8c4ebc8c20f158eca7ca4359c8db89991c4925132aaaf6702661" +dependencies = [ + "rust-embed-impl", + "rust-embed-utils", + "walkdir", +] + +[[package]] +name = "rust-embed-impl" +version = "6.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49b94b81e5b2c284684141a2fb9e2a31be90638caf040bf9afbc5a0416afe1ac" +dependencies = [ + "proc-macro2", + "quote", + "rust-embed-utils", + "syn 2.0.25", + "walkdir", +] + +[[package]] +name = "rust-embed-utils" +version = "7.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d38ff6bf570dc3bb7100fce9f7b60c33fa71d80e88da3f2580df4ff2bdded74" +dependencies = [ + "globset", + "sha2", + "walkdir", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc_version" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "0.37.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "rustybuzz" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ab463a295d00f3692e0974a0bfd83c7a9bcd119e27e07c2beecdb1b44a09d10" +dependencies = [ + "bitflags", + "bytemuck", + "smallvec", + "ttf-parser 0.9.0", + "unicode-bidi-mirroring", + "unicode-ccc", + "unicode-general-category", + "unicode-script", +] + +[[package]] +name = "ryu" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe232bdf6be8c8de797b22184ee71118d63780ea42ac85b61d1baa6d3b782ae9" + +[[package]] +name = "safe_arch" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1ff3d6d9696af502cc3110dacce942840fb06ff4514cad92236ecc455f2ce05" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schannel" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "schemars" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02c613288622e5f0c3fdc5dbd4db1c5fbe752746b1d1a56a0630b78fd00de44f" +dependencies = [ + "dyn-clone", + "schemars_derive", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109da1e6b197438deb6db99952990c7f959572794b80ff93707d55a232545e7c" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 1.0.109", +] + +[[package]] +name = "scoped_threadpool" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "seahash" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" + +[[package]] +name = "semver" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver-parser" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" +dependencies = [ + "pest", +] + +[[package]] +name = "serde" +version = "1.0.171" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30e27d1e4fd7659406c492fd6cfaf2066ba8773de45ca75e855590f856dc34a9" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.171" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389894603bd18c46fa56231694f8d827779c0951a667087194cf9de94ed24682" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.25", +] + +[[package]] +name = "serde_derive_internals" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "serde_fmt" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d4ddca14104cd60529e8c7f7ba71a2c8acd8f7f5cfcdc2faf97eeb7c3010a4" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_json" +version = "1.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5062a995d481b2308b6064e9af76011f2921c35f97b0468811ed9f6cd91dfed" +dependencies = [ + "indexmap", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "shlex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" + +[[package]] +name = "signal-hook" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "732768f1176d21d09e076c23a93123d40bba92d50c4058da34d45c8de8e682b9" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +dependencies = [ + "libc", +] + +[[package]] +name = "simplecss" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a11be7c62927d9427e9f40f3444d5499d868648e2edbc4e2116de69e7ec0e89d" +dependencies = [ + "log", +] + +[[package]] +name = "siphasher" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" + +[[package]] +name = "slab" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +dependencies = [ + "autocfg", +] + +[[package]] +name = "sluice" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d7400c0eff44aa2fcb5e31a5f24ba9716ed90138769e4977a2ba6014ae63eb5" +dependencies = [ + "async-channel", + "futures-core", + "futures-io", +] + +[[package]] +name = "smallvec" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" + +[[package]] +name = "smol" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13f2b548cd8447f8de0fdf1c592929f70f4fc7039a05e47404b0d096ec6987a1" +dependencies = [ + "async-channel", + "async-executor", + "async-fs", + "async-io", + "async-lock", + "async-net", + "async-process", + "blocking", + "futures-lite", +] + +[[package]] +name = "socket2" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "sqlez" +version = "0.1.0" +dependencies = [ + "anyhow", + "futures", + "indoc", + "lazy_static", + "libsqlite3-sys", + "parking_lot 0.11.2", + "smol", + "thread_local", + "uuid 1.4.0", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "sum_tree" +version = "0.1.0" +dependencies = [ + "arrayvec 0.7.4", + "log", +] + +[[package]] +name = "sval" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b031320a434d3e9477ccf9b5756d57d4272937b8d22cb88af80b7633a1b78b1" + +[[package]] +name = "sval_buffer" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bf7e9412af26b342f3f2cc5cc4122b0105e9d16eb76046cd14ed10106cf6028" +dependencies = [ + "sval", + "sval_ref", +] + +[[package]] +name = "sval_dynamic" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0ef628e8a77a46ed3338db8d1b08af77495123cc229453084e47cd716d403cf" +dependencies = [ + "sval", +] + +[[package]] +name = "sval_fmt" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dc09e9364c2045ab5fa38f7b04d077b3359d30c4c2b3ec4bae67a358bd64326" +dependencies = [ + "itoa", + "ryu", + "sval", +] + +[[package]] +name = "sval_json" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ada6f627e38cbb8860283649509d87bc4a5771141daa41c78fd31f2b9485888d" +dependencies = [ + "itoa", + "ryu", + "sval", +] + +[[package]] +name = "sval_ref" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703ca1942a984bd0d9b5a4c0a65ab8b4b794038d080af4eb303c71bc6bf22d7c" +dependencies = [ + "sval", +] + +[[package]] +name = "sval_serde" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830926cd0581f7c3e5d51efae4d35c6b6fc4db583842652891ba2f1bed8db046" +dependencies = [ + "serde", + "sval", + "sval_buffer", + "sval_fmt", +] + +[[package]] +name = "svg_fmt" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fb1df15f412ee2e9dfc1c504260fa695c1c3f10fe9f4a6ee2d2184d7d6450e2" + +[[package]] +name = "svgfilters" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb0dce2fee79ac40c21dafba48565ff7a5fa275e23ffe9ce047a40c9574ba34e" +dependencies = [ + "float-cmp", + "rgb", +] + +[[package]] +name = "svgtypes" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c536faaff1a10837cfe373142583f6e27d81e96beba339147e77b67c9f260ff" +dependencies = [ + "float-cmp", + "siphasher", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15e3fc8c0c74267e2df136e5e5fb656a464158aa57624053375eb9c8c6e25ae2" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "take-until" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bdb6fa0dfa67b38c1e66b7041ba9dcf23b99d8121907cd31c807a332f7a0bbb" + +[[package]] +name = "thiserror" +version = "1.0.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a35fc5b8971143ca348fa6df4f024d4d55264f3468c71ad1c2f365b0a4d58c42" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "463fe12d7993d3b327787537ce8dd4dfa058de32fc2b195ef3cde03dc4771e8f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.25", +] + +[[package]] +name = "thread_local" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "tiff" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a53f4706d65497df0c4349241deddf35f84cee19c87ed86ea8ca590f4464437" +dependencies = [ + "jpeg-decoder", + "miniz_oxide 0.4.4", + "weezl", +] + +[[package]] +name = "time" +version = "0.3.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59e399c068f43a5d116fedaf73b203fa4f9c519f17e2b34f63221d3792f81446" +dependencies = [ + "itoa", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" + +[[package]] +name = "time-macros" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96ba15a897f3c86766b757e5ac7221554c6750054d74d5b28844fce5fb36a6c4" +dependencies = [ + "time-core", +] + +[[package]] +name = "tiny-skia" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bf81f2900d2e235220e6f31ec9f63ade6a7f59090c556d74fe949bb3b15e9fe" +dependencies = [ + "arrayref", + "arrayvec 0.5.2", + "bytemuck", + "cfg-if", + "png", + "safe_arch", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tracing" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +dependencies = [ + "cfg-if", + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.25", +] + +[[package]] +name = "tracing-core" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "tracing-futures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" +dependencies = [ + "pin-project", + "tracing", +] + +[[package]] +name = "ttf-parser" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62ddb402ac6c2af6f7a2844243887631c4e94b51585b229fcfddb43958cd55ca" + +[[package]] +name = "ttf-parser" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ae2f58a822f08abdaf668897e96a5656fe72f5a9ce66422423e8849384872e6" + +[[package]] +name = "typenum" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" + +[[package]] +name = "ucd-trie" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" + +[[package]] +name = "unicode-bidi" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" + +[[package]] +name = "unicode-bidi-mirroring" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56d12260fb92d52f9008be7e4bca09f584780eb2266dc8fecc6a192bec561694" + +[[package]] +name = "unicode-ccc" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc2520efa644f8268dce4dcd3050eaa7fc044fca03961e9998ac7e2e92b77cf1" + +[[package]] +name = "unicode-general-category" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f9af028e052a610d99e066b33304625dea9613170a2563314490a4e6ec5cf7f" + +[[package]] +name = "unicode-ident" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22049a19f4a68748a168c0fc439f9516686aa045927ff767eca0a85101fb6e73" + +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-script" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d817255e1bed6dfd4ca47258685d14d2bdcfbc64fdc9e3819bd5848057b8ecc" + +[[package]] +name = "unicode-vo" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1d386ff53b415b7fe27b50bb44679e2cc4660272694b7b6f3326d8480823a94" + +[[package]] +name = "url" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "usvg" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef8352f317d8f9a918ba5154797fb2a93e2730244041cf7d5be35148266adfa5" +dependencies = [ + "base64", + "data-url", + "flate2", + "fontdb", + "kurbo", + "log", + "memmap2", + "pico-args", + "rctree", + "roxmltree", + "rustybuzz", + "simplecss", + "siphasher", + "svgtypes", + "ttf-parser 0.12.3", + "unicode-bidi", + "unicode-script", + "unicode-vo", + "xmlwriter", +] + +[[package]] +name = "util" +version = "0.1.0" +dependencies = [ + "anyhow", + "backtrace", + "dirs", + "futures", + "isahc", + "lazy_static", + "log", + "rand", + "rust-embed", + "serde", + "serde_json", + "smol", + "take-until", + "url", +] + +[[package]] +name = "uuid" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcc7e3b898aa6f6c08e5295b6c89258d1331e9ac578cc992fb818759951bdc22" + +[[package]] +name = "uuid" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d023da39d1fde5a8a3fe1f3e01ca9632ada0a63e9797de55a879d6e2236277be" +dependencies = [ + "getrandom", +] + +[[package]] +name = "value-bag" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d92ccd67fb88503048c01b59152a04effd0782d035a83a6d256ce6085f08f4a3" +dependencies = [ + "value-bag-serde1", + "value-bag-sval2", +] + +[[package]] +name = "value-bag-serde1" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0b9f3feef403a50d4d67e9741a6d8fc688bcbb4e4f31bd4aab72cc690284394" +dependencies = [ + "erased-serde", + "serde", + "serde_fmt", +] + +[[package]] +name = "value-bag-sval2" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30b24f4146b6f3361e91cbf527d1fb35e9376c3c0cef72ca5ec5af6d640fad7d" +dependencies = [ + "sval", + "sval_buffer", + "sval_dynamic", + "sval_fmt", + "sval_json", + "sval_ref", + "sval_serde", +] + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "waker-fn" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" + +[[package]] +name = "walkdir" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "weezl" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb" + +[[package]] +name = "which" +version = "4.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269" +dependencies = [ + "either", + "libc", + "once_cell", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" + +[[package]] +name = "wio" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d129932f4644ac2396cb456385cbf9e63b5b30c6e8dc4820bdca4eb082037a5" +dependencies = [ + "winapi", +] + +[[package]] +name = "xmlparser" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d25c75bf9ea12c4040a97f829154768bbbce366287e2dc044af160cd79a13fd" + +[[package]] +name = "xmlwriter" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec7a2a501ed189703dba8b08142f057e887dfc4b2cc4db2d343ac6376ba3e0b9" + +[[package]] +name = "yeslogic-fontconfig-sys" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2bbd69036d397ebbff671b1b8e4d918610c181c5a16073b96f984a38d08c386" +dependencies = [ + "const-cstr", + "dlib", + "once_cell", + "pkg-config", +] diff --git a/crates/gpui/playground/Cargo.toml b/crates/gpui/playground/Cargo.toml new file mode 100644 index 0000000000..3e5a5e5606 --- /dev/null +++ b/crates/gpui/playground/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "playground" +version = "0.1.0" +edition = "2021" +publish = false + +[[bin]] +name = "playground" +path = "src/playground.rs" + +[dependencies] +anyhow.workspace = true +derive_more.workspace = true +gpui = { path = ".." } +log.workspace = true +playground_macros = { path = "../playground_macros" } +parking_lot.workspace = true +refineable.workspace = true +serde.workspace = true +simplelog = "0.9" +smallvec.workspace = true +taffy = { git = "https://github.com/DioxusLabs/taffy", rev = "dab541d6104d58e2e10ce90c4a1dad0b703160cd", features = ["flexbox"] } +util = { path = "../../util" } + +[dev-dependencies] +gpui = { path = "..", features = ["test-support"] } diff --git a/crates/gpui/playground/docs/thoughts.md b/crates/gpui/playground/docs/thoughts.md new file mode 100644 index 0000000000..9416f25933 --- /dev/null +++ b/crates/gpui/playground/docs/thoughts.md @@ -0,0 +1,72 @@ +Much of element styling is now handled by an external engine. + + +How do I make an element hover. + +There's a hover style. + +Hoverable needs to wrap another element. That element can be styled. + +```rs +struct Hoverable { + +} + +impl Element for Hoverable { + +} + +``` + + + +```rs +#[derive(Styled, Interactive)] +pub struct Div { + declared_style: StyleRefinement, + interactions: Interactions +} + +pub trait Styled { + fn declared_style(&mut self) -> &mut StyleRefinement; + fn compute_style(&mut self) -> Style { + Style::default().refine(self.declared_style()) + } + + // All the tailwind classes, modifying self.declared_style() +} + +impl Style { + pub fn paint_background(layout: Layout, cx: &mut PaintContext); + pub fn paint_foreground(layout: Layout, cx: &mut PaintContext); +} + +pub trait Interactive { + fn interactions(&mut self) -> &mut Interactions; + + fn on_click(self, ) +} + +struct Interactions { + click: SmallVec<[; 1]>, +} + + +``` + + +```rs + + +trait Stylable { + type Style; + + fn with_style(self, style: Self::Style) -> Self; +} + + + + + + +``` diff --git a/crates/gpui/playground/src/adapter.rs b/crates/gpui/playground/src/adapter.rs new file mode 100644 index 0000000000..7a5a0399a8 --- /dev/null +++ b/crates/gpui/playground/src/adapter.rs @@ -0,0 +1,78 @@ +use crate::{layout_context::LayoutContext, paint_context::PaintContext}; +use gpui::{geometry::rect::RectF, LayoutEngine, LayoutId}; +use util::ResultExt; + +/// Makes a new, playground-style element into a legacy element. +pub struct AdapterElement(pub(crate) crate::element::AnyElement); + +impl gpui::Element for AdapterElement { + type LayoutState = Option<(LayoutEngine, LayoutId)>; + type PaintState = (); + + fn layout( + &mut self, + constraint: gpui::SizeConstraint, + view: &mut V, + cx: &mut gpui::LayoutContext, + ) -> (gpui::geometry::vector::Vector2F, Self::LayoutState) { + cx.push_layout_engine(LayoutEngine::new()); + + let size = constraint.max; + let mut cx = LayoutContext::new(cx); + let layout_id = self.0.layout(view, &mut cx).log_err(); + if let Some(layout_id) = layout_id { + cx.layout_engine() + .unwrap() + .compute_layout(layout_id, constraint.max) + .log_err(); + } + + let layout_engine = cx.pop_layout_engine(); + debug_assert!(layout_engine.is_some(), + "unexpected layout stack state. is there an unmatched pop_layout_engine in the called code?" + ); + + (constraint.max, layout_engine.zip(layout_id)) + } + + fn paint( + &mut self, + scene: &mut gpui::SceneBuilder, + bounds: RectF, + visible_bounds: RectF, + layout_data: &mut Option<(LayoutEngine, LayoutId)>, + view: &mut V, + legacy_cx: &mut gpui::PaintContext, + ) -> Self::PaintState { + let (layout_engine, layout_id) = layout_data.take().unwrap(); + legacy_cx.push_layout_engine(layout_engine); + let mut cx = PaintContext::new(legacy_cx, scene); + self.0.paint(view, &mut cx); + *layout_data = legacy_cx.pop_layout_engine().zip(Some(layout_id)); + debug_assert!(layout_data.is_some()); + } + + fn rect_for_text_range( + &self, + range_utf16: std::ops::Range, + bounds: RectF, + visible_bounds: RectF, + layout: &Self::LayoutState, + paint: &Self::PaintState, + view: &V, + cx: &gpui::ViewContext, + ) -> Option { + todo!("implement before merging to main") + } + + fn debug( + &self, + bounds: RectF, + layout: &Self::LayoutState, + paint: &Self::PaintState, + view: &V, + cx: &gpui::ViewContext, + ) -> gpui::serde_json::Value { + todo!("implement before merging to main") + } +} diff --git a/crates/gpui/playground/src/color.rs b/crates/gpui/playground/src/color.rs new file mode 100644 index 0000000000..14c60248aa --- /dev/null +++ b/crates/gpui/playground/src/color.rs @@ -0,0 +1,276 @@ +#![allow(dead_code)] + +use std::{num::ParseIntError, ops::Range}; + +use smallvec::SmallVec; + +pub fn rgb>(hex: u32) -> C { + let r = ((hex >> 16) & 0xFF) as f32 / 255.0; + let g = ((hex >> 8) & 0xFF) as f32 / 255.0; + let b = (hex & 0xFF) as f32 / 255.0; + Rgba { r, g, b, a: 1.0 }.into() +} + +#[derive(Clone, Copy, Default, Debug)] +pub struct Rgba { + pub r: f32, + pub g: f32, + pub b: f32, + pub a: f32, +} + +pub trait Lerp { + fn lerp(&self, level: f32) -> Hsla; +} + +impl Lerp for Range { + fn lerp(&self, level: f32) -> Hsla { + let level = level.clamp(0., 1.); + Hsla { + h: self.start.h + (level * (self.end.h - self.start.h)), + s: self.start.s + (level * (self.end.s - self.start.s)), + l: self.start.l + (level * (self.end.l - self.start.l)), + a: self.start.a + (level * (self.end.a - self.start.a)), + } + } +} + +impl From for Rgba { + fn from(value: gpui::color::Color) -> Self { + Self { + r: value.0.r as f32 / 255.0, + g: value.0.g as f32 / 255.0, + b: value.0.b as f32 / 255.0, + a: value.0.a as f32 / 255.0, + } + } +} + +impl From for Rgba { + fn from(color: Hsla) -> Self { + let h = color.h; + let s = color.s; + let l = color.l; + + let c = (1.0 - (2.0 * l - 1.0).abs()) * s; + let x = c * (1.0 - ((h * 6.0) % 2.0 - 1.0).abs()); + let m = l - c / 2.0; + let cm = c + m; + let xm = x + m; + + let (r, g, b) = match (h * 6.0).floor() as i32 { + 0 | 6 => (cm, xm, m), + 1 => (xm, cm, m), + 2 => (m, cm, xm), + 3 => (m, xm, cm), + 4 => (xm, m, cm), + _ => (cm, m, xm), + }; + + Rgba { + r, + g, + b, + a: color.a, + } + } +} + +impl TryFrom<&'_ str> for Rgba { + type Error = ParseIntError; + + fn try_from(value: &'_ str) -> Result { + let r = u8::from_str_radix(&value[1..3], 16)? as f32 / 255.0; + let g = u8::from_str_radix(&value[3..5], 16)? as f32 / 255.0; + let b = u8::from_str_radix(&value[5..7], 16)? as f32 / 255.0; + let a = if value.len() > 7 { + u8::from_str_radix(&value[7..9], 16)? as f32 / 255.0 + } else { + 1.0 + }; + + Ok(Rgba { r, g, b, a }) + } +} + +impl Into for Rgba { + fn into(self) -> gpui::color::Color { + gpui::color::rgba(self.r, self.g, self.b, self.a) + } +} + +#[derive(Default, Copy, Clone, Debug, PartialEq)] +pub struct Hsla { + pub h: f32, + pub s: f32, + pub l: f32, + pub a: f32, +} + +pub fn hsla(h: f32, s: f32, l: f32, a: f32) -> Hsla { + Hsla { + h: h.clamp(0., 1.), + s: s.clamp(0., 1.), + l: l.clamp(0., 1.), + a: a.clamp(0., 1.), + } +} + +pub fn black() -> Hsla { + Hsla { + h: 0., + s: 0., + l: 0., + a: 1., + } +} + +impl From for Hsla { + fn from(color: Rgba) -> Self { + let r = color.r; + let g = color.g; + let b = color.b; + + let max = r.max(g.max(b)); + let min = r.min(g.min(b)); + let delta = max - min; + + let l = (max + min) / 2.0; + let s = if l == 0.0 || l == 1.0 { + 0.0 + } else if l < 0.5 { + delta / (2.0 * l) + } else { + delta / (2.0 - 2.0 * l) + }; + + let h = if delta == 0.0 { + 0.0 + } else if max == r { + ((g - b) / delta).rem_euclid(6.0) / 6.0 + } else if max == g { + ((b - r) / delta + 2.0) / 6.0 + } else { + ((r - g) / delta + 4.0) / 6.0 + }; + + Hsla { + h, + s, + l, + a: color.a, + } + } +} + +impl Hsla { + /// Scales the saturation and lightness by the given values, clamping at 1.0. + pub fn scale_sl(mut self, s: f32, l: f32) -> Self { + self.s = (self.s * s).clamp(0., 1.); + self.l = (self.l * l).clamp(0., 1.); + self + } + + /// Increases the saturation of the color by a certain amount, with a max + /// value of 1.0. + pub fn saturate(mut self, amount: f32) -> Self { + self.s += amount; + self.s = self.s.clamp(0.0, 1.0); + self + } + + /// Decreases the saturation of the color by a certain amount, with a min + /// value of 0.0. + pub fn desaturate(mut self, amount: f32) -> Self { + self.s -= amount; + self.s = self.s.max(0.0); + if self.s < 0.0 { + self.s = 0.0; + } + self + } + + /// Brightens the color by increasing the lightness by a certain amount, + /// with a max value of 1.0. + pub fn brighten(mut self, amount: f32) -> Self { + self.l += amount; + self.l = self.l.clamp(0.0, 1.0); + self + } + + /// Darkens the color by decreasing the lightness by a certain amount, + /// with a max value of 0.0. + pub fn darken(mut self, amount: f32) -> Self { + self.l -= amount; + self.l = self.l.clamp(0.0, 1.0); + self + } +} + +impl From for Hsla { + fn from(value: gpui::color::Color) -> Self { + Rgba::from(value).into() + } +} + +impl Into for Hsla { + fn into(self) -> gpui::color::Color { + Rgba::from(self).into() + } +} + +pub struct ColorScale { + colors: SmallVec<[Hsla; 2]>, + positions: SmallVec<[f32; 2]>, +} + +pub fn scale(colors: I) -> ColorScale +where + I: IntoIterator, + C: Into, +{ + let mut scale = ColorScale { + colors: colors.into_iter().map(Into::into).collect(), + positions: SmallVec::new(), + }; + let num_colors: f32 = scale.colors.len() as f32 - 1.0; + scale.positions = (0..scale.colors.len()) + .map(|i| i as f32 / num_colors) + .collect(); + scale +} + +impl ColorScale { + fn at(&self, t: f32) -> Hsla { + // Ensure that the input is within [0.0, 1.0] + debug_assert!( + 0.0 <= t && t <= 1.0, + "t value {} is out of range. Expected value in range 0.0 to 1.0", + t + ); + + let position = match self + .positions + .binary_search_by(|a| a.partial_cmp(&t).unwrap()) + { + Ok(index) | Err(index) => index, + }; + let lower_bound = position.saturating_sub(1); + let upper_bound = position.min(self.colors.len() - 1); + let lower_color = &self.colors[lower_bound]; + let upper_color = &self.colors[upper_bound]; + + match upper_bound.checked_sub(lower_bound) { + Some(0) | None => *lower_color, + Some(_) => { + let interval_t = (t - self.positions[lower_bound]) + / (self.positions[upper_bound] - self.positions[lower_bound]); + let h = lower_color.h + interval_t * (upper_color.h - lower_color.h); + let s = lower_color.s + interval_t * (upper_color.s - lower_color.s); + let l = lower_color.l + interval_t * (upper_color.l - lower_color.l); + let a = lower_color.a + interval_t * (upper_color.a - lower_color.a); + Hsla { h, s, l, a } + } + } + } +} diff --git a/crates/gpui/playground/src/components.rs b/crates/gpui/playground/src/components.rs new file mode 100644 index 0000000000..3901968bfc --- /dev/null +++ b/crates/gpui/playground/src/components.rs @@ -0,0 +1,100 @@ +use crate::{ + div::div, + element::{Element, ParentElement}, + style::StyleHelpers, + text::ArcCow, + themes::rose_pine, +}; +use gpui::ViewContext; +use playground_macros::Element; +use std::{marker::PhantomData, rc::Rc}; + +struct ButtonHandlers { + click: Option)>>, +} + +impl Default for ButtonHandlers { + fn default() -> Self { + Self { click: None } + } +} + +use crate as playground; +#[derive(Element)] +pub struct Button { + handlers: ButtonHandlers, + label: Option>, + icon: Option>, + data: Rc, + view_type: PhantomData, +} + +// Impl block for buttons without data. +// See below for an impl block for any button. +impl Button { + fn new() -> Self { + Self { + handlers: ButtonHandlers::default(), + label: None, + icon: None, + data: Rc::new(()), + view_type: PhantomData, + } + } + + pub fn data(self, data: D) -> Button { + Button { + handlers: ButtonHandlers::default(), + label: self.label, + icon: self.icon, + data: Rc::new(data), + view_type: PhantomData, + } + } +} + +// Impl block for *any* button. +impl Button { + pub fn label(mut self, label: impl Into>) -> Self { + self.label = Some(label.into()); + self + } + + pub fn icon(mut self, icon: impl Into>) -> Self { + self.icon = Some(icon.into()); + self + } + + // pub fn click(self, handler: impl Fn(&mut V, &D, &mut ViewContext) + 'static) -> Self { + // let data = self.data.clone(); + // Self::click(self, MouseButton::Left, move |view, _, cx| { + // handler(view, data.as_ref(), cx); + // }) + // } +} + +pub fn button() -> Button { + Button::new() +} + +impl Button { + fn render(&mut self, view: &mut V, cx: &mut ViewContext) -> impl Element { + // TODO: Drive theme from the context + let button = div() + .fill(rose_pine::dawn().error(0.5)) + .h_4() + .children(self.label.clone()); + + button + + // TODO: Event handling + // if let Some(handler) = self.handlers.click.clone() { + // let data = self.data.clone(); + // // button.mouse_down(MouseButton::Left, move |view, event, cx| { + // // handler(view, data.as_ref(), cx) + // // }) + // } else { + // button + // } + } +} diff --git a/crates/gpui/playground/src/div.rs b/crates/gpui/playground/src/div.rs new file mode 100644 index 0000000000..8efe359025 --- /dev/null +++ b/crates/gpui/playground/src/div.rs @@ -0,0 +1,108 @@ +use crate::{ + element::{AnyElement, Element, Layout, ParentElement}, + interactive::{InteractionHandlers, Interactive}, + layout_context::LayoutContext, + paint_context::PaintContext, + style::{Style, StyleHelpers, StyleRefinement, Styleable}, +}; +use anyhow::Result; +use gpui::LayoutId; +use smallvec::SmallVec; + +pub struct Div { + style: StyleRefinement, + handlers: InteractionHandlers, + children: SmallVec<[AnyElement; 2]>, +} + +pub fn div() -> Div { + Div { + style: Default::default(), + handlers: Default::default(), + children: Default::default(), + } +} + +impl Element for Div { + type Layout = (); + + fn layout(&mut self, view: &mut V, cx: &mut LayoutContext) -> Result> + where + Self: Sized, + { + let children = self + .children + .iter_mut() + .map(|child| child.layout(view, cx)) + .collect::>>()?; + + cx.add_layout_node(self.style(), (), children) + } + + fn paint(&mut self, view: &mut V, layout: &mut Layout, cx: &mut PaintContext) + where + Self: Sized, + { + let style = self.style(); + + style.paint_background::(layout, cx); + for child in &mut self.children { + child.paint(view, cx); + } + } +} + +impl Styleable for Div { + type Style = Style; + + fn declared_style(&mut self) -> &mut StyleRefinement { + &mut self.style + } +} + +impl StyleHelpers for Div {} + +impl Interactive for Div { + fn interaction_handlers(&mut self) -> &mut InteractionHandlers { + &mut self.handlers + } +} + +impl ParentElement for Div { + fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]> { + &mut self.children + } +} + +#[test] +fn test() { + // let elt = div().w_auto(); +} + +// trait Element { +// type Style; + +// fn layout() +// } + +// trait Stylable: Element { +// type Style; + +// fn with_style(self, style: Self::Style) -> Self; +// } + +// pub struct HoverStyle { +// default: S, +// hovered: S, +// } + +// struct Hover> { +// child: C, +// style: HoverStyle, +// } + +// impl> Hover { +// fn new(child: C, style: HoverStyle) -> Self { +// Self { child, style } +// } +// } diff --git a/crates/gpui/playground/src/element.rs b/crates/gpui/playground/src/element.rs new file mode 100644 index 0000000000..082f3b02b0 --- /dev/null +++ b/crates/gpui/playground/src/element.rs @@ -0,0 +1,158 @@ +use anyhow::Result; +use derive_more::{Deref, DerefMut}; +use gpui::{geometry::rect::RectF, EngineLayout}; +use smallvec::SmallVec; +use std::marker::PhantomData; +use util::ResultExt; + +pub use crate::layout_context::LayoutContext; +pub use crate::paint_context::PaintContext; + +type LayoutId = gpui::LayoutId; + +pub trait Element: 'static { + type Layout; + + fn layout( + &mut self, + view: &mut V, + cx: &mut LayoutContext, + ) -> Result> + where + Self: Sized; + + fn paint( + &mut self, + view: &mut V, + layout: &mut Layout, + cx: &mut PaintContext, + ) where + Self: Sized; + + fn into_any(self) -> AnyElement + where + Self: 'static + Sized, + { + AnyElement(Box::new(ElementState { + element: self, + layout: None, + })) + } +} + +/// Used to make ElementState into a trait object, so we can wrap it in AnyElement. +trait ElementStateObject { + fn layout(&mut self, view: &mut V, cx: &mut LayoutContext) -> Result; + fn paint(&mut self, view: &mut V, cx: &mut PaintContext); +} + +/// A wrapper around an element that stores its layout state. +struct ElementState> { + element: E, + layout: Option>, +} + +/// We blanket-implement the object-safe ElementStateObject interface to make ElementStates into trait objects +impl> ElementStateObject for ElementState { + fn layout(&mut self, view: &mut V, cx: &mut LayoutContext) -> Result { + let layout = self.element.layout(view, cx)?; + let layout_id = layout.id; + self.layout = Some(layout); + Ok(layout_id) + } + + fn paint(&mut self, view: &mut V, cx: &mut PaintContext) { + let layout = self.layout.as_mut().expect("paint called before layout"); + if layout.engine_layout.is_none() { + layout.engine_layout = cx.computed_layout(layout.id).log_err() + } + self.element.paint(view, layout, cx) + } +} + +/// A dynamic element. +pub struct AnyElement(Box>); + +impl AnyElement { + pub fn layout(&mut self, view: &mut V, cx: &mut LayoutContext) -> Result { + self.0.layout(view, cx) + } + + pub fn paint(&mut self, view: &mut V, cx: &mut PaintContext) { + self.0.paint(view, cx) + } +} + +#[derive(Deref, DerefMut)] +pub struct Layout { + id: LayoutId, + engine_layout: Option, + #[deref] + #[deref_mut] + element_data: D, + view_type: PhantomData, +} + +impl Layout { + pub fn new(id: LayoutId, element_data: D) -> Self { + Self { + id, + engine_layout: None, + element_data: element_data, + view_type: PhantomData, + } + } + + pub fn bounds(&mut self, cx: &mut PaintContext) -> RectF { + self.engine_layout(cx).bounds + } + + pub fn order(&mut self, cx: &mut PaintContext) -> u32 { + self.engine_layout(cx).order + } + + fn engine_layout(&mut self, cx: &mut PaintContext<'_, '_, '_, '_, V>) -> &mut EngineLayout { + self.engine_layout + .get_or_insert_with(|| cx.computed_layout(self.id).log_err().unwrap_or_default()) + } +} + +impl Layout>> { + pub fn paint(&mut self, view: &mut V, cx: &mut PaintContext) { + let mut element = self.element_data.take().unwrap(); + element.paint(view, cx); + self.element_data = Some(element); + } +} + +pub trait ParentElement { + fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]>; + + fn child(mut self, child: impl IntoElement) -> Self + where + Self: Sized, + { + self.children_mut().push(child.into_element().into_any()); + self + } + + fn children(mut self, children: I) -> Self + where + I: IntoIterator, + E: IntoElement, + Self: Sized, + { + self.children_mut().extend( + children + .into_iter() + .map(|child| child.into_element().into_any()), + ); + self + } +} + +pub trait IntoElement { + type Element: Element; + + fn into_element(self) -> Self::Element; +} diff --git a/crates/gpui/playground/src/hoverable.rs b/crates/gpui/playground/src/hoverable.rs new file mode 100644 index 0000000000..5545155a60 --- /dev/null +++ b/crates/gpui/playground/src/hoverable.rs @@ -0,0 +1,76 @@ +use crate::{ + element::{Element, Layout}, + layout_context::LayoutContext, + paint_context::PaintContext, + style::{StyleRefinement, Styleable}, +}; +use anyhow::Result; +use gpui::platform::MouseMovedEvent; +use refineable::Refineable; +use std::{cell::Cell, marker::PhantomData}; + +pub struct Hoverable + Styleable> { + hovered: Cell, + child_style: StyleRefinement, + hovered_style: StyleRefinement, + child: E, + view_type: PhantomData, +} + +pub fn hoverable + Styleable>(mut child: E) -> Hoverable { + Hoverable { + hovered: Cell::new(false), + child_style: child.declared_style().clone(), + hovered_style: Default::default(), + child, + view_type: PhantomData, + } +} + +impl + Styleable> Styleable for Hoverable { + type Style = E::Style; + + fn declared_style(&mut self) -> &mut crate::style::StyleRefinement { + self.child.declared_style() + } +} + +impl + Styleable> Element for Hoverable { + type Layout = E::Layout; + + fn layout(&mut self, view: &mut V, cx: &mut LayoutContext) -> Result> + where + Self: Sized, + { + self.child.layout(view, cx) + } + + fn paint( + &mut self, + view: &mut V, + layout: &mut Layout, + cx: &mut PaintContext, + ) where + Self: Sized, + { + if self.hovered.get() { + // If hovered, refine the child's style with this element's style. + self.child.declared_style().refine(&self.hovered_style); + } else { + // Otherwise, set the child's style back to its original style. + *self.child.declared_style() = self.child_style.clone(); + } + + let bounds = layout.bounds(cx); + let order = layout.order(cx); + self.hovered.set(bounds.contains_point(cx.mouse_position())); + let was_hovered = self.hovered.clone(); + cx.on_event(order, move |view, event: &MouseMovedEvent, cx| { + let is_hovered = bounds.contains_point(event.position); + if is_hovered != was_hovered.get() { + was_hovered.set(is_hovered); + cx.repaint(); + } + }); + } +} diff --git a/crates/gpui/playground/src/interactive.rs b/crates/gpui/playground/src/interactive.rs new file mode 100644 index 0000000000..8debcb1692 --- /dev/null +++ b/crates/gpui/playground/src/interactive.rs @@ -0,0 +1,34 @@ +use gpui::{platform::MouseMovedEvent, EventContext}; +use smallvec::SmallVec; +use std::rc::Rc; + +pub trait Interactive { + fn interaction_handlers(&mut self) -> &mut InteractionHandlers; + + fn on_mouse_move(mut self, handler: H) -> Self + where + H: 'static + Fn(&mut V, &MouseMovedEvent, bool, &mut EventContext), + Self: Sized, + { + self.interaction_handlers() + .mouse_moved + .push(Rc::new(move |view, event, hit_test, cx| { + handler(view, event, hit_test, cx); + cx.bubble + })); + self + } +} + +pub struct InteractionHandlers { + mouse_moved: + SmallVec<[Rc) -> bool>; 2]>, +} + +impl Default for InteractionHandlers { + fn default() -> Self { + Self { + mouse_moved: Default::default(), + } + } +} diff --git a/crates/gpui/playground/src/layout_context.rs b/crates/gpui/playground/src/layout_context.rs new file mode 100644 index 0000000000..7c9f13e7f0 --- /dev/null +++ b/crates/gpui/playground/src/layout_context.rs @@ -0,0 +1,54 @@ +use anyhow::{anyhow, Result}; +use derive_more::{Deref, DerefMut}; +pub use gpui::LayoutContext as LegacyLayoutContext; +use gpui::{RenderContext, ViewContext}; +pub use taffy::tree::NodeId; + +use crate::{element::Layout, style::Style}; + +#[derive(Deref, DerefMut)] +pub struct LayoutContext<'a, 'b, 'c, 'd, V> { + #[deref] + #[deref_mut] + pub(crate) legacy_cx: &'d mut LegacyLayoutContext<'a, 'b, 'c, V>, +} + +impl<'a, 'b, V> RenderContext<'a, 'b, V> for LayoutContext<'a, 'b, '_, '_, V> { + fn text_style(&self) -> gpui::fonts::TextStyle { + self.legacy_cx.text_style() + } + + fn push_text_style(&mut self, style: gpui::fonts::TextStyle) { + self.legacy_cx.push_text_style(style) + } + + fn pop_text_style(&mut self) { + self.legacy_cx.pop_text_style() + } + + fn as_view_context(&mut self) -> &mut ViewContext<'a, 'b, V> { + &mut self.view_context + } +} + +impl<'a, 'b, 'c, 'd, V: 'static> LayoutContext<'a, 'b, 'c, 'd, V> { + pub fn new(legacy_cx: &'d mut LegacyLayoutContext<'a, 'b, 'c, V>) -> Self { + Self { legacy_cx } + } + + pub fn add_layout_node( + &mut self, + style: Style, + element_data: D, + children: impl IntoIterator, + ) -> Result> { + let rem_size = self.rem_pixels(); + let id = self + .legacy_cx + .layout_engine() + .ok_or_else(|| anyhow!("no layout engine"))? + .add_node(style.to_taffy(rem_size), children)?; + + Ok(Layout::new(id, element_data)) + } +} diff --git a/crates/gpui/playground/src/paint_context.rs b/crates/gpui/playground/src/paint_context.rs new file mode 100644 index 0000000000..d853aff7f8 --- /dev/null +++ b/crates/gpui/playground/src/paint_context.rs @@ -0,0 +1,71 @@ +use anyhow::{anyhow, Result}; +use derive_more::{Deref, DerefMut}; +use gpui::{scene::EventHandler, EngineLayout, EventContext, LayoutId, RenderContext, ViewContext}; +pub use gpui::{LayoutContext, PaintContext as LegacyPaintContext}; +use std::{any::TypeId, rc::Rc}; +pub use taffy::tree::NodeId; + +#[derive(Deref, DerefMut)] +pub struct PaintContext<'a, 'b, 'c, 'd, V> { + #[deref] + #[deref_mut] + pub(crate) legacy_cx: &'d mut LegacyPaintContext<'a, 'b, 'c, V>, + pub(crate) scene: &'d mut gpui::SceneBuilder, +} + +impl<'a, 'b, V> RenderContext<'a, 'b, V> for PaintContext<'a, 'b, '_, '_, V> { + fn text_style(&self) -> gpui::fonts::TextStyle { + self.legacy_cx.text_style() + } + + fn push_text_style(&mut self, style: gpui::fonts::TextStyle) { + self.legacy_cx.push_text_style(style) + } + + fn pop_text_style(&mut self) { + self.legacy_cx.pop_text_style() + } + + fn as_view_context(&mut self) -> &mut ViewContext<'a, 'b, V> { + &mut self.view_context + } +} + +impl<'a, 'b, 'c, 'd, V: 'static> PaintContext<'a, 'b, 'c, 'd, V> { + pub fn new( + legacy_cx: &'d mut LegacyPaintContext<'a, 'b, 'c, V>, + scene: &'d mut gpui::SceneBuilder, + ) -> Self { + Self { legacy_cx, scene } + } + + pub fn on_event( + &mut self, + order: u32, + handler: impl Fn(&mut V, &E, &mut ViewContext) + 'static, + ) { + let view = self.weak_handle(); + + self.scene.event_handlers.push(EventHandler { + order, + handler: Rc::new(move |event, window_cx| { + if let Some(view) = view.upgrade(window_cx) { + view.update(window_cx, |view, view_cx| { + let mut event_cx = EventContext::new(view_cx); + handler(view, event.downcast_ref().unwrap(), &mut event_cx); + event_cx.bubble + }) + } else { + true + } + }), + event_type: TypeId::of::(), + }) + } + + pub(crate) fn computed_layout(&mut self, layout_id: LayoutId) -> Result { + self.layout_engine() + .ok_or_else(|| anyhow!("no layout engine present"))? + .computed_layout(layout_id) + } +} diff --git a/crates/gpui/playground/src/playground.rs b/crates/gpui/playground/src/playground.rs new file mode 100644 index 0000000000..2462ac99f5 --- /dev/null +++ b/crates/gpui/playground/src/playground.rs @@ -0,0 +1,83 @@ +#![allow(dead_code, unused_variables)] +use crate::{color::black, style::StyleHelpers}; +use element::Element; +use gpui::{ + geometry::{rect::RectF, vector::vec2f}, + platform::WindowOptions, +}; +use log::LevelFilter; +use simplelog::SimpleLogger; +use themes::{rose_pine, ThemeColors}; +use view::view; + +mod adapter; +mod color; +mod components; +mod div; +mod element; +mod hoverable; +mod interactive; +mod layout_context; +mod paint_context; +mod style; +mod text; +mod themes; +mod view; + +fn main() { + SimpleLogger::init(LevelFilter::Info, Default::default()).expect("could not initialize logger"); + + gpui::App::new(()).unwrap().run(|cx| { + cx.add_window( + WindowOptions { + bounds: gpui::platform::WindowBounds::Fixed(RectF::new( + vec2f(0., 0.), + vec2f(400., 300.), + )), + center: true, + ..Default::default() + }, + |_| view(|_| playground(&rose_pine::moon())), + ); + cx.platform().activate(true); + }); +} + +fn playground(theme: &ThemeColors) -> impl Element { + use div::div; + + div() + .text_color(black()) + .h_full() + .w_1_2() + .fill(theme.success(0.5)) + // .hover() + // .fill(theme.error(0.5)) + // .child(button().label("Hello").click(|_, _, _| println!("click!"))) +} + +// todo!() +// // column() +// // .size(auto()) +// // .fill(theme.base(0.5)) +// // .text_color(theme.text(0.5)) +// // .child(title_bar(theme)) +// // .child(stage(theme)) +// // .child(status_bar(theme)) +// } + +// fn title_bar(theme: &ThemeColors) -> impl Element { +// row() +// .fill(theme.base(0.2)) +// .justify(0.) +// .width(auto()) +// .child(text("Zed Playground")) +// } + +// fn stage(theme: &ThemeColors) -> impl Element { +// row().fill(theme.surface(0.9)) +// } + +// fn status_bar(theme: &ThemeColors) -> impl Element { +// row().fill(theme.surface(0.1)) +// } diff --git a/crates/gpui/playground/src/style.rs b/crates/gpui/playground/src/style.rs new file mode 100644 index 0000000000..9216702f7f --- /dev/null +++ b/crates/gpui/playground/src/style.rs @@ -0,0 +1,286 @@ +use crate::{ + color::Hsla, + element::{Element, Layout}, + paint_context::PaintContext, +}; +use gpui::{ + fonts::TextStyleRefinement, + geometry::{ + AbsoluteLength, DefiniteLength, Edges, EdgesRefinement, Length, Point, PointRefinement, + Size, SizeRefinement, + }, +}; +use playground_macros::styleable_helpers; +use refineable::Refineable; +pub use taffy::style::{ + AlignContent, AlignItems, AlignSelf, Display, FlexDirection, FlexWrap, JustifyContent, + Overflow, Position, +}; + +#[derive(Clone, Refineable)] +pub struct Style { + /// What layout strategy should be used? + pub display: Display, + + // Overflow properties + /// How children overflowing their container should affect layout + #[refineable] + pub overflow: Point, + /// How much space (in points) should be reserved for the scrollbars of `Overflow::Scroll` and `Overflow::Auto` nodes. + pub scrollbar_width: f32, + + // Position properties + /// What should the `position` value of this struct use as a base offset? + pub position: Position, + /// How should the position of this element be tweaked relative to the layout defined? + #[refineable] + pub inset: Edges, + + // Size properies + /// Sets the initial size of the item + #[refineable] + pub size: Size, + /// Controls the minimum size of the item + #[refineable] + pub min_size: Size, + /// Controls the maximum size of the item + #[refineable] + pub max_size: Size, + /// Sets the preferred aspect ratio for the item. The ratio is calculated as width divided by height. + pub aspect_ratio: Option, + + // Spacing Properties + /// How large should the margin be on each side? + #[refineable] + pub margin: Edges, + /// How large should the padding be on each side? + #[refineable] + pub padding: Edges, + /// How large should the border be on each side? + #[refineable] + pub border: Edges, + + // Alignment properties + /// How this node's children aligned in the cross/block axis? + pub align_items: Option, + /// How this node should be aligned in the cross/block axis. Falls back to the parents [`AlignItems`] if not set + pub align_self: Option, + /// How should content contained within this item be aligned in the cross/block axis + pub align_content: Option, + /// How should contained within this item be aligned in the main/inline axis + pub justify_content: Option, + /// How large should the gaps between items in a flex container be? + #[refineable] + pub gap: Size, + + // Flexbox properies + /// Which direction does the main axis flow in? + pub flex_direction: FlexDirection, + /// Should elements wrap, or stay in a single line? + pub flex_wrap: FlexWrap, + /// Sets the initial main axis size of the item + pub flex_basis: Length, + /// The relative rate at which this item grows when it is expanding to fill space, 0.0 is the default value, and this value must be positive. + pub flex_grow: f32, + /// The relative rate at which this item shrinks when it is contracting to fit into space, 1.0 is the default value, and this value must be positive. + pub flex_shrink: f32, + + /// The fill color of this element + pub fill: Option, + /// The radius of the corners of this element + #[refineable] + pub corner_radii: CornerRadii, + /// The color of text within this element. Cascades to children unless overridden. + pub text_color: Option, +} + +impl Style { + pub fn to_taffy(&self, rem_size: f32) -> taffy::style::Style { + taffy::style::Style { + display: self.display, + overflow: self.overflow.clone().into(), + scrollbar_width: self.scrollbar_width, + position: self.position, + inset: self.inset.to_taffy(rem_size), + size: self.size.to_taffy(rem_size), + min_size: self.min_size.to_taffy(rem_size), + max_size: self.max_size.to_taffy(rem_size), + aspect_ratio: self.aspect_ratio, + margin: self.margin.to_taffy(rem_size), + padding: self.padding.to_taffy(rem_size), + border: self.border.to_taffy(rem_size), + align_items: self.align_items, + align_self: self.align_self, + align_content: self.align_content, + justify_content: self.justify_content, + gap: self.gap.to_taffy(rem_size), + flex_direction: self.flex_direction, + flex_wrap: self.flex_wrap, + flex_basis: self.flex_basis.to_taffy(rem_size).into(), + flex_grow: self.flex_grow, + flex_shrink: self.flex_shrink, + ..Default::default() // Ignore grid properties for now + } + } + + /// Paints the background of an element styled with this style. + /// Return the bounds in which to paint the content. + pub fn paint_background>( + &self, + layout: &mut Layout, + cx: &mut PaintContext, + ) { + let bounds = layout.bounds(cx); + let rem_size = cx.rem_pixels(); + if let Some(color) = self.fill.as_ref().and_then(Fill::color) { + cx.scene.push_quad(gpui::Quad { + bounds, + background: Some(color.into()), + corner_radii: self.corner_radii.to_gpui(rem_size), + border: Default::default(), + }); + } + } +} + +impl Default for Style { + fn default() -> Self { + Style { + display: Display::DEFAULT, + overflow: Point { + x: Overflow::Visible, + y: Overflow::Visible, + }, + scrollbar_width: 0.0, + position: Position::Relative, + inset: Edges::auto(), + margin: Edges::::zero(), + padding: Edges::::zero(), + border: Edges::::zero(), + size: Size::auto(), + min_size: Size::auto(), + max_size: Size::auto(), + aspect_ratio: None, + gap: Size::zero(), + // Aligment + align_items: None, + align_self: None, + align_content: None, + justify_content: None, + // Flexbox + flex_direction: FlexDirection::Row, + flex_wrap: FlexWrap::NoWrap, + flex_grow: 0.0, + flex_shrink: 1.0, + flex_basis: Length::Auto, + fill: None, + text_color: None, + corner_radii: CornerRadii::default(), + } + } +} + +impl StyleRefinement { + pub fn text_style(&self) -> Option { + self.text_color.map(|color| TextStyleRefinement { + color: Some(color.into()), + ..Default::default() + }) + } +} + +pub struct OptionalTextStyle { + color: Option, +} + +impl OptionalTextStyle { + pub fn apply(&self, style: &mut gpui::fonts::TextStyle) { + if let Some(color) = self.color { + style.color = color.into(); + } + } +} + +#[derive(Clone)] +pub enum Fill { + Color(Hsla), +} + +impl Fill { + pub fn color(&self) -> Option { + match self { + Fill::Color(color) => Some(*color), + } + } +} + +impl Default for Fill { + fn default() -> Self { + Self::Color(Hsla::default()) + } +} + +impl From for Fill { + fn from(color: Hsla) -> Self { + Self::Color(color) + } +} + +#[derive(Clone, Refineable, Default)] +pub struct CornerRadii { + top_left: AbsoluteLength, + top_right: AbsoluteLength, + bottom_left: AbsoluteLength, + bottom_right: AbsoluteLength, +} + +impl CornerRadii { + pub fn to_gpui(&self, rem_size: f32) -> gpui::scene::CornerRadii { + gpui::scene::CornerRadii { + top_left: self.top_left.to_pixels(rem_size), + top_right: self.top_right.to_pixels(rem_size), + bottom_left: self.bottom_left.to_pixels(rem_size), + bottom_right: self.bottom_right.to_pixels(rem_size), + } + } +} + +pub trait Styleable { + type Style: refineable::Refineable; + + fn declared_style(&mut self) -> &mut playground::style::StyleRefinement; + + fn style(&mut self) -> playground::style::Style { + let mut style = playground::style::Style::default(); + style.refine(self.declared_style()); + style + } +} + +// Helpers methods that take and return mut self. This includes tailwind style methods for standard sizes etc. +// +// Example: +// // Sets the padding to 0.5rem, just like class="p-2" in Tailwind. +// fn p_2(mut self) -> Self where Self: Sized; +use crate as playground; // Macro invocation references this crate as playground. +pub trait StyleHelpers: Styleable