Detailed changes
@@ -108,6 +108,33 @@ dependencies = [
"util",
]
+[[package]]
+name = "ai2"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "async-trait",
+ "bincode",
+ "futures 0.3.28",
+ "gpui2",
+ "isahc",
+ "language2",
+ "lazy_static",
+ "log",
+ "matrixmultiply",
+ "ordered-float 2.10.0",
+ "parking_lot 0.11.2",
+ "parse_duration",
+ "postage",
+ "rand 0.8.5",
+ "regex",
+ "rusqlite",
+ "serde",
+ "serde_json",
+ "tiktoken-rs",
+ "util",
+]
+
[[package]]
name = "alacritty_config"
version = "0.1.2-dev"
@@ -1138,7 +1165,7 @@ dependencies = [
"audio2",
"client2",
"collections",
- "fs",
+ "fs2",
"futures 0.3.28",
"gpui2",
"language2",
@@ -4795,6 +4822,13 @@ dependencies = [
"gpui",
]
+[[package]]
+name = "menu2"
+version = "0.1.0"
+dependencies = [
+ "gpui2",
+]
+
[[package]]
name = "metal"
version = "0.21.0"
@@ -6000,7 +6034,7 @@ dependencies = [
"anyhow",
"client2",
"collections",
- "fs",
+ "fs2",
"futures 0.3.28",
"gpui2",
"language2",
@@ -6167,7 +6201,7 @@ dependencies = [
"ctor",
"db2",
"env_logger 0.9.3",
- "fs",
+ "fs2",
"fsevent",
"futures 0.3.28",
"fuzzy2",
@@ -8740,6 +8774,7 @@ version = "0.1.0"
dependencies = [
"anyhow",
"clap 4.4.4",
+ "convert_case 0.6.0",
"gpui2",
"log",
"rust-embed",
@@ -10932,6 +10967,7 @@ dependencies = [
name = "zed2"
version = "0.109.0"
dependencies = [
+ "ai2",
"anyhow",
"async-compression",
"async-recursion 0.3.2",
@@ -59,6 +59,7 @@ members = [
"crates/lsp2",
"crates/media",
"crates/menu",
+ "crates/menu2",
"crates/multi_buffer",
"crates/node_runtime",
"crates/notifications",
@@ -0,0 +1,38 @@
+[package]
+name = "ai"
+version = "0.1.0"
+edition = "2021"
+publish = false
+
+[lib]
+path = "src/ai.rs"
+doctest = false
+
+[features]
+test-support = []
+
+[dependencies]
+gpui = { path = "../gpui" }
+util = { path = "../util" }
+language = { path = "../language" }
+async-trait.workspace = true
+anyhow.workspace = true
+futures.workspace = true
+lazy_static.workspace = true
+ordered-float.workspace = true
+parking_lot.workspace = true
+isahc.workspace = true
+regex.workspace = true
+serde.workspace = true
+serde_json.workspace = true
+postage.workspace = true
+rand.workspace = true
+log.workspace = true
+parse_duration = "2.1.1"
+tiktoken-rs = "0.5.0"
+matrixmultiply = "0.3.7"
+rusqlite = { version = "0.29.0", features = ["blob", "array", "modern_sqlite"] }
+bincode = "1.3.3"
+
+[dev-dependencies]
+gpui = { path = "../gpui", features = ["test-support"] }
@@ -8,6 +8,9 @@ publish = false
path = "src/ai.rs"
doctest = false
+[features]
+test-support = []
+
[dependencies]
gpui = { path = "../gpui" }
util = { path = "../util" }
@@ -1,4 +1,8 @@
+pub mod auth;
pub mod completion;
pub mod embedding;
pub mod models;
-pub mod templates;
+pub mod prompts;
+pub mod providers;
+#[cfg(any(test, feature = "test-support"))]
+pub mod test;
@@ -0,0 +1,15 @@
+use gpui::AppContext;
+
+#[derive(Clone, Debug)]
+pub enum ProviderCredential {
+ Credentials { api_key: String },
+ NoCredentials,
+ NotNeeded,
+}
+
+pub trait CredentialProvider: Send + Sync {
+ fn has_credentials(&self) -> bool;
+ fn retrieve_credentials(&self, cx: &AppContext) -> ProviderCredential;
+ fn save_credentials(&self, cx: &AppContext, credential: ProviderCredential);
+ fn delete_credentials(&self, cx: &AppContext);
+}
@@ -1,214 +1,23 @@
-use anyhow::{anyhow, Result};
-use futures::{
- future::BoxFuture, io::BufReader, stream::BoxStream, AsyncBufReadExt, AsyncReadExt, FutureExt,
- Stream, StreamExt,
-};
-use gpui::executor::Background;
-use isahc::{http::StatusCode, Request, RequestExt};
-use serde::{Deserialize, Serialize};
-use std::{
- fmt::{self, Display},
- io,
- sync::Arc,
-};
+use anyhow::Result;
+use futures::{future::BoxFuture, stream::BoxStream};
-pub const OPENAI_API_URL: &'static str = "https://api.openai.com/v1";
+use crate::{auth::CredentialProvider, models::LanguageModel};
-#[derive(Clone, Copy, Serialize, Deserialize, Debug, Eq, PartialEq)]
-#[serde(rename_all = "lowercase")]
-pub enum Role {
- User,
- Assistant,
- System,
+pub trait CompletionRequest: Send + Sync {
+ fn data(&self) -> serde_json::Result<String>;
}
-impl Role {
- pub fn cycle(&mut self) {
- *self = match self {
- Role::User => Role::Assistant,
- Role::Assistant => Role::System,
- Role::System => Role::User,
- }
- }
-}
-
-impl Display for Role {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result {
- match self {
- Role::User => write!(f, "User"),
- Role::Assistant => write!(f, "Assistant"),
- Role::System => write!(f, "System"),
- }
- }
-}
-
-#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
-pub struct RequestMessage {
- pub role: Role,
- pub content: String,
-}
-
-#[derive(Debug, Default, Serialize)]
-pub struct OpenAIRequest {
- pub model: String,
- pub messages: Vec<RequestMessage>,
- pub stream: bool,
- pub stop: Vec<String>,
- pub temperature: f32,
-}
-
-#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
-pub struct ResponseMessage {
- pub role: Option<Role>,
- pub content: Option<String>,
-}
-
-#[derive(Deserialize, Debug)]
-pub struct OpenAIUsage {
- pub prompt_tokens: u32,
- pub completion_tokens: u32,
- pub total_tokens: u32,
-}
-
-#[derive(Deserialize, Debug)]
-pub struct ChatChoiceDelta {
- pub index: u32,
- pub delta: ResponseMessage,
- pub finish_reason: Option<String>,
-}
-
-#[derive(Deserialize, Debug)]
-pub struct OpenAIResponseStreamEvent {
- pub id: Option<String>,
- pub object: String,
- pub created: u32,
- pub model: String,
- pub choices: Vec<ChatChoiceDelta>,
- pub usage: Option<OpenAIUsage>,
-}
-
-pub async fn stream_completion(
- api_key: String,
- executor: Arc<Background>,
- mut request: OpenAIRequest,
-) -> Result<impl Stream<Item = Result<OpenAIResponseStreamEvent>>> {
- request.stream = true;
-
- let (tx, rx) = futures::channel::mpsc::unbounded::<Result<OpenAIResponseStreamEvent>>();
-
- let json_data = serde_json::to_string(&request)?;
- let mut response = Request::post(format!("{OPENAI_API_URL}/chat/completions"))
- .header("Content-Type", "application/json")
- .header("Authorization", format!("Bearer {}", api_key))
- .body(json_data)?
- .send_async()
- .await?;
-
- let status = response.status();
- if status == StatusCode::OK {
- executor
- .spawn(async move {
- let mut lines = BufReader::new(response.body_mut()).lines();
-
- fn parse_line(
- line: Result<String, io::Error>,
- ) -> Result<Option<OpenAIResponseStreamEvent>> {
- if let Some(data) = line?.strip_prefix("data: ") {
- let event = serde_json::from_str(&data)?;
- Ok(Some(event))
- } else {
- Ok(None)
- }
- }
-
- while let Some(line) = lines.next().await {
- if let Some(event) = parse_line(line).transpose() {
- let done = event.as_ref().map_or(false, |event| {
- event
- .choices
- .last()
- .map_or(false, |choice| choice.finish_reason.is_some())
- });
- if tx.unbounded_send(event).is_err() {
- break;
- }
-
- if done {
- break;
- }
- }
- }
-
- anyhow::Ok(())
- })
- .detach();
-
- Ok(rx)
- } else {
- let mut body = String::new();
- response.body_mut().read_to_string(&mut body).await?;
-
- #[derive(Deserialize)]
- struct OpenAIResponse {
- error: OpenAIError,
- }
-
- #[derive(Deserialize)]
- struct OpenAIError {
- message: String,
- }
-
- match serde_json::from_str::<OpenAIResponse>(&body) {
- Ok(response) if !response.error.message.is_empty() => Err(anyhow!(
- "Failed to connect to OpenAI API: {}",
- response.error.message,
- )),
-
- _ => Err(anyhow!(
- "Failed to connect to OpenAI API: {} {}",
- response.status(),
- body,
- )),
- }
- }
-}
-
-pub trait CompletionProvider {
+pub trait CompletionProvider: CredentialProvider {
+ fn base_model(&self) -> Box<dyn LanguageModel>;
fn complete(
&self,
- prompt: OpenAIRequest,
+ prompt: Box<dyn CompletionRequest>,
) -> BoxFuture<'static, Result<BoxStream<'static, Result<String>>>>;
+ fn box_clone(&self) -> Box<dyn CompletionProvider>;
}
-pub struct OpenAICompletionProvider {
- api_key: String,
- executor: Arc<Background>,
-}
-
-impl OpenAICompletionProvider {
- pub fn new(api_key: String, executor: Arc<Background>) -> Self {
- Self { api_key, executor }
- }
-}
-
-impl CompletionProvider for OpenAICompletionProvider {
- fn complete(
- &self,
- prompt: OpenAIRequest,
- ) -> BoxFuture<'static, Result<BoxStream<'static, Result<String>>>> {
- let request = stream_completion(self.api_key.clone(), self.executor.clone(), prompt);
- async move {
- let response = request.await?;
- let stream = response
- .filter_map(|response| async move {
- match response {
- Ok(mut response) => Some(Ok(response.choices.pop()?.delta.content?)),
- Err(error) => Some(Err(error)),
- }
- })
- .boxed();
- Ok(stream)
- }
- .boxed()
+impl Clone for Box<dyn CompletionProvider> {
+ fn clone(&self) -> Box<dyn CompletionProvider> {
+ self.box_clone()
}
}
@@ -1,32 +1,13 @@
-use anyhow::{anyhow, Result};
+use std::time::Instant;
+
+use anyhow::Result;
use async_trait::async_trait;
-use futures::AsyncReadExt;
-use gpui::executor::Background;
-use gpui::{serde_json, AppContext};
-use isahc::http::StatusCode;
-use isahc::prelude::Configurable;
-use isahc::{AsyncBody, Response};
-use lazy_static::lazy_static;
use ordered_float::OrderedFloat;
-use parking_lot::Mutex;
-use parse_duration::parse;
-use postage::watch;
use rusqlite::types::{FromSql, FromSqlResult, ToSqlOutput, ValueRef};
use rusqlite::ToSql;
-use serde::{Deserialize, Serialize};
-use std::env;
-use std::ops::Add;
-use std::sync::Arc;
-use std::time::{Duration, Instant};
-use tiktoken_rs::{cl100k_base, CoreBPE};
-use util::http::{HttpClient, Request};
-use util::ResultExt;
-
-use crate::completion::OPENAI_API_URL;
-lazy_static! {
- static ref OPENAI_BPE_TOKENIZER: CoreBPE = cl100k_base().unwrap();
-}
+use crate::auth::CredentialProvider;
+use crate::models::LanguageModel;
#[derive(Debug, PartialEq, Clone)]
pub struct Embedding(pub Vec<f32>);
@@ -87,301 +68,14 @@ impl Embedding {
}
}
-#[derive(Clone)]
-pub struct OpenAIEmbeddings {
- pub client: Arc<dyn HttpClient>,
- pub executor: Arc<Background>,
- rate_limit_count_rx: watch::Receiver<Option<Instant>>,
- rate_limit_count_tx: Arc<Mutex<watch::Sender<Option<Instant>>>>,
-}
-
-#[derive(Serialize)]
-struct OpenAIEmbeddingRequest<'a> {
- model: &'static str,
- input: Vec<&'a str>,
-}
-
-#[derive(Deserialize)]
-struct OpenAIEmbeddingResponse {
- data: Vec<OpenAIEmbedding>,
- usage: OpenAIEmbeddingUsage,
-}
-
-#[derive(Debug, Deserialize)]
-struct OpenAIEmbedding {
- embedding: Vec<f32>,
- index: usize,
- object: String,
-}
-
-#[derive(Deserialize)]
-struct OpenAIEmbeddingUsage {
- prompt_tokens: usize,
- total_tokens: usize,
-}
-
#[async_trait]
-pub trait EmbeddingProvider: Sync + Send {
- fn retrieve_credentials(&self, cx: &AppContext) -> Option<String>;
- async fn embed_batch(
- &self,
- spans: Vec<String>,
- api_key: Option<String>,
- ) -> Result<Vec<Embedding>>;
+pub trait EmbeddingProvider: CredentialProvider {
+ fn base_model(&self) -> Box<dyn LanguageModel>;
+ async fn embed_batch(&self, spans: Vec<String>) -> Result<Vec<Embedding>>;
fn max_tokens_per_batch(&self) -> usize;
- fn truncate(&self, span: &str) -> (String, usize);
fn rate_limit_expiration(&self) -> Option<Instant>;
}
-pub struct DummyEmbeddings {}
-
-#[async_trait]
-impl EmbeddingProvider for DummyEmbeddings {
- fn retrieve_credentials(&self, _cx: &AppContext) -> Option<String> {
- Some("Dummy API KEY".to_string())
- }
- fn rate_limit_expiration(&self) -> Option<Instant> {
- None
- }
- async fn embed_batch(
- &self,
- spans: Vec<String>,
- _api_key: Option<String>,
- ) -> Result<Vec<Embedding>> {
- // 1024 is the OpenAI Embeddings size for ada models.
- // the model we will likely be starting with.
- let dummy_vec = Embedding::from(vec![0.32 as f32; 1536]);
- return Ok(vec![dummy_vec; spans.len()]);
- }
-
- fn max_tokens_per_batch(&self) -> usize {
- OPENAI_INPUT_LIMIT
- }
-
- fn truncate(&self, span: &str) -> (String, usize) {
- let mut tokens = OPENAI_BPE_TOKENIZER.encode_with_special_tokens(span);
- let token_count = tokens.len();
- let output = if token_count > OPENAI_INPUT_LIMIT {
- tokens.truncate(OPENAI_INPUT_LIMIT);
- let new_input = OPENAI_BPE_TOKENIZER.decode(tokens.clone());
- new_input.ok().unwrap_or_else(|| span.to_string())
- } else {
- span.to_string()
- };
-
- (output, tokens.len())
- }
-}
-
-const OPENAI_INPUT_LIMIT: usize = 8190;
-
-impl OpenAIEmbeddings {
- pub fn new(client: Arc<dyn HttpClient>, executor: Arc<Background>) -> Self {
- let (rate_limit_count_tx, rate_limit_count_rx) = watch::channel_with(None);
- let rate_limit_count_tx = Arc::new(Mutex::new(rate_limit_count_tx));
-
- OpenAIEmbeddings {
- client,
- executor,
- rate_limit_count_rx,
- rate_limit_count_tx,
- }
- }
-
- fn resolve_rate_limit(&self) {
- let reset_time = *self.rate_limit_count_tx.lock().borrow();
-
- if let Some(reset_time) = reset_time {
- if Instant::now() >= reset_time {
- *self.rate_limit_count_tx.lock().borrow_mut() = None
- }
- }
-
- log::trace!(
- "resolving reset time: {:?}",
- *self.rate_limit_count_tx.lock().borrow()
- );
- }
-
- fn update_reset_time(&self, reset_time: Instant) {
- let original_time = *self.rate_limit_count_tx.lock().borrow();
-
- let updated_time = if let Some(original_time) = original_time {
- if reset_time < original_time {
- Some(reset_time)
- } else {
- Some(original_time)
- }
- } else {
- Some(reset_time)
- };
-
- log::trace!("updating rate limit time: {:?}", updated_time);
-
- *self.rate_limit_count_tx.lock().borrow_mut() = updated_time;
- }
- async fn send_request(
- &self,
- api_key: &str,
- spans: Vec<&str>,
- request_timeout: u64,
- ) -> Result<Response<AsyncBody>> {
- let request = Request::post("https://api.openai.com/v1/embeddings")
- .redirect_policy(isahc::config::RedirectPolicy::Follow)
- .timeout(Duration::from_secs(request_timeout))
- .header("Content-Type", "application/json")
- .header("Authorization", format!("Bearer {}", api_key))
- .body(
- serde_json::to_string(&OpenAIEmbeddingRequest {
- input: spans.clone(),
- model: "text-embedding-ada-002",
- })
- .unwrap()
- .into(),
- )?;
-
- Ok(self.client.send(request).await?)
- }
-}
-
-#[async_trait]
-impl EmbeddingProvider for OpenAIEmbeddings {
- fn retrieve_credentials(&self, cx: &AppContext) -> Option<String> {
- if let Ok(api_key) = env::var("OPENAI_API_KEY") {
- Some(api_key)
- } else if let Some((_, api_key)) = cx
- .platform()
- .read_credentials(OPENAI_API_URL)
- .log_err()
- .flatten()
- {
- String::from_utf8(api_key).log_err()
- } else {
- None
- }
- }
-
- fn max_tokens_per_batch(&self) -> usize {
- 50000
- }
-
- fn rate_limit_expiration(&self) -> Option<Instant> {
- *self.rate_limit_count_rx.borrow()
- }
- fn truncate(&self, span: &str) -> (String, usize) {
- let mut tokens = OPENAI_BPE_TOKENIZER.encode_with_special_tokens(span);
- let output = if tokens.len() > OPENAI_INPUT_LIMIT {
- tokens.truncate(OPENAI_INPUT_LIMIT);
- OPENAI_BPE_TOKENIZER
- .decode(tokens.clone())
- .ok()
- .unwrap_or_else(|| span.to_string())
- } else {
- span.to_string()
- };
-
- (output, tokens.len())
- }
-
- async fn embed_batch(
- &self,
- spans: Vec<String>,
- api_key: Option<String>,
- ) -> Result<Vec<Embedding>> {
- const BACKOFF_SECONDS: [usize; 4] = [3, 5, 15, 45];
- const MAX_RETRIES: usize = 4;
-
- let Some(api_key) = api_key else {
- return Err(anyhow!("no open ai key provided"));
- };
-
- let mut request_number = 0;
- let mut rate_limiting = false;
- let mut request_timeout: u64 = 15;
- let mut response: Response<AsyncBody>;
- while request_number < MAX_RETRIES {
- response = self
- .send_request(
- &api_key,
- spans.iter().map(|x| &**x).collect(),
- request_timeout,
- )
- .await?;
-
- request_number += 1;
-
- match response.status() {
- StatusCode::REQUEST_TIMEOUT => {
- request_timeout += 5;
- }
- StatusCode::OK => {
- let mut body = String::new();
- response.body_mut().read_to_string(&mut body).await?;
- let response: OpenAIEmbeddingResponse = serde_json::from_str(&body)?;
-
- log::trace!(
- "openai embedding completed. tokens: {:?}",
- response.usage.total_tokens
- );
-
- // If we complete a request successfully that was previously rate_limited
- // resolve the rate limit
- if rate_limiting {
- self.resolve_rate_limit()
- }
-
- return Ok(response
- .data
- .into_iter()
- .map(|embedding| Embedding::from(embedding.embedding))
- .collect());
- }
- StatusCode::TOO_MANY_REQUESTS => {
- rate_limiting = true;
- let mut body = String::new();
- response.body_mut().read_to_string(&mut body).await?;
-
- let delay_duration = {
- let delay = Duration::from_secs(BACKOFF_SECONDS[request_number - 1] as u64);
- if let Some(time_to_reset) =
- response.headers().get("x-ratelimit-reset-tokens")
- {
- if let Ok(time_str) = time_to_reset.to_str() {
- parse(time_str).unwrap_or(delay)
- } else {
- delay
- }
- } else {
- delay
- }
- };
-
- // If we've previously rate limited, increment the duration but not the count
- let reset_time = Instant::now().add(delay_duration);
- self.update_reset_time(reset_time);
-
- log::trace!(
- "openai rate limiting: waiting {:?} until lifted",
- &delay_duration
- );
-
- self.executor.timer(delay_duration).await;
- }
- _ => {
- let mut body = String::new();
- response.body_mut().read_to_string(&mut body).await?;
- return Err(anyhow!(
- "open ai bad request: {:?} {:?}",
- &response.status(),
- body
- ));
- }
- }
- }
- Err(anyhow!("openai max retries"))
- }
-}
-
#[cfg(test)]
mod tests {
use super::*;
@@ -1,66 +1,16 @@
-use anyhow::anyhow;
-use tiktoken_rs::CoreBPE;
-use util::ResultExt;
+pub enum TruncationDirection {
+ Start,
+ End,
+}
pub trait LanguageModel {
fn name(&self) -> String;
fn count_tokens(&self, content: &str) -> anyhow::Result<usize>;
- fn truncate(&self, content: &str, length: usize) -> anyhow::Result<String>;
- fn truncate_start(&self, content: &str, length: usize) -> anyhow::Result<String>;
+ fn truncate(
+ &self,
+ content: &str,
+ length: usize,
+ direction: TruncationDirection,
+ ) -> anyhow::Result<String>;
fn capacity(&self) -> anyhow::Result<usize>;
}
-
-pub struct OpenAILanguageModel {
- name: String,
- bpe: Option<CoreBPE>,
-}
-
-impl OpenAILanguageModel {
- pub fn load(model_name: &str) -> Self {
- let bpe = tiktoken_rs::get_bpe_from_model(model_name).log_err();
- OpenAILanguageModel {
- name: model_name.to_string(),
- bpe,
- }
- }
-}
-
-impl LanguageModel for OpenAILanguageModel {
- fn name(&self) -> String {
- self.name.clone()
- }
- fn count_tokens(&self, content: &str) -> anyhow::Result<usize> {
- if let Some(bpe) = &self.bpe {
- anyhow::Ok(bpe.encode_with_special_tokens(content).len())
- } else {
- Err(anyhow!("bpe for open ai model was not retrieved"))
- }
- }
- fn truncate(&self, content: &str, length: usize) -> anyhow::Result<String> {
- if let Some(bpe) = &self.bpe {
- let tokens = bpe.encode_with_special_tokens(content);
- if tokens.len() > length {
- bpe.decode(tokens[..length].to_vec())
- } else {
- bpe.decode(tokens)
- }
- } else {
- Err(anyhow!("bpe for open ai model was not retrieved"))
- }
- }
- fn truncate_start(&self, content: &str, length: usize) -> anyhow::Result<String> {
- if let Some(bpe) = &self.bpe {
- let tokens = bpe.encode_with_special_tokens(content);
- if tokens.len() > length {
- bpe.decode(tokens[length..].to_vec())
- } else {
- bpe.decode(tokens)
- }
- } else {
- Err(anyhow!("bpe for open ai model was not retrieved"))
- }
- }
- fn capacity(&self) -> anyhow::Result<usize> {
- anyhow::Ok(tiktoken_rs::model::get_context_size(&self.name))
- }
-}
@@ -6,7 +6,7 @@ use language::BufferSnapshot;
use util::ResultExt;
use crate::models::LanguageModel;
-use crate::templates::repository_context::PromptCodeSnippet;
+use crate::prompts::repository_context::PromptCodeSnippet;
pub(crate) enum PromptFileType {
Text,
@@ -125,6 +125,9 @@ impl PromptChain {
#[cfg(test)]
pub(crate) mod tests {
+ use crate::models::TruncationDirection;
+ use crate::test::FakeLanguageModel;
+
use super::*;
#[test]
@@ -141,7 +144,11 @@ pub(crate) mod tests {
let mut token_count = args.model.count_tokens(&content)?;
if let Some(max_token_length) = max_token_length {
if token_count > max_token_length {
- content = args.model.truncate(&content, max_token_length)?;
+ content = args.model.truncate(
+ &content,
+ max_token_length,
+ TruncationDirection::End,
+ )?;
token_count = max_token_length;
}
}
@@ -162,7 +169,11 @@ pub(crate) mod tests {
let mut token_count = args.model.count_tokens(&content)?;
if let Some(max_token_length) = max_token_length {
if token_count > max_token_length {
- content = args.model.truncate(&content, max_token_length)?;
+ content = args.model.truncate(
+ &content,
+ max_token_length,
+ TruncationDirection::End,
+ )?;
token_count = max_token_length;
}
}
@@ -171,38 +182,7 @@ pub(crate) mod tests {
}
}
- #[derive(Clone)]
- struct DummyLanguageModel {
- capacity: usize,
- }
-
- impl LanguageModel for DummyLanguageModel {
- fn name(&self) -> String {
- "dummy".to_string()
- }
- fn count_tokens(&self, content: &str) -> anyhow::Result<usize> {
- anyhow::Ok(content.chars().collect::<Vec<char>>().len())
- }
- fn truncate(&self, content: &str, length: usize) -> anyhow::Result<String> {
- anyhow::Ok(
- content.chars().collect::<Vec<char>>()[..length]
- .into_iter()
- .collect::<String>(),
- )
- }
- fn truncate_start(&self, content: &str, length: usize) -> anyhow::Result<String> {
- anyhow::Ok(
- content.chars().collect::<Vec<char>>()[length..]
- .into_iter()
- .collect::<String>(),
- )
- }
- fn capacity(&self) -> anyhow::Result<usize> {
- anyhow::Ok(self.capacity)
- }
- }
-
- let model: Arc<dyn LanguageModel> = Arc::new(DummyLanguageModel { capacity: 100 });
+ let model: Arc<dyn LanguageModel> = Arc::new(FakeLanguageModel { capacity: 100 });
let args = PromptArguments {
model: model.clone(),
language_name: None,
@@ -238,7 +218,7 @@ pub(crate) mod tests {
// Testing with Truncation Off
// Should ignore capacity and return all prompts
- let model: Arc<dyn LanguageModel> = Arc::new(DummyLanguageModel { capacity: 20 });
+ let model: Arc<dyn LanguageModel> = Arc::new(FakeLanguageModel { capacity: 20 });
let args = PromptArguments {
model: model.clone(),
language_name: None,
@@ -275,7 +255,7 @@ pub(crate) mod tests {
// Testing with Truncation Off
// Should ignore capacity and return all prompts
let capacity = 20;
- let model: Arc<dyn LanguageModel> = Arc::new(DummyLanguageModel { capacity });
+ let model: Arc<dyn LanguageModel> = Arc::new(FakeLanguageModel { capacity });
let args = PromptArguments {
model: model.clone(),
language_name: None,
@@ -311,7 +291,7 @@ pub(crate) mod tests {
// Change Ordering of Prompts Based on Priority
let capacity = 120;
let reserved_tokens = 10;
- let model: Arc<dyn LanguageModel> = Arc::new(DummyLanguageModel { capacity });
+ let model: Arc<dyn LanguageModel> = Arc::new(FakeLanguageModel { capacity });
let args = PromptArguments {
model: model.clone(),
language_name: None,
@@ -3,8 +3,9 @@ use language::BufferSnapshot;
use language::ToOffset;
use crate::models::LanguageModel;
-use crate::templates::base::PromptArguments;
-use crate::templates::base::PromptTemplate;
+use crate::models::TruncationDirection;
+use crate::prompts::base::PromptArguments;
+use crate::prompts::base::PromptTemplate;
use std::fmt::Write;
use std::ops::Range;
use std::sync::Arc;
@@ -70,8 +71,9 @@ fn retrieve_context(
};
let truncated_start_window =
- model.truncate_start(&start_window, start_goal_tokens)?;
- let truncated_end_window = model.truncate(&end_window, end_goal_tokens)?;
+ model.truncate(&start_window, start_goal_tokens, TruncationDirection::Start)?;
+ let truncated_end_window =
+ model.truncate(&end_window, end_goal_tokens, TruncationDirection::End)?;
writeln!(
prompt,
"{truncated_start_window}{selected_window}{truncated_end_window}"
@@ -89,7 +91,7 @@ fn retrieve_context(
if let Some(max_token_count) = max_token_count {
if model.count_tokens(&prompt)? > max_token_count {
truncated = true;
- prompt = model.truncate(&prompt, max_token_count)?;
+ prompt = model.truncate(&prompt, max_token_count, TruncationDirection::End)?;
}
}
}
@@ -148,7 +150,9 @@ impl PromptTemplate for FileContext {
// Really dumb truncation strategy
if let Some(max_tokens) = max_token_length {
- prompt = args.model.truncate(&prompt, max_tokens)?;
+ prompt = args
+ .model
+ .truncate(&prompt, max_tokens, TruncationDirection::End)?;
}
let token_count = args.model.count_tokens(&prompt)?;
@@ -1,4 +1,4 @@
-use crate::templates::base::{PromptArguments, PromptFileType, PromptTemplate};
+use crate::prompts::base::{PromptArguments, PromptFileType, PromptTemplate};
use anyhow::anyhow;
use std::fmt::Write;
@@ -85,7 +85,11 @@ impl PromptTemplate for GenerateInlineContent {
// Really dumb truncation strategy
if let Some(max_tokens) = max_token_length {
- prompt = args.model.truncate(&prompt, max_tokens)?;
+ prompt = args.model.truncate(
+ &prompt,
+ max_tokens,
+ crate::models::TruncationDirection::End,
+ )?;
}
let token_count = args.model.count_tokens(&prompt)?;
@@ -1,4 +1,4 @@
-use crate::templates::base::{PromptArguments, PromptFileType, PromptTemplate};
+use crate::prompts::base::{PromptArguments, PromptFileType, PromptTemplate};
use std::fmt::Write;
pub struct EngineerPreamble {}
@@ -1,4 +1,4 @@
-use crate::templates::base::{PromptArguments, PromptTemplate};
+use crate::prompts::base::{PromptArguments, PromptTemplate};
use std::fmt::Write;
use std::{ops::Range, path::PathBuf};
@@ -0,0 +1 @@
+pub mod open_ai;
@@ -0,0 +1,298 @@
+use anyhow::{anyhow, Result};
+use futures::{
+ future::BoxFuture, io::BufReader, stream::BoxStream, AsyncBufReadExt, AsyncReadExt, FutureExt,
+ Stream, StreamExt,
+};
+use gpui::{executor::Background, AppContext};
+use isahc::{http::StatusCode, Request, RequestExt};
+use parking_lot::RwLock;
+use serde::{Deserialize, Serialize};
+use std::{
+ env,
+ fmt::{self, Display},
+ io,
+ sync::Arc,
+};
+use util::ResultExt;
+
+use crate::{
+ auth::{CredentialProvider, ProviderCredential},
+ completion::{CompletionProvider, CompletionRequest},
+ models::LanguageModel,
+};
+
+use crate::providers::open_ai::{OpenAILanguageModel, OPENAI_API_URL};
+
+#[derive(Clone, Copy, Serialize, Deserialize, Debug, Eq, PartialEq)]
+#[serde(rename_all = "lowercase")]
+pub enum Role {
+ User,
+ Assistant,
+ System,
+}
+
+impl Role {
+ pub fn cycle(&mut self) {
+ *self = match self {
+ Role::User => Role::Assistant,
+ Role::Assistant => Role::System,
+ Role::System => Role::User,
+ }
+ }
+}
+
+impl Display for Role {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result {
+ match self {
+ Role::User => write!(f, "User"),
+ Role::Assistant => write!(f, "Assistant"),
+ Role::System => write!(f, "System"),
+ }
+ }
+}
+
+#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
+pub struct RequestMessage {
+ pub role: Role,
+ pub content: String,
+}
+
+#[derive(Debug, Default, Serialize)]
+pub struct OpenAIRequest {
+ pub model: String,
+ pub messages: Vec<RequestMessage>,
+ pub stream: bool,
+ pub stop: Vec<String>,
+ pub temperature: f32,
+}
+
+impl CompletionRequest for OpenAIRequest {
+ fn data(&self) -> serde_json::Result<String> {
+ serde_json::to_string(self)
+ }
+}
+
+#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
+pub struct ResponseMessage {
+ pub role: Option<Role>,
+ pub content: Option<String>,
+}
+
+#[derive(Deserialize, Debug)]
+pub struct OpenAIUsage {
+ pub prompt_tokens: u32,
+ pub completion_tokens: u32,
+ pub total_tokens: u32,
+}
+
+#[derive(Deserialize, Debug)]
+pub struct ChatChoiceDelta {
+ pub index: u32,
+ pub delta: ResponseMessage,
+ pub finish_reason: Option<String>,
+}
+
+#[derive(Deserialize, Debug)]
+pub struct OpenAIResponseStreamEvent {
+ pub id: Option<String>,
+ pub object: String,
+ pub created: u32,
+ pub model: String,
+ pub choices: Vec<ChatChoiceDelta>,
+ pub usage: Option<OpenAIUsage>,
+}
+
+pub async fn stream_completion(
+ credential: ProviderCredential,
+ executor: Arc<Background>,
+ request: Box<dyn CompletionRequest>,
+) -> Result<impl Stream<Item = Result<OpenAIResponseStreamEvent>>> {
+ let api_key = match credential {
+ ProviderCredential::Credentials { api_key } => api_key,
+ _ => {
+ return Err(anyhow!("no credentials provider for completion"));
+ }
+ };
+
+ let (tx, rx) = futures::channel::mpsc::unbounded::<Result<OpenAIResponseStreamEvent>>();
+
+ let json_data = request.data()?;
+ let mut response = Request::post(format!("{OPENAI_API_URL}/chat/completions"))
+ .header("Content-Type", "application/json")
+ .header("Authorization", format!("Bearer {}", api_key))
+ .body(json_data)?
+ .send_async()
+ .await?;
+
+ let status = response.status();
+ if status == StatusCode::OK {
+ executor
+ .spawn(async move {
+ let mut lines = BufReader::new(response.body_mut()).lines();
+
+ fn parse_line(
+ line: Result<String, io::Error>,
+ ) -> Result<Option<OpenAIResponseStreamEvent>> {
+ if let Some(data) = line?.strip_prefix("data: ") {
+ let event = serde_json::from_str(&data)?;
+ Ok(Some(event))
+ } else {
+ Ok(None)
+ }
+ }
+
+ while let Some(line) = lines.next().await {
+ if let Some(event) = parse_line(line).transpose() {
+ let done = event.as_ref().map_or(false, |event| {
+ event
+ .choices
+ .last()
+ .map_or(false, |choice| choice.finish_reason.is_some())
+ });
+ if tx.unbounded_send(event).is_err() {
+ break;
+ }
+
+ if done {
+ break;
+ }
+ }
+ }
+
+ anyhow::Ok(())
+ })
+ .detach();
+
+ Ok(rx)
+ } else {
+ let mut body = String::new();
+ response.body_mut().read_to_string(&mut body).await?;
+
+ #[derive(Deserialize)]
+ struct OpenAIResponse {
+ error: OpenAIError,
+ }
+
+ #[derive(Deserialize)]
+ struct OpenAIError {
+ message: String,
+ }
+
+ match serde_json::from_str::<OpenAIResponse>(&body) {
+ Ok(response) if !response.error.message.is_empty() => Err(anyhow!(
+ "Failed to connect to OpenAI API: {}",
+ response.error.message,
+ )),
+
+ _ => Err(anyhow!(
+ "Failed to connect to OpenAI API: {} {}",
+ response.status(),
+ body,
+ )),
+ }
+ }
+}
+
+#[derive(Clone)]
+pub struct OpenAICompletionProvider {
+ model: OpenAILanguageModel,
+ credential: Arc<RwLock<ProviderCredential>>,
+ executor: Arc<Background>,
+}
+
+impl OpenAICompletionProvider {
+ pub fn new(model_name: &str, executor: Arc<Background>) -> Self {
+ let model = OpenAILanguageModel::load(model_name);
+ let credential = Arc::new(RwLock::new(ProviderCredential::NoCredentials));
+ Self {
+ model,
+ credential,
+ executor,
+ }
+ }
+}
+
+impl CredentialProvider for OpenAICompletionProvider {
+ fn has_credentials(&self) -> bool {
+ match *self.credential.read() {
+ ProviderCredential::Credentials { .. } => true,
+ _ => false,
+ }
+ }
+ fn retrieve_credentials(&self, cx: &AppContext) -> ProviderCredential {
+ let mut credential = self.credential.write();
+ match *credential {
+ ProviderCredential::Credentials { .. } => {
+ return credential.clone();
+ }
+ _ => {
+ if let Ok(api_key) = env::var("OPENAI_API_KEY") {
+ *credential = ProviderCredential::Credentials { api_key };
+ } else if let Some((_, api_key)) = cx
+ .platform()
+ .read_credentials(OPENAI_API_URL)
+ .log_err()
+ .flatten()
+ {
+ if let Some(api_key) = String::from_utf8(api_key).log_err() {
+ *credential = ProviderCredential::Credentials { api_key };
+ }
+ } else {
+ };
+ }
+ }
+
+ credential.clone()
+ }
+
+ fn save_credentials(&self, cx: &AppContext, credential: ProviderCredential) {
+ match credential.clone() {
+ ProviderCredential::Credentials { api_key } => {
+ cx.platform()
+ .write_credentials(OPENAI_API_URL, "Bearer", api_key.as_bytes())
+ .log_err();
+ }
+ _ => {}
+ }
+
+ *self.credential.write() = credential;
+ }
+ fn delete_credentials(&self, cx: &AppContext) {
+ cx.platform().delete_credentials(OPENAI_API_URL).log_err();
+ *self.credential.write() = ProviderCredential::NoCredentials;
+ }
+}
+
+impl CompletionProvider for OpenAICompletionProvider {
+ fn base_model(&self) -> Box<dyn LanguageModel> {
+ let model: Box<dyn LanguageModel> = Box::new(self.model.clone());
+ model
+ }
+ fn complete(
+ &self,
+ prompt: Box<dyn CompletionRequest>,
+ ) -> BoxFuture<'static, Result<BoxStream<'static, Result<String>>>> {
+ // Currently the CompletionRequest for OpenAI, includes a 'model' parameter
+ // This means that the model is determined by the CompletionRequest and not the CompletionProvider,
+ // which is currently model based, due to the langauge model.
+ // At some point in the future we should rectify this.
+ let credential = self.credential.read().clone();
+ let request = stream_completion(credential, self.executor.clone(), prompt);
+ async move {
+ let response = request.await?;
+ let stream = response
+ .filter_map(|response| async move {
+ match response {
+ Ok(mut response) => Some(Ok(response.choices.pop()?.delta.content?)),
+ Err(error) => Some(Err(error)),
+ }
+ })
+ .boxed();
+ Ok(stream)
+ }
+ .boxed()
+ }
+ fn box_clone(&self) -> Box<dyn CompletionProvider> {
+ Box::new((*self).clone())
+ }
+}
@@ -0,0 +1,306 @@
+use anyhow::{anyhow, Result};
+use async_trait::async_trait;
+use futures::AsyncReadExt;
+use gpui::executor::Background;
+use gpui::{serde_json, AppContext};
+use isahc::http::StatusCode;
+use isahc::prelude::Configurable;
+use isahc::{AsyncBody, Response};
+use lazy_static::lazy_static;
+use parking_lot::{Mutex, RwLock};
+use parse_duration::parse;
+use postage::watch;
+use serde::{Deserialize, Serialize};
+use std::env;
+use std::ops::Add;
+use std::sync::Arc;
+use std::time::{Duration, Instant};
+use tiktoken_rs::{cl100k_base, CoreBPE};
+use util::http::{HttpClient, Request};
+use util::ResultExt;
+
+use crate::auth::{CredentialProvider, ProviderCredential};
+use crate::embedding::{Embedding, EmbeddingProvider};
+use crate::models::LanguageModel;
+use crate::providers::open_ai::OpenAILanguageModel;
+
+use crate::providers::open_ai::OPENAI_API_URL;
+
+lazy_static! {
+ static ref OPENAI_BPE_TOKENIZER: CoreBPE = cl100k_base().unwrap();
+}
+
+#[derive(Clone)]
+pub struct OpenAIEmbeddingProvider {
+ model: OpenAILanguageModel,
+ credential: Arc<RwLock<ProviderCredential>>,
+ pub client: Arc<dyn HttpClient>,
+ pub executor: Arc<Background>,
+ rate_limit_count_rx: watch::Receiver<Option<Instant>>,
+ rate_limit_count_tx: Arc<Mutex<watch::Sender<Option<Instant>>>>,
+}
+
+#[derive(Serialize)]
+struct OpenAIEmbeddingRequest<'a> {
+ model: &'static str,
+ input: Vec<&'a str>,
+}
+
+#[derive(Deserialize)]
+struct OpenAIEmbeddingResponse {
+ data: Vec<OpenAIEmbedding>,
+ usage: OpenAIEmbeddingUsage,
+}
+
+#[derive(Debug, Deserialize)]
+struct OpenAIEmbedding {
+ embedding: Vec<f32>,
+ index: usize,
+ object: String,
+}
+
+#[derive(Deserialize)]
+struct OpenAIEmbeddingUsage {
+ prompt_tokens: usize,
+ total_tokens: usize,
+}
+
+impl OpenAIEmbeddingProvider {
+ pub fn new(client: Arc<dyn HttpClient>, executor: Arc<Background>) -> Self {
+ let (rate_limit_count_tx, rate_limit_count_rx) = watch::channel_with(None);
+ let rate_limit_count_tx = Arc::new(Mutex::new(rate_limit_count_tx));
+
+ let model = OpenAILanguageModel::load("text-embedding-ada-002");
+ let credential = Arc::new(RwLock::new(ProviderCredential::NoCredentials));
+
+ OpenAIEmbeddingProvider {
+ model,
+ credential,
+ client,
+ executor,
+ rate_limit_count_rx,
+ rate_limit_count_tx,
+ }
+ }
+
+ fn get_api_key(&self) -> Result<String> {
+ match self.credential.read().clone() {
+ ProviderCredential::Credentials { api_key } => Ok(api_key),
+ _ => Err(anyhow!("api credentials not provided")),
+ }
+ }
+
+ fn resolve_rate_limit(&self) {
+ let reset_time = *self.rate_limit_count_tx.lock().borrow();
+
+ if let Some(reset_time) = reset_time {
+ if Instant::now() >= reset_time {
+ *self.rate_limit_count_tx.lock().borrow_mut() = None
+ }
+ }
+
+ log::trace!(
+ "resolving reset time: {:?}",
+ *self.rate_limit_count_tx.lock().borrow()
+ );
+ }
+
+ fn update_reset_time(&self, reset_time: Instant) {
+ let original_time = *self.rate_limit_count_tx.lock().borrow();
+
+ let updated_time = if let Some(original_time) = original_time {
+ if reset_time < original_time {
+ Some(reset_time)
+ } else {
+ Some(original_time)
+ }
+ } else {
+ Some(reset_time)
+ };
+
+ log::trace!("updating rate limit time: {:?}", updated_time);
+
+ *self.rate_limit_count_tx.lock().borrow_mut() = updated_time;
+ }
+ async fn send_request(
+ &self,
+ api_key: &str,
+ spans: Vec<&str>,
+ request_timeout: u64,
+ ) -> Result<Response<AsyncBody>> {
+ let request = Request::post("https://api.openai.com/v1/embeddings")
+ .redirect_policy(isahc::config::RedirectPolicy::Follow)
+ .timeout(Duration::from_secs(request_timeout))
+ .header("Content-Type", "application/json")
+ .header("Authorization", format!("Bearer {}", api_key))
+ .body(
+ serde_json::to_string(&OpenAIEmbeddingRequest {
+ input: spans.clone(),
+ model: "text-embedding-ada-002",
+ })
+ .unwrap()
+ .into(),
+ )?;
+
+ Ok(self.client.send(request).await?)
+ }
+}
+
+impl CredentialProvider for OpenAIEmbeddingProvider {
+ fn has_credentials(&self) -> bool {
+ match *self.credential.read() {
+ ProviderCredential::Credentials { .. } => true,
+ _ => false,
+ }
+ }
+ fn retrieve_credentials(&self, cx: &AppContext) -> ProviderCredential {
+ let mut credential = self.credential.write();
+ match *credential {
+ ProviderCredential::Credentials { .. } => {
+ return credential.clone();
+ }
+ _ => {
+ if let Ok(api_key) = env::var("OPENAI_API_KEY") {
+ *credential = ProviderCredential::Credentials { api_key };
+ } else if let Some((_, api_key)) = cx
+ .platform()
+ .read_credentials(OPENAI_API_URL)
+ .log_err()
+ .flatten()
+ {
+ if let Some(api_key) = String::from_utf8(api_key).log_err() {
+ *credential = ProviderCredential::Credentials { api_key };
+ }
+ } else {
+ };
+ }
+ }
+
+ credential.clone()
+ }
+
+ fn save_credentials(&self, cx: &AppContext, credential: ProviderCredential) {
+ match credential.clone() {
+ ProviderCredential::Credentials { api_key } => {
+ cx.platform()
+ .write_credentials(OPENAI_API_URL, "Bearer", api_key.as_bytes())
+ .log_err();
+ }
+ _ => {}
+ }
+
+ *self.credential.write() = credential;
+ }
+ fn delete_credentials(&self, cx: &AppContext) {
+ cx.platform().delete_credentials(OPENAI_API_URL).log_err();
+ *self.credential.write() = ProviderCredential::NoCredentials;
+ }
+}
+
+#[async_trait]
+impl EmbeddingProvider for OpenAIEmbeddingProvider {
+ fn base_model(&self) -> Box<dyn LanguageModel> {
+ let model: Box<dyn LanguageModel> = Box::new(self.model.clone());
+ model
+ }
+
+ fn max_tokens_per_batch(&self) -> usize {
+ 50000
+ }
+
+ fn rate_limit_expiration(&self) -> Option<Instant> {
+ *self.rate_limit_count_rx.borrow()
+ }
+
+ async fn embed_batch(&self, spans: Vec<String>) -> Result<Vec<Embedding>> {
+ const BACKOFF_SECONDS: [usize; 4] = [3, 5, 15, 45];
+ const MAX_RETRIES: usize = 4;
+
+ let api_key = self.get_api_key()?;
+
+ let mut request_number = 0;
+ let mut rate_limiting = false;
+ let mut request_timeout: u64 = 15;
+ let mut response: Response<AsyncBody>;
+ while request_number < MAX_RETRIES {
+ response = self
+ .send_request(
+ &api_key,
+ spans.iter().map(|x| &**x).collect(),
+ request_timeout,
+ )
+ .await?;
+
+ request_number += 1;
+
+ match response.status() {
+ StatusCode::REQUEST_TIMEOUT => {
+ request_timeout += 5;
+ }
+ StatusCode::OK => {
+ let mut body = String::new();
+ response.body_mut().read_to_string(&mut body).await?;
+ let response: OpenAIEmbeddingResponse = serde_json::from_str(&body)?;
+
+ log::trace!(
+ "openai embedding completed. tokens: {:?}",
+ response.usage.total_tokens
+ );
+
+ // If we complete a request successfully that was previously rate_limited
+ // resolve the rate limit
+ if rate_limiting {
+ self.resolve_rate_limit()
+ }
+
+ return Ok(response
+ .data
+ .into_iter()
+ .map(|embedding| Embedding::from(embedding.embedding))
+ .collect());
+ }
+ StatusCode::TOO_MANY_REQUESTS => {
+ rate_limiting = true;
+ let mut body = String::new();
+ response.body_mut().read_to_string(&mut body).await?;
+
+ let delay_duration = {
+ let delay = Duration::from_secs(BACKOFF_SECONDS[request_number - 1] as u64);
+ if let Some(time_to_reset) =
+ response.headers().get("x-ratelimit-reset-tokens")
+ {
+ if let Ok(time_str) = time_to_reset.to_str() {
+ parse(time_str).unwrap_or(delay)
+ } else {
+ delay
+ }
+ } else {
+ delay
+ }
+ };
+
+ // If we've previously rate limited, increment the duration but not the count
+ let reset_time = Instant::now().add(delay_duration);
+ self.update_reset_time(reset_time);
+
+ log::trace!(
+ "openai rate limiting: waiting {:?} until lifted",
+ &delay_duration
+ );
+
+ self.executor.timer(delay_duration).await;
+ }
+ _ => {
+ let mut body = String::new();
+ response.body_mut().read_to_string(&mut body).await?;
+ return Err(anyhow!(
+ "open ai bad request: {:?} {:?}",
+ &response.status(),
+ body
+ ));
+ }
+ }
+ }
+ Err(anyhow!("openai max retries"))
+ }
+}
@@ -0,0 +1,9 @@
+pub mod completion;
+pub mod embedding;
+pub mod model;
+
+pub use completion::*;
+pub use embedding::*;
+pub use model::OpenAILanguageModel;
+
+pub const OPENAI_API_URL: &'static str = "https://api.openai.com/v1";
@@ -0,0 +1,57 @@
+use anyhow::anyhow;
+use tiktoken_rs::CoreBPE;
+use util::ResultExt;
+
+use crate::models::{LanguageModel, TruncationDirection};
+
+#[derive(Clone)]
+pub struct OpenAILanguageModel {
+ name: String,
+ bpe: Option<CoreBPE>,
+}
+
+impl OpenAILanguageModel {
+ pub fn load(model_name: &str) -> Self {
+ let bpe = tiktoken_rs::get_bpe_from_model(model_name).log_err();
+ OpenAILanguageModel {
+ name: model_name.to_string(),
+ bpe,
+ }
+ }
+}
+
+impl LanguageModel for OpenAILanguageModel {
+ fn name(&self) -> String {
+ self.name.clone()
+ }
+ fn count_tokens(&self, content: &str) -> anyhow::Result<usize> {
+ if let Some(bpe) = &self.bpe {
+ anyhow::Ok(bpe.encode_with_special_tokens(content).len())
+ } else {
+ Err(anyhow!("bpe for open ai model was not retrieved"))
+ }
+ }
+ fn truncate(
+ &self,
+ content: &str,
+ length: usize,
+ direction: TruncationDirection,
+ ) -> anyhow::Result<String> {
+ if let Some(bpe) = &self.bpe {
+ let tokens = bpe.encode_with_special_tokens(content);
+ if tokens.len() > length {
+ match direction {
+ TruncationDirection::End => bpe.decode(tokens[..length].to_vec()),
+ TruncationDirection::Start => bpe.decode(tokens[length..].to_vec()),
+ }
+ } else {
+ bpe.decode(tokens)
+ }
+ } else {
+ Err(anyhow!("bpe for open ai model was not retrieved"))
+ }
+ }
+ fn capacity(&self) -> anyhow::Result<usize> {
+ anyhow::Ok(tiktoken_rs::model::get_context_size(&self.name))
+ }
+}
@@ -0,0 +1,11 @@
+pub trait LanguageModel {
+ fn name(&self) -> String;
+ fn count_tokens(&self, content: &str) -> anyhow::Result<usize>;
+ fn truncate(
+ &self,
+ content: &str,
+ length: usize,
+ direction: TruncationDirection,
+ ) -> anyhow::Result<String>;
+ fn capacity(&self) -> anyhow::Result<usize>;
+}
@@ -0,0 +1,191 @@
+use std::{
+ sync::atomic::{self, AtomicUsize, Ordering},
+ time::Instant,
+};
+
+use async_trait::async_trait;
+use futures::{channel::mpsc, future::BoxFuture, stream::BoxStream, FutureExt, StreamExt};
+use gpui::AppContext;
+use parking_lot::Mutex;
+
+use crate::{
+ auth::{CredentialProvider, ProviderCredential},
+ completion::{CompletionProvider, CompletionRequest},
+ embedding::{Embedding, EmbeddingProvider},
+ models::{LanguageModel, TruncationDirection},
+};
+
+#[derive(Clone)]
+pub struct FakeLanguageModel {
+ pub capacity: usize,
+}
+
+impl LanguageModel for FakeLanguageModel {
+ fn name(&self) -> String {
+ "dummy".to_string()
+ }
+ fn count_tokens(&self, content: &str) -> anyhow::Result<usize> {
+ anyhow::Ok(content.chars().collect::<Vec<char>>().len())
+ }
+ fn truncate(
+ &self,
+ content: &str,
+ length: usize,
+ direction: TruncationDirection,
+ ) -> anyhow::Result<String> {
+ println!("TRYING TO TRUNCATE: {:?}", length.clone());
+
+ if length > self.count_tokens(content)? {
+ println!("NOT TRUNCATING");
+ return anyhow::Ok(content.to_string());
+ }
+
+ anyhow::Ok(match direction {
+ TruncationDirection::End => content.chars().collect::<Vec<char>>()[..length]
+ .into_iter()
+ .collect::<String>(),
+ TruncationDirection::Start => content.chars().collect::<Vec<char>>()[length..]
+ .into_iter()
+ .collect::<String>(),
+ })
+ }
+ fn capacity(&self) -> anyhow::Result<usize> {
+ anyhow::Ok(self.capacity)
+ }
+}
+
+pub struct FakeEmbeddingProvider {
+ pub embedding_count: AtomicUsize,
+}
+
+impl Clone for FakeEmbeddingProvider {
+ fn clone(&self) -> Self {
+ FakeEmbeddingProvider {
+ embedding_count: AtomicUsize::new(self.embedding_count.load(Ordering::SeqCst)),
+ }
+ }
+}
+
+impl Default for FakeEmbeddingProvider {
+ fn default() -> Self {
+ FakeEmbeddingProvider {
+ embedding_count: AtomicUsize::default(),
+ }
+ }
+}
+
+impl FakeEmbeddingProvider {
+ pub fn embedding_count(&self) -> usize {
+ self.embedding_count.load(atomic::Ordering::SeqCst)
+ }
+
+ pub fn embed_sync(&self, span: &str) -> Embedding {
+ let mut result = vec![1.0; 26];
+ for letter in span.chars() {
+ let letter = letter.to_ascii_lowercase();
+ if letter as u32 >= 'a' as u32 {
+ let ix = (letter as u32) - ('a' as u32);
+ if ix < 26 {
+ result[ix as usize] += 1.0;
+ }
+ }
+ }
+
+ let norm = result.iter().map(|x| x * x).sum::<f32>().sqrt();
+ for x in &mut result {
+ *x /= norm;
+ }
+
+ result.into()
+ }
+}
+
+impl CredentialProvider for FakeEmbeddingProvider {
+ fn has_credentials(&self) -> bool {
+ true
+ }
+ fn retrieve_credentials(&self, _cx: &AppContext) -> ProviderCredential {
+ ProviderCredential::NotNeeded
+ }
+ fn save_credentials(&self, _cx: &AppContext, _credential: ProviderCredential) {}
+ fn delete_credentials(&self, _cx: &AppContext) {}
+}
+
+#[async_trait]
+impl EmbeddingProvider for FakeEmbeddingProvider {
+ fn base_model(&self) -> Box<dyn LanguageModel> {
+ Box::new(FakeLanguageModel { capacity: 1000 })
+ }
+ fn max_tokens_per_batch(&self) -> usize {
+ 1000
+ }
+
+ fn rate_limit_expiration(&self) -> Option<Instant> {
+ None
+ }
+
+ async fn embed_batch(&self, spans: Vec<String>) -> anyhow::Result<Vec<Embedding>> {
+ self.embedding_count
+ .fetch_add(spans.len(), atomic::Ordering::SeqCst);
+
+ anyhow::Ok(spans.iter().map(|span| self.embed_sync(span)).collect())
+ }
+}
+
+pub struct FakeCompletionProvider {
+ last_completion_tx: Mutex<Option<mpsc::Sender<String>>>,
+}
+
+impl Clone for FakeCompletionProvider {
+ fn clone(&self) -> Self {
+ Self {
+ last_completion_tx: Mutex::new(None),
+ }
+ }
+}
+
+impl FakeCompletionProvider {
+ pub fn new() -> Self {
+ Self {
+ last_completion_tx: Mutex::new(None),
+ }
+ }
+
+ pub fn send_completion(&self, completion: impl Into<String>) {
+ let mut tx = self.last_completion_tx.lock();
+ tx.as_mut().unwrap().try_send(completion.into()).unwrap();
+ }
+
+ pub fn finish_completion(&self) {
+ self.last_completion_tx.lock().take().unwrap();
+ }
+}
+
+impl CredentialProvider for FakeCompletionProvider {
+ fn has_credentials(&self) -> bool {
+ true
+ }
+ fn retrieve_credentials(&self, _cx: &AppContext) -> ProviderCredential {
+ ProviderCredential::NotNeeded
+ }
+ fn save_credentials(&self, _cx: &AppContext, _credential: ProviderCredential) {}
+ fn delete_credentials(&self, _cx: &AppContext) {}
+}
+
+impl CompletionProvider for FakeCompletionProvider {
+ fn base_model(&self) -> Box<dyn LanguageModel> {
+ let model: Box<dyn LanguageModel> = Box::new(FakeLanguageModel { capacity: 8190 });
+ model
+ }
+ fn complete(
+ &self,
+ _prompt: Box<dyn CompletionRequest>,
+ ) -> BoxFuture<'static, anyhow::Result<BoxStream<'static, anyhow::Result<String>>>> {
+ let (tx, rx) = mpsc::channel(1);
+ *self.last_completion_tx.lock() = Some(tx);
+ async move { Ok(rx.map(|rx| Ok(rx)).boxed()) }.boxed()
+ }
+ fn box_clone(&self) -> Box<dyn CompletionProvider> {
+ Box::new((*self).clone())
+ }
+}
@@ -0,0 +1,38 @@
+[package]
+name = "ai2"
+version = "0.1.0"
+edition = "2021"
+publish = false
+
+[lib]
+path = "src/ai2.rs"
+doctest = false
+
+[features]
+test-support = []
+
+[dependencies]
+gpui2 = { path = "../gpui2" }
+util = { path = "../util" }
+language2 = { path = "../language2" }
+async-trait.workspace = true
+anyhow.workspace = true
+futures.workspace = true
+lazy_static.workspace = true
+ordered-float.workspace = true
+parking_lot.workspace = true
+isahc.workspace = true
+regex.workspace = true
+serde.workspace = true
+serde_json.workspace = true
+postage.workspace = true
+rand.workspace = true
+log.workspace = true
+parse_duration = "2.1.1"
+tiktoken-rs = "0.5.0"
+matrixmultiply = "0.3.7"
+rusqlite = { version = "0.29.0", features = ["blob", "array", "modern_sqlite"] }
+bincode = "1.3.3"
+
+[dev-dependencies]
+gpui2 = { path = "../gpui2", features = ["test-support"] }
@@ -0,0 +1,8 @@
+pub mod auth;
+pub mod completion;
+pub mod embedding;
+pub mod models;
+pub mod prompts;
+pub mod providers;
+#[cfg(any(test, feature = "test-support"))]
+pub mod test;
@@ -0,0 +1,17 @@
+use async_trait::async_trait;
+use gpui2::AppContext;
+
+#[derive(Clone, Debug)]
+pub enum ProviderCredential {
+ Credentials { api_key: String },
+ NoCredentials,
+ NotNeeded,
+}
+
+#[async_trait]
+pub trait CredentialProvider: Send + Sync {
+ fn has_credentials(&self) -> bool;
+ async fn retrieve_credentials(&self, cx: &mut AppContext) -> ProviderCredential;
+ async fn save_credentials(&self, cx: &mut AppContext, credential: ProviderCredential);
+ async fn delete_credentials(&self, cx: &mut AppContext);
+}
@@ -0,0 +1,23 @@
+use anyhow::Result;
+use futures::{future::BoxFuture, stream::BoxStream};
+
+use crate::{auth::CredentialProvider, models::LanguageModel};
+
+pub trait CompletionRequest: Send + Sync {
+ fn data(&self) -> serde_json::Result<String>;
+}
+
+pub trait CompletionProvider: CredentialProvider {
+ fn base_model(&self) -> Box<dyn LanguageModel>;
+ fn complete(
+ &self,
+ prompt: Box<dyn CompletionRequest>,
+ ) -> BoxFuture<'static, Result<BoxStream<'static, Result<String>>>>;
+ fn box_clone(&self) -> Box<dyn CompletionProvider>;
+}
+
+impl Clone for Box<dyn CompletionProvider> {
+ fn clone(&self) -> Box<dyn CompletionProvider> {
+ self.box_clone()
+ }
+}
@@ -0,0 +1,123 @@
+use std::time::Instant;
+
+use anyhow::Result;
+use async_trait::async_trait;
+use ordered_float::OrderedFloat;
+use rusqlite::types::{FromSql, FromSqlResult, ToSqlOutput, ValueRef};
+use rusqlite::ToSql;
+
+use crate::auth::CredentialProvider;
+use crate::models::LanguageModel;
+
+#[derive(Debug, PartialEq, Clone)]
+pub struct Embedding(pub Vec<f32>);
+
+// This is needed for semantic index functionality
+// Unfortunately it has to live wherever the "Embedding" struct is created.
+// Keeping this in here though, introduces a 'rusqlite' dependency into AI
+// which is less than ideal
+impl FromSql for Embedding {
+ fn column_result(value: ValueRef) -> FromSqlResult<Self> {
+ let bytes = value.as_blob()?;
+ let embedding: Result<Vec<f32>, Box<bincode::ErrorKind>> = bincode::deserialize(bytes);
+ if embedding.is_err() {
+ return Err(rusqlite::types::FromSqlError::Other(embedding.unwrap_err()));
+ }
+ Ok(Embedding(embedding.unwrap()))
+ }
+}
+
+impl ToSql for Embedding {
+ fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> {
+ let bytes = bincode::serialize(&self.0)
+ .map_err(|err| rusqlite::Error::ToSqlConversionFailure(Box::new(err)))?;
+ Ok(ToSqlOutput::Owned(rusqlite::types::Value::Blob(bytes)))
+ }
+}
+impl From<Vec<f32>> for Embedding {
+ fn from(value: Vec<f32>) -> Self {
+ Embedding(value)
+ }
+}
+
+impl Embedding {
+ pub fn similarity(&self, other: &Self) -> OrderedFloat<f32> {
+ let len = self.0.len();
+ assert_eq!(len, other.0.len());
+
+ let mut result = 0.0;
+ unsafe {
+ matrixmultiply::sgemm(
+ 1,
+ len,
+ 1,
+ 1.0,
+ self.0.as_ptr(),
+ len as isize,
+ 1,
+ other.0.as_ptr(),
+ 1,
+ len as isize,
+ 0.0,
+ &mut result as *mut f32,
+ 1,
+ 1,
+ );
+ }
+ OrderedFloat(result)
+ }
+}
+
+#[async_trait]
+pub trait EmbeddingProvider: CredentialProvider {
+ fn base_model(&self) -> Box<dyn LanguageModel>;
+ async fn embed_batch(&self, spans: Vec<String>) -> Result<Vec<Embedding>>;
+ fn max_tokens_per_batch(&self) -> usize;
+ fn rate_limit_expiration(&self) -> Option<Instant>;
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use rand::prelude::*;
+
+ #[gpui2::test]
+ fn test_similarity(mut rng: StdRng) {
+ assert_eq!(
+ Embedding::from(vec![1., 0., 0., 0., 0.])
+ .similarity(&Embedding::from(vec![0., 1., 0., 0., 0.])),
+ 0.
+ );
+ assert_eq!(
+ Embedding::from(vec![2., 0., 0., 0., 0.])
+ .similarity(&Embedding::from(vec![3., 1., 0., 0., 0.])),
+ 6.
+ );
+
+ for _ in 0..100 {
+ let size = 1536;
+ let mut a = vec![0.; size];
+ let mut b = vec![0.; size];
+ for (a, b) in a.iter_mut().zip(b.iter_mut()) {
+ *a = rng.gen();
+ *b = rng.gen();
+ }
+ let a = Embedding::from(a);
+ let b = Embedding::from(b);
+
+ assert_eq!(
+ round_to_decimals(a.similarity(&b), 1),
+ round_to_decimals(reference_dot(&a.0, &b.0), 1)
+ );
+ }
+
+ fn round_to_decimals(n: OrderedFloat<f32>, decimal_places: i32) -> f32 {
+ let factor = (10.0 as f32).powi(decimal_places);
+ (n * factor).round() / factor
+ }
+
+ fn reference_dot(a: &[f32], b: &[f32]) -> OrderedFloat<f32> {
+ OrderedFloat(a.iter().zip(b.iter()).map(|(a, b)| a * b).sum())
+ }
+ }
+}
@@ -0,0 +1,16 @@
+pub enum TruncationDirection {
+ Start,
+ End,
+}
+
+pub trait LanguageModel {
+ fn name(&self) -> String;
+ fn count_tokens(&self, content: &str) -> anyhow::Result<usize>;
+ fn truncate(
+ &self,
+ content: &str,
+ length: usize,
+ direction: TruncationDirection,
+ ) -> anyhow::Result<String>;
+ fn capacity(&self) -> anyhow::Result<usize>;
+}
@@ -0,0 +1,330 @@
+use std::cmp::Reverse;
+use std::ops::Range;
+use std::sync::Arc;
+
+use language2::BufferSnapshot;
+use util::ResultExt;
+
+use crate::models::LanguageModel;
+use crate::prompts::repository_context::PromptCodeSnippet;
+
+pub(crate) enum PromptFileType {
+ Text,
+ Code,
+}
+
+// TODO: Set this up to manage for defaults well
+pub struct PromptArguments {
+ pub model: Arc<dyn LanguageModel>,
+ pub user_prompt: Option<String>,
+ pub language_name: Option<String>,
+ pub project_name: Option<String>,
+ pub snippets: Vec<PromptCodeSnippet>,
+ pub reserved_tokens: usize,
+ pub buffer: Option<BufferSnapshot>,
+ pub selected_range: Option<Range<usize>>,
+}
+
+impl PromptArguments {
+ pub(crate) fn get_file_type(&self) -> PromptFileType {
+ if self
+ .language_name
+ .as_ref()
+ .and_then(|name| Some(!["Markdown", "Plain Text"].contains(&name.as_str())))
+ .unwrap_or(true)
+ {
+ PromptFileType::Code
+ } else {
+ PromptFileType::Text
+ }
+ }
+}
+
+pub trait PromptTemplate {
+ fn generate(
+ &self,
+ args: &PromptArguments,
+ max_token_length: Option<usize>,
+ ) -> anyhow::Result<(String, usize)>;
+}
+
+#[repr(i8)]
+#[derive(PartialEq, Eq, Ord)]
+pub enum PromptPriority {
+ Mandatory, // Ignores truncation
+ Ordered { order: usize }, // Truncates based on priority
+}
+
+impl PartialOrd for PromptPriority {
+ fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
+ match (self, other) {
+ (Self::Mandatory, Self::Mandatory) => Some(std::cmp::Ordering::Equal),
+ (Self::Mandatory, Self::Ordered { .. }) => Some(std::cmp::Ordering::Greater),
+ (Self::Ordered { .. }, Self::Mandatory) => Some(std::cmp::Ordering::Less),
+ (Self::Ordered { order: a }, Self::Ordered { order: b }) => b.partial_cmp(a),
+ }
+ }
+}
+
+pub struct PromptChain {
+ args: PromptArguments,
+ templates: Vec<(PromptPriority, Box<dyn PromptTemplate>)>,
+}
+
+impl PromptChain {
+ pub fn new(
+ args: PromptArguments,
+ templates: Vec<(PromptPriority, Box<dyn PromptTemplate>)>,
+ ) -> Self {
+ PromptChain { args, templates }
+ }
+
+ pub fn generate(&self, truncate: bool) -> anyhow::Result<(String, usize)> {
+ // Argsort based on Prompt Priority
+ let seperator = "\n";
+ let seperator_tokens = self.args.model.count_tokens(seperator)?;
+ let mut sorted_indices = (0..self.templates.len()).collect::<Vec<_>>();
+ sorted_indices.sort_by_key(|&i| Reverse(&self.templates[i].0));
+
+ // If Truncate
+ let mut tokens_outstanding = if truncate {
+ Some(self.args.model.capacity()? - self.args.reserved_tokens)
+ } else {
+ None
+ };
+
+ let mut prompts = vec!["".to_string(); sorted_indices.len()];
+ for idx in sorted_indices {
+ let (_, template) = &self.templates[idx];
+
+ if let Some((template_prompt, prompt_token_count)) =
+ template.generate(&self.args, tokens_outstanding).log_err()
+ {
+ if template_prompt != "" {
+ prompts[idx] = template_prompt;
+
+ if let Some(remaining_tokens) = tokens_outstanding {
+ let new_tokens = prompt_token_count + seperator_tokens;
+ tokens_outstanding = if remaining_tokens > new_tokens {
+ Some(remaining_tokens - new_tokens)
+ } else {
+ Some(0)
+ };
+ }
+ }
+ }
+ }
+
+ prompts.retain(|x| x != "");
+
+ let full_prompt = prompts.join(seperator);
+ let total_token_count = self.args.model.count_tokens(&full_prompt)?;
+ anyhow::Ok((prompts.join(seperator), total_token_count))
+ }
+}
+
+#[cfg(test)]
+pub(crate) mod tests {
+ use crate::models::TruncationDirection;
+ use crate::test::FakeLanguageModel;
+
+ use super::*;
+
+ #[test]
+ pub fn test_prompt_chain() {
+ struct TestPromptTemplate {}
+ impl PromptTemplate for TestPromptTemplate {
+ fn generate(
+ &self,
+ args: &PromptArguments,
+ max_token_length: Option<usize>,
+ ) -> anyhow::Result<(String, usize)> {
+ let mut content = "This is a test prompt template".to_string();
+
+ let mut token_count = args.model.count_tokens(&content)?;
+ if let Some(max_token_length) = max_token_length {
+ if token_count > max_token_length {
+ content = args.model.truncate(
+ &content,
+ max_token_length,
+ TruncationDirection::End,
+ )?;
+ token_count = max_token_length;
+ }
+ }
+
+ anyhow::Ok((content, token_count))
+ }
+ }
+
+ struct TestLowPriorityTemplate {}
+ impl PromptTemplate for TestLowPriorityTemplate {
+ fn generate(
+ &self,
+ args: &PromptArguments,
+ max_token_length: Option<usize>,
+ ) -> anyhow::Result<(String, usize)> {
+ let mut content = "This is a low priority test prompt template".to_string();
+
+ let mut token_count = args.model.count_tokens(&content)?;
+ if let Some(max_token_length) = max_token_length {
+ if token_count > max_token_length {
+ content = args.model.truncate(
+ &content,
+ max_token_length,
+ TruncationDirection::End,
+ )?;
+ token_count = max_token_length;
+ }
+ }
+
+ anyhow::Ok((content, token_count))
+ }
+ }
+
+ let model: Arc<dyn LanguageModel> = Arc::new(FakeLanguageModel { capacity: 100 });
+ let args = PromptArguments {
+ model: model.clone(),
+ language_name: None,
+ project_name: None,
+ snippets: Vec::new(),
+ reserved_tokens: 0,
+ buffer: None,
+ selected_range: None,
+ user_prompt: None,
+ };
+
+ let templates: Vec<(PromptPriority, Box<dyn PromptTemplate>)> = vec![
+ (
+ PromptPriority::Ordered { order: 0 },
+ Box::new(TestPromptTemplate {}),
+ ),
+ (
+ PromptPriority::Ordered { order: 1 },
+ Box::new(TestLowPriorityTemplate {}),
+ ),
+ ];
+ let chain = PromptChain::new(args, templates);
+
+ let (prompt, token_count) = chain.generate(false).unwrap();
+
+ assert_eq!(
+ prompt,
+ "This is a test prompt template\nThis is a low priority test prompt template"
+ .to_string()
+ );
+
+ assert_eq!(model.count_tokens(&prompt).unwrap(), token_count);
+
+ // Testing with Truncation Off
+ // Should ignore capacity and return all prompts
+ let model: Arc<dyn LanguageModel> = Arc::new(FakeLanguageModel { capacity: 20 });
+ let args = PromptArguments {
+ model: model.clone(),
+ language_name: None,
+ project_name: None,
+ snippets: Vec::new(),
+ reserved_tokens: 0,
+ buffer: None,
+ selected_range: None,
+ user_prompt: None,
+ };
+
+ let templates: Vec<(PromptPriority, Box<dyn PromptTemplate>)> = vec![
+ (
+ PromptPriority::Ordered { order: 0 },
+ Box::new(TestPromptTemplate {}),
+ ),
+ (
+ PromptPriority::Ordered { order: 1 },
+ Box::new(TestLowPriorityTemplate {}),
+ ),
+ ];
+ let chain = PromptChain::new(args, templates);
+
+ let (prompt, token_count) = chain.generate(false).unwrap();
+
+ assert_eq!(
+ prompt,
+ "This is a test prompt template\nThis is a low priority test prompt template"
+ .to_string()
+ );
+
+ assert_eq!(model.count_tokens(&prompt).unwrap(), token_count);
+
+ // Testing with Truncation Off
+ // Should ignore capacity and return all prompts
+ let capacity = 20;
+ let model: Arc<dyn LanguageModel> = Arc::new(FakeLanguageModel { capacity });
+ let args = PromptArguments {
+ model: model.clone(),
+ language_name: None,
+ project_name: None,
+ snippets: Vec::new(),
+ reserved_tokens: 0,
+ buffer: None,
+ selected_range: None,
+ user_prompt: None,
+ };
+
+ let templates: Vec<(PromptPriority, Box<dyn PromptTemplate>)> = vec![
+ (
+ PromptPriority::Ordered { order: 0 },
+ Box::new(TestPromptTemplate {}),
+ ),
+ (
+ PromptPriority::Ordered { order: 1 },
+ Box::new(TestLowPriorityTemplate {}),
+ ),
+ (
+ PromptPriority::Ordered { order: 2 },
+ Box::new(TestLowPriorityTemplate {}),
+ ),
+ ];
+ let chain = PromptChain::new(args, templates);
+
+ let (prompt, token_count) = chain.generate(true).unwrap();
+
+ assert_eq!(prompt, "This is a test promp".to_string());
+ assert_eq!(token_count, capacity);
+
+ // Change Ordering of Prompts Based on Priority
+ let capacity = 120;
+ let reserved_tokens = 10;
+ let model: Arc<dyn LanguageModel> = Arc::new(FakeLanguageModel { capacity });
+ let args = PromptArguments {
+ model: model.clone(),
+ language_name: None,
+ project_name: None,
+ snippets: Vec::new(),
+ reserved_tokens,
+ buffer: None,
+ selected_range: None,
+ user_prompt: None,
+ };
+ let templates: Vec<(PromptPriority, Box<dyn PromptTemplate>)> = vec![
+ (
+ PromptPriority::Mandatory,
+ Box::new(TestLowPriorityTemplate {}),
+ ),
+ (
+ PromptPriority::Ordered { order: 0 },
+ Box::new(TestPromptTemplate {}),
+ ),
+ (
+ PromptPriority::Ordered { order: 1 },
+ Box::new(TestLowPriorityTemplate {}),
+ ),
+ ];
+ let chain = PromptChain::new(args, templates);
+
+ let (prompt, token_count) = chain.generate(true).unwrap();
+
+ assert_eq!(
+ prompt,
+ "This is a low priority test prompt template\nThis is a test prompt template\nThis is a low priority test prompt "
+ .to_string()
+ );
+ assert_eq!(token_count, capacity - reserved_tokens);
+ }
+}
@@ -0,0 +1,164 @@
+use anyhow::anyhow;
+use language2::BufferSnapshot;
+use language2::ToOffset;
+
+use crate::models::LanguageModel;
+use crate::models::TruncationDirection;
+use crate::prompts::base::PromptArguments;
+use crate::prompts::base::PromptTemplate;
+use std::fmt::Write;
+use std::ops::Range;
+use std::sync::Arc;
+
+fn retrieve_context(
+ buffer: &BufferSnapshot,
+ selected_range: &Option<Range<usize>>,
+ model: Arc<dyn LanguageModel>,
+ max_token_count: Option<usize>,
+) -> anyhow::Result<(String, usize, bool)> {
+ let mut prompt = String::new();
+ let mut truncated = false;
+ if let Some(selected_range) = selected_range {
+ let start = selected_range.start.to_offset(buffer);
+ let end = selected_range.end.to_offset(buffer);
+
+ let start_window = buffer.text_for_range(0..start).collect::<String>();
+
+ let mut selected_window = String::new();
+ if start == end {
+ write!(selected_window, "<|START|>").unwrap();
+ } else {
+ write!(selected_window, "<|START|").unwrap();
+ }
+
+ write!(
+ selected_window,
+ "{}",
+ buffer.text_for_range(start..end).collect::<String>()
+ )
+ .unwrap();
+
+ if start != end {
+ write!(selected_window, "|END|>").unwrap();
+ }
+
+ let end_window = buffer.text_for_range(end..buffer.len()).collect::<String>();
+
+ if let Some(max_token_count) = max_token_count {
+ let selected_tokens = model.count_tokens(&selected_window)?;
+ if selected_tokens > max_token_count {
+ return Err(anyhow!(
+ "selected range is greater than model context window, truncation not possible"
+ ));
+ };
+
+ let mut remaining_tokens = max_token_count - selected_tokens;
+ let start_window_tokens = model.count_tokens(&start_window)?;
+ let end_window_tokens = model.count_tokens(&end_window)?;
+ let outside_tokens = start_window_tokens + end_window_tokens;
+ if outside_tokens > remaining_tokens {
+ let (start_goal_tokens, end_goal_tokens) =
+ if start_window_tokens < end_window_tokens {
+ let start_goal_tokens = (remaining_tokens / 2).min(start_window_tokens);
+ remaining_tokens -= start_goal_tokens;
+ let end_goal_tokens = remaining_tokens.min(end_window_tokens);
+ (start_goal_tokens, end_goal_tokens)
+ } else {
+ let end_goal_tokens = (remaining_tokens / 2).min(end_window_tokens);
+ remaining_tokens -= end_goal_tokens;
+ let start_goal_tokens = remaining_tokens.min(start_window_tokens);
+ (start_goal_tokens, end_goal_tokens)
+ };
+
+ let truncated_start_window =
+ model.truncate(&start_window, start_goal_tokens, TruncationDirection::Start)?;
+ let truncated_end_window =
+ model.truncate(&end_window, end_goal_tokens, TruncationDirection::End)?;
+ writeln!(
+ prompt,
+ "{truncated_start_window}{selected_window}{truncated_end_window}"
+ )
+ .unwrap();
+ truncated = true;
+ } else {
+ writeln!(prompt, "{start_window}{selected_window}{end_window}").unwrap();
+ }
+ } else {
+ // If we dont have a selected range, include entire file.
+ writeln!(prompt, "{}", &buffer.text()).unwrap();
+
+ // Dumb truncation strategy
+ if let Some(max_token_count) = max_token_count {
+ if model.count_tokens(&prompt)? > max_token_count {
+ truncated = true;
+ prompt = model.truncate(&prompt, max_token_count, TruncationDirection::End)?;
+ }
+ }
+ }
+ }
+
+ let token_count = model.count_tokens(&prompt)?;
+ anyhow::Ok((prompt, token_count, truncated))
+}
+
+pub struct FileContext {}
+
+impl PromptTemplate for FileContext {
+ fn generate(
+ &self,
+ args: &PromptArguments,
+ max_token_length: Option<usize>,
+ ) -> anyhow::Result<(String, usize)> {
+ if let Some(buffer) = &args.buffer {
+ let mut prompt = String::new();
+ // Add Initial Preamble
+ // TODO: Do we want to add the path in here?
+ writeln!(
+ prompt,
+ "The file you are currently working on has the following content:"
+ )
+ .unwrap();
+
+ let language_name = args
+ .language_name
+ .clone()
+ .unwrap_or("".to_string())
+ .to_lowercase();
+
+ let (context, _, truncated) = retrieve_context(
+ buffer,
+ &args.selected_range,
+ args.model.clone(),
+ max_token_length,
+ )?;
+ writeln!(prompt, "```{language_name}\n{context}\n```").unwrap();
+
+ if truncated {
+ writeln!(prompt, "Note the content has been truncated and only represents a portion of the file.").unwrap();
+ }
+
+ if let Some(selected_range) = &args.selected_range {
+ let start = selected_range.start.to_offset(buffer);
+ let end = selected_range.end.to_offset(buffer);
+
+ if start == end {
+ writeln!(prompt, "In particular, the user's cursor is currently on the '<|START|>' span in the above content, with no text selected.").unwrap();
+ } else {
+ writeln!(prompt, "In particular, the user has selected a section of the text between the '<|START|' and '|END|>' spans.").unwrap();
+ }
+ }
+
+ // Really dumb truncation strategy
+ if let Some(max_tokens) = max_token_length {
+ prompt = args
+ .model
+ .truncate(&prompt, max_tokens, TruncationDirection::End)?;
+ }
+
+ let token_count = args.model.count_tokens(&prompt)?;
+ anyhow::Ok((prompt, token_count))
+ } else {
+ Err(anyhow!("no buffer provided to retrieve file context from"))
+ }
+ }
+}
@@ -0,0 +1,99 @@
+use crate::prompts::base::{PromptArguments, PromptFileType, PromptTemplate};
+use anyhow::anyhow;
+use std::fmt::Write;
+
+pub fn capitalize(s: &str) -> String {
+ let mut c = s.chars();
+ match c.next() {
+ None => String::new(),
+ Some(f) => f.to_uppercase().collect::<String>() + c.as_str(),
+ }
+}
+
+pub struct GenerateInlineContent {}
+
+impl PromptTemplate for GenerateInlineContent {
+ fn generate(
+ &self,
+ args: &PromptArguments,
+ max_token_length: Option<usize>,
+ ) -> anyhow::Result<(String, usize)> {
+ let Some(user_prompt) = &args.user_prompt else {
+ return Err(anyhow!("user prompt not provided"));
+ };
+
+ let file_type = args.get_file_type();
+ let content_type = match &file_type {
+ PromptFileType::Code => "code",
+ PromptFileType::Text => "text",
+ };
+
+ let mut prompt = String::new();
+
+ if let Some(selected_range) = &args.selected_range {
+ if selected_range.start == selected_range.end {
+ writeln!(
+ prompt,
+ "Assume the cursor is located where the `<|START|>` span is."
+ )
+ .unwrap();
+ writeln!(
+ prompt,
+ "{} can't be replaced, so assume your answer will be inserted at the cursor.",
+ capitalize(content_type)
+ )
+ .unwrap();
+ writeln!(
+ prompt,
+ "Generate {content_type} based on the users prompt: {user_prompt}",
+ )
+ .unwrap();
+ } else {
+ writeln!(prompt, "Modify the user's selected {content_type} based upon the users prompt: '{user_prompt}'").unwrap();
+ writeln!(prompt, "You must reply with only the adjusted {content_type} (within the '<|START|' and '|END|>' spans) not the entire file.").unwrap();
+ writeln!(prompt, "Double check that you only return code and not the '<|START|' and '|END|'> spans").unwrap();
+ }
+ } else {
+ writeln!(
+ prompt,
+ "Generate {content_type} based on the users prompt: {user_prompt}"
+ )
+ .unwrap();
+ }
+
+ if let Some(language_name) = &args.language_name {
+ writeln!(
+ prompt,
+ "Your answer MUST always and only be valid {}.",
+ language_name
+ )
+ .unwrap();
+ }
+ writeln!(prompt, "Never make remarks about the output.").unwrap();
+ writeln!(
+ prompt,
+ "Do not return anything else, except the generated {content_type}."
+ )
+ .unwrap();
+
+ match file_type {
+ PromptFileType::Code => {
+ // writeln!(prompt, "Always wrap your code in a Markdown block.").unwrap();
+ }
+ _ => {}
+ }
+
+ // Really dumb truncation strategy
+ if let Some(max_tokens) = max_token_length {
+ prompt = args.model.truncate(
+ &prompt,
+ max_tokens,
+ crate::models::TruncationDirection::End,
+ )?;
+ }
+
+ let token_count = args.model.count_tokens(&prompt)?;
+
+ anyhow::Ok((prompt, token_count))
+ }
+}
@@ -0,0 +1,5 @@
+pub mod base;
+pub mod file_context;
+pub mod generate;
+pub mod preamble;
+pub mod repository_context;
@@ -0,0 +1,52 @@
+use crate::prompts::base::{PromptArguments, PromptFileType, PromptTemplate};
+use std::fmt::Write;
+
+pub struct EngineerPreamble {}
+
+impl PromptTemplate for EngineerPreamble {
+ fn generate(
+ &self,
+ args: &PromptArguments,
+ max_token_length: Option<usize>,
+ ) -> anyhow::Result<(String, usize)> {
+ let mut prompts = Vec::new();
+
+ match args.get_file_type() {
+ PromptFileType::Code => {
+ prompts.push(format!(
+ "You are an expert {}engineer.",
+ args.language_name.clone().unwrap_or("".to_string()) + " "
+ ));
+ }
+ PromptFileType::Text => {
+ prompts.push("You are an expert engineer.".to_string());
+ }
+ }
+
+ if let Some(project_name) = args.project_name.clone() {
+ prompts.push(format!(
+ "You are currently working inside the '{project_name}' project in code editor Zed."
+ ));
+ }
+
+ if let Some(mut remaining_tokens) = max_token_length {
+ let mut prompt = String::new();
+ let mut total_count = 0;
+ for prompt_piece in prompts {
+ let prompt_token_count =
+ args.model.count_tokens(&prompt_piece)? + args.model.count_tokens("\n")?;
+ if remaining_tokens > prompt_token_count {
+ writeln!(prompt, "{prompt_piece}").unwrap();
+ remaining_tokens -= prompt_token_count;
+ total_count += prompt_token_count;
+ }
+ }
+
+ anyhow::Ok((prompt, total_count))
+ } else {
+ let prompt = prompts.join("\n");
+ let token_count = args.model.count_tokens(&prompt)?;
+ anyhow::Ok((prompt, token_count))
+ }
+ }
+}
@@ -0,0 +1,98 @@
+use crate::prompts::base::{PromptArguments, PromptTemplate};
+use std::fmt::Write;
+use std::{ops::Range, path::PathBuf};
+
+use gpui2::{AsyncAppContext, Model};
+use language2::{Anchor, Buffer};
+
+#[derive(Clone)]
+pub struct PromptCodeSnippet {
+ path: Option<PathBuf>,
+ language_name: Option<String>,
+ content: String,
+}
+
+impl PromptCodeSnippet {
+ pub fn new(
+ buffer: Model<Buffer>,
+ range: Range<Anchor>,
+ cx: &mut AsyncAppContext,
+ ) -> anyhow::Result<Self> {
+ let (content, language_name, file_path) = buffer.update(cx, |buffer, _| {
+ let snapshot = buffer.snapshot();
+ let content = snapshot.text_for_range(range.clone()).collect::<String>();
+
+ let language_name = buffer
+ .language()
+ .and_then(|language| Some(language.name().to_string().to_lowercase()));
+
+ let file_path = buffer
+ .file()
+ .and_then(|file| Some(file.path().to_path_buf()));
+
+ (content, language_name, file_path)
+ })?;
+
+ anyhow::Ok(PromptCodeSnippet {
+ path: file_path,
+ language_name,
+ content,
+ })
+ }
+}
+
+impl ToString for PromptCodeSnippet {
+ fn to_string(&self) -> String {
+ let path = self
+ .path
+ .as_ref()
+ .and_then(|path| Some(path.to_string_lossy().to_string()))
+ .unwrap_or("".to_string());
+ let language_name = self.language_name.clone().unwrap_or("".to_string());
+ let content = self.content.clone();
+
+ format!("The below code snippet may be relevant from file: {path}\n```{language_name}\n{content}\n```")
+ }
+}
+
+pub struct RepositoryContext {}
+
+impl PromptTemplate for RepositoryContext {
+ fn generate(
+ &self,
+ args: &PromptArguments,
+ max_token_length: Option<usize>,
+ ) -> anyhow::Result<(String, usize)> {
+ const MAXIMUM_SNIPPET_TOKEN_COUNT: usize = 500;
+ let template = "You are working inside a large repository, here are a few code snippets that may be useful.";
+ let mut prompt = String::new();
+
+ let mut remaining_tokens = max_token_length.clone();
+ let seperator_token_length = args.model.count_tokens("\n")?;
+ for snippet in &args.snippets {
+ let mut snippet_prompt = template.to_string();
+ let content = snippet.to_string();
+ writeln!(snippet_prompt, "{content}").unwrap();
+
+ let token_count = args.model.count_tokens(&snippet_prompt)?;
+ if token_count <= MAXIMUM_SNIPPET_TOKEN_COUNT {
+ if let Some(tokens_left) = remaining_tokens {
+ if tokens_left >= token_count {
+ writeln!(prompt, "{snippet_prompt}").unwrap();
+ remaining_tokens = if tokens_left >= (token_count + seperator_token_length)
+ {
+ Some(tokens_left - token_count - seperator_token_length)
+ } else {
+ Some(0)
+ };
+ }
+ } else {
+ writeln!(prompt, "{snippet_prompt}").unwrap();
+ }
+ }
+ }
+
+ let total_token_count = args.model.count_tokens(&prompt)?;
+ anyhow::Ok((prompt, total_token_count))
+ }
+}
@@ -0,0 +1 @@
+pub mod open_ai;
@@ -0,0 +1,306 @@
+use anyhow::{anyhow, Result};
+use async_trait::async_trait;
+use futures::{
+ future::BoxFuture, io::BufReader, stream::BoxStream, AsyncBufReadExt, AsyncReadExt, FutureExt,
+ Stream, StreamExt,
+};
+use gpui2::{AppContext, Executor};
+use isahc::{http::StatusCode, Request, RequestExt};
+use parking_lot::RwLock;
+use serde::{Deserialize, Serialize};
+use std::{
+ env,
+ fmt::{self, Display},
+ io,
+ sync::Arc,
+};
+use util::ResultExt;
+
+use crate::{
+ auth::{CredentialProvider, ProviderCredential},
+ completion::{CompletionProvider, CompletionRequest},
+ models::LanguageModel,
+};
+
+use crate::providers::open_ai::{OpenAILanguageModel, OPENAI_API_URL};
+
+#[derive(Clone, Copy, Serialize, Deserialize, Debug, Eq, PartialEq)]
+#[serde(rename_all = "lowercase")]
+pub enum Role {
+ User,
+ Assistant,
+ System,
+}
+
+impl Role {
+ pub fn cycle(&mut self) {
+ *self = match self {
+ Role::User => Role::Assistant,
+ Role::Assistant => Role::System,
+ Role::System => Role::User,
+ }
+ }
+}
+
+impl Display for Role {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result {
+ match self {
+ Role::User => write!(f, "User"),
+ Role::Assistant => write!(f, "Assistant"),
+ Role::System => write!(f, "System"),
+ }
+ }
+}
+
+#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
+pub struct RequestMessage {
+ pub role: Role,
+ pub content: String,
+}
+
+#[derive(Debug, Default, Serialize)]
+pub struct OpenAIRequest {
+ pub model: String,
+ pub messages: Vec<RequestMessage>,
+ pub stream: bool,
+ pub stop: Vec<String>,
+ pub temperature: f32,
+}
+
+impl CompletionRequest for OpenAIRequest {
+ fn data(&self) -> serde_json::Result<String> {
+ serde_json::to_string(self)
+ }
+}
+
+#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
+pub struct ResponseMessage {
+ pub role: Option<Role>,
+ pub content: Option<String>,
+}
+
+#[derive(Deserialize, Debug)]
+pub struct OpenAIUsage {
+ pub prompt_tokens: u32,
+ pub completion_tokens: u32,
+ pub total_tokens: u32,
+}
+
+#[derive(Deserialize, Debug)]
+pub struct ChatChoiceDelta {
+ pub index: u32,
+ pub delta: ResponseMessage,
+ pub finish_reason: Option<String>,
+}
+
+#[derive(Deserialize, Debug)]
+pub struct OpenAIResponseStreamEvent {
+ pub id: Option<String>,
+ pub object: String,
+ pub created: u32,
+ pub model: String,
+ pub choices: Vec<ChatChoiceDelta>,
+ pub usage: Option<OpenAIUsage>,
+}
+
+pub async fn stream_completion(
+ credential: ProviderCredential,
+ executor: Arc<Executor>,
+ request: Box<dyn CompletionRequest>,
+) -> Result<impl Stream<Item = Result<OpenAIResponseStreamEvent>>> {
+ let api_key = match credential {
+ ProviderCredential::Credentials { api_key } => api_key,
+ _ => {
+ return Err(anyhow!("no credentials provider for completion"));
+ }
+ };
+
+ let (tx, rx) = futures::channel::mpsc::unbounded::<Result<OpenAIResponseStreamEvent>>();
+
+ let json_data = request.data()?;
+ let mut response = Request::post(format!("{OPENAI_API_URL}/chat/completions"))
+ .header("Content-Type", "application/json")
+ .header("Authorization", format!("Bearer {}", api_key))
+ .body(json_data)?
+ .send_async()
+ .await?;
+
+ let status = response.status();
+ if status == StatusCode::OK {
+ executor
+ .spawn(async move {
+ let mut lines = BufReader::new(response.body_mut()).lines();
+
+ fn parse_line(
+ line: Result<String, io::Error>,
+ ) -> Result<Option<OpenAIResponseStreamEvent>> {
+ if let Some(data) = line?.strip_prefix("data: ") {
+ let event = serde_json::from_str(&data)?;
+ Ok(Some(event))
+ } else {
+ Ok(None)
+ }
+ }
+
+ while let Some(line) = lines.next().await {
+ if let Some(event) = parse_line(line).transpose() {
+ let done = event.as_ref().map_or(false, |event| {
+ event
+ .choices
+ .last()
+ .map_or(false, |choice| choice.finish_reason.is_some())
+ });
+ if tx.unbounded_send(event).is_err() {
+ break;
+ }
+
+ if done {
+ break;
+ }
+ }
+ }
+
+ anyhow::Ok(())
+ })
+ .detach();
+
+ Ok(rx)
+ } else {
+ let mut body = String::new();
+ response.body_mut().read_to_string(&mut body).await?;
+
+ #[derive(Deserialize)]
+ struct OpenAIResponse {
+ error: OpenAIError,
+ }
+
+ #[derive(Deserialize)]
+ struct OpenAIError {
+ message: String,
+ }
+
+ match serde_json::from_str::<OpenAIResponse>(&body) {
+ Ok(response) if !response.error.message.is_empty() => Err(anyhow!(
+ "Failed to connect to OpenAI API: {}",
+ response.error.message,
+ )),
+
+ _ => Err(anyhow!(
+ "Failed to connect to OpenAI API: {} {}",
+ response.status(),
+ body,
+ )),
+ }
+ }
+}
+
+#[derive(Clone)]
+pub struct OpenAICompletionProvider {
+ model: OpenAILanguageModel,
+ credential: Arc<RwLock<ProviderCredential>>,
+ executor: Arc<Executor>,
+}
+
+impl OpenAICompletionProvider {
+ pub fn new(model_name: &str, executor: Arc<Executor>) -> Self {
+ let model = OpenAILanguageModel::load(model_name);
+ let credential = Arc::new(RwLock::new(ProviderCredential::NoCredentials));
+ Self {
+ model,
+ credential,
+ executor,
+ }
+ }
+}
+
+#[async_trait]
+impl CredentialProvider for OpenAICompletionProvider {
+ fn has_credentials(&self) -> bool {
+ match *self.credential.read() {
+ ProviderCredential::Credentials { .. } => true,
+ _ => false,
+ }
+ }
+ async fn retrieve_credentials(&self, cx: &mut AppContext) -> ProviderCredential {
+ let existing_credential = self.credential.read().clone();
+
+ let retrieved_credential = cx
+ .run_on_main(move |cx| match existing_credential {
+ ProviderCredential::Credentials { .. } => {
+ return existing_credential.clone();
+ }
+ _ => {
+ if let Some(api_key) = env::var("OPENAI_API_KEY").log_err() {
+ return ProviderCredential::Credentials { api_key };
+ }
+
+ if let Some(Some((_, api_key))) = cx.read_credentials(OPENAI_API_URL).log_err()
+ {
+ if let Some(api_key) = String::from_utf8(api_key).log_err() {
+ return ProviderCredential::Credentials { api_key };
+ } else {
+ return ProviderCredential::NoCredentials;
+ }
+ } else {
+ return ProviderCredential::NoCredentials;
+ }
+ }
+ })
+ .await;
+
+ *self.credential.write() = retrieved_credential.clone();
+ retrieved_credential
+ }
+
+ async fn save_credentials(&self, cx: &mut AppContext, credential: ProviderCredential) {
+ *self.credential.write() = credential.clone();
+ let credential = credential.clone();
+ cx.run_on_main(move |cx| match credential {
+ ProviderCredential::Credentials { api_key } => {
+ cx.write_credentials(OPENAI_API_URL, "Bearer", api_key.as_bytes())
+ .log_err();
+ }
+ _ => {}
+ })
+ .await;
+ }
+ async fn delete_credentials(&self, cx: &mut AppContext) {
+ cx.run_on_main(move |cx| cx.delete_credentials(OPENAI_API_URL).log_err())
+ .await;
+ *self.credential.write() = ProviderCredential::NoCredentials;
+ }
+}
+
+impl CompletionProvider for OpenAICompletionProvider {
+ fn base_model(&self) -> Box<dyn LanguageModel> {
+ let model: Box<dyn LanguageModel> = Box::new(self.model.clone());
+ model
+ }
+ fn complete(
+ &self,
+ prompt: Box<dyn CompletionRequest>,
+ ) -> BoxFuture<'static, Result<BoxStream<'static, Result<String>>>> {
+ // Currently the CompletionRequest for OpenAI, includes a 'model' parameter
+ // This means that the model is determined by the CompletionRequest and not the CompletionProvider,
+ // which is currently model based, due to the langauge model.
+ // At some point in the future we should rectify this.
+ let credential = self.credential.read().clone();
+ let request = stream_completion(credential, self.executor.clone(), prompt);
+ async move {
+ let response = request.await?;
+ let stream = response
+ .filter_map(|response| async move {
+ match response {
+ Ok(mut response) => Some(Ok(response.choices.pop()?.delta.content?)),
+ Err(error) => Some(Err(error)),
+ }
+ })
+ .boxed();
+ Ok(stream)
+ }
+ .boxed()
+ }
+ fn box_clone(&self) -> Box<dyn CompletionProvider> {
+ Box::new((*self).clone())
+ }
+}
@@ -0,0 +1,313 @@
+use anyhow::{anyhow, Result};
+use async_trait::async_trait;
+use futures::AsyncReadExt;
+use gpui2::Executor;
+use gpui2::{serde_json, AppContext};
+use isahc::http::StatusCode;
+use isahc::prelude::Configurable;
+use isahc::{AsyncBody, Response};
+use lazy_static::lazy_static;
+use parking_lot::{Mutex, RwLock};
+use parse_duration::parse;
+use postage::watch;
+use serde::{Deserialize, Serialize};
+use std::env;
+use std::ops::Add;
+use std::sync::Arc;
+use std::time::{Duration, Instant};
+use tiktoken_rs::{cl100k_base, CoreBPE};
+use util::http::{HttpClient, Request};
+use util::ResultExt;
+
+use crate::auth::{CredentialProvider, ProviderCredential};
+use crate::embedding::{Embedding, EmbeddingProvider};
+use crate::models::LanguageModel;
+use crate::providers::open_ai::OpenAILanguageModel;
+
+use crate::providers::open_ai::OPENAI_API_URL;
+
+lazy_static! {
+ static ref OPENAI_BPE_TOKENIZER: CoreBPE = cl100k_base().unwrap();
+}
+
+#[derive(Clone)]
+pub struct OpenAIEmbeddingProvider {
+ model: OpenAILanguageModel,
+ credential: Arc<RwLock<ProviderCredential>>,
+ pub client: Arc<dyn HttpClient>,
+ pub executor: Arc<Executor>,
+ rate_limit_count_rx: watch::Receiver<Option<Instant>>,
+ rate_limit_count_tx: Arc<Mutex<watch::Sender<Option<Instant>>>>,
+}
+
+#[derive(Serialize)]
+struct OpenAIEmbeddingRequest<'a> {
+ model: &'static str,
+ input: Vec<&'a str>,
+}
+
+#[derive(Deserialize)]
+struct OpenAIEmbeddingResponse {
+ data: Vec<OpenAIEmbedding>,
+ usage: OpenAIEmbeddingUsage,
+}
+
+#[derive(Debug, Deserialize)]
+struct OpenAIEmbedding {
+ embedding: Vec<f32>,
+ index: usize,
+ object: String,
+}
+
+#[derive(Deserialize)]
+struct OpenAIEmbeddingUsage {
+ prompt_tokens: usize,
+ total_tokens: usize,
+}
+
+impl OpenAIEmbeddingProvider {
+ pub fn new(client: Arc<dyn HttpClient>, executor: Arc<Executor>) -> Self {
+ let (rate_limit_count_tx, rate_limit_count_rx) = watch::channel_with(None);
+ let rate_limit_count_tx = Arc::new(Mutex::new(rate_limit_count_tx));
+
+ let model = OpenAILanguageModel::load("text-embedding-ada-002");
+ let credential = Arc::new(RwLock::new(ProviderCredential::NoCredentials));
+
+ OpenAIEmbeddingProvider {
+ model,
+ credential,
+ client,
+ executor,
+ rate_limit_count_rx,
+ rate_limit_count_tx,
+ }
+ }
+
+ fn get_api_key(&self) -> Result<String> {
+ match self.credential.read().clone() {
+ ProviderCredential::Credentials { api_key } => Ok(api_key),
+ _ => Err(anyhow!("api credentials not provided")),
+ }
+ }
+
+ fn resolve_rate_limit(&self) {
+ let reset_time = *self.rate_limit_count_tx.lock().borrow();
+
+ if let Some(reset_time) = reset_time {
+ if Instant::now() >= reset_time {
+ *self.rate_limit_count_tx.lock().borrow_mut() = None
+ }
+ }
+
+ log::trace!(
+ "resolving reset time: {:?}",
+ *self.rate_limit_count_tx.lock().borrow()
+ );
+ }
+
+ fn update_reset_time(&self, reset_time: Instant) {
+ let original_time = *self.rate_limit_count_tx.lock().borrow();
+
+ let updated_time = if let Some(original_time) = original_time {
+ if reset_time < original_time {
+ Some(reset_time)
+ } else {
+ Some(original_time)
+ }
+ } else {
+ Some(reset_time)
+ };
+
+ log::trace!("updating rate limit time: {:?}", updated_time);
+
+ *self.rate_limit_count_tx.lock().borrow_mut() = updated_time;
+ }
+ async fn send_request(
+ &self,
+ api_key: &str,
+ spans: Vec<&str>,
+ request_timeout: u64,
+ ) -> Result<Response<AsyncBody>> {
+ let request = Request::post("https://api.openai.com/v1/embeddings")
+ .redirect_policy(isahc::config::RedirectPolicy::Follow)
+ .timeout(Duration::from_secs(request_timeout))
+ .header("Content-Type", "application/json")
+ .header("Authorization", format!("Bearer {}", api_key))
+ .body(
+ serde_json::to_string(&OpenAIEmbeddingRequest {
+ input: spans.clone(),
+ model: "text-embedding-ada-002",
+ })
+ .unwrap()
+ .into(),
+ )?;
+
+ Ok(self.client.send(request).await?)
+ }
+}
+
+#[async_trait]
+impl CredentialProvider for OpenAIEmbeddingProvider {
+ fn has_credentials(&self) -> bool {
+ match *self.credential.read() {
+ ProviderCredential::Credentials { .. } => true,
+ _ => false,
+ }
+ }
+ async fn retrieve_credentials(&self, cx: &mut AppContext) -> ProviderCredential {
+ let existing_credential = self.credential.read().clone();
+
+ let retrieved_credential = cx
+ .run_on_main(move |cx| match existing_credential {
+ ProviderCredential::Credentials { .. } => {
+ return existing_credential.clone();
+ }
+ _ => {
+ if let Some(api_key) = env::var("OPENAI_API_KEY").log_err() {
+ return ProviderCredential::Credentials { api_key };
+ }
+
+ if let Some(Some((_, api_key))) = cx.read_credentials(OPENAI_API_URL).log_err()
+ {
+ if let Some(api_key) = String::from_utf8(api_key).log_err() {
+ return ProviderCredential::Credentials { api_key };
+ } else {
+ return ProviderCredential::NoCredentials;
+ }
+ } else {
+ return ProviderCredential::NoCredentials;
+ }
+ }
+ })
+ .await;
+
+ *self.credential.write() = retrieved_credential.clone();
+ retrieved_credential
+ }
+
+ async fn save_credentials(&self, cx: &mut AppContext, credential: ProviderCredential) {
+ *self.credential.write() = credential.clone();
+ let credential = credential.clone();
+ cx.run_on_main(move |cx| match credential {
+ ProviderCredential::Credentials { api_key } => {
+ cx.write_credentials(OPENAI_API_URL, "Bearer", api_key.as_bytes())
+ .log_err();
+ }
+ _ => {}
+ })
+ .await;
+ }
+ async fn delete_credentials(&self, cx: &mut AppContext) {
+ cx.run_on_main(move |cx| cx.delete_credentials(OPENAI_API_URL).log_err())
+ .await;
+ *self.credential.write() = ProviderCredential::NoCredentials;
+ }
+}
+
+#[async_trait]
+impl EmbeddingProvider for OpenAIEmbeddingProvider {
+ fn base_model(&self) -> Box<dyn LanguageModel> {
+ let model: Box<dyn LanguageModel> = Box::new(self.model.clone());
+ model
+ }
+
+ fn max_tokens_per_batch(&self) -> usize {
+ 50000
+ }
+
+ fn rate_limit_expiration(&self) -> Option<Instant> {
+ *self.rate_limit_count_rx.borrow()
+ }
+
+ async fn embed_batch(&self, spans: Vec<String>) -> Result<Vec<Embedding>> {
+ const BACKOFF_SECONDS: [usize; 4] = [3, 5, 15, 45];
+ const MAX_RETRIES: usize = 4;
+
+ let api_key = self.get_api_key()?;
+
+ let mut request_number = 0;
+ let mut rate_limiting = false;
+ let mut request_timeout: u64 = 15;
+ let mut response: Response<AsyncBody>;
+ while request_number < MAX_RETRIES {
+ response = self
+ .send_request(
+ &api_key,
+ spans.iter().map(|x| &**x).collect(),
+ request_timeout,
+ )
+ .await?;
+
+ request_number += 1;
+
+ match response.status() {
+ StatusCode::REQUEST_TIMEOUT => {
+ request_timeout += 5;
+ }
+ StatusCode::OK => {
+ let mut body = String::new();
+ response.body_mut().read_to_string(&mut body).await?;
+ let response: OpenAIEmbeddingResponse = serde_json::from_str(&body)?;
+
+ log::trace!(
+ "openai embedding completed. tokens: {:?}",
+ response.usage.total_tokens
+ );
+
+ // If we complete a request successfully that was previously rate_limited
+ // resolve the rate limit
+ if rate_limiting {
+ self.resolve_rate_limit()
+ }
+
+ return Ok(response
+ .data
+ .into_iter()
+ .map(|embedding| Embedding::from(embedding.embedding))
+ .collect());
+ }
+ StatusCode::TOO_MANY_REQUESTS => {
+ rate_limiting = true;
+ let mut body = String::new();
+ response.body_mut().read_to_string(&mut body).await?;
+
+ let delay_duration = {
+ let delay = Duration::from_secs(BACKOFF_SECONDS[request_number - 1] as u64);
+ if let Some(time_to_reset) =
+ response.headers().get("x-ratelimit-reset-tokens")
+ {
+ if let Ok(time_str) = time_to_reset.to_str() {
+ parse(time_str).unwrap_or(delay)
+ } else {
+ delay
+ }
+ } else {
+ delay
+ }
+ };
+
+ // If we've previously rate limited, increment the duration but not the count
+ let reset_time = Instant::now().add(delay_duration);
+ self.update_reset_time(reset_time);
+
+ log::trace!(
+ "openai rate limiting: waiting {:?} until lifted",
+ &delay_duration
+ );
+
+ self.executor.timer(delay_duration).await;
+ }
+ _ => {
+ let mut body = String::new();
+ response.body_mut().read_to_string(&mut body).await?;
+ return Err(anyhow!(
+ "open ai bad request: {:?} {:?}",
+ &response.status(),
+ body
+ ));
+ }
+ }
+ }
+ Err(anyhow!("openai max retries"))
+ }
+}
@@ -0,0 +1,9 @@
+pub mod completion;
+pub mod embedding;
+pub mod model;
+
+pub use completion::*;
+pub use embedding::*;
+pub use model::OpenAILanguageModel;
+
+pub const OPENAI_API_URL: &'static str = "https://api.openai.com/v1";
@@ -0,0 +1,57 @@
+use anyhow::anyhow;
+use tiktoken_rs::CoreBPE;
+use util::ResultExt;
+
+use crate::models::{LanguageModel, TruncationDirection};
+
+#[derive(Clone)]
+pub struct OpenAILanguageModel {
+ name: String,
+ bpe: Option<CoreBPE>,
+}
+
+impl OpenAILanguageModel {
+ pub fn load(model_name: &str) -> Self {
+ let bpe = tiktoken_rs::get_bpe_from_model(model_name).log_err();
+ OpenAILanguageModel {
+ name: model_name.to_string(),
+ bpe,
+ }
+ }
+}
+
+impl LanguageModel for OpenAILanguageModel {
+ fn name(&self) -> String {
+ self.name.clone()
+ }
+ fn count_tokens(&self, content: &str) -> anyhow::Result<usize> {
+ if let Some(bpe) = &self.bpe {
+ anyhow::Ok(bpe.encode_with_special_tokens(content).len())
+ } else {
+ Err(anyhow!("bpe for open ai model was not retrieved"))
+ }
+ }
+ fn truncate(
+ &self,
+ content: &str,
+ length: usize,
+ direction: TruncationDirection,
+ ) -> anyhow::Result<String> {
+ if let Some(bpe) = &self.bpe {
+ let tokens = bpe.encode_with_special_tokens(content);
+ if tokens.len() > length {
+ match direction {
+ TruncationDirection::End => bpe.decode(tokens[..length].to_vec()),
+ TruncationDirection::Start => bpe.decode(tokens[length..].to_vec()),
+ }
+ } else {
+ bpe.decode(tokens)
+ }
+ } else {
+ Err(anyhow!("bpe for open ai model was not retrieved"))
+ }
+ }
+ fn capacity(&self) -> anyhow::Result<usize> {
+ anyhow::Ok(tiktoken_rs::model::get_context_size(&self.name))
+ }
+}
@@ -0,0 +1,11 @@
+pub trait LanguageModel {
+ fn name(&self) -> String;
+ fn count_tokens(&self, content: &str) -> anyhow::Result<usize>;
+ fn truncate(
+ &self,
+ content: &str,
+ length: usize,
+ direction: TruncationDirection,
+ ) -> anyhow::Result<String>;
+ fn capacity(&self) -> anyhow::Result<usize>;
+}
@@ -0,0 +1,193 @@
+use std::{
+ sync::atomic::{self, AtomicUsize, Ordering},
+ time::Instant,
+};
+
+use async_trait::async_trait;
+use futures::{channel::mpsc, future::BoxFuture, stream::BoxStream, FutureExt, StreamExt};
+use gpui2::AppContext;
+use parking_lot::Mutex;
+
+use crate::{
+ auth::{CredentialProvider, ProviderCredential},
+ completion::{CompletionProvider, CompletionRequest},
+ embedding::{Embedding, EmbeddingProvider},
+ models::{LanguageModel, TruncationDirection},
+};
+
+#[derive(Clone)]
+pub struct FakeLanguageModel {
+ pub capacity: usize,
+}
+
+impl LanguageModel for FakeLanguageModel {
+ fn name(&self) -> String {
+ "dummy".to_string()
+ }
+ fn count_tokens(&self, content: &str) -> anyhow::Result<usize> {
+ anyhow::Ok(content.chars().collect::<Vec<char>>().len())
+ }
+ fn truncate(
+ &self,
+ content: &str,
+ length: usize,
+ direction: TruncationDirection,
+ ) -> anyhow::Result<String> {
+ println!("TRYING TO TRUNCATE: {:?}", length.clone());
+
+ if length > self.count_tokens(content)? {
+ println!("NOT TRUNCATING");
+ return anyhow::Ok(content.to_string());
+ }
+
+ anyhow::Ok(match direction {
+ TruncationDirection::End => content.chars().collect::<Vec<char>>()[..length]
+ .into_iter()
+ .collect::<String>(),
+ TruncationDirection::Start => content.chars().collect::<Vec<char>>()[length..]
+ .into_iter()
+ .collect::<String>(),
+ })
+ }
+ fn capacity(&self) -> anyhow::Result<usize> {
+ anyhow::Ok(self.capacity)
+ }
+}
+
+pub struct FakeEmbeddingProvider {
+ pub embedding_count: AtomicUsize,
+}
+
+impl Clone for FakeEmbeddingProvider {
+ fn clone(&self) -> Self {
+ FakeEmbeddingProvider {
+ embedding_count: AtomicUsize::new(self.embedding_count.load(Ordering::SeqCst)),
+ }
+ }
+}
+
+impl Default for FakeEmbeddingProvider {
+ fn default() -> Self {
+ FakeEmbeddingProvider {
+ embedding_count: AtomicUsize::default(),
+ }
+ }
+}
+
+impl FakeEmbeddingProvider {
+ pub fn embedding_count(&self) -> usize {
+ self.embedding_count.load(atomic::Ordering::SeqCst)
+ }
+
+ pub fn embed_sync(&self, span: &str) -> Embedding {
+ let mut result = vec![1.0; 26];
+ for letter in span.chars() {
+ let letter = letter.to_ascii_lowercase();
+ if letter as u32 >= 'a' as u32 {
+ let ix = (letter as u32) - ('a' as u32);
+ if ix < 26 {
+ result[ix as usize] += 1.0;
+ }
+ }
+ }
+
+ let norm = result.iter().map(|x| x * x).sum::<f32>().sqrt();
+ for x in &mut result {
+ *x /= norm;
+ }
+
+ result.into()
+ }
+}
+
+#[async_trait]
+impl CredentialProvider for FakeEmbeddingProvider {
+ fn has_credentials(&self) -> bool {
+ true
+ }
+ async fn retrieve_credentials(&self, _cx: &mut AppContext) -> ProviderCredential {
+ ProviderCredential::NotNeeded
+ }
+ async fn save_credentials(&self, _cx: &mut AppContext, _credential: ProviderCredential) {}
+ async fn delete_credentials(&self, _cx: &mut AppContext) {}
+}
+
+#[async_trait]
+impl EmbeddingProvider for FakeEmbeddingProvider {
+ fn base_model(&self) -> Box<dyn LanguageModel> {
+ Box::new(FakeLanguageModel { capacity: 1000 })
+ }
+ fn max_tokens_per_batch(&self) -> usize {
+ 1000
+ }
+
+ fn rate_limit_expiration(&self) -> Option<Instant> {
+ None
+ }
+
+ async fn embed_batch(&self, spans: Vec<String>) -> anyhow::Result<Vec<Embedding>> {
+ self.embedding_count
+ .fetch_add(spans.len(), atomic::Ordering::SeqCst);
+
+ anyhow::Ok(spans.iter().map(|span| self.embed_sync(span)).collect())
+ }
+}
+
+pub struct FakeCompletionProvider {
+ last_completion_tx: Mutex<Option<mpsc::Sender<String>>>,
+}
+
+impl Clone for FakeCompletionProvider {
+ fn clone(&self) -> Self {
+ Self {
+ last_completion_tx: Mutex::new(None),
+ }
+ }
+}
+
+impl FakeCompletionProvider {
+ pub fn new() -> Self {
+ Self {
+ last_completion_tx: Mutex::new(None),
+ }
+ }
+
+ pub fn send_completion(&self, completion: impl Into<String>) {
+ let mut tx = self.last_completion_tx.lock();
+ tx.as_mut().unwrap().try_send(completion.into()).unwrap();
+ }
+
+ pub fn finish_completion(&self) {
+ self.last_completion_tx.lock().take().unwrap();
+ }
+}
+
+#[async_trait]
+impl CredentialProvider for FakeCompletionProvider {
+ fn has_credentials(&self) -> bool {
+ true
+ }
+ async fn retrieve_credentials(&self, _cx: &mut AppContext) -> ProviderCredential {
+ ProviderCredential::NotNeeded
+ }
+ async fn save_credentials(&self, _cx: &mut AppContext, _credential: ProviderCredential) {}
+ async fn delete_credentials(&self, _cx: &mut AppContext) {}
+}
+
+impl CompletionProvider for FakeCompletionProvider {
+ fn base_model(&self) -> Box<dyn LanguageModel> {
+ let model: Box<dyn LanguageModel> = Box::new(FakeLanguageModel { capacity: 8190 });
+ model
+ }
+ fn complete(
+ &self,
+ _prompt: Box<dyn CompletionRequest>,
+ ) -> BoxFuture<'static, anyhow::Result<BoxStream<'static, anyhow::Result<String>>>> {
+ let (tx, rx) = mpsc::channel(1);
+ *self.last_completion_tx.lock() = Some(tx);
+ async move { Ok(rx.map(|rx| Ok(rx)).boxed()) }.boxed()
+ }
+ fn box_clone(&self) -> Box<dyn CompletionProvider> {
+ Box::new((*self).clone())
+ }
+}
@@ -45,6 +45,7 @@ tiktoken-rs = "0.5"
[dev-dependencies]
editor = { path = "../editor", features = ["test-support"] }
project = { path = "../project", features = ["test-support"] }
+ai = { path = "../ai", features = ["test-support"]}
ctor.workspace = true
env_logger.workspace = true
@@ -4,7 +4,7 @@ mod codegen;
mod prompts;
mod streaming_diff;
-use ai::completion::Role;
+use ai::providers::open_ai::Role;
use anyhow::Result;
pub use assistant_panel::AssistantPanel;
use assistant_settings::OpenAIModel;
@@ -5,12 +5,14 @@ use crate::{
MessageId, MessageMetadata, MessageStatus, Role, SavedConversation, SavedConversationMetadata,
SavedMessage,
};
+
use ai::{
- completion::{
- stream_completion, OpenAICompletionProvider, OpenAIRequest, RequestMessage, OPENAI_API_URL,
- },
- templates::repository_context::PromptCodeSnippet,
+ auth::ProviderCredential,
+ completion::{CompletionProvider, CompletionRequest},
+ providers::open_ai::{OpenAICompletionProvider, OpenAIRequest, RequestMessage},
};
+
+use ai::prompts::repository_context::PromptCodeSnippet;
use anyhow::{anyhow, Result};
use chrono::{DateTime, Local};
use client::{telemetry::AssistantKind, ClickhouseEvent, TelemetrySettings};
@@ -43,8 +45,8 @@ use search::BufferSearchBar;
use semantic_index::{SemanticIndex, SemanticIndexStatus};
use settings::SettingsStore;
use std::{
- cell::{Cell, RefCell},
- cmp, env,
+ cell::Cell,
+ cmp,
fmt::Write,
iter,
ops::Range,
@@ -97,8 +99,8 @@ pub fn init(cx: &mut AppContext) {
cx.capture_action(ConversationEditor::copy);
cx.add_action(ConversationEditor::split);
cx.capture_action(ConversationEditor::cycle_message_role);
- cx.add_action(AssistantPanel::save_api_key);
- cx.add_action(AssistantPanel::reset_api_key);
+ cx.add_action(AssistantPanel::save_credentials);
+ cx.add_action(AssistantPanel::reset_credentials);
cx.add_action(AssistantPanel::toggle_zoom);
cx.add_action(AssistantPanel::deploy);
cx.add_action(AssistantPanel::select_next_match);
@@ -140,9 +142,8 @@ pub struct AssistantPanel {
zoomed: bool,
has_focus: bool,
toolbar: ViewHandle<Toolbar>,
- api_key: Rc<RefCell<Option<String>>>,
+ completion_provider: Box<dyn CompletionProvider>,
api_key_editor: Option<ViewHandle<Editor>>,
- has_read_credentials: bool,
languages: Arc<LanguageRegistry>,
fs: Arc<dyn Fs>,
subscriptions: Vec<Subscription>,
@@ -202,6 +203,11 @@ impl AssistantPanel {
});
let semantic_index = SemanticIndex::global(cx);
+ // Defaulting currently to GPT4, allow for this to be set via config.
+ let completion_provider = Box::new(OpenAICompletionProvider::new(
+ "gpt-4",
+ cx.background().clone(),
+ ));
let mut this = Self {
workspace: workspace_handle,
@@ -213,9 +219,8 @@ impl AssistantPanel {
zoomed: false,
has_focus: false,
toolbar,
- api_key: Rc::new(RefCell::new(None)),
+ completion_provider,
api_key_editor: None,
- has_read_credentials: false,
languages: workspace.app_state().languages.clone(),
fs: workspace.app_state().fs.clone(),
width: None,
@@ -254,10 +259,7 @@ impl AssistantPanel {
cx: &mut ViewContext<Workspace>,
) {
let this = if let Some(this) = workspace.panel::<AssistantPanel>(cx) {
- if this
- .update(cx, |assistant, cx| assistant.load_api_key(cx))
- .is_some()
- {
+ if this.update(cx, |assistant, _| assistant.has_credentials()) {
this
} else {
workspace.focus_panel::<AssistantPanel>(cx);
@@ -289,12 +291,6 @@ impl AssistantPanel {
cx: &mut ViewContext<Self>,
project: &ModelHandle<Project>,
) {
- let api_key = if let Some(api_key) = self.api_key.borrow().clone() {
- api_key
- } else {
- return;
- };
-
let selection = editor.read(cx).selections.newest_anchor().clone();
if selection.start.excerpt_id != selection.end.excerpt_id {
return;
@@ -325,10 +321,13 @@ impl AssistantPanel {
let inline_assist_id = post_inc(&mut self.next_inline_assist_id);
let provider = Arc::new(OpenAICompletionProvider::new(
- api_key,
+ "gpt-4",
cx.background().clone(),
));
+ // Retrieve Credentials Authenticates the Provider
+ // provider.retrieve_credentials(cx);
+
let codegen = cx.add_model(|cx| {
Codegen::new(editor.read(cx).buffer().clone(), codegen_kind, provider, cx)
});
@@ -745,13 +744,14 @@ impl AssistantPanel {
content: prompt,
});
- let request = OpenAIRequest {
+ let request = Box::new(OpenAIRequest {
model: model.full_name().into(),
messages,
stream: true,
stop: vec!["|END|>".to_string()],
temperature,
- };
+ });
+
codegen.update(&mut cx, |codegen, cx| codegen.start(request, cx));
anyhow::Ok(())
})
@@ -811,7 +811,7 @@ impl AssistantPanel {
fn new_conversation(&mut self, cx: &mut ViewContext<Self>) -> ViewHandle<ConversationEditor> {
let editor = cx.add_view(|cx| {
ConversationEditor::new(
- self.api_key.clone(),
+ self.completion_provider.clone(),
self.languages.clone(),
self.fs.clone(),
self.workspace.clone(),
@@ -870,17 +870,19 @@ impl AssistantPanel {
}
}
- fn save_api_key(&mut self, _: &menu::Confirm, cx: &mut ViewContext<Self>) {
+ fn save_credentials(&mut self, _: &menu::Confirm, cx: &mut ViewContext<Self>) {
if let Some(api_key) = self
.api_key_editor
.as_ref()
.map(|editor| editor.read(cx).text(cx))
{
if !api_key.is_empty() {
- cx.platform()
- .write_credentials(OPENAI_API_URL, "Bearer", api_key.as_bytes())
- .log_err();
- *self.api_key.borrow_mut() = Some(api_key);
+ let credential = ProviderCredential::Credentials {
+ api_key: api_key.clone(),
+ };
+
+ self.completion_provider.save_credentials(cx, credential);
+
self.api_key_editor.take();
cx.focus_self();
cx.notify();
@@ -890,9 +892,8 @@ impl AssistantPanel {
}
}
- fn reset_api_key(&mut self, _: &ResetKey, cx: &mut ViewContext<Self>) {
- cx.platform().delete_credentials(OPENAI_API_URL).log_err();
- self.api_key.take();
+ fn reset_credentials(&mut self, _: &ResetKey, cx: &mut ViewContext<Self>) {
+ self.completion_provider.delete_credentials(cx);
self.api_key_editor = Some(build_api_key_editor(cx));
cx.focus_self();
cx.notify();
@@ -1151,13 +1152,12 @@ impl AssistantPanel {
let fs = self.fs.clone();
let workspace = self.workspace.clone();
- let api_key = self.api_key.clone();
let languages = self.languages.clone();
cx.spawn(|this, mut cx| async move {
let saved_conversation = fs.load(&path).await?;
let saved_conversation = serde_json::from_str(&saved_conversation)?;
let conversation = cx.add_model(|cx| {
- Conversation::deserialize(saved_conversation, path.clone(), api_key, languages, cx)
+ Conversation::deserialize(saved_conversation, path.clone(), languages, cx)
});
this.update(&mut cx, |this, cx| {
// If, by the time we've loaded the conversation, the user has already opened
@@ -1181,30 +1181,12 @@ impl AssistantPanel {
.position(|editor| editor.read(cx).conversation.read(cx).path.as_deref() == Some(path))
}
- fn load_api_key(&mut self, cx: &mut ViewContext<Self>) -> Option<String> {
- if self.api_key.borrow().is_none() && !self.has_read_credentials {
- self.has_read_credentials = true;
- let api_key = if let Ok(api_key) = env::var("OPENAI_API_KEY") {
- Some(api_key)
- } else if let Some((_, api_key)) = cx
- .platform()
- .read_credentials(OPENAI_API_URL)
- .log_err()
- .flatten()
- {
- String::from_utf8(api_key).log_err()
- } else {
- None
- };
- if let Some(api_key) = api_key {
- *self.api_key.borrow_mut() = Some(api_key);
- } else if self.api_key_editor.is_none() {
- self.api_key_editor = Some(build_api_key_editor(cx));
- cx.notify();
- }
- }
+ fn has_credentials(&mut self) -> bool {
+ self.completion_provider.has_credentials()
+ }
- self.api_key.borrow().clone()
+ fn load_credentials(&mut self, cx: &mut ViewContext<Self>) {
+ self.completion_provider.retrieve_credentials(cx);
}
}
@@ -1389,7 +1371,7 @@ impl Panel for AssistantPanel {
fn set_active(&mut self, active: bool, cx: &mut ViewContext<Self>) {
if active {
- self.load_api_key(cx);
+ self.load_credentials(cx);
if self.editors.is_empty() {
self.new_conversation(cx);
@@ -1454,10 +1436,10 @@ struct Conversation {
token_count: Option<usize>,
max_token_count: usize,
pending_token_count: Task<Option<()>>,
- api_key: Rc<RefCell<Option<String>>>,
pending_save: Task<Result<()>>,
path: Option<PathBuf>,
_subscriptions: Vec<Subscription>,
+ completion_provider: Box<dyn CompletionProvider>,
}
impl Entity for Conversation {
@@ -1466,9 +1448,9 @@ impl Entity for Conversation {
impl Conversation {
fn new(
- api_key: Rc<RefCell<Option<String>>>,
language_registry: Arc<LanguageRegistry>,
cx: &mut ModelContext<Self>,
+ completion_provider: Box<dyn CompletionProvider>,
) -> Self {
let markdown = language_registry.language_for_name("Markdown");
let buffer = cx.add_model(|cx| {
@@ -1507,8 +1489,8 @@ impl Conversation {
_subscriptions: vec![cx.subscribe(&buffer, Self::handle_buffer_event)],
pending_save: Task::ready(Ok(())),
path: None,
- api_key,
buffer,
+ completion_provider,
};
let message = MessageAnchor {
id: MessageId(post_inc(&mut this.next_message_id.0)),
@@ -1554,7 +1536,6 @@ impl Conversation {
fn deserialize(
saved_conversation: SavedConversation,
path: PathBuf,
- api_key: Rc<RefCell<Option<String>>>,
language_registry: Arc<LanguageRegistry>,
cx: &mut ModelContext<Self>,
) -> Self {
@@ -1563,6 +1544,10 @@ impl Conversation {
None => Some(Uuid::new_v4().to_string()),
};
let model = saved_conversation.model;
+ let completion_provider: Box<dyn CompletionProvider> = Box::new(
+ OpenAICompletionProvider::new(model.full_name(), cx.background().clone()),
+ );
+ completion_provider.retrieve_credentials(cx);
let markdown = language_registry.language_for_name("Markdown");
let mut message_anchors = Vec::new();
let mut next_message_id = MessageId(0);
@@ -1609,8 +1594,8 @@ impl Conversation {
_subscriptions: vec![cx.subscribe(&buffer, Self::handle_buffer_event)],
pending_save: Task::ready(Ok(())),
path: Some(path),
- api_key,
buffer,
+ completion_provider,
};
this.count_remaining_tokens(cx);
this
@@ -1731,11 +1716,11 @@ impl Conversation {
}
if should_assist {
- let Some(api_key) = self.api_key.borrow().clone() else {
+ if !self.completion_provider.has_credentials() {
return Default::default();
- };
+ }
- let request = OpenAIRequest {
+ let request: Box<dyn CompletionRequest> = Box::new(OpenAIRequest {
model: self.model.full_name().to_string(),
messages: self
.messages(cx)
@@ -1745,9 +1730,9 @@ impl Conversation {
stream: true,
stop: vec![],
temperature: 1.0,
- };
+ });
- let stream = stream_completion(api_key, cx.background().clone(), request);
+ let stream = self.completion_provider.complete(request);
let assistant_message = self
.insert_message_after(last_message_id, Role::Assistant, MessageStatus::Pending, cx)
.unwrap();
@@ -1765,33 +1750,28 @@ impl Conversation {
let mut messages = stream.await?;
while let Some(message) = messages.next().await {
- let mut message = message?;
- if let Some(choice) = message.choices.pop() {
- this.upgrade(&cx)
- .ok_or_else(|| anyhow!("conversation was dropped"))?
- .update(&mut cx, |this, cx| {
- let text: Arc<str> = choice.delta.content?.into();
- let message_ix =
- this.message_anchors.iter().position(|message| {
- message.id == assistant_message_id
- })?;
- this.buffer.update(cx, |buffer, cx| {
- let offset = this.message_anchors[message_ix + 1..]
- .iter()
- .find(|message| message.start.is_valid(buffer))
- .map_or(buffer.len(), |message| {
- message
- .start
- .to_offset(buffer)
- .saturating_sub(1)
- });
- buffer.edit([(offset..offset, text)], None, cx);
- });
- cx.emit(ConversationEvent::StreamedCompletion);
-
- Some(())
+ let text = message?;
+
+ this.upgrade(&cx)
+ .ok_or_else(|| anyhow!("conversation was dropped"))?
+ .update(&mut cx, |this, cx| {
+ let message_ix = this
+ .message_anchors
+ .iter()
+ .position(|message| message.id == assistant_message_id)?;
+ this.buffer.update(cx, |buffer, cx| {
+ let offset = this.message_anchors[message_ix + 1..]
+ .iter()
+ .find(|message| message.start.is_valid(buffer))
+ .map_or(buffer.len(), |message| {
+ message.start.to_offset(buffer).saturating_sub(1)
+ });
+ buffer.edit([(offset..offset, text)], None, cx);
});
- }
+ cx.emit(ConversationEvent::StreamedCompletion);
+
+ Some(())
+ });
smol::future::yield_now().await;
}
@@ -2013,57 +1993,54 @@ impl Conversation {
fn summarize(&mut self, cx: &mut ModelContext<Self>) {
if self.message_anchors.len() >= 2 && self.summary.is_none() {
- let api_key = self.api_key.borrow().clone();
- if let Some(api_key) = api_key {
- let messages = self
- .messages(cx)
- .take(2)
- .map(|message| message.to_open_ai_message(self.buffer.read(cx)))
- .chain(Some(RequestMessage {
- role: Role::User,
- content:
- "Summarize the conversation into a short title without punctuation"
- .into(),
- }));
- let request = OpenAIRequest {
- model: self.model.full_name().to_string(),
- messages: messages.collect(),
- stream: true,
- stop: vec![],
- temperature: 1.0,
- };
+ if !self.completion_provider.has_credentials() {
+ return;
+ }
- let stream = stream_completion(api_key, cx.background().clone(), request);
- self.pending_summary = cx.spawn(|this, mut cx| {
- async move {
- let mut messages = stream.await?;
+ let messages = self
+ .messages(cx)
+ .take(2)
+ .map(|message| message.to_open_ai_message(self.buffer.read(cx)))
+ .chain(Some(RequestMessage {
+ role: Role::User,
+ content: "Summarize the conversation into a short title without punctuation"
+ .into(),
+ }));
+ let request: Box<dyn CompletionRequest> = Box::new(OpenAIRequest {
+ model: self.model.full_name().to_string(),
+ messages: messages.collect(),
+ stream: true,
+ stop: vec![],
+ temperature: 1.0,
+ });
- while let Some(message) = messages.next().await {
- let mut message = message?;
- if let Some(choice) = message.choices.pop() {
- let text = choice.delta.content.unwrap_or_default();
- this.update(&mut cx, |this, cx| {
- this.summary
- .get_or_insert(Default::default())
- .text
- .push_str(&text);
- cx.emit(ConversationEvent::SummaryChanged);
- });
- }
- }
+ let stream = self.completion_provider.complete(request);
+ self.pending_summary = cx.spawn(|this, mut cx| {
+ async move {
+ let mut messages = stream.await?;
+ while let Some(message) = messages.next().await {
+ let text = message?;
this.update(&mut cx, |this, cx| {
- if let Some(summary) = this.summary.as_mut() {
- summary.done = true;
- cx.emit(ConversationEvent::SummaryChanged);
- }
+ this.summary
+ .get_or_insert(Default::default())
+ .text
+ .push_str(&text);
+ cx.emit(ConversationEvent::SummaryChanged);
});
-
- anyhow::Ok(())
}
- .log_err()
- });
- }
+
+ this.update(&mut cx, |this, cx| {
+ if let Some(summary) = this.summary.as_mut() {
+ summary.done = true;
+ cx.emit(ConversationEvent::SummaryChanged);
+ }
+ });
+
+ anyhow::Ok(())
+ }
+ .log_err()
+ });
}
}
@@ -2224,13 +2201,14 @@ struct ConversationEditor {
impl ConversationEditor {
fn new(
- api_key: Rc<RefCell<Option<String>>>,
+ completion_provider: Box<dyn CompletionProvider>,
language_registry: Arc<LanguageRegistry>,
fs: Arc<dyn Fs>,
workspace: WeakViewHandle<Workspace>,
cx: &mut ViewContext<Self>,
) -> Self {
- let conversation = cx.add_model(|cx| Conversation::new(api_key, language_registry, cx));
+ let conversation =
+ cx.add_model(|cx| Conversation::new(language_registry, cx, completion_provider));
Self::for_conversation(conversation, fs, workspace, cx)
}
@@ -3419,6 +3397,7 @@ fn merge_ranges(ranges: &mut Vec<Range<Anchor>>, buffer: &MultiBufferSnapshot) {
mod tests {
use super::*;
use crate::MessageId;
+ use ai::test::FakeCompletionProvider;
use gpui::AppContext;
#[gpui::test]
@@ -3426,7 +3405,9 @@ mod tests {
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 completion_provider = Box::new(FakeCompletionProvider::new());
+ let conversation = cx.add_model(|cx| Conversation::new(registry, cx, completion_provider));
let buffer = conversation.read(cx).buffer.clone();
let message_1 = conversation.read(cx).message_anchors[0].clone();
@@ -3554,7 +3535,9 @@ mod tests {
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 completion_provider = Box::new(FakeCompletionProvider::new());
+
+ let conversation = cx.add_model(|cx| Conversation::new(registry, cx, completion_provider));
let buffer = conversation.read(cx).buffer.clone();
let message_1 = conversation.read(cx).message_anchors[0].clone();
@@ -3650,7 +3633,8 @@ mod tests {
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 completion_provider = Box::new(FakeCompletionProvider::new());
+ let conversation = cx.add_model(|cx| Conversation::new(registry, cx, completion_provider));
let buffer = conversation.read(cx).buffer.clone();
let message_1 = conversation.read(cx).message_anchors[0].clone();
@@ -3732,8 +3716,9 @@ mod tests {
cx.set_global(SettingsStore::test(cx));
init(cx);
let registry = Arc::new(LanguageRegistry::test());
+ let completion_provider = Box::new(FakeCompletionProvider::new());
let conversation =
- cx.add_model(|cx| Conversation::new(Default::default(), registry.clone(), cx));
+ cx.add_model(|cx| Conversation::new(registry.clone(), cx, completion_provider));
let buffer = conversation.read(cx).buffer.clone();
let message_0 = conversation.read(cx).message_anchors[0].id;
let message_1 = conversation.update(cx, |conversation, cx| {
@@ -3770,7 +3755,6 @@ mod tests {
Conversation::deserialize(
conversation.read(cx).serialize(cx),
Default::default(),
- Default::default(),
registry.clone(),
cx,
)
@@ -1,5 +1,5 @@
use crate::streaming_diff::{Hunk, StreamingDiff};
-use ai::completion::{CompletionProvider, OpenAIRequest};
+use ai::completion::{CompletionProvider, CompletionRequest};
use anyhow::Result;
use editor::{Anchor, MultiBuffer, MultiBufferSnapshot, ToOffset, ToPoint};
use futures::{channel::mpsc, SinkExt, Stream, StreamExt};
@@ -96,7 +96,7 @@ impl Codegen {
self.error.as_ref()
}
- pub fn start(&mut self, prompt: OpenAIRequest, cx: &mut ModelContext<Self>) {
+ pub fn start(&mut self, prompt: Box<dyn CompletionRequest>, cx: &mut ModelContext<Self>) {
let range = self.range();
let snapshot = self.snapshot.clone();
let selected_text = snapshot
@@ -336,17 +336,25 @@ fn strip_markdown_codeblock(
#[cfg(test)]
mod tests {
use super::*;
- use futures::{
- future::BoxFuture,
- stream::{self, BoxStream},
- };
+ use ai::test::FakeCompletionProvider;
+ use futures::stream::{self};
use gpui::{executor::Deterministic, TestAppContext};
use indoc::indoc;
use language::{language_settings, tree_sitter_rust, Buffer, Language, LanguageConfig, Point};
- use parking_lot::Mutex;
use rand::prelude::*;
+ use serde::Serialize;
use settings::SettingsStore;
- use smol::future::FutureExt;
+
+ #[derive(Serialize)]
+ pub struct DummyCompletionRequest {
+ pub name: String,
+ }
+
+ impl CompletionRequest for DummyCompletionRequest {
+ fn data(&self) -> serde_json::Result<String> {
+ serde_json::to_string(self)
+ }
+ }
#[gpui::test(iterations = 10)]
async fn test_transform_autoindent(
@@ -372,7 +380,7 @@ mod tests {
let snapshot = buffer.snapshot(cx);
snapshot.anchor_before(Point::new(1, 0))..snapshot.anchor_after(Point::new(4, 5))
});
- let provider = Arc::new(TestCompletionProvider::new());
+ let provider = Arc::new(FakeCompletionProvider::new());
let codegen = cx.add_model(|cx| {
Codegen::new(
buffer.clone(),
@@ -381,7 +389,11 @@ mod tests {
cx,
)
});
- codegen.update(cx, |codegen, cx| codegen.start(Default::default(), cx));
+
+ let request = Box::new(DummyCompletionRequest {
+ name: "test".to_string(),
+ });
+ codegen.update(cx, |codegen, cx| codegen.start(request, cx));
let mut new_text = concat!(
" let mut x = 0;\n",
@@ -434,7 +446,7 @@ mod tests {
let snapshot = buffer.snapshot(cx);
snapshot.anchor_before(Point::new(1, 6))
});
- let provider = Arc::new(TestCompletionProvider::new());
+ let provider = Arc::new(FakeCompletionProvider::new());
let codegen = cx.add_model(|cx| {
Codegen::new(
buffer.clone(),
@@ -443,7 +455,11 @@ mod tests {
cx,
)
});
- codegen.update(cx, |codegen, cx| codegen.start(Default::default(), cx));
+
+ let request = Box::new(DummyCompletionRequest {
+ name: "test".to_string(),
+ });
+ codegen.update(cx, |codegen, cx| codegen.start(request, cx));
let mut new_text = concat!(
"t mut x = 0;\n",
@@ -496,7 +512,7 @@ mod tests {
let snapshot = buffer.snapshot(cx);
snapshot.anchor_before(Point::new(1, 2))
});
- let provider = Arc::new(TestCompletionProvider::new());
+ let provider = Arc::new(FakeCompletionProvider::new());
let codegen = cx.add_model(|cx| {
Codegen::new(
buffer.clone(),
@@ -505,7 +521,11 @@ mod tests {
cx,
)
});
- codegen.update(cx, |codegen, cx| codegen.start(Default::default(), cx));
+
+ let request = Box::new(DummyCompletionRequest {
+ name: "test".to_string(),
+ });
+ codegen.update(cx, |codegen, cx| codegen.start(request, cx));
let mut new_text = concat!(
"let mut x = 0;\n",
@@ -593,38 +613,6 @@ mod tests {
}
}
- struct TestCompletionProvider {
- last_completion_tx: Mutex<Option<mpsc::Sender<String>>>,
- }
-
- impl TestCompletionProvider {
- fn new() -> Self {
- Self {
- last_completion_tx: Mutex::new(None),
- }
- }
-
- fn send_completion(&self, completion: impl Into<String>) {
- let mut tx = self.last_completion_tx.lock();
- tx.as_mut().unwrap().try_send(completion.into()).unwrap();
- }
-
- fn finish_completion(&self) {
- self.last_completion_tx.lock().take().unwrap();
- }
- }
-
- impl CompletionProvider for TestCompletionProvider {
- fn complete(
- &self,
- _prompt: OpenAIRequest,
- ) -> BoxFuture<'static, Result<BoxStream<'static, Result<String>>>> {
- let (tx, rx) = mpsc::channel(1);
- *self.last_completion_tx.lock() = Some(tx);
- async move { Ok(rx.map(|rx| Ok(rx)).boxed()) }.boxed()
- }
- }
-
fn rust_lang() -> Language {
Language::new(
LanguageConfig {
@@ -1,9 +1,10 @@
-use ai::models::{LanguageModel, OpenAILanguageModel};
-use ai::templates::base::{PromptArguments, PromptChain, PromptPriority, PromptTemplate};
-use ai::templates::file_context::FileContext;
-use ai::templates::generate::GenerateInlineContent;
-use ai::templates::preamble::EngineerPreamble;
-use ai::templates::repository_context::{PromptCodeSnippet, RepositoryContext};
+use ai::models::LanguageModel;
+use ai::prompts::base::{PromptArguments, PromptChain, PromptPriority, PromptTemplate};
+use ai::prompts::file_context::FileContext;
+use ai::prompts::generate::GenerateInlineContent;
+use ai::prompts::preamble::EngineerPreamble;
+use ai::prompts::repository_context::{PromptCodeSnippet, RepositoryContext};
+use ai::providers::open_ai::OpenAILanguageModel;
use language::{BufferSnapshot, OffsetRangeExt, ToOffset};
use std::cmp::{self, Reverse};
use std::ops::Range;
@@ -25,7 +25,7 @@ collections = { path = "../collections" }
gpui2 = { path = "../gpui2" }
log.workspace = true
live_kit_client = { path = "../live_kit_client" }
-fs = { path = "../fs" }
+fs2 = { path = "../fs2" }
language2 = { path = "../language2" }
media = { path = "../media" }
project2 = { path = "../project2" }
@@ -43,7 +43,7 @@ serde_derive.workspace = true
[dev-dependencies]
client2 = { path = "../client2", features = ["test-support"] }
-fs = { path = "../fs", features = ["test-support"] }
+fs2 = { path = "../fs2", features = ["test-support"] }
language2 = { path = "../language2", features = ["test-support"] }
collections = { path = "../collections", features = ["test-support"] }
gpui2 = { path = "../gpui2", features = ["test-support"] }
@@ -12,8 +12,8 @@ use client2::{
use collections::HashSet;
use futures::{future::Shared, FutureExt};
use gpui2::{
- AppContext, AsyncAppContext, Context, EventEmitter, Handle, ModelContext, Subscription, Task,
- WeakHandle,
+ AppContext, AsyncAppContext, Context, EventEmitter, Model, ModelContext, Subscription, Task,
+ WeakModel,
};
use postage::watch;
use project2::Project;
@@ -23,10 +23,10 @@ use std::sync::Arc;
pub use participant::ParticipantLocation;
pub use room::Room;
-pub fn init(client: Arc<Client>, user_store: Handle<UserStore>, cx: &mut AppContext) {
+pub fn init(client: Arc<Client>, user_store: Model<UserStore>, cx: &mut AppContext) {
CallSettings::register(cx);
- let active_call = cx.entity(|cx| ActiveCall::new(client, user_store, cx));
+ let active_call = cx.build_model(|cx| ActiveCall::new(client, user_store, cx));
cx.set_global(active_call);
}
@@ -40,16 +40,16 @@ pub struct IncomingCall {
/// Singleton global maintaining the user's participation in a room across workspaces.
pub struct ActiveCall {
- room: Option<(Handle<Room>, Vec<Subscription>)>,
- pending_room_creation: Option<Shared<Task<Result<Handle<Room>, Arc<anyhow::Error>>>>>,
- location: Option<WeakHandle<Project>>,
+ room: Option<(Model<Room>, Vec<Subscription>)>,
+ pending_room_creation: Option<Shared<Task<Result<Model<Room>, Arc<anyhow::Error>>>>>,
+ location: Option<WeakModel<Project>>,
pending_invites: HashSet<u64>,
incoming_call: (
watch::Sender<Option<IncomingCall>>,
watch::Receiver<Option<IncomingCall>>,
),
client: Arc<Client>,
- user_store: Handle<UserStore>,
+ user_store: Model<UserStore>,
_subscriptions: Vec<client2::Subscription>,
}
@@ -58,11 +58,7 @@ impl EventEmitter for ActiveCall {
}
impl ActiveCall {
- fn new(
- client: Arc<Client>,
- user_store: Handle<UserStore>,
- cx: &mut ModelContext<Self>,
- ) -> Self {
+ fn new(client: Arc<Client>, user_store: Model<UserStore>, cx: &mut ModelContext<Self>) -> Self {
Self {
room: None,
pending_room_creation: None,
@@ -84,7 +80,7 @@ impl ActiveCall {
}
async fn handle_incoming_call(
- this: Handle<Self>,
+ this: Model<Self>,
envelope: TypedEnvelope<proto::IncomingCall>,
_: Arc<Client>,
mut cx: AsyncAppContext,
@@ -112,7 +108,7 @@ impl ActiveCall {
}
async fn handle_call_canceled(
- this: Handle<Self>,
+ this: Model<Self>,
envelope: TypedEnvelope<proto::CallCanceled>,
_: Arc<Client>,
mut cx: AsyncAppContext,
@@ -129,14 +125,14 @@ impl ActiveCall {
Ok(())
}
- pub fn global(cx: &AppContext) -> Handle<Self> {
- cx.global::<Handle<Self>>().clone()
+ pub fn global(cx: &AppContext) -> Model<Self> {
+ cx.global::<Model<Self>>().clone()
}
pub fn invite(
&mut self,
called_user_id: u64,
- initial_project: Option<Handle<Project>>,
+ initial_project: Option<Model<Project>>,
cx: &mut ModelContext<Self>,
) -> Task<Result<()>> {
if !self.pending_invites.insert(called_user_id) {
@@ -291,7 +287,7 @@ impl ActiveCall {
&mut self,
channel_id: u64,
cx: &mut ModelContext<Self>,
- ) -> Task<Result<Handle<Room>>> {
+ ) -> Task<Result<Model<Room>>> {
if let Some(room) = self.room().cloned() {
if room.read(cx).channel_id() == Some(channel_id) {
return Task::ready(Ok(room));
@@ -327,7 +323,7 @@ impl ActiveCall {
pub fn share_project(
&mut self,
- project: Handle<Project>,
+ project: Model<Project>,
cx: &mut ModelContext<Self>,
) -> Task<Result<u64>> {
if let Some((room, _)) = self.room.as_ref() {
@@ -340,7 +336,7 @@ impl ActiveCall {
pub fn unshare_project(
&mut self,
- project: Handle<Project>,
+ project: Model<Project>,
cx: &mut ModelContext<Self>,
) -> Result<()> {
if let Some((room, _)) = self.room.as_ref() {
@@ -351,13 +347,13 @@ impl ActiveCall {
}
}
- pub fn location(&self) -> Option<&WeakHandle<Project>> {
+ pub fn location(&self) -> Option<&WeakModel<Project>> {
self.location.as_ref()
}
pub fn set_location(
&mut self,
- project: Option<&Handle<Project>>,
+ project: Option<&Model<Project>>,
cx: &mut ModelContext<Self>,
) -> Task<Result<()>> {
if project.is_some() || !*ZED_ALWAYS_ACTIVE {
@@ -371,7 +367,7 @@ impl ActiveCall {
fn set_room(
&mut self,
- room: Option<Handle<Room>>,
+ room: Option<Model<Room>>,
cx: &mut ModelContext<Self>,
) -> Task<Result<()>> {
if room.as_ref() != self.room.as_ref().map(|room| &room.0) {
@@ -407,7 +403,7 @@ impl ActiveCall {
}
}
- pub fn room(&self) -> Option<&Handle<Room>> {
+ pub fn room(&self) -> Option<&Model<Room>> {
self.room.as_ref().map(|(room, _)| room)
}
@@ -1,7 +1,7 @@
use anyhow::{anyhow, Result};
use client2::ParticipantIndex;
use client2::{proto, User};
-use gpui2::WeakHandle;
+use gpui2::WeakModel;
pub use live_kit_client::Frame;
use project2::Project;
use std::{fmt, sync::Arc};
@@ -33,7 +33,7 @@ impl ParticipantLocation {
#[derive(Clone, Default)]
pub struct LocalParticipant {
pub projects: Vec<proto::ParticipantProject>,
- pub active_project: Option<WeakHandle<Project>>,
+ pub active_project: Option<WeakModel<Project>>,
}
#[derive(Clone, Debug)]
@@ -13,10 +13,10 @@ use client2::{
Client, ParticipantIndex, TypedEnvelope, User, UserStore,
};
use collections::{BTreeMap, HashMap, HashSet};
-use fs::Fs;
+use fs2::Fs;
use futures::{FutureExt, StreamExt};
use gpui2::{
- AppContext, AsyncAppContext, Context, EventEmitter, Handle, ModelContext, Task, WeakHandle,
+ AppContext, AsyncAppContext, Context, EventEmitter, Model, ModelContext, Task, WeakModel,
};
use language2::LanguageRegistry;
use live_kit_client::{LocalTrackPublication, RemoteAudioTrackUpdate, RemoteVideoTrackUpdate};
@@ -61,8 +61,8 @@ pub struct Room {
channel_id: Option<u64>,
// live_kit: Option<LiveKitRoom>,
status: RoomStatus,
- shared_projects: HashSet<WeakHandle<Project>>,
- joined_projects: HashSet<WeakHandle<Project>>,
+ shared_projects: HashSet<WeakModel<Project>>,
+ joined_projects: HashSet<WeakModel<Project>>,
local_participant: LocalParticipant,
remote_participants: BTreeMap<u64, RemoteParticipant>,
pending_participants: Vec<Arc<User>>,
@@ -70,7 +70,7 @@ pub struct Room {
pending_call_count: usize,
leave_when_empty: bool,
client: Arc<Client>,
- user_store: Handle<UserStore>,
+ user_store: Model<UserStore>,
follows_by_leader_id_project_id: HashMap<(PeerId, u64), Vec<PeerId>>,
client_subscriptions: Vec<client2::Subscription>,
_subscriptions: Vec<gpui2::Subscription>,
@@ -111,7 +111,7 @@ impl Room {
channel_id: Option<u64>,
live_kit_connection_info: Option<proto::LiveKitConnectionInfo>,
client: Arc<Client>,
- user_store: Handle<UserStore>,
+ user_store: Model<UserStore>,
cx: &mut ModelContext<Self>,
) -> Self {
todo!()
@@ -237,15 +237,15 @@ impl Room {
pub(crate) fn create(
called_user_id: u64,
- initial_project: Option<Handle<Project>>,
+ initial_project: Option<Model<Project>>,
client: Arc<Client>,
- user_store: Handle<UserStore>,
+ user_store: Model<UserStore>,
cx: &mut AppContext,
- ) -> Task<Result<Handle<Self>>> {
+ ) -> Task<Result<Model<Self>>> {
cx.spawn(move |mut cx| async move {
let response = client.request(proto::CreateRoom {}).await?;
let room_proto = response.room.ok_or_else(|| anyhow!("invalid room"))?;
- let room = cx.entity(|cx| {
+ let room = cx.build_model(|cx| {
Self::new(
room_proto.id,
None,
@@ -283,9 +283,9 @@ impl Room {
pub(crate) fn join_channel(
channel_id: u64,
client: Arc<Client>,
- user_store: Handle<UserStore>,
+ user_store: Model<UserStore>,
cx: &mut AppContext,
- ) -> Task<Result<Handle<Self>>> {
+ ) -> Task<Result<Model<Self>>> {
cx.spawn(move |cx| async move {
Self::from_join_response(
client.request(proto::JoinChannel { channel_id }).await?,
@@ -299,9 +299,9 @@ impl Room {
pub(crate) fn join(
call: &IncomingCall,
client: Arc<Client>,
- user_store: Handle<UserStore>,
+ user_store: Model<UserStore>,
cx: &mut AppContext,
- ) -> Task<Result<Handle<Self>>> {
+ ) -> Task<Result<Model<Self>>> {
let id = call.room_id;
cx.spawn(move |cx| async move {
Self::from_join_response(
@@ -343,11 +343,11 @@ impl Room {
fn from_join_response(
response: proto::JoinRoomResponse,
client: Arc<Client>,
- user_store: Handle<UserStore>,
+ user_store: Model<UserStore>,
mut cx: AsyncAppContext,
- ) -> Result<Handle<Self>> {
+ ) -> Result<Model<Self>> {
let room_proto = response.room.ok_or_else(|| anyhow!("invalid room"))?;
- let room = cx.entity(|cx| {
+ let room = cx.build_model(|cx| {
Self::new(
room_proto.id,
response.channel_id,
@@ -424,7 +424,7 @@ impl Room {
}
async fn maintain_connection(
- this: WeakHandle<Self>,
+ this: WeakModel<Self>,
client: Arc<Client>,
mut cx: AsyncAppContext,
) -> Result<()> {
@@ -661,7 +661,7 @@ impl Room {
}
async fn handle_room_updated(
- this: Handle<Self>,
+ this: Model<Self>,
envelope: TypedEnvelope<proto::RoomUpdated>,
_: Arc<Client>,
mut cx: AsyncAppContext,
@@ -1101,7 +1101,7 @@ impl Room {
language_registry: Arc<LanguageRegistry>,
fs: Arc<dyn Fs>,
cx: &mut ModelContext<Self>,
- ) -> Task<Result<Handle<Project>>> {
+ ) -> Task<Result<Model<Project>>> {
let client = self.client.clone();
let user_store = self.user_store.clone();
cx.emit(Event::RemoteProjectJoined { project_id: id });
@@ -1125,7 +1125,7 @@ impl Room {
pub(crate) fn share_project(
&mut self,
- project: Handle<Project>,
+ project: Model<Project>,
cx: &mut ModelContext<Self>,
) -> Task<Result<u64>> {
if let Some(project_id) = project.read(cx).remote_id() {
@@ -1161,7 +1161,7 @@ impl Room {
pub(crate) fn unshare_project(
&mut self,
- project: Handle<Project>,
+ project: Model<Project>,
cx: &mut ModelContext<Self>,
) -> Result<()> {
let project_id = match project.read(cx).remote_id() {
@@ -1175,7 +1175,7 @@ impl Room {
pub(crate) fn set_location(
&mut self,
- project: Option<&Handle<Project>>,
+ project: Option<&Model<Project>>,
cx: &mut ModelContext<Self>,
) -> Task<Result<()>> {
if self.status.is_offline() {
@@ -14,8 +14,8 @@ use futures::{
future::BoxFuture, AsyncReadExt, FutureExt, SinkExt, StreamExt, TryFutureExt as _, TryStreamExt,
};
use gpui2::{
- serde_json, AnyHandle, AnyWeakHandle, AppContext, AsyncAppContext, Handle, SemanticVersion,
- Task, WeakHandle,
+ serde_json, AnyModel, AnyWeakModel, AppContext, AsyncAppContext, Model, SemanticVersion, Task,
+ WeakModel,
};
use lazy_static::lazy_static;
use parking_lot::RwLock;
@@ -227,7 +227,7 @@ struct ClientState {
_reconnect_task: Option<Task<()>>,
reconnect_interval: Duration,
entities_by_type_and_remote_id: HashMap<(TypeId, u64), WeakSubscriber>,
- models_by_message_type: HashMap<TypeId, AnyWeakHandle>,
+ models_by_message_type: HashMap<TypeId, AnyWeakModel>,
entity_types_by_message_type: HashMap<TypeId, TypeId>,
#[allow(clippy::type_complexity)]
message_handlers: HashMap<
@@ -236,7 +236,7 @@ struct ClientState {
dyn Send
+ Sync
+ Fn(
- AnyHandle,
+ AnyModel,
Box<dyn AnyTypedEnvelope>,
&Arc<Client>,
AsyncAppContext,
@@ -246,7 +246,7 @@ struct ClientState {
}
enum WeakSubscriber {
- Entity { handle: AnyWeakHandle },
+ Entity { handle: AnyWeakModel },
Pending(Vec<Box<dyn AnyTypedEnvelope>>),
}
@@ -314,7 +314,7 @@ impl<T> PendingEntitySubscription<T>
where
T: 'static + Send,
{
- pub fn set_model(mut self, model: &Handle<T>, cx: &mut AsyncAppContext) -> Subscription {
+ pub fn set_model(mut self, model: &Model<T>, cx: &mut AsyncAppContext) -> Subscription {
self.consumed = true;
let mut state = self.client.state.write();
let id = (TypeId::of::<T>(), self.remote_id);
@@ -552,13 +552,13 @@ impl Client {
#[track_caller]
pub fn add_message_handler<M, E, H, F>(
self: &Arc<Self>,
- entity: WeakHandle<E>,
+ entity: WeakModel<E>,
handler: H,
) -> Subscription
where
M: EnvelopedMessage,
E: 'static + Send,
- H: 'static + Send + Sync + Fn(Handle<E>, TypedEnvelope<M>, Arc<Self>, AsyncAppContext) -> F,
+ H: 'static + Send + Sync + Fn(Model<E>, TypedEnvelope<M>, Arc<Self>, AsyncAppContext) -> F,
F: 'static + Future<Output = Result<()>> + Send,
{
let message_type_id = TypeId::of::<M>();
@@ -594,13 +594,13 @@ impl Client {
pub fn add_request_handler<M, E, H, F>(
self: &Arc<Self>,
- model: WeakHandle<E>,
+ model: WeakModel<E>,
handler: H,
) -> Subscription
where
M: RequestMessage,
E: 'static + Send,
- H: 'static + Send + Sync + Fn(Handle<E>, TypedEnvelope<M>, Arc<Self>, AsyncAppContext) -> F,
+ H: 'static + Send + Sync + Fn(Model<E>, TypedEnvelope<M>, Arc<Self>, AsyncAppContext) -> F,
F: 'static + Future<Output = Result<M::Response>> + Send,
{
self.add_message_handler(model, move |handle, envelope, this, cx| {
@@ -616,7 +616,7 @@ impl Client {
where
M: EntityMessage,
E: 'static + Send,
- H: 'static + Send + Sync + Fn(Handle<E>, TypedEnvelope<M>, Arc<Self>, AsyncAppContext) -> F,
+ H: 'static + Send + Sync + Fn(Model<E>, TypedEnvelope<M>, Arc<Self>, AsyncAppContext) -> F,
F: 'static + Future<Output = Result<()>> + Send,
{
self.add_entity_message_handler::<M, E, _, _>(move |subscriber, message, client, cx| {
@@ -628,7 +628,7 @@ impl Client {
where
M: EntityMessage,
E: 'static + Send,
- H: 'static + Send + Sync + Fn(AnyHandle, TypedEnvelope<M>, Arc<Self>, AsyncAppContext) -> F,
+ H: 'static + Send + Sync + Fn(AnyModel, TypedEnvelope<M>, Arc<Self>, AsyncAppContext) -> F,
F: 'static + Future<Output = Result<()>> + Send,
{
let model_type_id = TypeId::of::<E>();
@@ -667,7 +667,7 @@ impl Client {
where
M: EntityMessage + RequestMessage,
E: 'static + Send,
- H: 'static + Send + Sync + Fn(Handle<E>, TypedEnvelope<M>, Arc<Self>, AsyncAppContext) -> F,
+ H: 'static + Send + Sync + Fn(Model<E>, TypedEnvelope<M>, Arc<Self>, AsyncAppContext) -> F,
F: 'static + Future<Output = Result<M::Response>> + Send,
{
self.add_model_message_handler(move |entity, envelope, client, cx| {
@@ -1546,7 +1546,7 @@ mod tests {
let (done_tx1, mut done_rx1) = smol::channel::unbounded();
let (done_tx2, mut done_rx2) = smol::channel::unbounded();
client.add_model_message_handler(
- move |model: Handle<Model>, _: TypedEnvelope<proto::JoinProject>, _, mut cx| {
+ move |model: Model<TestModel>, _: TypedEnvelope<proto::JoinProject>, _, mut cx| {
match model.update(&mut cx, |model, _| model.id).unwrap() {
1 => done_tx1.try_send(()).unwrap(),
2 => done_tx2.try_send(()).unwrap(),
@@ -1555,15 +1555,15 @@ mod tests {
async { Ok(()) }
},
);
- let model1 = cx.entity(|_| Model {
+ let model1 = cx.build_model(|_| TestModel {
id: 1,
subscription: None,
});
- let model2 = cx.entity(|_| Model {
+ let model2 = cx.build_model(|_| TestModel {
id: 2,
subscription: None,
});
- let model3 = cx.entity(|_| Model {
+ let model3 = cx.build_model(|_| TestModel {
id: 3,
subscription: None,
});
@@ -1596,7 +1596,7 @@ mod tests {
let client = cx.update(|cx| Client::new(FakeHttpClient::with_404_response(), cx));
let server = FakeServer::for_client(user_id, &client, cx).await;
- let model = cx.entity(|_| Model::default());
+ let model = cx.build_model(|_| TestModel::default());
let (done_tx1, _done_rx1) = smol::channel::unbounded();
let (done_tx2, mut done_rx2) = smol::channel::unbounded();
let subscription1 = client.add_message_handler(
@@ -1624,11 +1624,11 @@ mod tests {
let client = cx.update(|cx| Client::new(FakeHttpClient::with_404_response(), cx));
let server = FakeServer::for_client(user_id, &client, cx).await;
- let model = cx.entity(|_| Model::default());
+ let model = cx.build_model(|_| TestModel::default());
let (done_tx, mut done_rx) = smol::channel::unbounded();
let subscription = client.add_message_handler(
model.clone().downgrade(),
- move |model: Handle<Model>, _: TypedEnvelope<proto::Ping>, _, mut cx| {
+ move |model: Model<TestModel>, _: TypedEnvelope<proto::Ping>, _, mut cx| {
model
.update(&mut cx, |model, _| model.subscription.take())
.unwrap();
@@ -1644,7 +1644,7 @@ mod tests {
}
#[derive(Default)]
- struct Model {
+ struct TestModel {
id: usize,
subscription: Option<Subscription>,
}
@@ -5,7 +5,9 @@ use parking_lot::Mutex;
use serde::Serialize;
use settings2::Settings;
use std::{env, io::Write, mem, path::PathBuf, sync::Arc, time::Duration};
-use sysinfo::{Pid, PidExt, ProcessExt, System, SystemExt};
+use sysinfo::{
+ CpuRefreshKind, Pid, PidExt, ProcessExt, ProcessRefreshKind, RefreshKind, System, SystemExt,
+};
use tempfile::NamedTempFile;
use util::http::HttpClient;
use util::{channel::ReleaseChannel, TryFutureExt};
@@ -161,8 +163,16 @@ impl Telemetry {
let this = self.clone();
cx.spawn(|cx| async move {
- let mut system = System::new_all();
- system.refresh_all();
+ // Avoiding calling `System::new_all()`, as there have been crashes related to it
+ let refresh_kind = RefreshKind::new()
+ .with_memory() // For memory usage
+ .with_processes(ProcessRefreshKind::everything()) // For process usage
+ .with_cpu(CpuRefreshKind::everything()); // For core count
+
+ let mut system = System::new_with_specifics(refresh_kind);
+
+ // Avoiding calling `refresh_all()`, just update what we need
+ system.refresh_specifics(refresh_kind);
loop {
// Waiting some amount of time before the first query is important to get a reasonable value
@@ -170,8 +180,7 @@ impl Telemetry {
const DURATION_BETWEEN_SYSTEM_EVENTS: Duration = Duration::from_secs(60);
smol::Timer::after(DURATION_BETWEEN_SYSTEM_EVENTS).await;
- system.refresh_memory();
- system.refresh_processes();
+ system.refresh_specifics(refresh_kind);
let current_process = Pid::from_u32(std::process::id());
let Some(process) = system.processes().get(¤t_process) else {
@@ -1,7 +1,7 @@
use crate::{Client, Connection, Credentials, EstablishConnectionError, UserStore};
use anyhow::{anyhow, Result};
use futures::{stream::BoxStream, StreamExt};
-use gpui2::{Context, Executor, Handle, TestAppContext};
+use gpui2::{Context, Executor, Model, TestAppContext};
use parking_lot::Mutex;
use rpc2::{
proto::{self, GetPrivateUserInfo, GetPrivateUserInfoResponse},
@@ -194,9 +194,9 @@ impl FakeServer {
&self,
client: Arc<Client>,
cx: &mut TestAppContext,
- ) -> Handle<UserStore> {
+ ) -> Model<UserStore> {
let http_client = FakeHttpClient::with_404_response();
- let user_store = cx.entity(|cx| UserStore::new(client, http_client, cx));
+ let user_store = cx.build_model(|cx| UserStore::new(client, http_client, cx));
assert_eq!(
self.receive::<proto::GetUsers>()
.await
@@ -3,7 +3,7 @@ use anyhow::{anyhow, Context, Result};
use collections::{hash_map::Entry, HashMap, HashSet};
use feature_flags2::FeatureFlagAppExt;
use futures::{channel::mpsc, future, AsyncReadExt, Future, StreamExt};
-use gpui2::{AsyncAppContext, EventEmitter, Handle, ImageData, ModelContext, Task};
+use gpui2::{AsyncAppContext, EventEmitter, ImageData, Model, ModelContext, Task};
use postage::{sink::Sink, watch};
use rpc2::proto::{RequestMessage, UsersResponse};
use std::sync::{Arc, Weak};
@@ -213,7 +213,7 @@ impl UserStore {
}
async fn handle_update_invite_info(
- this: Handle<Self>,
+ this: Model<Self>,
message: TypedEnvelope<proto::UpdateInviteInfo>,
_: Arc<Client>,
mut cx: AsyncAppContext,
@@ -229,7 +229,7 @@ impl UserStore {
}
async fn handle_show_contacts(
- this: Handle<Self>,
+ this: Model<Self>,
_: TypedEnvelope<proto::ShowContacts>,
_: Arc<Client>,
mut cx: AsyncAppContext,
@@ -243,7 +243,7 @@ impl UserStore {
}
async fn handle_update_contacts(
- this: Handle<Self>,
+ this: Model<Self>,
message: TypedEnvelope<proto::UpdateContacts>,
_: Arc<Client>,
mut cx: AsyncAppContext,
@@ -690,7 +690,7 @@ impl User {
impl Contact {
async fn from_proto(
contact: proto::Contact,
- user_store: &Handle<UserStore>,
+ user_store: &Model<UserStore>,
cx: &mut AsyncAppContext,
) -> Result<Self> {
let user = user_store
@@ -7,8 +7,8 @@ use async_tar::Archive;
use collections::{HashMap, HashSet};
use futures::{channel::oneshot, future::Shared, Future, FutureExt, TryFutureExt};
use gpui2::{
- AppContext, AsyncAppContext, Context, EntityId, EventEmitter, Handle, ModelContext, Task,
- WeakHandle,
+ AppContext, AsyncAppContext, Context, EntityId, EventEmitter, Model, ModelContext, Task,
+ WeakModel,
};
use language2::{
language_settings::{all_language_settings, language_settings},
@@ -49,7 +49,7 @@ pub fn init(
node_runtime: Arc<dyn NodeRuntime>,
cx: &mut AppContext,
) {
- let copilot = cx.entity({
+ let copilot = cx.build_model({
let node_runtime = node_runtime.clone();
move |cx| Copilot::start(new_server_id, http, node_runtime, cx)
});
@@ -183,7 +183,7 @@ struct RegisteredBuffer {
impl RegisteredBuffer {
fn report_changes(
&mut self,
- buffer: &Handle<Buffer>,
+ buffer: &Model<Buffer>,
cx: &mut ModelContext<Copilot>,
) -> oneshot::Receiver<(i32, BufferSnapshot)> {
let (done_tx, done_rx) = oneshot::channel();
@@ -278,7 +278,7 @@ pub struct Copilot {
http: Arc<dyn HttpClient>,
node_runtime: Arc<dyn NodeRuntime>,
server: CopilotServer,
- buffers: HashSet<WeakHandle<Buffer>>,
+ buffers: HashSet<WeakModel<Buffer>>,
server_id: LanguageServerId,
_subscription: gpui2::Subscription,
}
@@ -292,9 +292,9 @@ impl EventEmitter for Copilot {
}
impl Copilot {
- pub fn global(cx: &AppContext) -> Option<Handle<Self>> {
- if cx.has_global::<Handle<Self>>() {
- Some(cx.global::<Handle<Self>>().clone())
+ pub fn global(cx: &AppContext) -> Option<Model<Self>> {
+ if cx.has_global::<Model<Self>>() {
+ Some(cx.global::<Model<Self>>().clone())
} else {
None
}
@@ -383,7 +383,7 @@ impl Copilot {
new_server_id: LanguageServerId,
http: Arc<dyn HttpClient>,
node_runtime: Arc<dyn NodeRuntime>,
- this: WeakHandle<Self>,
+ this: WeakModel<Self>,
mut cx: AsyncAppContext,
) -> impl Future<Output = ()> {
async move {
@@ -590,7 +590,7 @@ impl Copilot {
}
}
- pub fn register_buffer(&mut self, buffer: &Handle<Buffer>, cx: &mut ModelContext<Self>) {
+ pub fn register_buffer(&mut self, buffer: &Model<Buffer>, cx: &mut ModelContext<Self>) {
let weak_buffer = buffer.downgrade();
self.buffers.insert(weak_buffer.clone());
@@ -646,7 +646,7 @@ impl Copilot {
fn handle_buffer_event(
&mut self,
- buffer: Handle<Buffer>,
+ buffer: Model<Buffer>,
event: &language2::Event,
cx: &mut ModelContext<Self>,
) -> Result<()> {
@@ -706,7 +706,7 @@ impl Copilot {
Ok(())
}
- fn unregister_buffer(&mut self, buffer: &WeakHandle<Buffer>) {
+ fn unregister_buffer(&mut self, buffer: &WeakModel<Buffer>) {
if let Ok(server) = self.server.as_running() {
if let Some(buffer) = server.registered_buffers.remove(&buffer.entity_id()) {
server
@@ -723,7 +723,7 @@ impl Copilot {
pub fn completions<T>(
&mut self,
- buffer: &Handle<Buffer>,
+ buffer: &Model<Buffer>,
position: T,
cx: &mut ModelContext<Self>,
) -> Task<Result<Vec<Completion>>>
@@ -735,7 +735,7 @@ impl Copilot {
pub fn completions_cycling<T>(
&mut self,
- buffer: &Handle<Buffer>,
+ buffer: &Model<Buffer>,
position: T,
cx: &mut ModelContext<Self>,
) -> Task<Result<Vec<Completion>>>
@@ -792,7 +792,7 @@ impl Copilot {
fn request_completions<R, T>(
&mut self,
- buffer: &Handle<Buffer>,
+ buffer: &Model<Buffer>,
position: T,
cx: &mut ModelContext<Self>,
) -> Task<Result<Vec<Completion>>>
@@ -926,7 +926,7 @@ fn id_for_language(language: Option<&Arc<Language>>) -> String {
}
}
-fn uri_for_buffer(buffer: &Handle<Buffer>, cx: &AppContext) -> lsp2::Url {
+fn uri_for_buffer(buffer: &Model<Buffer>, cx: &AppContext) -> lsp2::Url {
if let Some(file) = buffer.read(cx).file().and_then(|file| file.as_local()) {
lsp2::Url::from_file_path(file.abs_path(cx)).unwrap()
} else {
@@ -967,7 +967,6 @@ impl CompletionsMenu {
self.selected_item -= 1;
} else {
self.selected_item = self.matches.len() - 1;
- self.list.scroll_to(ScrollTarget::Show(self.selected_item));
}
self.list.scroll_to(ScrollTarget::Show(self.selected_item));
self.attempt_resolve_selected_completion_documentation(project, cx);
@@ -1538,7 +1537,6 @@ impl CodeActionsMenu {
self.selected_item -= 1;
} else {
self.selected_item = self.actions.len() - 1;
- self.list.scroll_to(ScrollTarget::Show(self.selected_item));
}
self.list.scroll_to(ScrollTarget::Show(self.selected_item));
cx.notify();
@@ -1547,11 +1545,10 @@ impl CodeActionsMenu {
fn select_next(&mut self, cx: &mut ViewContext<Editor>) {
if self.selected_item + 1 < self.actions.len() {
self.selected_item += 1;
- self.list.scroll_to(ScrollTarget::Show(self.selected_item));
} else {
self.selected_item = 0;
- self.list.scroll_to(ScrollTarget::Show(self.selected_item));
}
+ self.list.scroll_to(ScrollTarget::Show(self.selected_item));
cx.notify();
}
@@ -16,7 +16,7 @@ use crate::{
current_platform, image_cache::ImageCache, Action, AnyBox, AnyView, AnyWindowHandle,
AppMetadata, AssetSource, ClipboardItem, Context, DispatchPhase, DisplayId, Executor,
FocusEvent, FocusHandle, FocusId, KeyBinding, Keymap, LayoutId, MainThread, MainThreadOnly,
- Pixels, Platform, Point, SharedString, SubscriberSet, Subscription, SvgRenderer, Task,
+ Pixels, Platform, Point, Render, SharedString, SubscriberSet, Subscription, SvgRenderer, Task,
TextStyle, TextStyleRefinement, TextSystem, View, ViewContext, Window, WindowContext,
WindowHandle, WindowId,
};
@@ -309,10 +309,17 @@ impl AppContext {
update: impl FnOnce(&mut V, &mut ViewContext<'_, '_, V>) -> R,
) -> Result<R>
where
- V: 'static,
+ V: 'static + Send,
{
self.update_window(handle.any_handle, |cx| {
- let root_view = cx.window.root_view.as_ref().unwrap().downcast().unwrap();
+ let root_view = cx
+ .window
+ .root_view
+ .as_ref()
+ .unwrap()
+ .clone()
+ .downcast()
+ .unwrap();
root_view.update(cx, update)
})
}
@@ -685,7 +692,7 @@ impl AppContext {
pub fn observe_release<E: 'static>(
&mut self,
- handle: &Handle<E>,
+ handle: &Model<E>,
mut on_release: impl FnMut(&mut E, &mut AppContext) + Send + 'static,
) -> Subscription {
self.release_listeners.insert(
@@ -750,35 +757,35 @@ impl AppContext {
}
impl Context for AppContext {
- type EntityContext<'a, T> = ModelContext<'a, T>;
+ type ModelContext<'a, T> = ModelContext<'a, T>;
type Result<T> = T;
/// Build an entity that is owned by the application. The given function will be invoked with
- /// a `ModelContext` and must return an object representing the entity. A `Handle` will be returned
+ /// a `ModelContext` and must return an object representing the entity. A `Model` will be returned
/// which can be used to access the entity in a context.
- fn entity<T: 'static + Send>(
+ fn build_model<T: 'static + Send>(
&mut self,
- build_entity: impl FnOnce(&mut Self::EntityContext<'_, T>) -> T,
- ) -> Handle<T> {
+ build_model: impl FnOnce(&mut Self::ModelContext<'_, T>) -> T,
+ ) -> Model<T> {
self.update(|cx| {
let slot = cx.entities.reserve();
- let entity = build_entity(&mut ModelContext::mutable(cx, slot.downgrade()));
+ let entity = build_model(&mut ModelContext::mutable(cx, slot.downgrade()));
cx.entities.insert(slot, entity)
})
}
- /// Update the entity referenced by the given handle. The function is passed a mutable reference to the
+ /// Update the entity referenced by the given model. The function is passed a mutable reference to the
/// entity along with a `ModelContext` for the entity.
fn update_entity<T: 'static, R>(
&mut self,
- handle: &Handle<T>,
- update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, T>) -> R,
+ model: &Model<T>,
+ update: impl FnOnce(&mut T, &mut Self::ModelContext<'_, T>) -> R,
) -> R {
self.update(|cx| {
- let mut entity = cx.entities.lease(handle);
+ let mut entity = cx.entities.lease(model);
let result = update(
&mut entity,
- &mut ModelContext::mutable(cx, handle.downgrade()),
+ &mut ModelContext::mutable(cx, model.downgrade()),
);
cx.entities.end_lease(entity);
result
@@ -861,10 +868,17 @@ impl MainThread<AppContext> {
update: impl FnOnce(&mut V, &mut MainThread<ViewContext<'_, '_, V>>) -> R,
) -> Result<R>
where
- V: 'static,
+ V: 'static + Send,
{
self.update_window(handle.any_handle, |cx| {
- let root_view = cx.window.root_view.as_ref().unwrap().downcast().unwrap();
+ let root_view = cx
+ .window
+ .root_view
+ .as_ref()
+ .unwrap()
+ .clone()
+ .downcast()
+ .unwrap();
root_view.update(cx, update)
})
}
@@ -872,7 +886,7 @@ impl MainThread<AppContext> {
/// Opens a new window with the given option and the root view returned by the given function.
/// The function is invoked with a `WindowContext`, which can be used to interact with window-specific
/// functionality.
- pub fn open_window<V: 'static>(
+ pub fn open_window<V: Render>(
&mut self,
options: crate::WindowOptions,
build_root_view: impl FnOnce(&mut WindowContext) -> View<V> + Send + 'static,
@@ -955,10 +969,8 @@ impl<G: 'static> DerefMut for GlobalLease<G> {
/// Contains state associated with an active drag operation, started by dragging an element
/// within the window or by dragging into the app from the underlying platform.
pub(crate) struct AnyDrag {
- pub drag_handle_view: Option<AnyView>,
+ pub view: AnyView,
pub cursor_offset: Point<Pixels>,
- pub state: AnyBox,
- pub state_type: TypeId,
}
#[cfg(test)]
@@ -1,6 +1,6 @@
use crate::{
- AnyWindowHandle, AppContext, Component, Context, Executor, Handle, MainThread, ModelContext,
- Result, Task, View, ViewContext, VisualContext, WindowContext, WindowHandle,
+ AnyWindowHandle, AppContext, Context, Executor, MainThread, Model, ModelContext, Result, Task,
+ View, ViewContext, VisualContext, WindowContext, WindowHandle,
};
use anyhow::Context as _;
use derive_more::{Deref, DerefMut};
@@ -14,25 +14,25 @@ pub struct AsyncAppContext {
}
impl Context for AsyncAppContext {
- type EntityContext<'a, T> = ModelContext<'a, T>;
+ type ModelContext<'a, T> = ModelContext<'a, T>;
type Result<T> = Result<T>;
- fn entity<T: 'static>(
+ fn build_model<T: 'static>(
&mut self,
- build_entity: impl FnOnce(&mut Self::EntityContext<'_, T>) -> T,
- ) -> Self::Result<Handle<T>>
+ build_model: impl FnOnce(&mut Self::ModelContext<'_, T>) -> T,
+ ) -> Self::Result<Model<T>>
where
T: 'static + Send,
{
let app = self.app.upgrade().context("app was released")?;
let mut lock = app.lock(); // Need this to compile
- Ok(lock.entity(build_entity))
+ Ok(lock.build_model(build_model))
}
fn update_entity<T: 'static, R>(
&mut self,
- handle: &Handle<T>,
- update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, T>) -> R,
+ handle: &Model<T>,
+ update: impl FnOnce(&mut T, &mut Self::ModelContext<'_, T>) -> R,
) -> Self::Result<R> {
let app = self.app.upgrade().context("app was released")?;
let mut lock = app.lock(); // Need this to compile
@@ -84,7 +84,7 @@ impl AsyncAppContext {
update: impl FnOnce(&mut V, &mut ViewContext<'_, '_, V>) -> R,
) -> Result<R>
where
- V: 'static,
+ V: 'static + Send,
{
let app = self.app.upgrade().context("app was released")?;
let mut app_context = app.lock();
@@ -234,24 +234,24 @@ impl AsyncWindowContext {
}
impl Context for AsyncWindowContext {
- type EntityContext<'a, T> = ModelContext<'a, T>;
+ type ModelContext<'a, T> = ModelContext<'a, T>;
type Result<T> = Result<T>;
- fn entity<T>(
+ fn build_model<T>(
&mut self,
- build_entity: impl FnOnce(&mut Self::EntityContext<'_, T>) -> T,
- ) -> Result<Handle<T>>
+ build_model: impl FnOnce(&mut Self::ModelContext<'_, T>) -> T,
+ ) -> Result<Model<T>>
where
T: 'static + Send,
{
self.app
- .update_window(self.window, |cx| cx.entity(build_entity))
+ .update_window(self.window, |cx| cx.build_model(build_model))
}
fn update_entity<T: 'static, R>(
&mut self,
- handle: &Handle<T>,
- update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, T>) -> R,
+ handle: &Model<T>,
+ update: impl FnOnce(&mut T, &mut Self::ModelContext<'_, T>) -> R,
) -> Result<R> {
self.app
.update_window(self.window, |cx| cx.update_entity(handle, update))
@@ -261,17 +261,15 @@ impl Context for AsyncWindowContext {
impl VisualContext for AsyncWindowContext {
type ViewContext<'a, 'w, V> = ViewContext<'a, 'w, V>;
- fn build_view<E, V>(
+ fn build_view<V>(
&mut self,
- build_entity: impl FnOnce(&mut Self::ViewContext<'_, '_, V>) -> V,
- render: impl Fn(&mut V, &mut ViewContext<'_, '_, V>) -> E + Send + 'static,
+ build_view_state: impl FnOnce(&mut Self::ViewContext<'_, '_, V>) -> V,
) -> Self::Result<View<V>>
where
- E: Component<V>,
V: 'static + Send,
{
self.app
- .update_window(self.window, |cx| cx.build_view(build_entity, render))
+ .update_window(self.window, |cx| cx.build_view(build_view_state))
}
fn update_view<V: 'static, R>(
@@ -1,4 +1,4 @@
-use crate::{AnyBox, AppContext, Context, EntityHandle};
+use crate::{AnyBox, AppContext, Context};
use anyhow::{anyhow, Result};
use derive_more::{Deref, DerefMut};
use parking_lot::{RwLock, RwLockUpgradableReadGuard};
@@ -53,29 +53,29 @@ impl EntityMap {
/// Reserve a slot for an entity, which you can subsequently use with `insert`.
pub fn reserve<T: 'static>(&self) -> Slot<T> {
let id = self.ref_counts.write().counts.insert(1.into());
- Slot(Handle::new(id, Arc::downgrade(&self.ref_counts)))
+ Slot(Model::new(id, Arc::downgrade(&self.ref_counts)))
}
/// Insert an entity into a slot obtained by calling `reserve`.
- pub fn insert<T>(&mut self, slot: Slot<T>, entity: T) -> Handle<T>
+ pub fn insert<T>(&mut self, slot: Slot<T>, entity: T) -> Model<T>
where
T: 'static + Send,
{
- let handle = slot.0;
- self.entities.insert(handle.entity_id, Box::new(entity));
- handle
+ let model = slot.0;
+ self.entities.insert(model.entity_id, Box::new(entity));
+ model
}
/// Move an entity to the stack.
- pub fn lease<'a, T>(&mut self, handle: &'a Handle<T>) -> Lease<'a, T> {
- self.assert_valid_context(handle);
+ pub fn lease<'a, T>(&mut self, model: &'a Model<T>) -> Lease<'a, T> {
+ self.assert_valid_context(model);
let entity = Some(
self.entities
- .remove(handle.entity_id)
+ .remove(model.entity_id)
.expect("Circular entity lease. Is the entity already being updated?"),
);
Lease {
- handle,
+ model,
entity,
entity_type: PhantomData,
}
@@ -84,18 +84,18 @@ impl EntityMap {
/// Return an entity after moving it to the stack.
pub fn end_lease<T>(&mut self, mut lease: Lease<T>) {
self.entities
- .insert(lease.handle.entity_id, lease.entity.take().unwrap());
+ .insert(lease.model.entity_id, lease.entity.take().unwrap());
}
- pub fn read<T: 'static>(&self, handle: &Handle<T>) -> &T {
- self.assert_valid_context(handle);
- self.entities[handle.entity_id].downcast_ref().unwrap()
+ pub fn read<T: 'static>(&self, model: &Model<T>) -> &T {
+ self.assert_valid_context(model);
+ self.entities[model.entity_id].downcast_ref().unwrap()
}
- fn assert_valid_context(&self, handle: &AnyHandle) {
+ fn assert_valid_context(&self, model: &AnyModel) {
debug_assert!(
- Weak::ptr_eq(&handle.entity_map, &Arc::downgrade(&self.ref_counts)),
- "used a handle with the wrong context"
+ Weak::ptr_eq(&model.entity_map, &Arc::downgrade(&self.ref_counts)),
+ "used a model with the wrong context"
);
}
@@ -115,7 +115,7 @@ impl EntityMap {
pub struct Lease<'a, T> {
entity: Option<AnyBox>,
- pub handle: &'a Handle<T>,
+ pub model: &'a Model<T>,
entity_type: PhantomData<T>,
}
@@ -143,15 +143,15 @@ impl<'a, T> Drop for Lease<'a, T> {
}
#[derive(Deref, DerefMut)]
-pub struct Slot<T>(Handle<T>);
+pub struct Slot<T>(Model<T>);
-pub struct AnyHandle {
+pub struct AnyModel {
pub(crate) entity_id: EntityId,
- entity_type: TypeId,
+ pub(crate) entity_type: TypeId,
entity_map: Weak<RwLock<EntityRefCounts>>,
}
-impl AnyHandle {
+impl AnyModel {
fn new(id: EntityId, entity_type: TypeId, entity_map: Weak<RwLock<EntityRefCounts>>) -> Self {
Self {
entity_id: id,
@@ -164,18 +164,18 @@ impl AnyHandle {
self.entity_id
}
- pub fn downgrade(&self) -> AnyWeakHandle {
- AnyWeakHandle {
+ pub fn downgrade(&self) -> AnyWeakModel {
+ AnyWeakModel {
entity_id: self.entity_id,
entity_type: self.entity_type,
entity_ref_counts: self.entity_map.clone(),
}
}
- pub fn downcast<T: 'static>(&self) -> Option<Handle<T>> {
+ pub fn downcast<T: 'static>(&self) -> Option<Model<T>> {
if TypeId::of::<T>() == self.entity_type {
- Some(Handle {
- any_handle: self.clone(),
+ Some(Model {
+ any_model: self.clone(),
entity_type: PhantomData,
})
} else {
@@ -184,16 +184,16 @@ impl AnyHandle {
}
}
-impl Clone for AnyHandle {
+impl Clone for AnyModel {
fn clone(&self) -> Self {
if let Some(entity_map) = self.entity_map.upgrade() {
let entity_map = entity_map.read();
let count = entity_map
.counts
.get(self.entity_id)
- .expect("detected over-release of a handle");
+ .expect("detected over-release of a model");
let prev_count = count.fetch_add(1, SeqCst);
- assert_ne!(prev_count, 0, "Detected over-release of a handle.");
+ assert_ne!(prev_count, 0, "Detected over-release of a model.");
}
Self {
@@ -204,16 +204,16 @@ impl Clone for AnyHandle {
}
}
-impl Drop for AnyHandle {
+impl Drop for AnyModel {
fn drop(&mut self) {
if let Some(entity_map) = self.entity_map.upgrade() {
let entity_map = entity_map.upgradable_read();
let count = entity_map
.counts
.get(self.entity_id)
- .expect("Detected over-release of a handle.");
+ .expect("Detected over-release of a model.");
let prev_count = count.fetch_sub(1, SeqCst);
- assert_ne!(prev_count, 0, "Detected over-release of a handle.");
+ assert_ne!(prev_count, 0, "Detected over-release of a model.");
if prev_count == 1 {
// We were the last reference to this entity, so we can remove it.
let mut entity_map = RwLockUpgradableReadGuard::upgrade(entity_map);
@@ -223,60 +223,65 @@ impl Drop for AnyHandle {
}
}
-impl<T> From<Handle<T>> for AnyHandle {
- fn from(handle: Handle<T>) -> Self {
- handle.any_handle
+impl<T> From<Model<T>> for AnyModel {
+ fn from(model: Model<T>) -> Self {
+ model.any_model
}
}
-impl Hash for AnyHandle {
+impl Hash for AnyModel {
fn hash<H: Hasher>(&self, state: &mut H) {
self.entity_id.hash(state);
}
}
-impl PartialEq for AnyHandle {
+impl PartialEq for AnyModel {
fn eq(&self, other: &Self) -> bool {
self.entity_id == other.entity_id
}
}
-impl Eq for AnyHandle {}
+impl Eq for AnyModel {}
#[derive(Deref, DerefMut)]
-pub struct Handle<T> {
+pub struct Model<T> {
#[deref]
#[deref_mut]
- any_handle: AnyHandle,
- entity_type: PhantomData<T>,
+ pub(crate) any_model: AnyModel,
+ pub(crate) entity_type: PhantomData<T>,
}
-unsafe impl<T> Send for Handle<T> {}
-unsafe impl<T> Sync for Handle<T> {}
+unsafe impl<T> Send for Model<T> {}
+unsafe impl<T> Sync for Model<T> {}
-impl<T: 'static> Handle<T> {
+impl<T: 'static> Model<T> {
fn new(id: EntityId, entity_map: Weak<RwLock<EntityRefCounts>>) -> Self
where
T: 'static,
{
Self {
- any_handle: AnyHandle::new(id, TypeId::of::<T>(), entity_map),
+ any_model: AnyModel::new(id, TypeId::of::<T>(), entity_map),
entity_type: PhantomData,
}
}
- pub fn downgrade(&self) -> WeakHandle<T> {
- WeakHandle {
- any_handle: self.any_handle.downgrade(),
+ pub fn downgrade(&self) -> WeakModel<T> {
+ WeakModel {
+ any_model: self.any_model.downgrade(),
entity_type: self.entity_type,
}
}
+ /// Convert this into a dynamically typed model.
+ pub fn into_any(self) -> AnyModel {
+ self.any_model
+ }
+
pub fn read<'a>(&self, cx: &'a AppContext) -> &'a T {
cx.entities.read(self)
}
- /// Update the entity referenced by this handle with the given function.
+ /// Update the entity referenced by this model with the given function.
///
/// The update function receives a context appropriate for its environment.
/// When updating in an `AppContext`, it receives a `ModelContext`.
@@ -284,7 +289,7 @@ impl<T: 'static> Handle<T> {
pub fn update<C, R>(
&self,
cx: &mut C,
- update: impl FnOnce(&mut T, &mut C::EntityContext<'_, T>) -> R,
+ update: impl FnOnce(&mut T, &mut C::ModelContext<'_, T>) -> R,
) -> C::Result<R>
where
C: Context,
@@ -293,73 +298,54 @@ impl<T: 'static> Handle<T> {
}
}
-impl<T> Clone for Handle<T> {
+impl<T> Clone for Model<T> {
fn clone(&self) -> Self {
Self {
- any_handle: self.any_handle.clone(),
+ any_model: self.any_model.clone(),
entity_type: self.entity_type,
}
}
}
-impl<T> std::fmt::Debug for Handle<T> {
+impl<T> std::fmt::Debug for Model<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
- "Handle {{ entity_id: {:?}, entity_type: {:?} }}",
- self.any_handle.entity_id,
+ "Model {{ entity_id: {:?}, entity_type: {:?} }}",
+ self.any_model.entity_id,
type_name::<T>()
)
}
}
-impl<T> Hash for Handle<T> {
+impl<T> Hash for Model<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
- self.any_handle.hash(state);
+ self.any_model.hash(state);
}
}
-impl<T> PartialEq for Handle<T> {
+impl<T> PartialEq for Model<T> {
fn eq(&self, other: &Self) -> bool {
- self.any_handle == other.any_handle
+ self.any_model == other.any_model
}
}
-impl<T> Eq for Handle<T> {}
+impl<T> Eq for Model<T> {}
-impl<T> PartialEq<WeakHandle<T>> for Handle<T> {
- fn eq(&self, other: &WeakHandle<T>) -> bool {
- self.entity_id == other.entity_id
- }
-}
-
-impl<T: 'static> EntityHandle<T> for Handle<T> {
- type Weak = WeakHandle<T>;
-
- fn entity_id(&self) -> EntityId {
- self.entity_id
- }
-
- fn downgrade(&self) -> Self::Weak {
- self.downgrade()
- }
-
- fn upgrade_from(weak: &Self::Weak) -> Option<Self>
- where
- Self: Sized,
- {
- weak.upgrade()
+impl<T> PartialEq<WeakModel<T>> for Model<T> {
+ fn eq(&self, other: &WeakModel<T>) -> bool {
+ self.entity_id() == other.entity_id()
}
}
#[derive(Clone)]
-pub struct AnyWeakHandle {
+pub struct AnyWeakModel {
pub(crate) entity_id: EntityId,
entity_type: TypeId,
entity_ref_counts: Weak<RwLock<EntityRefCounts>>,
}
-impl AnyWeakHandle {
+impl AnyWeakModel {
pub fn entity_id(&self) -> EntityId {
self.entity_id
}
@@ -373,14 +359,14 @@ impl AnyWeakHandle {
ref_count > 0
}
- pub fn upgrade(&self) -> Option<AnyHandle> {
+ pub fn upgrade(&self) -> Option<AnyModel> {
let entity_map = self.entity_ref_counts.upgrade()?;
entity_map
.read()
.counts
.get(self.entity_id)?
.fetch_add(1, SeqCst);
- Some(AnyHandle {
+ Some(AnyModel {
entity_id: self.entity_id,
entity_type: self.entity_type,
entity_map: self.entity_ref_counts.clone(),
@@ -388,55 +374,55 @@ impl AnyWeakHandle {
}
}
-impl<T> From<WeakHandle<T>> for AnyWeakHandle {
- fn from(handle: WeakHandle<T>) -> Self {
- handle.any_handle
+impl<T> From<WeakModel<T>> for AnyWeakModel {
+ fn from(model: WeakModel<T>) -> Self {
+ model.any_model
}
}
-impl Hash for AnyWeakHandle {
+impl Hash for AnyWeakModel {
fn hash<H: Hasher>(&self, state: &mut H) {
self.entity_id.hash(state);
}
}
-impl PartialEq for AnyWeakHandle {
+impl PartialEq for AnyWeakModel {
fn eq(&self, other: &Self) -> bool {
self.entity_id == other.entity_id
}
}
-impl Eq for AnyWeakHandle {}
+impl Eq for AnyWeakModel {}
#[derive(Deref, DerefMut)]
-pub struct WeakHandle<T> {
+pub struct WeakModel<T> {
#[deref]
#[deref_mut]
- any_handle: AnyWeakHandle,
+ any_model: AnyWeakModel,
entity_type: PhantomData<T>,
}
-unsafe impl<T> Send for WeakHandle<T> {}
-unsafe impl<T> Sync for WeakHandle<T> {}
+unsafe impl<T> Send for WeakModel<T> {}
+unsafe impl<T> Sync for WeakModel<T> {}
-impl<T> Clone for WeakHandle<T> {
+impl<T> Clone for WeakModel<T> {
fn clone(&self) -> Self {
Self {
- any_handle: self.any_handle.clone(),
+ any_model: self.any_model.clone(),
entity_type: self.entity_type,
}
}
}
-impl<T: 'static> WeakHandle<T> {
- pub fn upgrade(&self) -> Option<Handle<T>> {
- Some(Handle {
- any_handle: self.any_handle.upgrade()?,
+impl<T: 'static> WeakModel<T> {
+ pub fn upgrade(&self) -> Option<Model<T>> {
+ Some(Model {
+ any_model: self.any_model.upgrade()?,
entity_type: self.entity_type,
})
}
- /// Update the entity referenced by this handle with the given function if
+ /// Update the entity referenced by this model with the given function if
/// the referenced entity still exists. Returns an error if the entity has
/// been released.
///
@@ -446,7 +432,7 @@ impl<T: 'static> WeakHandle<T> {
pub fn update<C, R>(
&self,
cx: &mut C,
- update: impl FnOnce(&mut T, &mut C::EntityContext<'_, T>) -> R,
+ update: impl FnOnce(&mut T, &mut C::ModelContext<'_, T>) -> R,
) -> Result<R>
where
C: Context,
@@ -460,22 +446,22 @@ impl<T: 'static> WeakHandle<T> {
}
}
-impl<T> Hash for WeakHandle<T> {
+impl<T> Hash for WeakModel<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
- self.any_handle.hash(state);
+ self.any_model.hash(state);
}
}
-impl<T> PartialEq for WeakHandle<T> {
+impl<T> PartialEq for WeakModel<T> {
fn eq(&self, other: &Self) -> bool {
- self.any_handle == other.any_handle
+ self.any_model == other.any_model
}
}
-impl<T> Eq for WeakHandle<T> {}
+impl<T> Eq for WeakModel<T> {}
-impl<T> PartialEq<Handle<T>> for WeakHandle<T> {
- fn eq(&self, other: &Handle<T>) -> bool {
- self.entity_id == other.entity_id
+impl<T> PartialEq<Model<T>> for WeakModel<T> {
+ fn eq(&self, other: &Model<T>) -> bool {
+ self.entity_id() == other.entity_id()
}
}
@@ -1,6 +1,6 @@
use crate::{
- AppContext, AsyncAppContext, Context, Effect, EntityId, EventEmitter, Handle, MainThread,
- Reference, Subscription, Task, WeakHandle,
+ AppContext, AsyncAppContext, Context, Effect, EntityId, EventEmitter, MainThread, Model,
+ Reference, Subscription, Task, WeakModel,
};
use derive_more::{Deref, DerefMut};
use futures::FutureExt;
@@ -15,11 +15,11 @@ pub struct ModelContext<'a, T> {
#[deref]
#[deref_mut]
app: Reference<'a, AppContext>,
- model_state: WeakHandle<T>,
+ model_state: WeakModel<T>,
}
impl<'a, T: 'static> ModelContext<'a, T> {
- pub(crate) fn mutable(app: &'a mut AppContext, model_state: WeakHandle<T>) -> Self {
+ pub(crate) fn mutable(app: &'a mut AppContext, model_state: WeakModel<T>) -> Self {
Self {
app: Reference::Mutable(app),
model_state,
@@ -30,20 +30,20 @@ impl<'a, T: 'static> ModelContext<'a, T> {
self.model_state.entity_id
}
- pub fn handle(&self) -> Handle<T> {
+ pub fn handle(&self) -> Model<T> {
self.weak_handle()
.upgrade()
.expect("The entity must be alive if we have a model context")
}
- pub fn weak_handle(&self) -> WeakHandle<T> {
+ pub fn weak_handle(&self) -> WeakModel<T> {
self.model_state.clone()
}
pub fn observe<T2: 'static>(
&mut self,
- handle: &Handle<T2>,
- mut on_notify: impl FnMut(&mut T, Handle<T2>, &mut ModelContext<'_, T>) + Send + 'static,
+ handle: &Model<T2>,
+ mut on_notify: impl FnMut(&mut T, Model<T2>, &mut ModelContext<'_, T>) + Send + 'static,
) -> Subscription
where
T: 'static + Send,
@@ -65,10 +65,8 @@ impl<'a, T: 'static> ModelContext<'a, T> {
pub fn subscribe<E: 'static + EventEmitter>(
&mut self,
- handle: &Handle<E>,
- mut on_event: impl FnMut(&mut T, Handle<E>, &E::Event, &mut ModelContext<'_, T>)
- + Send
- + 'static,
+ handle: &Model<E>,
+ mut on_event: impl FnMut(&mut T, Model<E>, &E::Event, &mut ModelContext<'_, T>) + Send + 'static,
) -> Subscription
where
T: 'static + Send,
@@ -107,7 +105,7 @@ impl<'a, T: 'static> ModelContext<'a, T> {
pub fn observe_release<E: 'static>(
&mut self,
- handle: &Handle<E>,
+ handle: &Model<E>,
mut on_release: impl FnMut(&mut T, &mut E, &mut ModelContext<'_, T>) + Send + 'static,
) -> Subscription
where
@@ -182,7 +180,7 @@ impl<'a, T: 'static> ModelContext<'a, T> {
pub fn spawn<Fut, R>(
&self,
- f: impl FnOnce(WeakHandle<T>, AsyncAppContext) -> Fut + Send + 'static,
+ f: impl FnOnce(WeakModel<T>, AsyncAppContext) -> Fut + Send + 'static,
) -> Task<R>
where
T: 'static,
@@ -195,7 +193,7 @@ impl<'a, T: 'static> ModelContext<'a, T> {
pub fn spawn_on_main<Fut, R>(
&self,
- f: impl FnOnce(WeakHandle<T>, MainThread<AsyncAppContext>) -> Fut + Send + 'static,
+ f: impl FnOnce(WeakModel<T>, MainThread<AsyncAppContext>) -> Fut + Send + 'static,
) -> Task<R>
where
Fut: Future<Output = R> + 'static,
@@ -220,23 +218,23 @@ where
}
impl<'a, T> Context for ModelContext<'a, T> {
- type EntityContext<'b, U> = ModelContext<'b, U>;
+ type ModelContext<'b, U> = ModelContext<'b, U>;
type Result<U> = U;
- fn entity<U>(
+ fn build_model<U>(
&mut self,
- build_entity: impl FnOnce(&mut Self::EntityContext<'_, U>) -> U,
- ) -> Handle<U>
+ build_model: impl FnOnce(&mut Self::ModelContext<'_, U>) -> U,
+ ) -> Model<U>
where
U: 'static + Send,
{
- self.app.entity(build_entity)
+ self.app.build_model(build_model)
}
fn update_entity<U: 'static, R>(
&mut self,
- handle: &Handle<U>,
- update: impl FnOnce(&mut U, &mut Self::EntityContext<'_, U>) -> R,
+ handle: &Model<U>,
+ update: impl FnOnce(&mut U, &mut Self::ModelContext<'_, U>) -> R,
) -> R {
self.app.update_entity(handle, update)
}
@@ -1,5 +1,5 @@
use crate::{
- AnyWindowHandle, AppContext, AsyncAppContext, Context, Executor, Handle, MainThread,
+ AnyWindowHandle, AppContext, AsyncAppContext, Context, Executor, MainThread, Model,
ModelContext, Result, Task, TestDispatcher, TestPlatform, WindowContext,
};
use parking_lot::Mutex;
@@ -12,24 +12,24 @@ pub struct TestAppContext {
}
impl Context for TestAppContext {
- type EntityContext<'a, T> = ModelContext<'a, T>;
+ type ModelContext<'a, T> = ModelContext<'a, T>;
type Result<T> = T;
- fn entity<T: 'static>(
+ fn build_model<T: 'static>(
&mut self,
- build_entity: impl FnOnce(&mut Self::EntityContext<'_, T>) -> T,
- ) -> Self::Result<Handle<T>>
+ build_model: impl FnOnce(&mut Self::ModelContext<'_, T>) -> T,
+ ) -> Self::Result<Model<T>>
where
T: 'static + Send,
{
let mut lock = self.app.lock();
- lock.entity(build_entity)
+ lock.build_model(build_model)
}
fn update_entity<T: 'static, R>(
&mut self,
- handle: &Handle<T>,
- update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, T>) -> R,
+ handle: &Model<T>,
+ update: impl FnOnce(&mut T, &mut Self::ModelContext<'_, T>) -> R,
) -> Self::Result<R> {
let mut lock = self.app.lock();
lock.update_entity(handle, update)
@@ -4,7 +4,7 @@ pub(crate) use smallvec::SmallVec;
use std::{any::Any, mem};
pub trait Element<V: 'static> {
- type ElementState: 'static;
+ type ElementState: 'static + Send;
fn id(&self) -> Option<ElementId>;
@@ -70,33 +70,31 @@ use taffy::TaffyLayoutEngine;
type AnyBox = Box<dyn Any + Send>;
pub trait Context {
- type EntityContext<'a, T>;
+ type ModelContext<'a, T>;
type Result<T>;
- fn entity<T>(
+ fn build_model<T>(
&mut self,
- build_entity: impl FnOnce(&mut Self::EntityContext<'_, T>) -> T,
- ) -> Self::Result<Handle<T>>
+ build_model: impl FnOnce(&mut Self::ModelContext<'_, T>) -> T,
+ ) -> Self::Result<Model<T>>
where
T: 'static + Send;
fn update_entity<T: 'static, R>(
&mut self,
- handle: &Handle<T>,
- update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, T>) -> R,
+ handle: &Model<T>,
+ update: impl FnOnce(&mut T, &mut Self::ModelContext<'_, T>) -> R,
) -> Self::Result<R>;
}
pub trait VisualContext: Context {
type ViewContext<'a, 'w, V>;
- fn build_view<E, V>(
+ fn build_view<V>(
&mut self,
- build_entity: impl FnOnce(&mut Self::ViewContext<'_, '_, V>) -> V,
- render: impl Fn(&mut V, &mut ViewContext<'_, '_, V>) -> E + Send + 'static,
+ build_view_state: impl FnOnce(&mut Self::ViewContext<'_, '_, V>) -> V,
) -> Self::Result<View<V>>
where
- E: Component<V>,
V: 'static + Send;
fn update_view<V: 'static, R>(
@@ -140,37 +138,37 @@ impl<T> DerefMut for MainThread<T> {
}
impl<C: Context> Context for MainThread<C> {
- type EntityContext<'a, T> = MainThread<C::EntityContext<'a, T>>;
+ type ModelContext<'a, T> = MainThread<C::ModelContext<'a, T>>;
type Result<T> = C::Result<T>;
- fn entity<T>(
+ fn build_model<T>(
&mut self,
- build_entity: impl FnOnce(&mut Self::EntityContext<'_, T>) -> T,
- ) -> Self::Result<Handle<T>>
+ build_model: impl FnOnce(&mut Self::ModelContext<'_, T>) -> T,
+ ) -> Self::Result<Model<T>>
where
T: 'static + Send,
{
- self.0.entity(|cx| {
+ self.0.build_model(|cx| {
let cx = unsafe {
mem::transmute::<
- &mut C::EntityContext<'_, T>,
- &mut MainThread<C::EntityContext<'_, T>>,
+ &mut C::ModelContext<'_, T>,
+ &mut MainThread<C::ModelContext<'_, T>>,
>(cx)
};
- build_entity(cx)
+ build_model(cx)
})
}
fn update_entity<T: 'static, R>(
&mut self,
- handle: &Handle<T>,
- update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, T>) -> R,
+ handle: &Model<T>,
+ update: impl FnOnce(&mut T, &mut Self::ModelContext<'_, T>) -> R,
) -> Self::Result<R> {
self.0.update_entity(handle, |entity, cx| {
let cx = unsafe {
mem::transmute::<
- &mut C::EntityContext<'_, T>,
- &mut MainThread<C::EntityContext<'_, T>>,
+ &mut C::ModelContext<'_, T>,
+ &mut MainThread<C::ModelContext<'_, T>>,
>(cx)
};
update(entity, cx)
@@ -181,27 +179,22 @@ impl<C: Context> Context for MainThread<C> {
impl<C: VisualContext> VisualContext for MainThread<C> {
type ViewContext<'a, 'w, V> = MainThread<C::ViewContext<'a, 'w, V>>;
- fn build_view<E, V>(
+ fn build_view<V>(
&mut self,
- build_entity: impl FnOnce(&mut Self::ViewContext<'_, '_, V>) -> V,
- render: impl Fn(&mut V, &mut ViewContext<'_, '_, V>) -> E + Send + 'static,
+ build_view_state: impl FnOnce(&mut Self::ViewContext<'_, '_, V>) -> V,
) -> Self::Result<View<V>>
where
- E: Component<V>,
V: 'static + Send,
{
- self.0.build_view(
- |cx| {
- let cx = unsafe {
- mem::transmute::<
- &mut C::ViewContext<'_, '_, V>,
- &mut MainThread<C::ViewContext<'_, '_, V>>,
- >(cx)
- };
- build_entity(cx)
- },
- render,
- )
+ self.0.build_view(|cx| {
+ let cx = unsafe {
+ mem::transmute::<
+ &mut C::ViewContext<'_, '_, V>,
+ &mut MainThread<C::ViewContext<'_, '_, V>>,
+ >(cx)
+ };
+ build_view_state(cx)
+ })
}
fn update_view<V: 'static, R>(
@@ -1,7 +1,7 @@
use crate::{
- point, px, Action, AnyBox, AnyDrag, AppContext, BorrowWindow, Bounds, Component,
- DispatchContext, DispatchPhase, Element, ElementId, FocusHandle, KeyMatch, Keystroke,
- Modifiers, Overflow, Pixels, Point, SharedString, Size, Style, StyleRefinement, View,
+ div, point, px, Action, AnyDrag, AnyView, AppContext, BorrowWindow, Bounds, Component,
+ DispatchContext, DispatchPhase, Div, Element, ElementId, FocusHandle, KeyMatch, Keystroke,
+ Modifiers, Overflow, Pixels, Point, Render, SharedString, Size, Style, StyleRefinement, View,
ViewContext,
};
use collections::HashMap;
@@ -258,17 +258,17 @@ pub trait StatelessInteractive<V: 'static>: Element<V> {
self
}
- fn on_drop<S: 'static>(
+ fn on_drop<W: 'static + Send>(
mut self,
- listener: impl Fn(&mut V, S, &mut ViewContext<V>) + Send + 'static,
+ listener: impl Fn(&mut V, View<W>, &mut ViewContext<V>) + Send + 'static,
) -> Self
where
Self: Sized,
{
self.stateless_interaction().drop_listeners.push((
- TypeId::of::<S>(),
- Box::new(move |view, drag_state, cx| {
- listener(view, *drag_state.downcast().unwrap(), cx);
+ TypeId::of::<W>(),
+ Box::new(move |view, dragged_view, cx| {
+ listener(view, dragged_view.downcast().unwrap(), cx);
}),
));
self
@@ -314,36 +314,22 @@ pub trait StatefulInteractive<V: 'static>: StatelessInteractive<V> {
self
}
- fn on_drag<S, R, E>(
+ fn on_drag<W>(
mut self,
- listener: impl Fn(&mut V, &mut ViewContext<V>) -> Drag<S, R, V, E> + Send + 'static,
+ listener: impl Fn(&mut V, &mut ViewContext<V>) -> View<W> + Send + 'static,
) -> Self
where
Self: Sized,
- S: Any + Send,
- R: Fn(&mut V, &mut ViewContext<V>) -> E,
- R: 'static + Send,
- E: Component<V>,
+ W: 'static + Send + Render,
{
debug_assert!(
self.stateful_interaction().drag_listener.is_none(),
"calling on_drag more than once on the same element is not supported"
);
self.stateful_interaction().drag_listener =
- Some(Box::new(move |view_state, cursor_offset, cx| {
- let drag = listener(view_state, cx);
- let drag_handle_view = Some(
- View::for_handle(cx.handle().upgrade().unwrap(), move |view_state, cx| {
- (drag.render_drag_handle)(view_state, cx)
- })
- .into_any(),
- );
- AnyDrag {
- drag_handle_view,
- cursor_offset,
- state: Box::new(drag.state),
- state_type: TypeId::of::<S>(),
- }
+ Some(Box::new(move |view_state, cursor_offset, cx| AnyDrag {
+ view: listener(view_state, cx).into_any(),
+ cursor_offset,
}));
self
}
@@ -412,7 +398,7 @@ pub trait ElementInteraction<V: 'static>: 'static + Send {
if let Some(drag) = cx.active_drag.take() {
for (state_type, group_drag_style) in &self.as_stateless().group_drag_over_styles {
if let Some(group_bounds) = GroupBounds::get(&group_drag_style.group, cx) {
- if *state_type == drag.state_type
+ if *state_type == drag.view.entity_type()
&& group_bounds.contains_point(&mouse_position)
{
style.refine(&group_drag_style.style);
@@ -421,7 +407,8 @@ pub trait ElementInteraction<V: 'static>: 'static + Send {
}
for (state_type, drag_over_style) in &self.as_stateless().drag_over_styles {
- if *state_type == drag.state_type && bounds.contains_point(&mouse_position) {
+ if *state_type == drag.view.entity_type() && bounds.contains_point(&mouse_position)
+ {
style.refine(drag_over_style);
}
}
@@ -509,7 +496,7 @@ pub trait ElementInteraction<V: 'static>: 'static + Send {
cx.on_mouse_event(move |view, event: &MouseUpEvent, phase, cx| {
if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
if let Some(drag_state_type) =
- cx.active_drag.as_ref().map(|drag| drag.state_type)
+ cx.active_drag.as_ref().map(|drag| drag.view.entity_type())
{
for (drop_state_type, listener) in &drop_listeners {
if *drop_state_type == drag_state_type {
@@ -517,7 +504,7 @@ pub trait ElementInteraction<V: 'static>: 'static + Send {
.active_drag
.take()
.expect("checked for type drag state type above");
- listener(view, drag.state, cx);
+ listener(view, drag.view.clone(), cx);
cx.notify();
cx.stop_propagation();
}
@@ -685,7 +672,7 @@ impl<V> From<ElementId> for StatefulInteraction<V> {
}
}
-type DropListener<V> = dyn Fn(&mut V, AnyBox, &mut ViewContext<V>) + 'static + Send;
+type DropListener<V> = dyn Fn(&mut V, AnyView, &mut ViewContext<V>) + 'static + Send;
pub struct StatelessInteraction<V> {
pub dispatch_context: DispatchContext,
@@ -866,7 +853,7 @@ pub struct Drag<S, R, V, E>
where
R: Fn(&mut V, &mut ViewContext<V>) -> E,
V: 'static,
- E: Component<V>,
+ E: Component<()>,
{
pub state: S,
pub render_drag_handle: R,
@@ -877,7 +864,7 @@ impl<S, R, V, E> Drag<S, R, V, E>
where
R: Fn(&mut V, &mut ViewContext<V>) -> E,
V: 'static,
- E: Component<V>,
+ E: Component<()>,
{
pub fn new(state: S, render_drag_handle: R) -> Self {
Drag {
@@ -888,6 +875,10 @@ where
}
}
+// impl<S, R, V, E> Render for Drag<S, R, V, E> {
+// // fn render(&mut self, cx: ViewContext<Self>) ->
+// }
+
#[derive(Hash, PartialEq, Eq, Copy, Clone, Debug)]
pub enum MouseButton {
Left,
@@ -995,6 +986,14 @@ impl Deref for MouseExitEvent {
#[derive(Debug, Clone, Default)]
pub struct ExternalPaths(pub(crate) SmallVec<[PathBuf; 2]>);
+impl Render for ExternalPaths {
+ type Element = Div<Self>;
+
+ fn render(&mut self, _: &mut ViewContext<Self>) -> Self::Element {
+ div() // Intentionally left empty because the platform will render icons for the dragged files
+ }
+}
+
#[derive(Debug, Clone)]
pub enum FileDropEvent {
Entered {
@@ -1,45 +1,35 @@
use crate::{
- AnyBox, AnyElement, AppContext, AvailableSpace, BorrowWindow, Bounds, Component, Element,
- ElementId, EntityHandle, EntityId, Flatten, Handle, LayoutId, Pixels, Size, ViewContext,
- VisualContext, WeakHandle, WindowContext,
+ AnyBox, AnyElement, AnyModel, AppContext, AvailableSpace, BorrowWindow, Bounds, Component,
+ Element, ElementId, EntityHandle, EntityId, Flatten, LayoutId, Model, Pixels, Size,
+ ViewContext, VisualContext, WeakModel, WindowContext,
};
use anyhow::{Context, Result};
-use parking_lot::Mutex;
use std::{
- any::Any,
+ any::{Any, TypeId},
marker::PhantomData,
- sync::{Arc, Weak},
+ sync::Arc,
};
-pub struct View<V> {
- pub(crate) state: Handle<V>,
- render: Arc<Mutex<dyn Fn(&mut V, &mut ViewContext<V>) -> AnyElement<V> + Send + 'static>>,
+pub trait Render: 'static + Sized {
+ type Element: Element<Self> + 'static + Send;
+
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element;
}
-impl<V: 'static> View<V> {
- pub fn for_handle<E>(
- state: Handle<V>,
- render: impl Fn(&mut V, &mut ViewContext<'_, '_, V>) -> E + Send + 'static,
- ) -> View<V>
- where
- E: Component<V>,
- {
- View {
- state,
- render: Arc::new(Mutex::new(
- move |state: &mut V, cx: &mut ViewContext<'_, '_, V>| render(state, cx).render(),
- )),
- }
- }
+pub struct View<V> {
+ pub(crate) model: Model<V>,
+}
+impl<V: Render> View<V> {
pub fn into_any(self) -> AnyView {
AnyView(Arc::new(self))
}
+}
+impl<V: 'static> View<V> {
pub fn downgrade(&self) -> WeakView<V> {
WeakView {
- state: self.state.downgrade(),
- render: Arc::downgrade(&self.render),
+ model: self.model.downgrade(),
}
}
@@ -55,20 +45,19 @@ impl<V: 'static> View<V> {
}
pub fn read<'a>(&self, cx: &'a AppContext) -> &'a V {
- cx.entities.read(&self.state)
+ self.model.read(cx)
}
}
impl<V> Clone for View<V> {
fn clone(&self) -> Self {
Self {
- state: self.state.clone(),
- render: self.render.clone(),
+ model: self.model.clone(),
}
}
}
-impl<V: 'static, ParentViewState: 'static> Component<ParentViewState> for View<V> {
+impl<V: Render, ParentViewState: 'static> Component<ParentViewState> for View<V> {
fn render(self) -> AnyElement<ParentViewState> {
AnyElement::new(EraseViewState {
view: self,
@@ -77,11 +66,14 @@ impl<V: 'static, ParentViewState: 'static> Component<ParentViewState> for View<V
}
}
-impl<V: 'static> Element<()> for View<V> {
+impl<V> Element<()> for View<V>
+where
+ V: Render,
+{
type ElementState = AnyElement<V>;
- fn id(&self) -> Option<ElementId> {
- Some(ElementId::View(self.state.entity_id))
+ fn id(&self) -> Option<crate::ElementId> {
+ Some(ElementId::View(self.model.entity_id))
}
fn initialize(
@@ -91,7 +83,7 @@ impl<V: 'static> Element<()> for View<V> {
cx: &mut ViewContext<()>,
) -> Self::ElementState {
self.update(cx, |state, cx| {
- let mut any_element = (self.render.lock())(state, cx);
+ let mut any_element = AnyElement::new(state.render(cx));
any_element.initialize(state, cx);
any_element
})
@@ -121,7 +113,7 @@ impl<T: 'static> EntityHandle<T> for View<T> {
type Weak = WeakView<T>;
fn entity_id(&self) -> EntityId {
- self.state.entity_id
+ self.model.entity_id
}
fn downgrade(&self) -> Self::Weak {
@@ -137,15 +129,13 @@ impl<T: 'static> EntityHandle<T> for View<T> {
}
pub struct WeakView<V> {
- pub(crate) state: WeakHandle<V>,
- render: Weak<Mutex<dyn Fn(&mut V, &mut ViewContext<V>) -> AnyElement<V> + Send + 'static>>,
+ pub(crate) model: WeakModel<V>,
}
impl<V: 'static> WeakView<V> {
pub fn upgrade(&self) -> Option<View<V>> {
- let state = self.state.upgrade()?;
- let render = self.render.upgrade()?;
- Some(View { state, render })
+ let model = self.model.upgrade()?;
+ Some(View { model })
}
pub fn update<C, R>(
@@ -165,8 +155,7 @@ impl<V: 'static> WeakView<V> {
impl<V> Clone for WeakView<V> {
fn clone(&self) -> Self {
Self {
- state: self.state.clone(),
- render: self.render.clone(),
+ model: self.model.clone(),
}
}
}
@@ -178,13 +167,13 @@ struct EraseViewState<V, ParentV> {
unsafe impl<V, ParentV> Send for EraseViewState<V, ParentV> {}
-impl<V: 'static, ParentV: 'static> Component<ParentV> for EraseViewState<V, ParentV> {
+impl<V: Render, ParentV: 'static> Component<ParentV> for EraseViewState<V, ParentV> {
fn render(self) -> AnyElement<ParentV> {
AnyElement::new(self)
}
}
-impl<V: 'static, ParentV: 'static> Element<ParentV> for EraseViewState<V, ParentV> {
+impl<V: Render, ParentV: 'static> Element<ParentV> for EraseViewState<V, ParentV> {
type ElementState = AnyBox;
fn id(&self) -> Option<ElementId> {
@@ -221,30 +210,43 @@ impl<V: 'static, ParentV: 'static> Element<ParentV> for EraseViewState<V, Parent
}
trait ViewObject: Send + Sync {
+ fn entity_type(&self) -> TypeId;
fn entity_id(&self) -> EntityId;
+ fn model(&self) -> AnyModel;
fn initialize(&self, cx: &mut WindowContext) -> AnyBox;
fn layout(&self, element: &mut AnyBox, cx: &mut WindowContext) -> LayoutId;
fn paint(&self, bounds: Bounds<Pixels>, element: &mut AnyBox, cx: &mut WindowContext);
fn as_any(&self) -> &dyn Any;
}
-impl<V: 'static> ViewObject for View<V> {
+impl<V> ViewObject for View<V>
+where
+ V: Render,
+{
+ fn entity_type(&self) -> TypeId {
+ TypeId::of::<V>()
+ }
+
fn entity_id(&self) -> EntityId {
- self.state.entity_id
+ self.model.entity_id
+ }
+
+ fn model(&self) -> AnyModel {
+ self.model.clone().into_any()
}
fn initialize(&self, cx: &mut WindowContext) -> AnyBox {
- cx.with_element_id(self.state.entity_id, |_global_id, cx| {
+ cx.with_element_id(self.model.entity_id, |_global_id, cx| {
self.update(cx, |state, cx| {
- let mut any_element = Box::new((self.render.lock())(state, cx));
+ let mut any_element = Box::new(AnyElement::new(state.render(cx)));
any_element.initialize(state, cx);
- any_element as AnyBox
+ any_element
})
})
}
fn layout(&self, element: &mut AnyBox, cx: &mut WindowContext) -> LayoutId {
- cx.with_element_id(self.state.entity_id, |_global_id, cx| {
+ cx.with_element_id(self.model.entity_id, |_global_id, cx| {
self.update(cx, |state, cx| {
let element = element.downcast_mut::<AnyElement<V>>().unwrap();
element.layout(state, cx)
@@ -253,7 +255,7 @@ impl<V: 'static> ViewObject for View<V> {
}
fn paint(&self, _: Bounds<Pixels>, element: &mut AnyBox, cx: &mut WindowContext) {
- cx.with_element_id(self.state.entity_id, |_global_id, cx| {
+ cx.with_element_id(self.model.entity_id, |_global_id, cx| {
self.update(cx, |state, cx| {
let element = element.downcast_mut::<AnyElement<V>>().unwrap();
element.paint(state, cx);
@@ -270,8 +272,12 @@ impl<V: 'static> ViewObject for View<V> {
pub struct AnyView(Arc<dyn ViewObject>);
impl AnyView {
- pub fn downcast<V: 'static>(&self) -> Option<View<V>> {
- self.0.as_any().downcast_ref().cloned()
+ pub fn downcast<V: 'static + Send>(self) -> Option<View<V>> {
+ self.0.model().downcast().map(|model| View { model })
+ }
+
+ pub(crate) fn entity_type(&self) -> TypeId {
+ self.0.entity_type()
}
pub(crate) fn draw(&self, available_space: Size<AvailableSpace>, cx: &mut WindowContext) {
@@ -343,6 +349,18 @@ impl<ParentV: 'static> Component<ParentV> for EraseAnyViewState<ParentV> {
}
}
+impl<T, E> Render for T
+where
+ T: 'static + FnMut(&mut WindowContext) -> E,
+ E: 'static + Send + Element<T>,
+{
+ type Element = E;
+
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
+ (self)(cx)
+ }
+}
+
impl<ParentV: 'static> Element<ParentV> for EraseAnyViewState<ParentV> {
type ElementState = AnyBox;
@@ -1,14 +1,14 @@
use crate::{
px, size, Action, AnyBox, AnyDrag, AnyView, AppContext, AsyncWindowContext, AvailableSpace,
Bounds, BoxShadow, Context, Corners, DevicePixels, DispatchContext, DisplayId, Edges, Effect,
- EntityHandle, EntityId, EventEmitter, ExternalPaths, FileDropEvent, FocusEvent, FontId,
- GlobalElementId, GlyphId, Handle, Hsla, ImageData, InputEvent, IsZero, KeyListener, KeyMatch,
- KeyMatcher, Keystroke, LayoutId, MainThread, MainThreadOnly, ModelContext, Modifiers,
- MonochromeSprite, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, Path, Pixels,
- PlatformAtlas, PlatformWindow, Point, PolychromeSprite, Quad, Reference, RenderGlyphParams,
- RenderImageParams, RenderSvgParams, ScaledPixels, SceneBuilder, Shadow, SharedString, Size,
- Style, Subscription, TaffyLayoutEngine, Task, Underline, UnderlineStyle, View, VisualContext,
- WeakHandle, WeakView, WindowOptions, SUBPIXEL_VARIANTS,
+ EntityHandle, EntityId, EventEmitter, FileDropEvent, FocusEvent, FontId, GlobalElementId,
+ GlyphId, Hsla, ImageData, InputEvent, IsZero, KeyListener, KeyMatch, KeyMatcher, Keystroke,
+ LayoutId, MainThread, MainThreadOnly, Model, ModelContext, Modifiers, MonochromeSprite,
+ MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, Path, Pixels, PlatformAtlas,
+ PlatformWindow, Point, PolychromeSprite, Quad, Reference, RenderGlyphParams, RenderImageParams,
+ RenderSvgParams, ScaledPixels, SceneBuilder, Shadow, SharedString, Size, Style, Subscription,
+ TaffyLayoutEngine, Task, Underline, UnderlineStyle, View, VisualContext, WeakModel, WeakView,
+ WindowOptions, SUBPIXEL_VARIANTS,
};
use anyhow::Result;
use collections::HashMap;
@@ -918,15 +918,13 @@ impl<'a, 'w> WindowContext<'a, 'w> {
root_view.draw(available_space, cx);
});
- if let Some(mut active_drag) = self.app.active_drag.take() {
+ if let Some(active_drag) = self.app.active_drag.take() {
self.stack(1, |cx| {
let offset = cx.mouse_position() - active_drag.cursor_offset;
cx.with_element_offset(Some(offset), |cx| {
let available_space =
size(AvailableSpace::MinContent, AvailableSpace::MinContent);
- if let Some(drag_handle_view) = &mut active_drag.drag_handle_view {
- drag_handle_view.draw(available_space, cx);
- }
+ active_drag.view.draw(available_space, cx);
cx.active_drag = Some(active_drag);
});
});
@@ -994,12 +992,12 @@ impl<'a, 'w> WindowContext<'a, 'w> {
InputEvent::FileDrop(file_drop) => match file_drop {
FileDropEvent::Entered { position, files } => {
self.window.mouse_position = position;
- self.active_drag.get_or_insert_with(|| AnyDrag {
- drag_handle_view: None,
- cursor_offset: position,
- state: Box::new(files),
- state_type: TypeId::of::<ExternalPaths>(),
- });
+ if self.active_drag.is_none() {
+ self.active_drag = Some(AnyDrag {
+ view: self.build_view(|_| files).into_any(),
+ cursor_offset: position,
+ });
+ }
InputEvent::MouseDown(MouseDownEvent {
position,
button: MouseButton::Left,
@@ -1267,30 +1265,30 @@ impl<'a, 'w> WindowContext<'a, 'w> {
}
impl Context for WindowContext<'_, '_> {
- type EntityContext<'a, T> = ModelContext<'a, T>;
+ type ModelContext<'a, T> = ModelContext<'a, T>;
type Result<T> = T;
- fn entity<T>(
+ fn build_model<T>(
&mut self,
- build_entity: impl FnOnce(&mut Self::EntityContext<'_, T>) -> T,
- ) -> Handle<T>
+ build_model: impl FnOnce(&mut Self::ModelContext<'_, T>) -> T,
+ ) -> Model<T>
where
T: 'static + Send,
{
let slot = self.app.entities.reserve();
- let entity = build_entity(&mut ModelContext::mutable(&mut *self.app, slot.downgrade()));
- self.entities.insert(slot, entity)
+ let model = build_model(&mut ModelContext::mutable(&mut *self.app, slot.downgrade()));
+ self.entities.insert(slot, model)
}
fn update_entity<T: 'static, R>(
&mut self,
- handle: &Handle<T>,
- update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, T>) -> R,
+ model: &Model<T>,
+ update: impl FnOnce(&mut T, &mut Self::ModelContext<'_, T>) -> R,
) -> R {
- let mut entity = self.entities.lease(handle);
+ let mut entity = self.entities.lease(model);
let result = update(
&mut *entity,
- &mut ModelContext::mutable(&mut *self.app, handle.downgrade()),
+ &mut ModelContext::mutable(&mut *self.app, model.downgrade()),
);
self.entities.end_lease(entity);
result
@@ -1300,21 +1298,17 @@ impl Context for WindowContext<'_, '_> {
impl VisualContext for WindowContext<'_, '_> {
type ViewContext<'a, 'w, V> = ViewContext<'a, 'w, V>;
- /// Builds a new view in the current window. The first argument is a function that builds
- /// an entity representing the view's state. It is invoked with a `ViewContext` that provides
- /// entity-specific access to the window and application state during construction. The second
- /// argument is a render function that returns a component based on the view's state.
- fn build_view<E, V>(
+ fn build_view<V>(
&mut self,
build_view_state: impl FnOnce(&mut Self::ViewContext<'_, '_, V>) -> V,
- render: impl Fn(&mut V, &mut ViewContext<'_, '_, V>) -> E + Send + 'static,
) -> Self::Result<View<V>>
where
- E: crate::Component<V>,
V: 'static + Send,
{
let slot = self.app.entities.reserve();
- let view = View::for_handle(slot.clone(), render);
+ let view = View {
+ model: slot.clone(),
+ };
let mut cx = ViewContext::mutable(&mut *self.app, &mut *self.window, view.downgrade());
let entity = build_view_state(&mut cx);
self.entities.insert(slot, entity);
@@ -1327,7 +1321,7 @@ impl VisualContext for WindowContext<'_, '_> {
view: &View<T>,
update: impl FnOnce(&mut T, &mut Self::ViewContext<'_, '_, T>) -> R,
) -> Self::Result<R> {
- let mut lease = self.app.entities.lease(&view.state);
+ let mut lease = self.app.entities.lease(&view.model);
let mut cx = ViewContext::mutable(&mut *self.app, &mut *self.window, view.downgrade());
let result = update(&mut *lease, &mut cx);
cx.app.entities.end_lease(lease);
@@ -1582,8 +1576,8 @@ impl<'a, 'w, V: 'static> ViewContext<'a, 'w, V> {
self.view.clone()
}
- pub fn handle(&self) -> WeakHandle<V> {
- self.view.state.clone()
+ pub fn model(&self) -> WeakModel<V> {
+ self.view.model.clone()
}
pub fn stack<R>(&mut self, order: u32, f: impl FnOnce(&mut Self) -> R) -> R {
@@ -1603,8 +1597,8 @@ impl<'a, 'w, V: 'static> ViewContext<'a, 'w, V> {
pub fn observe<E>(
&mut self,
- handle: &Handle<E>,
- mut on_notify: impl FnMut(&mut V, Handle<E>, &mut ViewContext<'_, '_, V>) + Send + 'static,
+ handle: &Model<E>,
+ mut on_notify: impl FnMut(&mut V, Model<E>, &mut ViewContext<'_, '_, V>) + Send + 'static,
) -> Subscription
where
E: 'static,
@@ -1665,7 +1659,7 @@ impl<'a, 'w, V: 'static> ViewContext<'a, 'w, V> {
) -> Subscription {
let window_handle = self.window.handle;
self.app.release_listeners.insert(
- self.view.state.entity_id,
+ self.view.model.entity_id,
Box::new(move |this, cx| {
let this = this.downcast_mut().expect("invalid entity type");
// todo!("are we okay with silently swallowing the error?")
@@ -1676,7 +1670,7 @@ impl<'a, 'w, V: 'static> ViewContext<'a, 'w, V> {
pub fn observe_release<T: 'static>(
&mut self,
- handle: &Handle<T>,
+ handle: &Model<T>,
mut on_release: impl FnMut(&mut V, &mut T, &mut ViewContext<'_, '_, V>) + Send + 'static,
) -> Subscription
where
@@ -1698,7 +1692,7 @@ impl<'a, 'w, V: 'static> ViewContext<'a, 'w, V> {
pub fn notify(&mut self) {
self.window_cx.notify();
self.window_cx.app.push_effect(Effect::Notify {
- emitter: self.view.state.entity_id,
+ emitter: self.view.model.entity_id,
});
}
@@ -1878,7 +1872,7 @@ where
V::Event: Any + Send,
{
pub fn emit(&mut self, event: V::Event) {
- let emitter = self.view.state.entity_id;
+ let emitter = self.view.model.entity_id;
self.app.push_effect(Effect::Emit {
emitter,
event: Box::new(event),
@@ -1897,41 +1891,36 @@ impl<'a, 'w, V: 'static> MainThread<ViewContext<'a, 'w, V>> {
}
impl<'a, 'w, V> Context for ViewContext<'a, 'w, V> {
- type EntityContext<'b, U> = ModelContext<'b, U>;
+ type ModelContext<'b, U> = ModelContext<'b, U>;
type Result<U> = U;
- fn entity<T>(
+ fn build_model<T>(
&mut self,
- build_entity: impl FnOnce(&mut Self::EntityContext<'_, T>) -> T,
- ) -> Handle<T>
+ build_model: impl FnOnce(&mut Self::ModelContext<'_, T>) -> T,
+ ) -> Model<T>
where
T: 'static + Send,
{
- self.window_cx.entity(build_entity)
+ self.window_cx.build_model(build_model)
}
fn update_entity<T: 'static, R>(
&mut self,
- handle: &Handle<T>,
- update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, T>) -> R,
+ model: &Model<T>,
+ update: impl FnOnce(&mut T, &mut Self::ModelContext<'_, T>) -> R,
) -> R {
- self.window_cx.update_entity(handle, update)
+ self.window_cx.update_entity(model, update)
}
}
impl<V: 'static> VisualContext for ViewContext<'_, '_, V> {
type ViewContext<'a, 'w, V2> = ViewContext<'a, 'w, V2>;
- fn build_view<E, V2>(
+ fn build_view<W: 'static + Send>(
&mut self,
- build_entity: impl FnOnce(&mut Self::ViewContext<'_, '_, V2>) -> V2,
- render: impl Fn(&mut V2, &mut ViewContext<'_, '_, V2>) -> E + Send + 'static,
- ) -> Self::Result<View<V2>>
- where
- E: crate::Component<V2>,
- V2: 'static + Send,
- {
- self.window_cx.build_view(build_entity, render)
+ build_view: impl FnOnce(&mut Self::ViewContext<'_, '_, W>) -> W,
+ ) -> Self::Result<View<W>> {
+ self.window_cx.build_view(build_view)
}
fn update_view<V2: 'static, R>(
@@ -5,7 +5,7 @@ use crate::language_settings::{
use crate::Buffer;
use clock::ReplicaId;
use collections::BTreeMap;
-use gpui2::{AppContext, Handle};
+use gpui2::{AppContext, Model};
use gpui2::{Context, TestAppContext};
use indoc::indoc;
use proto::deserialize_operation;
@@ -42,7 +42,7 @@ fn init_logger() {
fn test_line_endings(cx: &mut gpui2::AppContext) {
init_settings(cx, |_| {});
- cx.entity(|cx| {
+ cx.build_model(|cx| {
let mut buffer = Buffer::new(0, cx.entity_id().as_u64(), "one\r\ntwo\rthree")
.with_language(Arc::new(rust_lang()), cx);
assert_eq!(buffer.text(), "one\ntwo\nthree");
@@ -138,8 +138,8 @@ fn test_edit_events(cx: &mut gpui2::AppContext) {
let buffer_1_events = Arc::new(Mutex::new(Vec::new()));
let buffer_2_events = Arc::new(Mutex::new(Vec::new()));
- let buffer1 = cx.entity(|cx| Buffer::new(0, cx.entity_id().as_u64(), "abcdef"));
- let buffer2 = cx.entity(|cx| Buffer::new(1, cx.entity_id().as_u64(), "abcdef"));
+ let buffer1 = cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "abcdef"));
+ let buffer2 = cx.build_model(|cx| Buffer::new(1, cx.entity_id().as_u64(), "abcdef"));
let buffer1_ops = Arc::new(Mutex::new(Vec::new()));
buffer1.update(cx, {
let buffer1_ops = buffer1_ops.clone();
@@ -218,7 +218,7 @@ fn test_edit_events(cx: &mut gpui2::AppContext) {
#[gpui2::test]
async fn test_apply_diff(cx: &mut TestAppContext) {
let text = "a\nbb\nccc\ndddd\neeeee\nffffff\n";
- let buffer = cx.entity(|cx| Buffer::new(0, cx.entity_id().as_u64(), text));
+ let buffer = cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), text));
let anchor = buffer.update(cx, |buffer, _| buffer.anchor_before(Point::new(3, 3)));
let text = "a\nccc\ndddd\nffffff\n";
@@ -250,7 +250,7 @@ async fn test_normalize_whitespace(cx: &mut gpui2::TestAppContext) {
]
.join("\n");
- let buffer = cx.entity(|cx| Buffer::new(0, cx.entity_id().as_u64(), text));
+ let buffer = cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), text));
// Spawn a task to format the buffer's whitespace.
// Pause so that the foratting task starts running.
@@ -314,7 +314,7 @@ async fn test_normalize_whitespace(cx: &mut gpui2::TestAppContext) {
#[gpui2::test]
async fn test_reparse(cx: &mut gpui2::TestAppContext) {
let text = "fn a() {}";
- let buffer = cx.entity(|cx| {
+ let buffer = cx.build_model(|cx| {
Buffer::new(0, cx.entity_id().as_u64(), text).with_language(Arc::new(rust_lang()), cx)
});
@@ -442,7 +442,7 @@ async fn test_reparse(cx: &mut gpui2::TestAppContext) {
#[gpui2::test]
async fn test_resetting_language(cx: &mut gpui2::TestAppContext) {
- let buffer = cx.entity(|cx| {
+ let buffer = cx.build_model(|cx| {
let mut buffer =
Buffer::new(0, cx.entity_id().as_u64(), "{}").with_language(Arc::new(rust_lang()), cx);
buffer.set_sync_parse_timeout(Duration::ZERO);
@@ -492,7 +492,7 @@ async fn test_outline(cx: &mut gpui2::TestAppContext) {
"#
.unindent();
- let buffer = cx.entity(|cx| {
+ let buffer = cx.build_model(|cx| {
Buffer::new(0, cx.entity_id().as_u64(), text).with_language(Arc::new(rust_lang()), cx)
});
let outline = buffer
@@ -578,7 +578,7 @@ async fn test_outline_nodes_with_newlines(cx: &mut gpui2::TestAppContext) {
"#
.unindent();
- let buffer = cx.entity(|cx| {
+ let buffer = cx.build_model(|cx| {
Buffer::new(0, cx.entity_id().as_u64(), text).with_language(Arc::new(rust_lang()), cx)
});
let outline = buffer
@@ -616,7 +616,7 @@ async fn test_outline_with_extra_context(cx: &mut gpui2::TestAppContext) {
"#
.unindent();
- let buffer = cx.entity(|cx| {
+ let buffer = cx.build_model(|cx| {
Buffer::new(0, cx.entity_id().as_u64(), text).with_language(Arc::new(language), cx)
});
let snapshot = buffer.update(cx, |buffer, _| buffer.snapshot());
@@ -660,7 +660,7 @@ async fn test_symbols_containing(cx: &mut gpui2::TestAppContext) {
"#
.unindent();
- let buffer = cx.entity(|cx| {
+ let buffer = cx.build_model(|cx| {
Buffer::new(0, cx.entity_id().as_u64(), text).with_language(Arc::new(rust_lang()), cx)
});
let snapshot = buffer.update(cx, |buffer, _| buffer.snapshot());
@@ -881,7 +881,7 @@ fn test_enclosing_bracket_ranges_where_brackets_are_not_outermost_children(cx: &
#[gpui2::test]
fn test_range_for_syntax_ancestor(cx: &mut AppContext) {
- cx.entity(|cx| {
+ cx.build_model(|cx| {
let text = "fn a() { b(|c| {}) }";
let buffer =
Buffer::new(0, cx.entity_id().as_u64(), text).with_language(Arc::new(rust_lang()), cx);
@@ -922,7 +922,7 @@ fn test_range_for_syntax_ancestor(cx: &mut AppContext) {
fn test_autoindent_with_soft_tabs(cx: &mut AppContext) {
init_settings(cx, |_| {});
- cx.entity(|cx| {
+ cx.build_model(|cx| {
let text = "fn a() {}";
let mut buffer =
Buffer::new(0, cx.entity_id().as_u64(), text).with_language(Arc::new(rust_lang()), cx);
@@ -965,7 +965,7 @@ fn test_autoindent_with_hard_tabs(cx: &mut AppContext) {
settings.defaults.hard_tabs = Some(true);
});
- cx.entity(|cx| {
+ cx.build_model(|cx| {
let text = "fn a() {}";
let mut buffer =
Buffer::new(0, cx.entity_id().as_u64(), text).with_language(Arc::new(rust_lang()), cx);
@@ -1006,7 +1006,7 @@ fn test_autoindent_with_hard_tabs(cx: &mut AppContext) {
fn test_autoindent_does_not_adjust_lines_with_unchanged_suggestion(cx: &mut AppContext) {
init_settings(cx, |_| {});
- cx.entity(|cx| {
+ cx.build_model(|cx| {
let entity_id = cx.entity_id();
let mut buffer = Buffer::new(
0,
@@ -1080,7 +1080,7 @@ fn test_autoindent_does_not_adjust_lines_with_unchanged_suggestion(cx: &mut AppC
buffer
});
- cx.entity(|cx| {
+ cx.build_model(|cx| {
eprintln!("second buffer: {:?}", cx.entity_id());
let mut buffer = Buffer::new(
@@ -1147,7 +1147,7 @@ fn test_autoindent_does_not_adjust_lines_with_unchanged_suggestion(cx: &mut AppC
fn test_autoindent_does_not_adjust_lines_within_newly_created_errors(cx: &mut AppContext) {
init_settings(cx, |_| {});
- cx.entity(|cx| {
+ cx.build_model(|cx| {
let mut buffer = Buffer::new(
0,
cx.entity_id().as_u64(),
@@ -1209,7 +1209,7 @@ fn test_autoindent_does_not_adjust_lines_within_newly_created_errors(cx: &mut Ap
fn test_autoindent_adjusts_lines_when_only_text_changes(cx: &mut AppContext) {
init_settings(cx, |_| {});
- cx.entity(|cx| {
+ cx.build_model(|cx| {
let mut buffer = Buffer::new(
0,
cx.entity_id().as_u64(),
@@ -1266,7 +1266,7 @@ fn test_autoindent_adjusts_lines_when_only_text_changes(cx: &mut AppContext) {
fn test_autoindent_with_edit_at_end_of_buffer(cx: &mut AppContext) {
init_settings(cx, |_| {});
- cx.entity(|cx| {
+ cx.build_model(|cx| {
let text = "a\nb";
let mut buffer =
Buffer::new(0, cx.entity_id().as_u64(), text).with_language(Arc::new(rust_lang()), cx);
@@ -1284,7 +1284,7 @@ fn test_autoindent_with_edit_at_end_of_buffer(cx: &mut AppContext) {
fn test_autoindent_multi_line_insertion(cx: &mut AppContext) {
init_settings(cx, |_| {});
- cx.entity(|cx| {
+ cx.build_model(|cx| {
let text = "
const a: usize = 1;
fn b() {
@@ -1326,7 +1326,7 @@ fn test_autoindent_multi_line_insertion(cx: &mut AppContext) {
fn test_autoindent_block_mode(cx: &mut AppContext) {
init_settings(cx, |_| {});
- cx.entity(|cx| {
+ cx.build_model(|cx| {
let text = r#"
fn a() {
b();
@@ -1410,7 +1410,7 @@ fn test_autoindent_block_mode(cx: &mut AppContext) {
fn test_autoindent_block_mode_without_original_indent_columns(cx: &mut AppContext) {
init_settings(cx, |_| {});
- cx.entity(|cx| {
+ cx.build_model(|cx| {
let text = r#"
fn a() {
if b() {
@@ -1490,7 +1490,7 @@ fn test_autoindent_block_mode_without_original_indent_columns(cx: &mut AppContex
fn test_autoindent_language_without_indents_query(cx: &mut AppContext) {
init_settings(cx, |_| {});
- cx.entity(|cx| {
+ cx.build_model(|cx| {
let text = "
* one
- a
@@ -1559,7 +1559,7 @@ fn test_autoindent_with_injected_languages(cx: &mut AppContext) {
language_registry.add(html_language.clone());
language_registry.add(javascript_language.clone());
- cx.entity(|cx| {
+ cx.build_model(|cx| {
let (text, ranges) = marked_text_ranges(
&"
<div>ˇ
@@ -1610,7 +1610,7 @@ fn test_autoindent_query_with_outdent_captures(cx: &mut AppContext) {
settings.defaults.tab_size = Some(2.try_into().unwrap());
});
- cx.entity(|cx| {
+ cx.build_model(|cx| {
let mut buffer =
Buffer::new(0, cx.entity_id().as_u64(), "").with_language(Arc::new(ruby_lang()), cx);
@@ -1653,7 +1653,7 @@ fn test_autoindent_query_with_outdent_captures(cx: &mut AppContext) {
fn test_language_scope_at_with_javascript(cx: &mut AppContext) {
init_settings(cx, |_| {});
- cx.entity(|cx| {
+ cx.build_model(|cx| {
let language = Language::new(
LanguageConfig {
name: "JavaScript".into(),
@@ -1742,7 +1742,7 @@ fn test_language_scope_at_with_javascript(cx: &mut AppContext) {
fn test_language_scope_at_with_rust(cx: &mut AppContext) {
init_settings(cx, |_| {});
- cx.entity(|cx| {
+ cx.build_model(|cx| {
let language = Language::new(
LanguageConfig {
name: "Rust".into(),
@@ -1810,7 +1810,7 @@ fn test_language_scope_at_with_rust(cx: &mut AppContext) {
fn test_language_scope_at_with_combined_injections(cx: &mut AppContext) {
init_settings(cx, |_| {});
- cx.entity(|cx| {
+ cx.build_model(|cx| {
let text = r#"
<ol>
<% people.each do |person| %>
@@ -1858,7 +1858,7 @@ fn test_language_scope_at_with_combined_injections(cx: &mut AppContext) {
fn test_serialization(cx: &mut gpui2::AppContext) {
let mut now = Instant::now();
- let buffer1 = cx.entity(|cx| {
+ let buffer1 = cx.build_model(|cx| {
let mut buffer = Buffer::new(0, cx.entity_id().as_u64(), "abc");
buffer.edit([(3..3, "D")], None, cx);
@@ -1881,7 +1881,7 @@ fn test_serialization(cx: &mut gpui2::AppContext) {
let ops = cx
.executor()
.block(buffer1.read(cx).serialize_ops(None, cx));
- let buffer2 = cx.entity(|cx| {
+ let buffer2 = cx.build_model(|cx| {
let mut buffer = Buffer::from_proto(1, state, None).unwrap();
buffer
.apply_ops(
@@ -1914,10 +1914,11 @@ fn test_random_collaboration(cx: &mut AppContext, mut rng: StdRng) {
let mut replica_ids = Vec::new();
let mut buffers = Vec::new();
let network = Arc::new(Mutex::new(Network::new(rng.clone())));
- let base_buffer = cx.entity(|cx| Buffer::new(0, cx.entity_id().as_u64(), base_text.as_str()));
+ let base_buffer =
+ cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), base_text.as_str()));
for i in 0..rng.gen_range(min_peers..=max_peers) {
- let buffer = cx.entity(|cx| {
+ let buffer = cx.build_model(|cx| {
let state = base_buffer.read(cx).to_proto();
let ops = cx
.executor()
@@ -2034,7 +2035,7 @@ fn test_random_collaboration(cx: &mut AppContext, mut rng: StdRng) {
new_replica_id,
replica_id
);
- new_buffer = Some(cx.entity(|cx| {
+ new_buffer = Some(cx.build_model(|cx| {
let mut new_buffer =
Buffer::from_proto(new_replica_id, old_buffer_state, None).unwrap();
new_buffer
@@ -2396,7 +2397,7 @@ fn javascript_lang() -> Language {
.unwrap()
}
-fn get_tree_sexp(buffer: &Handle<Buffer>, cx: &mut gpui2::TestAppContext) -> String {
+fn get_tree_sexp(buffer: &Model<Buffer>, cx: &mut gpui2::TestAppContext) -> String {
buffer.update(cx, |buffer, _| {
let snapshot = buffer.snapshot();
let layers = snapshot.syntax.layers(buffer.as_text_snapshot());
@@ -2412,7 +2413,7 @@ fn assert_bracket_pairs(
cx: &mut AppContext,
) {
let (expected_text, selection_ranges) = marked_text_ranges(selection_text, false);
- let buffer = cx.entity(|cx| {
+ let buffer = cx.build_model(|cx| {
Buffer::new(0, cx.entity_id().as_u64(), expected_text.clone())
.with_language(Arc::new(language), cx)
});
@@ -0,0 +1,12 @@
+[package]
+name = "menu2"
+version = "0.1.0"
+edition = "2021"
+publish = false
+
+[lib]
+path = "src/menu2.rs"
+doctest = false
+
+[dependencies]
+gpui2 = { path = "../gpui2" }
@@ -0,0 +1,25 @@
+// todo!(use actions! macro)
+
+#[derive(Clone, Debug, Default, PartialEq)]
+pub struct Cancel;
+
+#[derive(Clone, Debug, Default, PartialEq)]
+pub struct Confirm;
+
+#[derive(Clone, Debug, Default, PartialEq)]
+pub struct SecondaryConfirm;
+
+#[derive(Clone, Debug, Default, PartialEq)]
+pub struct SelectPrev;
+
+#[derive(Clone, Debug, Default, PartialEq)]
+pub struct SelectNext;
+
+#[derive(Clone, Debug, Default, PartialEq)]
+pub struct SelectFirst;
+
+#[derive(Clone, Debug, Default, PartialEq)]
+pub struct SelectLast;
+
+#[derive(Clone, Debug, Default, PartialEq)]
+pub struct ShowContextMenu;
@@ -16,7 +16,7 @@ client2 = { path = "../client2" }
collections = { path = "../collections"}
language2 = { path = "../language2" }
gpui2 = { path = "../gpui2" }
-fs = { path = "../fs" }
+fs2 = { path = "../fs2" }
lsp2 = { path = "../lsp2" }
node_runtime = { path = "../node_runtime"}
util = { path = "../util" }
@@ -32,4 +32,4 @@ parking_lot.workspace = true
[dev-dependencies]
language2 = { path = "../language2", features = ["test-support"] }
gpui2 = { path = "../gpui2", features = ["test-support"] }
-fs = { path = "../fs", features = ["test-support"] }
+fs2 = { path = "../fs2", features = ["test-support"] }
@@ -1,7 +1,7 @@
use anyhow::Context;
use collections::{HashMap, HashSet};
-use fs::Fs;
-use gpui2::{AsyncAppContext, Handle};
+use fs2::Fs;
+use gpui2::{AsyncAppContext, Model};
use language2::{language_settings::language_settings, Buffer, BundledFormatter, Diff};
use lsp2::{LanguageServer, LanguageServerId};
use node_runtime::NodeRuntime;
@@ -183,7 +183,7 @@ impl Prettier {
pub async fn format(
&self,
- buffer: &Handle<Buffer>,
+ buffer: &Model<Buffer>,
buffer_path: Option<PathBuf>,
cx: &mut AsyncAppContext,
) -> anyhow::Result<Diff> {
@@ -25,7 +25,7 @@ client2 = { path = "../client2" }
clock = { path = "../clock" }
collections = { path = "../collections" }
db2 = { path = "../db2" }
-fs = { path = "../fs" }
+fs2 = { path = "../fs2" }
fsevent = { path = "../fsevent" }
fuzzy2 = { path = "../fuzzy2" }
git = { path = "../git" }
@@ -71,7 +71,7 @@ pretty_assertions.workspace = true
client2 = { path = "../client2", features = ["test-support"] }
collections = { path = "../collections", features = ["test-support"] }
db2 = { path = "../db2", features = ["test-support"] }
-fs = { path = "../fs", features = ["test-support"] }
+fs2 = { path = "../fs2", features = ["test-support"] }
gpui2 = { path = "../gpui2", features = ["test-support"] }
language2 = { path = "../language2", features = ["test-support"] }
lsp2 = { path = "../lsp2", features = ["test-support"] }
@@ -7,7 +7,7 @@ use anyhow::{anyhow, Context, Result};
use async_trait::async_trait;
use client2::proto::{self, PeerId};
use futures::future;
-use gpui2::{AppContext, AsyncAppContext, Handle};
+use gpui2::{AppContext, AsyncAppContext, Model};
use language2::{
language_settings::{language_settings, InlayHintKind},
point_from_lsp, point_to_lsp,
@@ -53,8 +53,8 @@ pub(crate) trait LspCommand: 'static + Sized + Send {
async fn response_from_lsp(
self,
message: <Self::LspRequest as lsp2::request::Request>::Result,
- project: Handle<Project>,
- buffer: Handle<Buffer>,
+ project: Model<Project>,
+ buffer: Model<Buffer>,
server_id: LanguageServerId,
cx: AsyncAppContext,
) -> Result<Self::Response>;
@@ -63,8 +63,8 @@ pub(crate) trait LspCommand: 'static + Sized + Send {
async fn from_proto(
message: Self::ProtoRequest,
- project: Handle<Project>,
- buffer: Handle<Buffer>,
+ project: Model<Project>,
+ buffer: Model<Buffer>,
cx: AsyncAppContext,
) -> Result<Self>;
@@ -79,8 +79,8 @@ pub(crate) trait LspCommand: 'static + Sized + Send {
async fn response_from_proto(
self,
message: <Self::ProtoRequest as proto::RequestMessage>::Response,
- project: Handle<Project>,
- buffer: Handle<Buffer>,
+ project: Model<Project>,
+ buffer: Model<Buffer>,
cx: AsyncAppContext,
) -> Result<Self::Response>;
@@ -180,8 +180,8 @@ impl LspCommand for PrepareRename {
async fn response_from_lsp(
self,
message: Option<lsp2::PrepareRenameResponse>,
- _: Handle<Project>,
- buffer: Handle<Buffer>,
+ _: Model<Project>,
+ buffer: Model<Buffer>,
_: LanguageServerId,
mut cx: AsyncAppContext,
) -> Result<Option<Range<Anchor>>> {
@@ -215,8 +215,8 @@ impl LspCommand for PrepareRename {
async fn from_proto(
message: proto::PrepareRename,
- _: Handle<Project>,
- buffer: Handle<Buffer>,
+ _: Model<Project>,
+ buffer: Model<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Self> {
let position = message
@@ -256,8 +256,8 @@ impl LspCommand for PrepareRename {
async fn response_from_proto(
self,
message: proto::PrepareRenameResponse,
- _: Handle<Project>,
- buffer: Handle<Buffer>,
+ _: Model<Project>,
+ buffer: Model<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Option<Range<Anchor>>> {
if message.can_rename {
@@ -307,8 +307,8 @@ impl LspCommand for PerformRename {
async fn response_from_lsp(
self,
message: Option<lsp2::WorkspaceEdit>,
- project: Handle<Project>,
- buffer: Handle<Buffer>,
+ project: Model<Project>,
+ buffer: Model<Buffer>,
server_id: LanguageServerId,
mut cx: AsyncAppContext,
) -> Result<ProjectTransaction> {
@@ -343,8 +343,8 @@ impl LspCommand for PerformRename {
async fn from_proto(
message: proto::PerformRename,
- _: Handle<Project>,
- buffer: Handle<Buffer>,
+ _: Model<Project>,
+ buffer: Model<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Self> {
let position = message
@@ -379,8 +379,8 @@ impl LspCommand for PerformRename {
async fn response_from_proto(
self,
message: proto::PerformRenameResponse,
- project: Handle<Project>,
- _: Handle<Buffer>,
+ project: Model<Project>,
+ _: Model<Buffer>,
mut cx: AsyncAppContext,
) -> Result<ProjectTransaction> {
let message = message
@@ -426,8 +426,8 @@ impl LspCommand for GetDefinition {
async fn response_from_lsp(
self,
message: Option<lsp2::GotoDefinitionResponse>,
- project: Handle<Project>,
- buffer: Handle<Buffer>,
+ project: Model<Project>,
+ buffer: Model<Buffer>,
server_id: LanguageServerId,
cx: AsyncAppContext,
) -> Result<Vec<LocationLink>> {
@@ -447,8 +447,8 @@ impl LspCommand for GetDefinition {
async fn from_proto(
message: proto::GetDefinition,
- _: Handle<Project>,
- buffer: Handle<Buffer>,
+ _: Model<Project>,
+ buffer: Model<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Self> {
let position = message
@@ -479,8 +479,8 @@ impl LspCommand for GetDefinition {
async fn response_from_proto(
self,
message: proto::GetDefinitionResponse,
- project: Handle<Project>,
- _: Handle<Buffer>,
+ project: Model<Project>,
+ _: Model<Buffer>,
cx: AsyncAppContext,
) -> Result<Vec<LocationLink>> {
location_links_from_proto(message.links, project, cx).await
@@ -527,8 +527,8 @@ impl LspCommand for GetTypeDefinition {
async fn response_from_lsp(
self,
message: Option<lsp2::GotoTypeDefinitionResponse>,
- project: Handle<Project>,
- buffer: Handle<Buffer>,
+ project: Model<Project>,
+ buffer: Model<Buffer>,
server_id: LanguageServerId,
cx: AsyncAppContext,
) -> Result<Vec<LocationLink>> {
@@ -548,8 +548,8 @@ impl LspCommand for GetTypeDefinition {
async fn from_proto(
message: proto::GetTypeDefinition,
- _: Handle<Project>,
- buffer: Handle<Buffer>,
+ _: Model<Project>,
+ buffer: Model<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Self> {
let position = message
@@ -580,8 +580,8 @@ impl LspCommand for GetTypeDefinition {
async fn response_from_proto(
self,
message: proto::GetTypeDefinitionResponse,
- project: Handle<Project>,
- _: Handle<Buffer>,
+ project: Model<Project>,
+ _: Model<Buffer>,
cx: AsyncAppContext,
) -> Result<Vec<LocationLink>> {
location_links_from_proto(message.links, project, cx).await
@@ -593,8 +593,8 @@ impl LspCommand for GetTypeDefinition {
}
fn language_server_for_buffer(
- project: &Handle<Project>,
- buffer: &Handle<Buffer>,
+ project: &Model<Project>,
+ buffer: &Model<Buffer>,
server_id: LanguageServerId,
cx: &mut AsyncAppContext,
) -> Result<(Arc<CachedLspAdapter>, Arc<LanguageServer>)> {
@@ -609,7 +609,7 @@ fn language_server_for_buffer(
async fn location_links_from_proto(
proto_links: Vec<proto::LocationLink>,
- project: Handle<Project>,
+ project: Model<Project>,
mut cx: AsyncAppContext,
) -> Result<Vec<LocationLink>> {
let mut links = Vec::new();
@@ -671,8 +671,8 @@ async fn location_links_from_proto(
async fn location_links_from_lsp(
message: Option<lsp2::GotoDefinitionResponse>,
- project: Handle<Project>,
- buffer: Handle<Buffer>,
+ project: Model<Project>,
+ buffer: Model<Buffer>,
server_id: LanguageServerId,
mut cx: AsyncAppContext,
) -> Result<Vec<LocationLink>> {
@@ -814,8 +814,8 @@ impl LspCommand for GetReferences {
async fn response_from_lsp(
self,
locations: Option<Vec<lsp2::Location>>,
- project: Handle<Project>,
- buffer: Handle<Buffer>,
+ project: Model<Project>,
+ buffer: Model<Buffer>,
server_id: LanguageServerId,
mut cx: AsyncAppContext,
) -> Result<Vec<Location>> {
@@ -868,8 +868,8 @@ impl LspCommand for GetReferences {
async fn from_proto(
message: proto::GetReferences,
- _: Handle<Project>,
- buffer: Handle<Buffer>,
+ _: Model<Project>,
+ buffer: Model<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Self> {
let position = message
@@ -910,8 +910,8 @@ impl LspCommand for GetReferences {
async fn response_from_proto(
self,
message: proto::GetReferencesResponse,
- project: Handle<Project>,
- _: Handle<Buffer>,
+ project: Model<Project>,
+ _: Model<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Vec<Location>> {
let mut locations = Vec::new();
@@ -977,8 +977,8 @@ impl LspCommand for GetDocumentHighlights {
async fn response_from_lsp(
self,
lsp_highlights: Option<Vec<lsp2::DocumentHighlight>>,
- _: Handle<Project>,
- buffer: Handle<Buffer>,
+ _: Model<Project>,
+ buffer: Model<Buffer>,
_: LanguageServerId,
mut cx: AsyncAppContext,
) -> Result<Vec<DocumentHighlight>> {
@@ -1016,8 +1016,8 @@ impl LspCommand for GetDocumentHighlights {
async fn from_proto(
message: proto::GetDocumentHighlights,
- _: Handle<Project>,
- buffer: Handle<Buffer>,
+ _: Model<Project>,
+ buffer: Model<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Self> {
let position = message
@@ -1060,8 +1060,8 @@ impl LspCommand for GetDocumentHighlights {
async fn response_from_proto(
self,
message: proto::GetDocumentHighlightsResponse,
- _: Handle<Project>,
- buffer: Handle<Buffer>,
+ _: Model<Project>,
+ buffer: Model<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Vec<DocumentHighlight>> {
let mut highlights = Vec::new();
@@ -1123,8 +1123,8 @@ impl LspCommand for GetHover {
async fn response_from_lsp(
self,
message: Option<lsp2::Hover>,
- _: Handle<Project>,
- buffer: Handle<Buffer>,
+ _: Model<Project>,
+ buffer: Model<Buffer>,
_: LanguageServerId,
mut cx: AsyncAppContext,
) -> Result<Self::Response> {
@@ -1206,8 +1206,8 @@ impl LspCommand for GetHover {
async fn from_proto(
message: Self::ProtoRequest,
- _: Handle<Project>,
- buffer: Handle<Buffer>,
+ _: Model<Project>,
+ buffer: Model<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Self> {
let position = message
@@ -1272,8 +1272,8 @@ impl LspCommand for GetHover {
async fn response_from_proto(
self,
message: proto::GetHoverResponse,
- _: Handle<Project>,
- buffer: Handle<Buffer>,
+ _: Model<Project>,
+ buffer: Model<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Self::Response> {
let contents: Vec<_> = message
@@ -1341,8 +1341,8 @@ impl LspCommand for GetCompletions {
async fn response_from_lsp(
self,
completions: Option<lsp2::CompletionResponse>,
- _: Handle<Project>,
- buffer: Handle<Buffer>,
+ _: Model<Project>,
+ buffer: Model<Buffer>,
server_id: LanguageServerId,
mut cx: AsyncAppContext,
) -> Result<Vec<Completion>> {
@@ -1484,8 +1484,8 @@ impl LspCommand for GetCompletions {
async fn from_proto(
message: proto::GetCompletions,
- _: Handle<Project>,
- buffer: Handle<Buffer>,
+ _: Model<Project>,
+ buffer: Model<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Self> {
let version = deserialize_version(&message.version);
@@ -1523,8 +1523,8 @@ impl LspCommand for GetCompletions {
async fn response_from_proto(
self,
message: proto::GetCompletionsResponse,
- _: Handle<Project>,
- buffer: Handle<Buffer>,
+ _: Model<Project>,
+ buffer: Model<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Vec<Completion>> {
buffer
@@ -1589,8 +1589,8 @@ impl LspCommand for GetCodeActions {
async fn response_from_lsp(
self,
actions: Option<lsp2::CodeActionResponse>,
- _: Handle<Project>,
- _: Handle<Buffer>,
+ _: Model<Project>,
+ _: Model<Buffer>,
server_id: LanguageServerId,
_: AsyncAppContext,
) -> Result<Vec<CodeAction>> {
@@ -1623,8 +1623,8 @@ impl LspCommand for GetCodeActions {
async fn from_proto(
message: proto::GetCodeActions,
- _: Handle<Project>,
- buffer: Handle<Buffer>,
+ _: Model<Project>,
+ buffer: Model<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Self> {
let start = message
@@ -1663,8 +1663,8 @@ impl LspCommand for GetCodeActions {
async fn response_from_proto(
self,
message: proto::GetCodeActionsResponse,
- _: Handle<Project>,
- buffer: Handle<Buffer>,
+ _: Model<Project>,
+ buffer: Model<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Vec<CodeAction>> {
buffer
@@ -1726,8 +1726,8 @@ impl LspCommand for OnTypeFormatting {
async fn response_from_lsp(
self,
message: Option<Vec<lsp2::TextEdit>>,
- project: Handle<Project>,
- buffer: Handle<Buffer>,
+ project: Model<Project>,
+ buffer: Model<Buffer>,
server_id: LanguageServerId,
mut cx: AsyncAppContext,
) -> Result<Option<Transaction>> {
@@ -1763,8 +1763,8 @@ impl LspCommand for OnTypeFormatting {
async fn from_proto(
message: proto::OnTypeFormatting,
- _: Handle<Project>,
- buffer: Handle<Buffer>,
+ _: Model<Project>,
+ buffer: Model<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Self> {
let position = message
@@ -1805,8 +1805,8 @@ impl LspCommand for OnTypeFormatting {
async fn response_from_proto(
self,
message: proto::OnTypeFormattingResponse,
- _: Handle<Project>,
- _: Handle<Buffer>,
+ _: Model<Project>,
+ _: Model<Buffer>,
_: AsyncAppContext,
) -> Result<Option<Transaction>> {
let Some(transaction) = message.transaction else {
@@ -1825,7 +1825,7 @@ impl LspCommand for OnTypeFormatting {
impl InlayHints {
pub async fn lsp_to_project_hint(
lsp_hint: lsp2::InlayHint,
- buffer_handle: &Handle<Buffer>,
+ buffer_handle: &Model<Buffer>,
server_id: LanguageServerId,
resolve_state: ResolveState,
force_no_type_left_padding: bool,
@@ -2230,8 +2230,8 @@ impl LspCommand for InlayHints {
async fn response_from_lsp(
self,
message: Option<Vec<lsp2::InlayHint>>,
- project: Handle<Project>,
- buffer: Handle<Buffer>,
+ project: Model<Project>,
+ buffer: Model<Buffer>,
server_id: LanguageServerId,
mut cx: AsyncAppContext,
) -> anyhow::Result<Vec<InlayHint>> {
@@ -2286,8 +2286,8 @@ impl LspCommand for InlayHints {
async fn from_proto(
message: proto::InlayHints,
- _: Handle<Project>,
- buffer: Handle<Buffer>,
+ _: Model<Project>,
+ buffer: Model<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Self> {
let start = message
@@ -2326,8 +2326,8 @@ impl LspCommand for InlayHints {
async fn response_from_proto(
self,
message: proto::InlayHintsResponse,
- _: Handle<Project>,
- buffer: Handle<Buffer>,
+ _: Model<Project>,
+ buffer: Model<Buffer>,
mut cx: AsyncAppContext,
) -> anyhow::Result<Vec<InlayHint>> {
buffer
@@ -26,8 +26,8 @@ use futures::{
};
use globset::{Glob, GlobSet, GlobSetBuilder};
use gpui2::{
- AnyHandle, AppContext, AsyncAppContext, Context, EventEmitter, Executor, Handle, ModelContext,
- Task, WeakHandle,
+ AnyModel, AppContext, AsyncAppContext, Context, EventEmitter, Executor, Model, ModelContext,
+ Task, WeakModel,
};
use itertools::Itertools;
use language2::{
@@ -89,7 +89,7 @@ use util::{
post_inc, ResultExt, TryFutureExt as _,
};
-pub use fs::*;
+pub use fs2::*;
pub use worktree::*;
const MAX_SERVER_REINSTALL_ATTEMPT_COUNT: u64 = 4;
@@ -128,7 +128,7 @@ pub struct Project {
next_entry_id: Arc<AtomicUsize>,
join_project_response_message_id: u32,
next_diagnostic_group_id: usize,
- user_store: Handle<UserStore>,
+ user_store: Model<UserStore>,
fs: Arc<dyn Fs>,
client_state: Option<ProjectClientState>,
collaborators: HashMap<proto::PeerId, Collaborator>,
@@ -140,20 +140,20 @@ pub struct Project {
#[allow(clippy::type_complexity)]
loading_buffers_by_path: HashMap<
ProjectPath,
- postage::watch::Receiver<Option<Result<Handle<Buffer>, Arc<anyhow::Error>>>>,
+ postage::watch::Receiver<Option<Result<Model<Buffer>, Arc<anyhow::Error>>>>,
>,
#[allow(clippy::type_complexity)]
loading_local_worktrees:
- HashMap<Arc<Path>, Shared<Task<Result<Handle<Worktree>, Arc<anyhow::Error>>>>>,
+ HashMap<Arc<Path>, Shared<Task<Result<Model<Worktree>, Arc<anyhow::Error>>>>>,
opened_buffers: HashMap<u64, OpenBuffer>,
local_buffer_ids_by_path: HashMap<ProjectPath, u64>,
local_buffer_ids_by_entry_id: HashMap<ProjectEntryId, u64>,
/// A mapping from a buffer ID to None means that we've started waiting for an ID but haven't finished loading it.
/// Used for re-issuing buffer requests when peers temporarily disconnect
- incomplete_remote_buffers: HashMap<u64, Option<Handle<Buffer>>>,
+ incomplete_remote_buffers: HashMap<u64, Option<Model<Buffer>>>,
buffer_snapshots: HashMap<u64, HashMap<LanguageServerId, Vec<LspBufferSnapshot>>>, // buffer_id -> server_id -> vec of snapshots
buffers_being_formatted: HashSet<u64>,
- buffers_needing_diff: HashSet<WeakHandle<Buffer>>,
+ buffers_needing_diff: HashSet<WeakModel<Buffer>>,
git_diff_debouncer: DelayedDebounced,
nonce: u128,
_maintain_buffer_languages: Task<()>,
@@ -244,15 +244,15 @@ enum LocalProjectUpdate {
}
enum OpenBuffer {
- Strong(Handle<Buffer>),
- Weak(WeakHandle<Buffer>),
+ Strong(Model<Buffer>),
+ Weak(WeakModel<Buffer>),
Operations(Vec<Operation>),
}
#[derive(Clone)]
enum WorktreeHandle {
- Strong(Handle<Worktree>),
- Weak(WeakHandle<Worktree>),
+ Strong(Model<Worktree>),
+ Weak(WeakModel<Worktree>),
}
enum ProjectClientState {
@@ -344,7 +344,7 @@ pub struct DiagnosticSummary {
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Location {
- pub buffer: Handle<Buffer>,
+ pub buffer: Model<Buffer>,
pub range: Range<language2::Anchor>,
}
@@ -457,7 +457,7 @@ impl Hover {
}
#[derive(Default)]
-pub struct ProjectTransaction(pub HashMap<Handle<Buffer>, language2::Transaction>);
+pub struct ProjectTransaction(pub HashMap<Model<Buffer>, language2::Transaction>);
impl DiagnosticSummary {
fn new<'a, T: 'a>(diagnostics: impl IntoIterator<Item = &'a DiagnosticEntry<T>>) -> Self {
@@ -527,7 +527,7 @@ pub enum FormatTrigger {
}
struct ProjectLspAdapterDelegate {
- project: Handle<Project>,
+ project: Model<Project>,
http_client: Arc<dyn HttpClient>,
}
@@ -543,7 +543,7 @@ impl FormatTrigger {
#[derive(Clone, Debug, PartialEq)]
enum SearchMatchCandidate {
OpenBuffer {
- buffer: Handle<Buffer>,
+ buffer: Model<Buffer>,
// This might be an unnamed file without representation on filesystem
path: Option<Arc<Path>>,
},
@@ -621,12 +621,12 @@ impl Project {
pub fn local(
client: Arc<Client>,
node: Arc<dyn NodeRuntime>,
- user_store: Handle<UserStore>,
+ user_store: Model<UserStore>,
languages: Arc<LanguageRegistry>,
fs: Arc<dyn Fs>,
cx: &mut AppContext,
- ) -> Handle<Self> {
- cx.entity(|cx: &mut ModelContext<Self>| {
+ ) -> Model<Self> {
+ cx.build_model(|cx: &mut ModelContext<Self>| {
let (tx, rx) = mpsc::unbounded();
cx.spawn(move |this, cx| Self::send_buffer_ordered_messages(this, rx, cx))
.detach();
@@ -687,11 +687,11 @@ impl Project {
pub async fn remote(
remote_id: u64,
client: Arc<Client>,
- user_store: Handle<UserStore>,
+ user_store: Model<UserStore>,
languages: Arc<LanguageRegistry>,
fs: Arc<dyn Fs>,
mut cx: AsyncAppContext,
- ) -> Result<Handle<Self>> {
+ ) -> Result<Model<Self>> {
client.authenticate_and_connect(true, &cx).await?;
let subscription = client.subscribe_to_entity(remote_id)?;
@@ -700,7 +700,7 @@ impl Project {
project_id: remote_id,
})
.await?;
- let this = cx.entity(|cx| {
+ let this = cx.build_model(|cx| {
let replica_id = response.payload.replica_id as ReplicaId;
let mut worktrees = Vec::new();
@@ -981,7 +981,7 @@ impl Project {
cx.notify();
}
- pub fn buffer_for_id(&self, remote_id: u64) -> Option<Handle<Buffer>> {
+ pub fn buffer_for_id(&self, remote_id: u64) -> Option<Model<Buffer>> {
self.opened_buffers
.get(&remote_id)
.and_then(|buffer| buffer.upgrade())
@@ -995,11 +995,11 @@ impl Project {
self.client.clone()
}
- pub fn user_store(&self) -> Handle<UserStore> {
+ pub fn user_store(&self) -> Model<UserStore> {
self.user_store.clone()
}
- pub fn opened_buffers(&self) -> Vec<Handle<Buffer>> {
+ pub fn opened_buffers(&self) -> Vec<Model<Buffer>> {
self.opened_buffers
.values()
.filter_map(|b| b.upgrade())
@@ -1061,7 +1061,7 @@ impl Project {
}
/// Collect all worktrees, including ones that don't appear in the project panel
- pub fn worktrees<'a>(&'a self) -> impl 'a + DoubleEndedIterator<Item = Handle<Worktree>> {
+ pub fn worktrees<'a>(&'a self) -> impl 'a + DoubleEndedIterator<Item = Model<Worktree>> {
self.worktrees
.iter()
.filter_map(move |worktree| worktree.upgrade())
@@ -1071,7 +1071,7 @@ impl Project {
pub fn visible_worktrees<'a>(
&'a self,
cx: &'a AppContext,
- ) -> impl 'a + DoubleEndedIterator<Item = Handle<Worktree>> {
+ ) -> impl 'a + DoubleEndedIterator<Item = Model<Worktree>> {
self.worktrees.iter().filter_map(|worktree| {
worktree.upgrade().and_then(|worktree| {
if worktree.read(cx).is_visible() {
@@ -1088,7 +1088,7 @@ impl Project {
.map(|tree| tree.read(cx).root_name())
}
- pub fn worktree_for_id(&self, id: WorktreeId, cx: &AppContext) -> Option<Handle<Worktree>> {
+ pub fn worktree_for_id(&self, id: WorktreeId, cx: &AppContext) -> Option<Model<Worktree>> {
self.worktrees()
.find(|worktree| worktree.read(cx).id() == id)
}
@@ -1097,7 +1097,7 @@ impl Project {
&self,
entry_id: ProjectEntryId,
cx: &AppContext,
- ) -> Option<Handle<Worktree>> {
+ ) -> Option<Model<Worktree>> {
self.worktrees()
.find(|worktree| worktree.read(cx).contains_entry(entry_id))
}
@@ -1652,12 +1652,12 @@ impl Project {
text: &str,
language: Option<Arc<Language>>,
cx: &mut ModelContext<Self>,
- ) -> Result<Handle<Buffer>> {
+ ) -> Result<Model<Buffer>> {
if self.is_remote() {
return Err(anyhow!("creating buffers as a guest is not supported yet"));
}
let id = post_inc(&mut self.next_buffer_id);
- let buffer = cx.entity(|cx| {
+ let buffer = cx.build_model(|cx| {
Buffer::new(self.replica_id(), id, text).with_language(
language.unwrap_or_else(|| language2::PLAIN_TEXT.clone()),
cx,
@@ -1671,7 +1671,7 @@ impl Project {
&mut self,
path: impl Into<ProjectPath>,
cx: &mut ModelContext<Self>,
- ) -> Task<Result<(ProjectEntryId, AnyHandle)>> {
+ ) -> Task<Result<(ProjectEntryId, AnyModel)>> {
let task = self.open_buffer(path, cx);
cx.spawn(move |_, mut cx| async move {
let buffer = task.await?;
@@ -1681,7 +1681,7 @@ impl Project {
})?
.ok_or_else(|| anyhow!("no project entry"))?;
- let buffer: &AnyHandle = &buffer;
+ let buffer: &AnyModel = &buffer;
Ok((project_entry_id, buffer.clone()))
})
}
@@ -1690,7 +1690,7 @@ impl Project {
&mut self,
abs_path: impl AsRef<Path>,
cx: &mut ModelContext<Self>,
- ) -> Task<Result<Handle<Buffer>>> {
+ ) -> Task<Result<Model<Buffer>>> {
if let Some((worktree, relative_path)) = self.find_local_worktree(abs_path.as_ref(), cx) {
self.open_buffer((worktree.read(cx).id(), relative_path), cx)
} else {
@@ -1702,7 +1702,7 @@ impl Project {
&mut self,
path: impl Into<ProjectPath>,
cx: &mut ModelContext<Self>,
- ) -> Task<Result<Handle<Buffer>>> {
+ ) -> Task<Result<Model<Buffer>>> {
let project_path = path.into();
let worktree = if let Some(worktree) = self.worktree_for_id(project_path.worktree_id, cx) {
worktree
@@ -1757,9 +1757,9 @@ impl Project {
fn open_local_buffer_internal(
&mut self,
path: &Arc<Path>,
- worktree: &Handle<Worktree>,
+ worktree: &Model<Worktree>,
cx: &mut ModelContext<Self>,
- ) -> Task<Result<Handle<Buffer>>> {
+ ) -> Task<Result<Model<Buffer>>> {
let buffer_id = post_inc(&mut self.next_buffer_id);
let load_buffer = worktree.update(cx, |worktree, cx| {
let worktree = worktree.as_local_mut().unwrap();
@@ -1775,9 +1775,9 @@ impl Project {
fn open_remote_buffer_internal(
&mut self,
path: &Arc<Path>,
- worktree: &Handle<Worktree>,
+ worktree: &Model<Worktree>,
cx: &mut ModelContext<Self>,
- ) -> Task<Result<Handle<Buffer>>> {
+ ) -> Task<Result<Model<Buffer>>> {
let rpc = self.client.clone();
let project_id = self.remote_id().unwrap();
let remote_worktree_id = worktree.read(cx).id();
@@ -1805,7 +1805,7 @@ impl Project {
language_server_id: LanguageServerId,
language_server_name: LanguageServerName,
cx: &mut ModelContext<Self>,
- ) -> Task<Result<Handle<Buffer>>> {
+ ) -> Task<Result<Model<Buffer>>> {
cx.spawn(move |this, mut cx| async move {
let abs_path = abs_path
.to_file_path()
@@ -1843,7 +1843,7 @@ impl Project {
&mut self,
id: u64,
cx: &mut ModelContext<Self>,
- ) -> Task<Result<Handle<Buffer>>> {
+ ) -> Task<Result<Model<Buffer>>> {
if let Some(buffer) = self.buffer_for_id(id) {
Task::ready(Ok(buffer))
} else if self.is_local() {
@@ -1866,7 +1866,7 @@ impl Project {
pub fn save_buffers(
&self,
- buffers: HashSet<Handle<Buffer>>,
+ buffers: HashSet<Model<Buffer>>,
cx: &mut ModelContext<Self>,
) -> Task<Result<()>> {
cx.spawn(move |this, mut cx| async move {
@@ -1881,7 +1881,7 @@ impl Project {
pub fn save_buffer(
&self,
- buffer: Handle<Buffer>,
+ buffer: Model<Buffer>,
cx: &mut ModelContext<Self>,
) -> Task<Result<()>> {
let Some(file) = File::from_dyn(buffer.read(cx).file()) else {
@@ -1897,7 +1897,7 @@ impl Project {
pub fn save_buffer_as(
&mut self,
- buffer: Handle<Buffer>,
+ buffer: Model<Buffer>,
abs_path: PathBuf,
cx: &mut ModelContext<Self>,
) -> Task<Result<()>> {
@@ -1933,7 +1933,7 @@ impl Project {
&mut self,
path: &ProjectPath,
cx: &mut ModelContext<Self>,
- ) -> Option<Handle<Buffer>> {
+ ) -> Option<Model<Buffer>> {
let worktree = self.worktree_for_id(path.worktree_id, cx)?;
self.opened_buffers.values().find_map(|buffer| {
let buffer = buffer.upgrade()?;
@@ -1948,7 +1948,7 @@ impl Project {
fn register_buffer(
&mut self,
- buffer: &Handle<Buffer>,
+ buffer: &Model<Buffer>,
cx: &mut ModelContext<Self>,
) -> Result<()> {
self.request_buffer_diff_recalculation(buffer, cx);
@@ -2030,7 +2030,7 @@ impl Project {
fn register_buffer_with_language_servers(
&mut self,
- buffer_handle: &Handle<Buffer>,
+ buffer_handle: &Model<Buffer>,
cx: &mut ModelContext<Self>,
) {
let buffer = buffer_handle.read(cx);
@@ -2114,7 +2114,7 @@ impl Project {
fn unregister_buffer_from_language_servers(
&mut self,
- buffer: &Handle<Buffer>,
+ buffer: &Model<Buffer>,
old_file: &File,
cx: &mut ModelContext<Self>,
) {
@@ -2149,7 +2149,7 @@ impl Project {
fn register_buffer_with_copilot(
&self,
- buffer_handle: &Handle<Buffer>,
+ buffer_handle: &Model<Buffer>,
cx: &mut ModelContext<Self>,
) {
if let Some(copilot) = Copilot::global(cx) {
@@ -2158,7 +2158,7 @@ impl Project {
}
async fn send_buffer_ordered_messages(
- this: WeakHandle<Self>,
+ this: WeakModel<Self>,
rx: UnboundedReceiver<BufferOrderedMessage>,
mut cx: AsyncAppContext,
) -> Result<()> {
@@ -2166,7 +2166,7 @@ impl Project {
let mut operations_by_buffer_id = HashMap::default();
async fn flush_operations(
- this: &WeakHandle<Project>,
+ this: &WeakModel<Project>,
operations_by_buffer_id: &mut HashMap<u64, Vec<proto::Operation>>,
needs_resync_with_host: &mut bool,
is_local: bool,
@@ -2267,7 +2267,7 @@ impl Project {
fn on_buffer_event(
&mut self,
- buffer: Handle<Buffer>,
+ buffer: Model<Buffer>,
event: &BufferEvent,
cx: &mut ModelContext<Self>,
) -> Option<()> {
@@ -2480,7 +2480,7 @@ impl Project {
fn request_buffer_diff_recalculation(
&mut self,
- buffer: &Handle<Buffer>,
+ buffer: &Model<Buffer>,
cx: &mut ModelContext<Self>,
) {
self.buffers_needing_diff.insert(buffer.downgrade());
@@ -2676,7 +2676,7 @@ impl Project {
fn detect_language_for_buffer(
&mut self,
- buffer_handle: &Handle<Buffer>,
+ buffer_handle: &Model<Buffer>,
cx: &mut ModelContext<Self>,
) -> Option<()> {
// If the buffer has a language, set it and start the language server if we haven't already.
@@ -2694,7 +2694,7 @@ impl Project {
pub fn set_language_for_buffer(
&mut self,
- buffer: &Handle<Buffer>,
+ buffer: &Model<Buffer>,
new_language: Arc<Language>,
cx: &mut ModelContext<Self>,
) {
@@ -2735,7 +2735,7 @@ impl Project {
fn start_language_servers(
&mut self,
- worktree: &Handle<Worktree>,
+ worktree: &Model<Worktree>,
worktree_path: Arc<Path>,
language: Arc<Language>,
cx: &mut ModelContext<Self>,
@@ -2931,7 +2931,7 @@ impl Project {
}
async fn setup_and_insert_language_server(
- this: WeakHandle<Self>,
+ this: WeakModel<Self>,
initialization_options: Option<serde_json::Value>,
pending_server: PendingLanguageServer,
adapter: Arc<CachedLspAdapter>,
@@ -2970,7 +2970,7 @@ impl Project {
}
async fn setup_pending_language_server(
- this: WeakHandle<Self>,
+ this: WeakModel<Self>,
initialization_options: Option<serde_json::Value>,
pending_server: PendingLanguageServer,
adapter: Arc<CachedLspAdapter>,
@@ -3350,10 +3350,10 @@ impl Project {
pub fn restart_language_servers_for_buffers(
&mut self,
- buffers: impl IntoIterator<Item = Handle<Buffer>>,
+ buffers: impl IntoIterator<Item = Model<Buffer>>,
cx: &mut ModelContext<Self>,
) -> Option<()> {
- let language_server_lookup_info: HashSet<(Handle<Worktree>, Arc<Language>)> = buffers
+ let language_server_lookup_info: HashSet<(Model<Worktree>, Arc<Language>)> = buffers
.into_iter()
.filter_map(|buffer| {
let buffer = buffer.read(cx);
@@ -3377,7 +3377,7 @@ impl Project {
// TODO This will break in the case where the adapter's root paths and worktrees are not equal
fn restart_language_servers(
&mut self,
- worktree: Handle<Worktree>,
+ worktree: Model<Worktree>,
language: Arc<Language>,
cx: &mut ModelContext<Self>,
) {
@@ -3748,7 +3748,7 @@ impl Project {
}
async fn on_lsp_workspace_edit(
- this: WeakHandle<Self>,
+ this: WeakModel<Self>,
params: lsp2::ApplyWorkspaceEditParams,
server_id: LanguageServerId,
adapter: Arc<CachedLspAdapter>,
@@ -3949,7 +3949,7 @@ impl Project {
fn update_buffer_diagnostics(
&mut self,
- buffer: &Handle<Buffer>,
+ buffer: &Model<Buffer>,
server_id: LanguageServerId,
version: Option<i32>,
mut diagnostics: Vec<DiagnosticEntry<Unclipped<PointUtf16>>>,
@@ -4022,7 +4022,7 @@ impl Project {
pub fn reload_buffers(
&self,
- buffers: HashSet<Handle<Buffer>>,
+ buffers: HashSet<Model<Buffer>>,
push_to_history: bool,
cx: &mut ModelContext<Self>,
) -> Task<Result<ProjectTransaction>> {
@@ -4088,7 +4088,7 @@ impl Project {
pub fn format(
&self,
- buffers: HashSet<Handle<Buffer>>,
+ buffers: HashSet<Model<Buffer>>,
push_to_history: bool,
trigger: FormatTrigger,
cx: &mut ModelContext<Project>,
@@ -4360,8 +4360,8 @@ impl Project {
}
async fn format_via_lsp(
- this: &WeakHandle<Self>,
- buffer: &Handle<Buffer>,
+ this: &WeakModel<Self>,
+ buffer: &Model<Buffer>,
abs_path: &Path,
language_server: &Arc<LanguageServer>,
tab_size: NonZeroU32,
@@ -4410,7 +4410,7 @@ impl Project {
}
async fn format_via_external_command(
- buffer: &Handle<Buffer>,
+ buffer: &Model<Buffer>,
buffer_abs_path: &Path,
command: &str,
arguments: &[String],
@@ -4470,7 +4470,7 @@ impl Project {
pub fn definition<T: ToPointUtf16>(
&self,
- buffer: &Handle<Buffer>,
+ buffer: &Model<Buffer>,
position: T,
cx: &mut ModelContext<Self>,
) -> Task<Result<Vec<LocationLink>>> {
@@ -4485,7 +4485,7 @@ impl Project {
pub fn type_definition<T: ToPointUtf16>(
&self,
- buffer: &Handle<Buffer>,
+ buffer: &Model<Buffer>,
position: T,
cx: &mut ModelContext<Self>,
) -> Task<Result<Vec<LocationLink>>> {
@@ -4500,7 +4500,7 @@ impl Project {
pub fn references<T: ToPointUtf16>(
&self,
- buffer: &Handle<Buffer>,
+ buffer: &Model<Buffer>,
position: T,
cx: &mut ModelContext<Self>,
) -> Task<Result<Vec<Location>>> {
@@ -4515,7 +4515,7 @@ impl Project {
pub fn document_highlights<T: ToPointUtf16>(
&self,
- buffer: &Handle<Buffer>,
+ buffer: &Model<Buffer>,
position: T,
cx: &mut ModelContext<Self>,
) -> Task<Result<Vec<DocumentHighlight>>> {
@@ -4694,7 +4694,7 @@ impl Project {
&mut self,
symbol: &Symbol,
cx: &mut ModelContext<Self>,
- ) -> Task<Result<Handle<Buffer>>> {
+ ) -> Task<Result<Model<Buffer>>> {
if self.is_local() {
let language_server_id = if let Some(id) = self.language_server_ids.get(&(
symbol.source_worktree_id,
@@ -4748,7 +4748,7 @@ impl Project {
pub fn hover<T: ToPointUtf16>(
&self,
- buffer: &Handle<Buffer>,
+ buffer: &Model<Buffer>,
position: T,
cx: &mut ModelContext<Self>,
) -> Task<Result<Option<Hover>>> {
@@ -4763,7 +4763,7 @@ impl Project {
pub fn completions<T: ToOffset + ToPointUtf16>(
&self,
- buffer: &Handle<Buffer>,
+ buffer: &Model<Buffer>,
position: T,
cx: &mut ModelContext<Self>,
) -> Task<Result<Vec<Completion>>> {
@@ -4817,7 +4817,7 @@ impl Project {
pub fn apply_additional_edits_for_completion(
&self,
- buffer_handle: Handle<Buffer>,
+ buffer_handle: Model<Buffer>,
completion: Completion,
push_to_history: bool,
cx: &mut ModelContext<Self>,
@@ -4928,7 +4928,7 @@ impl Project {
pub fn code_actions<T: Clone + ToOffset>(
&self,
- buffer_handle: &Handle<Buffer>,
+ buffer_handle: &Model<Buffer>,
range: Range<T>,
cx: &mut ModelContext<Self>,
) -> Task<Result<Vec<CodeAction>>> {
@@ -4944,7 +4944,7 @@ impl Project {
pub fn apply_code_action(
&self,
- buffer_handle: Handle<Buffer>,
+ buffer_handle: Model<Buffer>,
mut action: CodeAction,
push_to_history: bool,
cx: &mut ModelContext<Self>,
@@ -5052,7 +5052,7 @@ impl Project {
fn apply_on_type_formatting(
&self,
- buffer: Handle<Buffer>,
+ buffer: Model<Buffer>,
position: Anchor,
trigger: String,
cx: &mut ModelContext<Self>,
@@ -5113,8 +5113,8 @@ impl Project {
}
async fn deserialize_edits(
- this: Handle<Self>,
- buffer_to_edit: Handle<Buffer>,
+ this: Model<Self>,
+ buffer_to_edit: Model<Buffer>,
edits: Vec<lsp2::TextEdit>,
push_to_history: bool,
_: Arc<CachedLspAdapter>,
@@ -5155,7 +5155,7 @@ impl Project {
}
async fn deserialize_workspace_edit(
- this: Handle<Self>,
+ this: Model<Self>,
edit: lsp2::WorkspaceEdit,
push_to_history: bool,
lsp_adapter: Arc<CachedLspAdapter>,
@@ -5201,7 +5201,7 @@ impl Project {
fs.create_file(
&abs_path,
op.options
- .map(|options| fs::CreateOptions {
+ .map(|options| fs2::CreateOptions {
overwrite: options.overwrite.unwrap_or(false),
ignore_if_exists: options.ignore_if_exists.unwrap_or(false),
})
@@ -5224,7 +5224,7 @@ impl Project {
&source_abs_path,
&target_abs_path,
op.options
- .map(|options| fs::RenameOptions {
+ .map(|options| fs2::RenameOptions {
overwrite: options.overwrite.unwrap_or(false),
ignore_if_exists: options.ignore_if_exists.unwrap_or(false),
})
@@ -5240,7 +5240,7 @@ impl Project {
.map_err(|_| anyhow!("can't convert URI to path"))?;
let options = op
.options
- .map(|options| fs::RemoveOptions {
+ .map(|options| fs2::RemoveOptions {
recursive: options.recursive.unwrap_or(false),
ignore_if_not_exists: options.ignore_if_not_exists.unwrap_or(false),
})
@@ -5310,7 +5310,7 @@ impl Project {
pub fn prepare_rename<T: ToPointUtf16>(
&self,
- buffer: Handle<Buffer>,
+ buffer: Model<Buffer>,
position: T,
cx: &mut ModelContext<Self>,
) -> Task<Result<Option<Range<Anchor>>>> {
@@ -5325,7 +5325,7 @@ impl Project {
pub fn perform_rename<T: ToPointUtf16>(
&self,
- buffer: Handle<Buffer>,
+ buffer: Model<Buffer>,
position: T,
new_name: String,
push_to_history: bool,
@@ -5346,7 +5346,7 @@ impl Project {
pub fn on_type_format<T: ToPointUtf16>(
&self,
- buffer: Handle<Buffer>,
+ buffer: Model<Buffer>,
position: T,
trigger: String,
push_to_history: bool,
@@ -5375,7 +5375,7 @@ impl Project {
pub fn inlay_hints<T: ToOffset>(
&self,
- buffer_handle: Handle<Buffer>,
+ buffer_handle: Model<Buffer>,
range: Range<T>,
cx: &mut ModelContext<Self>,
) -> Task<anyhow::Result<Vec<InlayHint>>> {
@@ -5436,7 +5436,7 @@ impl Project {
pub fn resolve_inlay_hint(
&self,
hint: InlayHint,
- buffer_handle: Handle<Buffer>,
+ buffer_handle: Model<Buffer>,
server_id: LanguageServerId,
cx: &mut ModelContext<Self>,
) -> Task<anyhow::Result<InlayHint>> {
@@ -5501,7 +5501,7 @@ impl Project {
&self,
query: SearchQuery,
cx: &mut ModelContext<Self>,
- ) -> Receiver<(Handle<Buffer>, Vec<Range<Anchor>>)> {
+ ) -> Receiver<(Model<Buffer>, Vec<Range<Anchor>>)> {
if self.is_local() {
self.search_local(query, cx)
} else if let Some(project_id) = self.remote_id() {
@@ -5545,7 +5545,7 @@ impl Project {
&self,
query: SearchQuery,
cx: &mut ModelContext<Self>,
- ) -> Receiver<(Handle<Buffer>, Vec<Range<Anchor>>)> {
+ ) -> Receiver<(Model<Buffer>, Vec<Range<Anchor>>)> {
// Local search is split into several phases.
// TL;DR is that we do 2 passes; initial pass to pick files which contain at least one match
// and the second phase that finds positions of all the matches found in the candidate files.
@@ -5638,7 +5638,7 @@ impl Project {
.scoped(|scope| {
#[derive(Clone)]
struct FinishedStatus {
- entry: Option<(Handle<Buffer>, Vec<Range<Anchor>>)>,
+ entry: Option<(Model<Buffer>, Vec<Range<Anchor>>)>,
buffer_index: SearchMatchCandidateIndex,
}
@@ -5728,8 +5728,8 @@ impl Project {
/// Pick paths that might potentially contain a match of a given search query.
async fn background_search(
- unnamed_buffers: Vec<Handle<Buffer>>,
- opened_buffers: HashMap<Arc<Path>, (Handle<Buffer>, BufferSnapshot)>,
+ unnamed_buffers: Vec<Model<Buffer>>,
+ opened_buffers: HashMap<Arc<Path>, (Model<Buffer>, BufferSnapshot)>,
executor: Executor,
fs: Arc<dyn Fs>,
workers: usize,
@@ -5829,7 +5829,7 @@ impl Project {
fn request_lsp<R: LspCommand>(
&self,
- buffer_handle: Handle<Buffer>,
+ buffer_handle: Model<Buffer>,
server: LanguageServerToQuery,
request: R,
cx: &mut ModelContext<Self>,
@@ -5893,7 +5893,7 @@ impl Project {
fn send_lsp_proto_request<R: LspCommand>(
&self,
- buffer: Handle<Buffer>,
+ buffer: Model<Buffer>,
project_id: u64,
request: R,
cx: &mut ModelContext<'_, Project>,
@@ -5922,7 +5922,7 @@ impl Project {
) -> (
futures::channel::oneshot::Receiver<Vec<SearchMatchCandidate>>,
Receiver<(
- Option<(Handle<Buffer>, BufferSnapshot)>,
+ Option<(Model<Buffer>, BufferSnapshot)>,
SearchMatchCandidateIndex,
)>,
) {
@@ -5976,7 +5976,7 @@ impl Project {
abs_path: impl AsRef<Path>,
visible: bool,
cx: &mut ModelContext<Self>,
- ) -> Task<Result<(Handle<Worktree>, PathBuf)>> {
+ ) -> Task<Result<(Model<Worktree>, PathBuf)>> {
let abs_path = abs_path.as_ref();
if let Some((tree, relative_path)) = self.find_local_worktree(abs_path, cx) {
Task::ready(Ok((tree, relative_path)))
@@ -5991,7 +5991,7 @@ impl Project {
&self,
abs_path: &Path,
cx: &AppContext,
- ) -> Option<(Handle<Worktree>, PathBuf)> {
+ ) -> Option<(Model<Worktree>, PathBuf)> {
for tree in &self.worktrees {
if let Some(tree) = tree.upgrade() {
if let Some(relative_path) = tree
@@ -6018,7 +6018,7 @@ impl Project {
abs_path: impl AsRef<Path>,
visible: bool,
cx: &mut ModelContext<Self>,
- ) -> Task<Result<Handle<Worktree>>> {
+ ) -> Task<Result<Model<Worktree>>> {
let fs = self.fs.clone();
let client = self.client.clone();
let next_entry_id = self.next_entry_id.clone();
@@ -6078,7 +6078,7 @@ impl Project {
self.metadata_changed(cx);
}
- fn add_worktree(&mut self, worktree: &Handle<Worktree>, cx: &mut ModelContext<Self>) {
+ fn add_worktree(&mut self, worktree: &Model<Worktree>, cx: &mut ModelContext<Self>) {
cx.observe(worktree, |_, _, cx| cx.notify()).detach();
if worktree.read(cx).is_local() {
cx.subscribe(worktree, |this, worktree, event, cx| match event {
@@ -6128,7 +6128,7 @@ impl Project {
fn update_local_worktree_buffers(
&mut self,
- worktree_handle: &Handle<Worktree>,
+ worktree_handle: &Model<Worktree>,
changes: &[(Arc<Path>, ProjectEntryId, PathChange)],
cx: &mut ModelContext<Self>,
) {
@@ -6242,7 +6242,7 @@ impl Project {
fn update_local_worktree_language_servers(
&mut self,
- worktree_handle: &Handle<Worktree>,
+ worktree_handle: &Model<Worktree>,
changes: &[(Arc<Path>, ProjectEntryId, PathChange)],
cx: &mut ModelContext<Self>,
) {
@@ -6304,7 +6304,7 @@ impl Project {
fn update_local_worktree_buffers_git_repos(
&mut self,
- worktree_handle: Handle<Worktree>,
+ worktree_handle: Model<Worktree>,
changed_repos: &UpdatedGitRepositoriesSet,
cx: &mut ModelContext<Self>,
) {
@@ -6407,7 +6407,7 @@ impl Project {
fn update_local_worktree_settings(
&mut self,
- worktree: &Handle<Worktree>,
+ worktree: &Model<Worktree>,
changes: &UpdatedEntriesSet,
cx: &mut ModelContext<Self>,
) {
@@ -6473,7 +6473,7 @@ impl Project {
fn update_prettier_settings(
&self,
- worktree: &Handle<Worktree>,
+ worktree: &Model<Worktree>,
changes: &[(Arc<Path>, ProjectEntryId, PathChange)],
cx: &mut ModelContext<'_, Project>,
) {
@@ -6636,7 +6636,7 @@ impl Project {
// RPC message handlers
async fn handle_unshare_project(
- this: Handle<Self>,
+ this: Model<Self>,
_: TypedEnvelope<proto::UnshareProject>,
_: Arc<Client>,
mut cx: AsyncAppContext,
@@ -6652,7 +6652,7 @@ impl Project {
}
async fn handle_add_collaborator(
- this: Handle<Self>,
+ this: Model<Self>,
mut envelope: TypedEnvelope<proto::AddProjectCollaborator>,
_: Arc<Client>,
mut cx: AsyncAppContext,
@@ -6676,7 +6676,7 @@ impl Project {
}
async fn handle_update_project_collaborator(
- this: Handle<Self>,
+ this: Model<Self>,
envelope: TypedEnvelope<proto::UpdateProjectCollaborator>,
_: Arc<Client>,
mut cx: AsyncAppContext,
@@ -6726,7 +6726,7 @@ impl Project {
}
async fn handle_remove_collaborator(
- this: Handle<Self>,
+ this: Model<Self>,
envelope: TypedEnvelope<proto::RemoveProjectCollaborator>,
_: Arc<Client>,
mut cx: AsyncAppContext,
@@ -6755,7 +6755,7 @@ impl Project {
}
async fn handle_update_project(
- this: Handle<Self>,
+ this: Model<Self>,
envelope: TypedEnvelope<proto::UpdateProject>,
_: Arc<Client>,
mut cx: AsyncAppContext,
@@ -6770,7 +6770,7 @@ impl Project {
}
async fn handle_update_worktree(
- this: Handle<Self>,
+ this: Model<Self>,
envelope: TypedEnvelope<proto::UpdateWorktree>,
_: Arc<Client>,
mut cx: AsyncAppContext,
@@ -6788,7 +6788,7 @@ impl Project {
}
async fn handle_update_worktree_settings(
- this: Handle<Self>,
+ this: Model<Self>,
envelope: TypedEnvelope<proto::UpdateWorktreeSettings>,
_: Arc<Client>,
mut cx: AsyncAppContext,
@@ -6812,7 +6812,7 @@ impl Project {
}
async fn handle_create_project_entry(
- this: Handle<Self>,
+ this: Model<Self>,
envelope: TypedEnvelope<proto::CreateProjectEntry>,
_: Arc<Client>,
mut cx: AsyncAppContext,
@@ -6837,7 +6837,7 @@ impl Project {
}
async fn handle_rename_project_entry(
- this: Handle<Self>,
+ this: Model<Self>,
envelope: TypedEnvelope<proto::RenameProjectEntry>,
_: Arc<Client>,
mut cx: AsyncAppContext,
@@ -6865,7 +6865,7 @@ impl Project {
}
async fn handle_copy_project_entry(
- this: Handle<Self>,
+ this: Model<Self>,
envelope: TypedEnvelope<proto::CopyProjectEntry>,
_: Arc<Client>,
mut cx: AsyncAppContext,
@@ -6893,7 +6893,7 @@ impl Project {
}
async fn handle_delete_project_entry(
- this: Handle<Self>,
+ this: Model<Self>,
envelope: TypedEnvelope<proto::DeleteProjectEntry>,
_: Arc<Client>,
mut cx: AsyncAppContext,
@@ -6923,7 +6923,7 @@ impl Project {
}
async fn handle_expand_project_entry(
- this: Handle<Self>,
+ this: Model<Self>,
envelope: TypedEnvelope<proto::ExpandProjectEntry>,
_: Arc<Client>,
mut cx: AsyncAppContext,
@@ -6946,7 +6946,7 @@ impl Project {
}
async fn handle_update_diagnostic_summary(
- this: Handle<Self>,
+ this: Model<Self>,
envelope: TypedEnvelope<proto::UpdateDiagnosticSummary>,
_: Arc<Client>,
mut cx: AsyncAppContext,
@@ -6976,7 +6976,7 @@ impl Project {
}
async fn handle_start_language_server(
- this: Handle<Self>,
+ this: Model<Self>,
envelope: TypedEnvelope<proto::StartLanguageServer>,
_: Arc<Client>,
mut cx: AsyncAppContext,
@@ -7001,7 +7001,7 @@ impl Project {
}
async fn handle_update_language_server(
- this: Handle<Self>,
+ this: Model<Self>,
envelope: TypedEnvelope<proto::UpdateLanguageServer>,
_: Arc<Client>,
mut cx: AsyncAppContext,
@@ -1,5 +1,5 @@
use crate::Project;
-use gpui2::{AnyWindowHandle, Context, Handle, ModelContext, WeakHandle};
+use gpui2::{AnyWindowHandle, Context, Model, ModelContext, WeakModel};
use settings2::Settings;
use std::path::{Path, PathBuf};
use terminal2::{
@@ -11,7 +11,7 @@ use terminal2::{
use std::os::unix::ffi::OsStrExt;
pub struct Terminals {
- pub(crate) local_handles: Vec<WeakHandle<terminal2::Terminal>>,
+ pub(crate) local_handles: Vec<WeakModel<terminal2::Terminal>>,
}
impl Project {
@@ -20,7 +20,7 @@ impl Project {
working_directory: Option<PathBuf>,
window: AnyWindowHandle,
cx: &mut ModelContext<Self>,
- ) -> anyhow::Result<Handle<Terminal>> {
+ ) -> anyhow::Result<Model<Terminal>> {
if self.is_remote() {
return Err(anyhow::anyhow!(
"creating terminals as a guest is not supported yet"
@@ -40,7 +40,7 @@ impl Project {
|_, _| todo!("color_for_index"),
)
.map(|builder| {
- let terminal_handle = cx.entity(|cx| builder.subscribe(cx));
+ let terminal_handle = cx.build_model(|cx| builder.subscribe(cx));
self.terminals
.local_handles
@@ -108,7 +108,7 @@ impl Project {
fn activate_python_virtual_environment(
&mut self,
activate_script: Option<PathBuf>,
- terminal_handle: &Handle<Terminal>,
+ terminal_handle: &Model<Terminal>,
cx: &mut ModelContext<Project>,
) {
if let Some(activate_script) = activate_script {
@@ -121,7 +121,7 @@ impl Project {
}
}
- pub fn local_terminal_handles(&self) -> &Vec<WeakHandle<terminal2::Terminal>> {
+ pub fn local_terminal_handles(&self) -> &Vec<WeakModel<terminal2::Terminal>> {
&self.terminals.local_handles
}
}
@@ -6,7 +6,7 @@ use anyhow::{anyhow, Context as _, Result};
use client2::{proto, Client};
use clock::ReplicaId;
use collections::{HashMap, HashSet, VecDeque};
-use fs::{
+use fs2::{
repository::{GitFileStatus, GitRepository, RepoPath},
Fs,
};
@@ -22,7 +22,7 @@ use futures::{
use fuzzy2::CharBag;
use git::{DOT_GIT, GITIGNORE};
use gpui2::{
- AppContext, AsyncAppContext, Context, EventEmitter, Executor, Handle, ModelContext, Task,
+ AppContext, AsyncAppContext, Context, EventEmitter, Executor, Model, ModelContext, Task,
};
use language2::{
proto::{
@@ -292,7 +292,7 @@ impl Worktree {
fs: Arc<dyn Fs>,
next_entry_id: Arc<AtomicUsize>,
cx: &mut AsyncAppContext,
- ) -> Result<Handle<Self>> {
+ ) -> Result<Model<Self>> {
// After determining whether the root entry is a file or a directory, populate the
// snapshot's "root name", which will be used for the purpose of fuzzy matching.
let abs_path = path.into();
@@ -301,7 +301,7 @@ impl Worktree {
.await
.context("failed to stat worktree path")?;
- cx.entity(move |cx: &mut ModelContext<Worktree>| {
+ cx.build_model(move |cx: &mut ModelContext<Worktree>| {
let root_name = abs_path
.file_name()
.map_or(String::new(), |f| f.to_string_lossy().to_string());
@@ -406,8 +406,8 @@ impl Worktree {
worktree: proto::WorktreeMetadata,
client: Arc<Client>,
cx: &mut AppContext,
- ) -> Handle<Self> {
- cx.entity(|cx: &mut ModelContext<Self>| {
+ ) -> Model<Self> {
+ cx.build_model(|cx: &mut ModelContext<Self>| {
let snapshot = Snapshot {
id: WorktreeId(worktree.id as usize),
abs_path: Arc::from(PathBuf::from(worktree.abs_path)),
@@ -593,7 +593,7 @@ impl LocalWorktree {
id: u64,
path: &Path,
cx: &mut ModelContext<Worktree>,
- ) -> Task<Result<Handle<Buffer>>> {
+ ) -> Task<Result<Model<Buffer>>> {
let path = Arc::from(path);
cx.spawn(move |this, mut cx| async move {
let (file, contents, diff_base) = this
@@ -603,7 +603,7 @@ impl LocalWorktree {
.executor()
.spawn(async move { text::Buffer::new(0, id, contents) })
.await;
- cx.entity(|_| Buffer::build(text_buffer, diff_base, Some(Arc::new(file))))
+ cx.build_model(|_| Buffer::build(text_buffer, diff_base, Some(Arc::new(file))))
})
}
@@ -920,7 +920,7 @@ impl LocalWorktree {
pub fn save_buffer(
&self,
- buffer_handle: Handle<Buffer>,
+ buffer_handle: Model<Buffer>,
path: Arc<Path>,
has_changed_file: bool,
cx: &mut ModelContext<Worktree>,
@@ -1331,7 +1331,7 @@ impl RemoteWorktree {
pub fn save_buffer(
&self,
- buffer_handle: Handle<Buffer>,
+ buffer_handle: Model<Buffer>,
cx: &mut ModelContext<Worktree>,
) -> Task<Result<()>> {
let buffer = buffer_handle.read(cx);
@@ -2577,7 +2577,7 @@ impl fmt::Debug for Snapshot {
#[derive(Clone, PartialEq)]
pub struct File {
- pub worktree: Handle<Worktree>,
+ pub worktree: Model<Worktree>,
pub path: Arc<Path>,
pub mtime: SystemTime,
pub(crate) entry_id: ProjectEntryId,
@@ -2701,7 +2701,7 @@ impl language2::LocalFile for File {
}
impl File {
- pub fn for_entry(entry: Entry, worktree: Handle<Worktree>) -> Arc<Self> {
+ pub fn for_entry(entry: Entry, worktree: Model<Worktree>) -> Arc<Self> {
Arc::new(Self {
worktree,
path: entry.path.clone(),
@@ -2714,7 +2714,7 @@ impl File {
pub fn from_proto(
proto: rpc2::proto::File,
- worktree: Handle<Worktree>,
+ worktree: Model<Worktree>,
cx: &AppContext,
) -> Result<Self> {
let worktree_id = worktree
@@ -2815,7 +2815,7 @@ pub type UpdatedGitRepositoriesSet = Arc<[(Arc<Path>, GitRepositoryChange)]>;
impl Entry {
fn new(
path: Arc<Path>,
- metadata: &fs::Metadata,
+ metadata: &fs2::Metadata,
next_entry_id: &AtomicUsize,
root_char_bag: CharBag,
) -> Self {
@@ -42,6 +42,7 @@ sha1 = "0.10.5"
ndarray = { version = "0.15.0" }
[dev-dependencies]
+ai = { path = "../ai", features = ["test-support"] }
collections = { path = "../collections", features = ["test-support"] }
gpui = { path = "../gpui", features = ["test-support"] }
language = { path = "../language", features = ["test-support"] }
@@ -41,7 +41,6 @@ pub struct EmbeddingQueue {
pending_batch_token_count: usize,
finished_files_tx: channel::Sender<FileToEmbed>,
finished_files_rx: channel::Receiver<FileToEmbed>,
- api_key: Option<String>,
}
#[derive(Clone)]
@@ -51,11 +50,7 @@ pub struct FileFragmentToEmbed {
}
impl EmbeddingQueue {
- pub fn new(
- embedding_provider: Arc<dyn EmbeddingProvider>,
- executor: Arc<Background>,
- api_key: Option<String>,
- ) -> Self {
+ pub fn new(embedding_provider: Arc<dyn EmbeddingProvider>, executor: Arc<Background>) -> Self {
let (finished_files_tx, finished_files_rx) = channel::unbounded();
Self {
embedding_provider,
@@ -64,14 +59,9 @@ impl EmbeddingQueue {
pending_batch_token_count: 0,
finished_files_tx,
finished_files_rx,
- api_key,
}
}
- pub fn set_api_key(&mut self, api_key: Option<String>) {
- self.api_key = api_key
- }
-
pub fn push(&mut self, file: FileToEmbed) {
if file.spans.is_empty() {
self.finished_files_tx.try_send(file).unwrap();
@@ -118,7 +108,6 @@ impl EmbeddingQueue {
let finished_files_tx = self.finished_files_tx.clone();
let embedding_provider = self.embedding_provider.clone();
- let api_key = self.api_key.clone();
self.executor
.spawn(async move {
@@ -143,7 +132,7 @@ impl EmbeddingQueue {
return;
};
- match embedding_provider.embed_batch(spans, api_key).await {
+ match embedding_provider.embed_batch(spans).await {
Ok(embeddings) => {
let mut embeddings = embeddings.into_iter();
for fragment in batch {
@@ -1,4 +1,7 @@
-use ai::embedding::{Embedding, EmbeddingProvider};
+use ai::{
+ embedding::{Embedding, EmbeddingProvider},
+ models::TruncationDirection,
+};
use anyhow::{anyhow, Result};
use language::{Grammar, Language};
use rusqlite::{
@@ -108,7 +111,14 @@ impl CodeContextRetriever {
.replace("<language>", language_name.as_ref())
.replace("<item>", &content);
let digest = SpanDigest::from(document_span.as_str());
- let (document_span, token_count) = self.embedding_provider.truncate(&document_span);
+ let model = self.embedding_provider.base_model();
+ let document_span = model.truncate(
+ &document_span,
+ model.capacity()?,
+ ai::models::TruncationDirection::End,
+ )?;
+ let token_count = model.count_tokens(&document_span)?;
+
Ok(vec![Span {
range: 0..content.len(),
content: document_span,
@@ -131,7 +141,15 @@ impl CodeContextRetriever {
)
.replace("<item>", &content);
let digest = SpanDigest::from(document_span.as_str());
- let (document_span, token_count) = self.embedding_provider.truncate(&document_span);
+
+ let model = self.embedding_provider.base_model();
+ let document_span = model.truncate(
+ &document_span,
+ model.capacity()?,
+ ai::models::TruncationDirection::End,
+ )?;
+ let token_count = model.count_tokens(&document_span)?;
+
Ok(vec![Span {
range: 0..content.len(),
content: document_span,
@@ -222,8 +240,13 @@ impl CodeContextRetriever {
.replace("<language>", language_name.as_ref())
.replace("item", &span.content);
- let (document_content, token_count) =
- self.embedding_provider.truncate(&document_content);
+ let model = self.embedding_provider.base_model();
+ let document_content = model.truncate(
+ &document_content,
+ model.capacity()?,
+ TruncationDirection::End,
+ )?;
+ let token_count = model.count_tokens(&document_content)?;
span.content = document_content;
span.token_count = token_count;
@@ -7,7 +7,8 @@ pub mod semantic_index_settings;
mod semantic_index_tests;
use crate::semantic_index_settings::SemanticIndexSettings;
-use ai::embedding::{Embedding, EmbeddingProvider, OpenAIEmbeddings};
+use ai::embedding::{Embedding, EmbeddingProvider};
+use ai::providers::open_ai::OpenAIEmbeddingProvider;
use anyhow::{anyhow, Result};
use collections::{BTreeMap, HashMap, HashSet};
use db::VectorDatabase;
@@ -88,7 +89,7 @@ pub fn init(
let semantic_index = SemanticIndex::new(
fs,
db_file_path,
- Arc::new(OpenAIEmbeddings::new(http_client, cx.background())),
+ Arc::new(OpenAIEmbeddingProvider::new(http_client, cx.background())),
language_registry,
cx.clone(),
)
@@ -123,8 +124,6 @@ pub struct SemanticIndex {
_embedding_task: Task<()>,
_parsing_files_tasks: Vec<Task<()>>,
projects: HashMap<WeakModelHandle<Project>, ProjectState>,
- api_key: Option<String>,
- embedding_queue: Arc<Mutex<EmbeddingQueue>>,
}
struct ProjectState {
@@ -278,18 +277,18 @@ impl SemanticIndex {
}
}
- pub fn authenticate(&mut self, cx: &AppContext) {
- if self.api_key.is_none() {
- self.api_key = self.embedding_provider.retrieve_credentials(cx);
-
- self.embedding_queue
- .lock()
- .set_api_key(self.api_key.clone());
+ pub fn authenticate(&mut self, cx: &AppContext) -> bool {
+ if !self.embedding_provider.has_credentials() {
+ self.embedding_provider.retrieve_credentials(cx);
+ } else {
+ return true;
}
+
+ self.embedding_provider.has_credentials()
}
pub fn is_authenticated(&self) -> bool {
- self.api_key.is_some()
+ self.embedding_provider.has_credentials()
}
pub fn enabled(cx: &AppContext) -> bool {
@@ -339,7 +338,7 @@ impl SemanticIndex {
Ok(cx.add_model(|cx| {
let t0 = Instant::now();
let embedding_queue =
- EmbeddingQueue::new(embedding_provider.clone(), cx.background().clone(), None);
+ EmbeddingQueue::new(embedding_provider.clone(), cx.background().clone());
let _embedding_task = cx.background().spawn({
let embedded_files = embedding_queue.finished_files();
let db = db.clone();
@@ -404,8 +403,6 @@ impl SemanticIndex {
_embedding_task,
_parsing_files_tasks,
projects: Default::default(),
- api_key: None,
- embedding_queue
}
}))
}
@@ -720,13 +717,13 @@ impl SemanticIndex {
let index = self.index_project(project.clone(), cx);
let embedding_provider = self.embedding_provider.clone();
- let api_key = self.api_key.clone();
cx.spawn(|this, mut cx| async move {
index.await?;
let t0 = Instant::now();
+
let query = embedding_provider
- .embed_batch(vec![query], api_key)
+ .embed_batch(vec![query])
.await?
.pop()
.ok_or_else(|| anyhow!("could not embed query"))?;
@@ -944,7 +941,6 @@ impl SemanticIndex {
let fs = self.fs.clone();
let db_path = self.db.path().clone();
let background = cx.background().clone();
- let api_key = self.api_key.clone();
cx.background().spawn(async move {
let db = VectorDatabase::new(fs, db_path.clone(), background).await?;
let mut results = Vec::<SearchResult>::new();
@@ -959,15 +955,10 @@ impl SemanticIndex {
.parse_file_with_template(None, &snapshot.text(), language)
.log_err()
.unwrap_or_default();
- if Self::embed_spans(
- &mut spans,
- embedding_provider.as_ref(),
- &db,
- api_key.clone(),
- )
- .await
- .log_err()
- .is_some()
+ if Self::embed_spans(&mut spans, embedding_provider.as_ref(), &db)
+ .await
+ .log_err()
+ .is_some()
{
for span in spans {
let similarity = span.embedding.unwrap().similarity(&query);
@@ -1007,9 +998,8 @@ impl SemanticIndex {
project: ModelHandle<Project>,
cx: &mut ModelContext<Self>,
) -> Task<Result<()>> {
- if self.api_key.is_none() {
- self.authenticate(cx);
- if self.api_key.is_none() {
+ if !self.is_authenticated() {
+ if !self.authenticate(cx) {
return Task::ready(Err(anyhow!("user is not authenticated")));
}
}
@@ -1192,7 +1182,6 @@ impl SemanticIndex {
spans: &mut [Span],
embedding_provider: &dyn EmbeddingProvider,
db: &VectorDatabase,
- api_key: Option<String>,
) -> Result<()> {
let mut batch = Vec::new();
let mut batch_tokens = 0;
@@ -1215,7 +1204,7 @@ impl SemanticIndex {
if batch_tokens + span.token_count > embedding_provider.max_tokens_per_batch() {
let batch_embeddings = embedding_provider
- .embed_batch(mem::take(&mut batch), api_key.clone())
+ .embed_batch(mem::take(&mut batch))
.await?;
embeddings.extend(batch_embeddings);
batch_tokens = 0;
@@ -1227,7 +1216,7 @@ impl SemanticIndex {
if !batch.is_empty() {
let batch_embeddings = embedding_provider
- .embed_batch(mem::take(&mut batch), api_key)
+ .embed_batch(mem::take(&mut batch))
.await?;
embeddings.extend(batch_embeddings);
@@ -4,10 +4,9 @@ use crate::{
semantic_index_settings::SemanticIndexSettings,
FileToEmbed, JobHandle, SearchResult, SemanticIndex, EMBEDDING_QUEUE_FLUSH_TIMEOUT,
};
-use ai::embedding::{DummyEmbeddings, Embedding, EmbeddingProvider};
-use anyhow::Result;
-use async_trait::async_trait;
-use gpui::{executor::Deterministic, AppContext, Task, TestAppContext};
+use ai::test::FakeEmbeddingProvider;
+
+use gpui::{executor::Deterministic, Task, TestAppContext};
use language::{Language, LanguageConfig, LanguageRegistry, ToOffset};
use parking_lot::Mutex;
use pretty_assertions::assert_eq;
@@ -15,14 +14,7 @@ use project::{project_settings::ProjectSettings, search::PathMatcher, FakeFs, Fs
use rand::{rngs::StdRng, Rng};
use serde_json::json;
use settings::SettingsStore;
-use std::{
- path::Path,
- sync::{
- atomic::{self, AtomicUsize},
- Arc,
- },
- time::{Instant, SystemTime},
-};
+use std::{path::Path, sync::Arc, time::SystemTime};
use unindent::Unindent;
use util::RandomCharIter;
@@ -228,7 +220,7 @@ async fn test_embedding_batching(cx: &mut TestAppContext, mut rng: StdRng) {
let embedding_provider = Arc::new(FakeEmbeddingProvider::default());
- let mut queue = EmbeddingQueue::new(embedding_provider.clone(), cx.background(), None);
+ let mut queue = EmbeddingQueue::new(embedding_provider.clone(), cx.background());
for file in &files {
queue.push(file.clone());
}
@@ -280,7 +272,7 @@ fn assert_search_results(
#[gpui::test]
async fn test_code_context_retrieval_rust() {
let language = rust_lang();
- let embedding_provider = Arc::new(DummyEmbeddings {});
+ let embedding_provider = Arc::new(FakeEmbeddingProvider::default());
let mut retriever = CodeContextRetriever::new(embedding_provider);
let text = "
@@ -382,7 +374,7 @@ async fn test_code_context_retrieval_rust() {
#[gpui::test]
async fn test_code_context_retrieval_json() {
let language = json_lang();
- let embedding_provider = Arc::new(DummyEmbeddings {});
+ let embedding_provider = Arc::new(FakeEmbeddingProvider::default());
let mut retriever = CodeContextRetriever::new(embedding_provider);
let text = r#"
@@ -466,7 +458,7 @@ fn assert_documents_eq(
#[gpui::test]
async fn test_code_context_retrieval_javascript() {
let language = js_lang();
- let embedding_provider = Arc::new(DummyEmbeddings {});
+ let embedding_provider = Arc::new(FakeEmbeddingProvider::default());
let mut retriever = CodeContextRetriever::new(embedding_provider);
let text = "
@@ -565,7 +557,7 @@ async fn test_code_context_retrieval_javascript() {
#[gpui::test]
async fn test_code_context_retrieval_lua() {
let language = lua_lang();
- let embedding_provider = Arc::new(DummyEmbeddings {});
+ let embedding_provider = Arc::new(FakeEmbeddingProvider::default());
let mut retriever = CodeContextRetriever::new(embedding_provider);
let text = r#"
@@ -639,7 +631,7 @@ async fn test_code_context_retrieval_lua() {
#[gpui::test]
async fn test_code_context_retrieval_elixir() {
let language = elixir_lang();
- let embedding_provider = Arc::new(DummyEmbeddings {});
+ let embedding_provider = Arc::new(FakeEmbeddingProvider::default());
let mut retriever = CodeContextRetriever::new(embedding_provider);
let text = r#"
@@ -756,7 +748,7 @@ async fn test_code_context_retrieval_elixir() {
#[gpui::test]
async fn test_code_context_retrieval_cpp() {
let language = cpp_lang();
- let embedding_provider = Arc::new(DummyEmbeddings {});
+ let embedding_provider = Arc::new(FakeEmbeddingProvider::default());
let mut retriever = CodeContextRetriever::new(embedding_provider);
let text = "
@@ -909,7 +901,7 @@ async fn test_code_context_retrieval_cpp() {
#[gpui::test]
async fn test_code_context_retrieval_ruby() {
let language = ruby_lang();
- let embedding_provider = Arc::new(DummyEmbeddings {});
+ let embedding_provider = Arc::new(FakeEmbeddingProvider::default());
let mut retriever = CodeContextRetriever::new(embedding_provider);
let text = r#"
@@ -1100,7 +1092,7 @@ async fn test_code_context_retrieval_ruby() {
#[gpui::test]
async fn test_code_context_retrieval_php() {
let language = php_lang();
- let embedding_provider = Arc::new(DummyEmbeddings {});
+ let embedding_provider = Arc::new(FakeEmbeddingProvider::default());
let mut retriever = CodeContextRetriever::new(embedding_provider);
let text = r#"
@@ -1248,65 +1240,6 @@ async fn test_code_context_retrieval_php() {
);
}
-#[derive(Default)]
-struct FakeEmbeddingProvider {
- embedding_count: AtomicUsize,
-}
-
-impl FakeEmbeddingProvider {
- fn embedding_count(&self) -> usize {
- self.embedding_count.load(atomic::Ordering::SeqCst)
- }
-
- fn embed_sync(&self, span: &str) -> Embedding {
- let mut result = vec![1.0; 26];
- for letter in span.chars() {
- let letter = letter.to_ascii_lowercase();
- if letter as u32 >= 'a' as u32 {
- let ix = (letter as u32) - ('a' as u32);
- if ix < 26 {
- result[ix as usize] += 1.0;
- }
- }
- }
-
- let norm = result.iter().map(|x| x * x).sum::<f32>().sqrt();
- for x in &mut result {
- *x /= norm;
- }
-
- result.into()
- }
-}
-
-#[async_trait]
-impl EmbeddingProvider for FakeEmbeddingProvider {
- fn retrieve_credentials(&self, _cx: &AppContext) -> Option<String> {
- Some("Fake Credentials".to_string())
- }
- fn truncate(&self, span: &str) -> (String, usize) {
- (span.to_string(), 1)
- }
-
- fn max_tokens_per_batch(&self) -> usize {
- 200
- }
-
- fn rate_limit_expiration(&self) -> Option<Instant> {
- None
- }
-
- async fn embed_batch(
- &self,
- spans: Vec<String>,
- _api_key: Option<String>,
- ) -> Result<Vec<Embedding>> {
- self.embedding_count
- .fetch_add(spans.len(), atomic::Ordering::SeqCst);
- Ok(spans.iter().map(|span| self.embed_sync(span)).collect())
- }
-}
-
fn js_lang() -> Arc<Language> {
Arc::new(
Language::new(
@@ -1,9 +1,11 @@
+mod colors;
mod focus;
mod kitchen_sink;
mod scroll;
mod text;
mod z_index;
+pub use colors::*;
pub use focus::*;
pub use kitchen_sink::*;
pub use scroll::*;
@@ -0,0 +1,38 @@
+use crate::story::Story;
+use gpui2::{px, Div, Render};
+use ui::prelude::*;
+
+pub struct ColorsStory;
+
+impl Render for ColorsStory {
+ type Element = Div<Self>;
+
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
+ let color_scales = theme2::default_color_scales();
+
+ Story::container(cx)
+ .child(Story::title(cx, "Colors"))
+ .child(
+ div()
+ .id("colors")
+ .flex()
+ .flex_col()
+ .gap_1()
+ .overflow_y_scroll()
+ .text_color(gpui2::white())
+ .children(color_scales.into_iter().map(|(name, scale)| {
+ div()
+ .flex()
+ .child(
+ div()
+ .w(px(75.))
+ .line_height(px(24.))
+ .child(name.to_string()),
+ )
+ .child(div().flex().gap_1().children(
+ (1..=12).map(|step| div().flex().size_6().bg(scale.step(cx, step))),
+ ))
+ })),
+ )
+ }
+}
@@ -1,9 +1,9 @@
-use crate::themes::rose_pine;
use gpui2::{
- div, Focusable, KeyBinding, ParentElement, StatelessInteractive, Styled, View, VisualContext,
- WindowContext,
+ div, Div, FocusEnabled, Focusable, KeyBinding, ParentElement, Render, StatefulInteraction,
+ StatelessInteractive, Styled, View, VisualContext, WindowContext,
};
use serde::Deserialize;
+use theme2::theme;
#[derive(Clone, Default, PartialEq, Deserialize)]
struct ActionA;
@@ -14,12 +14,10 @@ struct ActionB;
#[derive(Clone, Default, PartialEq, Deserialize)]
struct ActionC;
-pub struct FocusStory {
- text: View<()>,
-}
+pub struct FocusStory {}
impl FocusStory {
- pub fn view(cx: &mut WindowContext) -> View<()> {
+ pub fn view(cx: &mut WindowContext) -> View<Self> {
cx.bind_keys([
KeyBinding::new("cmd-a", ActionA, Some("parent")),
KeyBinding::new("cmd-a", ActionB, Some("child-1")),
@@ -27,91 +25,92 @@ impl FocusStory {
]);
cx.register_action_type::<ActionA>();
cx.register_action_type::<ActionB>();
- let theme = rose_pine();
- let color_1 = theme.lowest.negative.default.foreground;
- let color_2 = theme.lowest.positive.default.foreground;
- let color_3 = theme.lowest.warning.default.foreground;
- let color_4 = theme.lowest.accent.default.foreground;
- let color_5 = theme.lowest.variant.default.foreground;
- let color_6 = theme.highest.negative.default.foreground;
+ cx.build_view(move |cx| Self {})
+ }
+}
+
+impl Render for FocusStory {
+ type Element = Div<Self, StatefulInteraction<Self>, FocusEnabled<Self>>;
+
+ fn render(&mut self, cx: &mut gpui2::ViewContext<Self>) -> Self::Element {
+ let theme = theme(cx);
+ let color_1 = theme.git_created;
+ let color_2 = theme.git_modified;
+ let color_3 = theme.git_deleted;
+ let color_4 = theme.git_conflict;
+ let color_5 = theme.git_ignored;
+ let color_6 = theme.git_renamed;
let child_1 = cx.focus_handle();
let child_2 = cx.focus_handle();
- cx.build_view(
- |_| (),
- move |_, cx| {
+ div()
+ .id("parent")
+ .focusable()
+ .context("parent")
+ .on_action(|_, action: &ActionA, phase, cx| {
+ println!("Action A dispatched on parent during {:?}", phase);
+ })
+ .on_action(|_, action: &ActionB, phase, cx| {
+ println!("Action B dispatched on parent during {:?}", phase);
+ })
+ .on_focus(|_, _, _| println!("Parent focused"))
+ .on_blur(|_, _, _| println!("Parent blurred"))
+ .on_focus_in(|_, _, _| println!("Parent focus_in"))
+ .on_focus_out(|_, _, _| println!("Parent focus_out"))
+ .on_key_down(|_, event, phase, _| {
+ println!("Key down on parent {:?} {:?}", phase, event)
+ })
+ .on_key_up(|_, event, phase, _| println!("Key up on parent {:?} {:?}", phase, event))
+ .size_full()
+ .bg(color_1)
+ .focus(|style| style.bg(color_2))
+ .focus_in(|style| style.bg(color_3))
+ .child(
div()
- .id("parent")
- .focusable()
- .context("parent")
- .on_action(|_, action: &ActionA, phase, cx| {
- println!("Action A dispatched on parent during {:?}", phase);
- })
+ .track_focus(&child_1)
+ .context("child-1")
.on_action(|_, action: &ActionB, phase, cx| {
- println!("Action B dispatched on parent during {:?}", phase);
+ println!("Action B dispatched on child 1 during {:?}", phase);
+ })
+ .w_full()
+ .h_6()
+ .bg(color_4)
+ .focus(|style| style.bg(color_5))
+ .in_focus(|style| style.bg(color_6))
+ .on_focus(|_, _, _| println!("Child 1 focused"))
+ .on_blur(|_, _, _| println!("Child 1 blurred"))
+ .on_focus_in(|_, _, _| println!("Child 1 focus_in"))
+ .on_focus_out(|_, _, _| println!("Child 1 focus_out"))
+ .on_key_down(|_, event, phase, _| {
+ println!("Key down on child 1 {:?} {:?}", phase, event)
+ })
+ .on_key_up(|_, event, phase, _| {
+ println!("Key up on child 1 {:?} {:?}", phase, event)
+ })
+ .child("Child 1"),
+ )
+ .child(
+ div()
+ .track_focus(&child_2)
+ .context("child-2")
+ .on_action(|_, action: &ActionC, phase, cx| {
+ println!("Action C dispatched on child 2 during {:?}", phase);
})
- .on_focus(|_, _, _| println!("Parent focused"))
- .on_blur(|_, _, _| println!("Parent blurred"))
- .on_focus_in(|_, _, _| println!("Parent focus_in"))
- .on_focus_out(|_, _, _| println!("Parent focus_out"))
+ .w_full()
+ .h_6()
+ .bg(color_4)
+ .on_focus(|_, _, _| println!("Child 2 focused"))
+ .on_blur(|_, _, _| println!("Child 2 blurred"))
+ .on_focus_in(|_, _, _| println!("Child 2 focus_in"))
+ .on_focus_out(|_, _, _| println!("Child 2 focus_out"))
.on_key_down(|_, event, phase, _| {
- println!("Key down on parent {:?} {:?}", phase, event)
+ println!("Key down on child 2 {:?} {:?}", phase, event)
})
.on_key_up(|_, event, phase, _| {
- println!("Key up on parent {:?} {:?}", phase, event)
+ println!("Key up on child 2 {:?} {:?}", phase, event)
})
- .size_full()
- .bg(color_1)
- .focus(|style| style.bg(color_2))
- .focus_in(|style| style.bg(color_3))
- .child(
- div()
- .track_focus(&child_1)
- .context("child-1")
- .on_action(|_, action: &ActionB, phase, cx| {
- println!("Action B dispatched on child 1 during {:?}", phase);
- })
- .w_full()
- .h_6()
- .bg(color_4)
- .focus(|style| style.bg(color_5))
- .in_focus(|style| style.bg(color_6))
- .on_focus(|_, _, _| println!("Child 1 focused"))
- .on_blur(|_, _, _| println!("Child 1 blurred"))
- .on_focus_in(|_, _, _| println!("Child 1 focus_in"))
- .on_focus_out(|_, _, _| println!("Child 1 focus_out"))
- .on_key_down(|_, event, phase, _| {
- println!("Key down on child 1 {:?} {:?}", phase, event)
- })
- .on_key_up(|_, event, phase, _| {
- println!("Key up on child 1 {:?} {:?}", phase, event)
- })
- .child("Child 1"),
- )
- .child(
- div()
- .track_focus(&child_2)
- .context("child-2")
- .on_action(|_, action: &ActionC, phase, cx| {
- println!("Action C dispatched on child 2 during {:?}", phase);
- })
- .w_full()
- .h_6()
- .bg(color_4)
- .on_focus(|_, _, _| println!("Child 2 focused"))
- .on_blur(|_, _, _| println!("Child 2 blurred"))
- .on_focus_in(|_, _, _| println!("Child 2 focus_in"))
- .on_focus_out(|_, _, _| println!("Child 2 focus_out"))
- .on_key_down(|_, event, phase, _| {
- println!("Key down on child 2 {:?} {:?}", phase, event)
- })
- .on_key_up(|_, event, phase, _| {
- println!("Key up on child 2 {:?} {:?}", phase, event)
- })
- .child("Child 2"),
- )
- },
- )
+ .child("Child 2"),
+ )
}
}
@@ -1,26 +1,23 @@
-use gpui2::{AppContext, Context, View};
+use crate::{
+ story::Story,
+ story_selector::{ComponentStory, ElementStory},
+};
+use gpui2::{Div, Render, StatefulInteraction, View, VisualContext};
use strum::IntoEnumIterator;
use ui::prelude::*;
-use crate::story::Story;
-use crate::story_selector::{ComponentStory, ElementStory};
-
-pub struct KitchenSinkStory {}
+pub struct KitchenSinkStory;
impl KitchenSinkStory {
- pub fn new() -> Self {
- Self {}
+ pub fn view(cx: &mut WindowContext) -> View<Self> {
+ cx.build_view(|cx| Self)
}
+}
- pub fn view(cx: &mut AppContext) -> View<Self> {
- {
- let state = cx.entity(|cx| Self::new());
- let render = Self::render;
- View::for_handle(state, render)
- }
- }
+impl Render for KitchenSinkStory {
+ type Element = Div<Self, StatefulInteraction<Self>>;
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Component<Self> {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
let element_stories = ElementStory::iter()
.map(|selector| selector.story(cx))
.collect::<Vec<_>>();
@@ -1,58 +1,54 @@
-use crate::themes::rose_pine;
use gpui2::{
- div, px, Component, ParentElement, SharedString, Styled, View, VisualContext, WindowContext,
+ div, px, Component, Div, ParentElement, Render, SharedString, StatefulInteraction, Styled,
+ View, VisualContext, WindowContext,
};
+use theme2::theme;
-pub struct ScrollStory {
- text: View<()>,
-}
+pub struct ScrollStory;
impl ScrollStory {
- pub fn view(cx: &mut WindowContext) -> View<()> {
- let theme = rose_pine();
-
- {
- cx.build_view(|cx| (), move |_, cx| checkerboard(1))
- }
+ pub fn view(cx: &mut WindowContext) -> View<ScrollStory> {
+ cx.build_view(|cx| ScrollStory)
}
}
-fn checkerboard<S>(depth: usize) -> impl Component<S>
-where
- S: 'static + Send + Sync,
-{
- let theme = rose_pine();
- let color_1 = theme.lowest.positive.default.background;
- let color_2 = theme.lowest.warning.default.background;
+impl Render for ScrollStory {
+ type Element = Div<Self, StatefulInteraction<Self>>;
- div()
- .id("parent")
- .bg(theme.lowest.base.default.background)
- .size_full()
- .overflow_scroll()
- .children((0..10).map(|row| {
- div()
- .w(px(1000.))
- .h(px(100.))
- .flex()
- .flex_row()
- .children((0..10).map(|column| {
- let id = SharedString::from(format!("{}, {}", row, column));
- let bg = if row % 2 == column % 2 {
- color_1
- } else {
- color_2
- };
- div().id(id).bg(bg).size(px(100. / depth as f32)).when(
- row >= 5 && column >= 5,
- |d| {
- d.overflow_scroll()
- .child(div().size(px(50.)).bg(color_1))
- .child(div().size(px(50.)).bg(color_2))
- .child(div().size(px(50.)).bg(color_1))
- .child(div().size(px(50.)).bg(color_2))
- },
- )
- }))
- }))
+ fn render(&mut self, cx: &mut gpui2::ViewContext<Self>) -> Self::Element {
+ let theme = theme(cx);
+ let color_1 = theme.git_created;
+ let color_2 = theme.git_modified;
+
+ div()
+ .id("parent")
+ .bg(theme.background)
+ .size_full()
+ .overflow_scroll()
+ .children((0..10).map(|row| {
+ div()
+ .w(px(1000.))
+ .h(px(100.))
+ .flex()
+ .flex_row()
+ .children((0..10).map(|column| {
+ let id = SharedString::from(format!("{}, {}", row, column));
+ let bg = if row % 2 == column % 2 {
+ color_1
+ } else {
+ color_2
+ };
+ div().id(id).bg(bg).size(px(100. as f32)).when(
+ row >= 5 && column >= 5,
+ |d| {
+ d.overflow_scroll()
+ .child(div().size(px(50.)).bg(color_1))
+ .child(div().size(px(50.)).bg(color_2))
+ .child(div().size(px(50.)).bg(color_1))
+ .child(div().size(px(50.)).bg(color_2))
+ },
+ )
+ }))
+ }))
+ }
}
@@ -1,20 +1,21 @@
-use gpui2::{div, white, ParentElement, Styled, View, VisualContext, WindowContext};
+use gpui2::{div, white, Div, ParentElement, Render, Styled, View, VisualContext, WindowContext};
-pub struct TextStory {
- text: View<()>,
-}
+pub struct TextStory;
impl TextStory {
- pub fn view(cx: &mut WindowContext) -> View<()> {
- cx.build_view(|cx| (), |_, cx| {
- div()
- .size_full()
- .bg(white())
- .child(concat!(
- "The quick brown fox jumps over the lazy dog. ",
- "Meanwhile, the lazy dog decided it was time for a change. ",
- "He started daily workout routines, ate healthier and became the fastest dog in town.",
- ))
- })
+ pub fn view(cx: &mut WindowContext) -> View<Self> {
+ cx.build_view(|cx| Self)
+ }
+}
+
+impl Render for TextStory {
+ type Element = Div<Self>;
+
+ fn render(&mut self, cx: &mut gpui2::ViewContext<Self>) -> Self::Element {
+ div().size_full().bg(white()).child(concat!(
+ "The quick brown fox jumps over the lazy dog. ",
+ "Meanwhile, the lazy dog decided it was time for a change. ",
+ "He started daily workout routines, ate healthier and became the fastest dog in town.",
+ ))
}
}
@@ -1,15 +1,16 @@
-use gpui2::{px, rgb, Div, Hsla};
+use gpui2::{px, rgb, Div, Hsla, Render};
use ui::prelude::*;
use crate::story::Story;
/// A reimplementation of the MDN `z-index` example, found here:
/// [https://developer.mozilla.org/en-US/docs/Web/CSS/z-index](https://developer.mozilla.org/en-US/docs/Web/CSS/z-index).
-#[derive(Component)]
pub struct ZIndexStory;
-impl ZIndexStory {
- fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
+impl Render for ZIndexStory {
+ type Element = Div<Self>;
+
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
Story::container(cx)
.child(Story::title(cx, "z-index"))
.child(
@@ -7,13 +7,14 @@ use clap::builder::PossibleValue;
use clap::ValueEnum;
use gpui2::{AnyView, VisualContext};
use strum::{EnumIter, EnumString, IntoEnumIterator};
-use ui::prelude::*;
+use ui::{prelude::*, AvatarStory, ButtonStory, DetailsStory, IconStory, InputStory, LabelStory};
#[derive(Debug, PartialEq, Eq, Clone, Copy, strum::Display, EnumString, EnumIter)]
#[strum(serialize_all = "snake_case")]
pub enum ElementStory {
Avatar,
Button,
+ Colors,
Details,
Focus,
Icon,
@@ -27,18 +28,17 @@ pub enum ElementStory {
impl ElementStory {
pub fn story(&self, cx: &mut WindowContext) -> AnyView {
match self {
- Self::Avatar => { cx.build_view(|cx| (), |_, _| ui::AvatarStory.render()) }.into_any(),
- Self::Button => { cx.build_view(|cx| (), |_, _| ui::ButtonStory.render()) }.into_any(),
- Self::Details => {
- { cx.build_view(|cx| (), |_, _| ui::DetailsStory.render()) }.into_any()
- }
+ Self::Colors => cx.build_view(|_| ColorsStory).into_any(),
+ Self::Avatar => cx.build_view(|_| AvatarStory).into_any(),
+ Self::Button => cx.build_view(|_| ButtonStory).into_any(),
+ Self::Details => cx.build_view(|_| DetailsStory).into_any(),
Self::Focus => FocusStory::view(cx).into_any(),
- Self::Icon => { cx.build_view(|cx| (), |_, _| ui::IconStory.render()) }.into_any(),
- Self::Input => { cx.build_view(|cx| (), |_, _| ui::InputStory.render()) }.into_any(),
- Self::Label => { cx.build_view(|cx| (), |_, _| ui::LabelStory.render()) }.into_any(),
+ Self::Icon => cx.build_view(|_| IconStory).into_any(),
+ Self::Input => cx.build_view(|_| InputStory).into_any(),
+ Self::Label => cx.build_view(|_| LabelStory).into_any(),
Self::Scroll => ScrollStory::view(cx).into_any(),
Self::Text => TextStory::view(cx).into_any(),
- Self::ZIndex => { cx.build_view(|cx| (), |_, _| ZIndexStory.render()) }.into_any(),
+ Self::ZIndex => cx.build_view(|_| ZIndexStory).into_any(),
}
}
}
@@ -77,69 +77,31 @@ pub enum ComponentStory {
impl ComponentStory {
pub fn story(&self, cx: &mut WindowContext) -> AnyView {
match self {
- Self::AssistantPanel => {
- { cx.build_view(|cx| (), |_, _| ui::AssistantPanelStory.render()) }.into_any()
- }
- Self::Buffer => { cx.build_view(|cx| (), |_, _| ui::BufferStory.render()) }.into_any(),
- Self::Breadcrumb => {
- { cx.build_view(|cx| (), |_, _| ui::BreadcrumbStory.render()) }.into_any()
- }
- Self::ChatPanel => {
- { cx.build_view(|cx| (), |_, _| ui::ChatPanelStory.render()) }.into_any()
- }
- Self::CollabPanel => {
- { cx.build_view(|cx| (), |_, _| ui::CollabPanelStory.render()) }.into_any()
- }
- Self::CommandPalette => {
- { cx.build_view(|cx| (), |_, _| ui::CommandPaletteStory.render()) }.into_any()
- }
- Self::ContextMenu => {
- { cx.build_view(|cx| (), |_, _| ui::ContextMenuStory.render()) }.into_any()
- }
- Self::Facepile => {
- { cx.build_view(|cx| (), |_, _| ui::FacepileStory.render()) }.into_any()
- }
- Self::Keybinding => {
- { cx.build_view(|cx| (), |_, _| ui::KeybindingStory.render()) }.into_any()
- }
- Self::LanguageSelector => {
- { cx.build_view(|cx| (), |_, _| ui::LanguageSelectorStory.render()) }.into_any()
- }
- Self::MultiBuffer => {
- { cx.build_view(|cx| (), |_, _| ui::MultiBufferStory.render()) }.into_any()
- }
- Self::NotificationsPanel => {
- { cx.build_view(|cx| (), |_, _| ui::NotificationsPanelStory.render()) }.into_any()
- }
- Self::Palette => {
- { cx.build_view(|cx| (), |_, _| ui::PaletteStory.render()) }.into_any()
- }
- Self::Panel => { cx.build_view(|cx| (), |_, _| ui::PanelStory.render()) }.into_any(),
- Self::ProjectPanel => {
- { cx.build_view(|cx| (), |_, _| ui::ProjectPanelStory.render()) }.into_any()
- }
- Self::RecentProjects => {
- { cx.build_view(|cx| (), |_, _| ui::RecentProjectsStory.render()) }.into_any()
- }
- Self::Tab => { cx.build_view(|cx| (), |_, _| ui::TabStory.render()) }.into_any(),
- Self::TabBar => { cx.build_view(|cx| (), |_, _| ui::TabBarStory.render()) }.into_any(),
- Self::Terminal => {
- { cx.build_view(|cx| (), |_, _| ui::TerminalStory.render()) }.into_any()
- }
- Self::ThemeSelector => {
- { cx.build_view(|cx| (), |_, _| ui::ThemeSelectorStory.render()) }.into_any()
- }
+ Self::AssistantPanel => cx.build_view(|_| ui::AssistantPanelStory).into_any(),
+ Self::Buffer => cx.build_view(|_| ui::BufferStory).into_any(),
+ Self::Breadcrumb => cx.build_view(|_| ui::BreadcrumbStory).into_any(),
+ Self::ChatPanel => cx.build_view(|_| ui::ChatPanelStory).into_any(),
+ Self::CollabPanel => cx.build_view(|_| ui::CollabPanelStory).into_any(),
+ Self::CommandPalette => cx.build_view(|_| ui::CommandPaletteStory).into_any(),
+ Self::ContextMenu => cx.build_view(|_| ui::ContextMenuStory).into_any(),
+ Self::Facepile => cx.build_view(|_| ui::FacepileStory).into_any(),
+ Self::Keybinding => cx.build_view(|_| ui::KeybindingStory).into_any(),
+ Self::LanguageSelector => cx.build_view(|_| ui::LanguageSelectorStory).into_any(),
+ Self::MultiBuffer => cx.build_view(|_| ui::MultiBufferStory).into_any(),
+ Self::NotificationsPanel => cx.build_view(|cx| ui::NotificationsPanelStory).into_any(),
+ Self::Palette => cx.build_view(|cx| ui::PaletteStory).into_any(),
+ Self::Panel => cx.build_view(|cx| ui::PanelStory).into_any(),
+ Self::ProjectPanel => cx.build_view(|_| ui::ProjectPanelStory).into_any(),
+ Self::RecentProjects => cx.build_view(|_| ui::RecentProjectsStory).into_any(),
+ Self::Tab => cx.build_view(|_| ui::TabStory).into_any(),
+ Self::TabBar => cx.build_view(|_| ui::TabBarStory).into_any(),
+ Self::Terminal => cx.build_view(|_| ui::TerminalStory).into_any(),
+ Self::ThemeSelector => cx.build_view(|_| ui::ThemeSelectorStory).into_any(),
+ Self::Toast => cx.build_view(|_| ui::ToastStory).into_any(),
+ Self::Toolbar => cx.build_view(|_| ui::ToolbarStory).into_any(),
+ Self::TrafficLights => cx.build_view(|_| ui::TrafficLightsStory).into_any(),
+ Self::Copilot => cx.build_view(|_| ui::CopilotModalStory).into_any(),
Self::TitleBar => ui::TitleBarStory::view(cx).into_any(),
- Self::Toast => { cx.build_view(|cx| (), |_, _| ui::ToastStory.render()) }.into_any(),
- Self::Toolbar => {
- { cx.build_view(|cx| (), |_, _| ui::ToolbarStory.render()) }.into_any()
- }
- Self::TrafficLights => {
- { cx.build_view(|cx| (), |_, _| ui::TrafficLightsStory.render()) }.into_any()
- }
- Self::Copilot => {
- { cx.build_view(|cx| (), |_, _| ui::CopilotModalStory.render()) }.into_any()
- }
Self::Workspace => ui::WorkspaceStory::view(cx).into_any(),
}
}
@@ -4,21 +4,20 @@ mod assets;
mod stories;
mod story;
mod story_selector;
-mod themes;
use std::sync::Arc;
use clap::Parser;
use gpui2::{
- div, px, size, AnyView, AppContext, Bounds, ViewContext, VisualContext, WindowBounds,
- WindowOptions,
+ div, px, size, AnyView, AppContext, Bounds, Div, Render, ViewContext, VisualContext,
+ WindowBounds, WindowOptions,
};
use log::LevelFilter;
use settings2::{default_settings, Settings, SettingsStore};
use simplelog::SimpleLogger;
use story_selector::ComponentStory;
use theme2::{ThemeRegistry, ThemeSettings};
-use ui::{prelude::*, themed};
+use ui::prelude::*;
use crate::assets::Assets;
use crate::story_selector::StorySelector;
@@ -50,7 +49,6 @@ fn main() {
let story_selector = args.story.clone();
let theme_name = args.theme.unwrap_or("One Dark".to_string());
- let theme = themes::load_theme(theme_name.clone()).unwrap();
let asset_source = Arc::new(Assets);
gpui2::App::production(asset_source).run(move |cx| {
@@ -84,12 +82,7 @@ fn main() {
}),
..Default::default()
},
- move |cx| {
- cx.build_view(
- |cx| StoryWrapper::new(selector.story(cx), theme),
- StoryWrapper::render,
- )
- },
+ move |cx| cx.build_view(|cx| StoryWrapper::new(selector.story(cx))),
);
cx.activate(true);
@@ -99,22 +92,23 @@ fn main() {
#[derive(Clone)]
pub struct StoryWrapper {
story: AnyView,
- theme: Theme,
}
impl StoryWrapper {
- pub(crate) fn new(story: AnyView, theme: Theme) -> Self {
- Self { story, theme }
+ pub(crate) fn new(story: AnyView) -> Self {
+ Self { story }
}
+}
+
+impl Render for StoryWrapper {
+ type Element = Div<Self>;
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Component<Self> {
- themed(self.theme.clone(), cx, |cx| {
- div()
- .flex()
- .flex_col()
- .size_full()
- .child(self.story.clone())
- })
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
+ div()
+ .flex()
+ .flex_col()
+ .size_full()
+ .child(self.story.clone())
}
}
@@ -1,30 +0,0 @@
-mod rose_pine;
-
-pub use rose_pine::*;
-
-use anyhow::{Context, Result};
-use gpui2::serde_json;
-use serde::Deserialize;
-use ui::Theme;
-
-use crate::assets::Assets;
-
-#[derive(Deserialize)]
-struct LegacyTheme {
- pub base_theme: serde_json::Value,
-}
-
-/// Loads the [`Theme`] with the given name.
-pub fn load_theme(name: String) -> Result<Theme> {
- let theme_contents = Assets::get(&format!("themes/{name}.json"))
- .with_context(|| format!("theme file not found: '{name}'"))?;
-
- let legacy_theme: LegacyTheme =
- serde_json::from_str(std::str::from_utf8(&theme_contents.data)?)
- .context("failed to parse legacy theme")?;
-
- let theme: Theme = serde_json::from_value(legacy_theme.base_theme.clone())
- .context("failed to parse `base_theme`")?;
-
- Ok(theme)
-}
@@ -1,1686 +0,0 @@
-use gpui2::serde_json::{self, json};
-use ui::Theme;
-
-pub fn rose_pine() -> Theme {
- serde_json::from_value(json! {
- {
- "name": "Rosé Pine",
- "is_light": false,
- "ramps": {},
- "lowest": {
- "base": {
- "default": {
- "background": "#292739",
- "border": "#423f55",
- "foreground": "#e0def4"
- },
- "hovered": {
- "background": "#423f55",
- "border": "#423f55",
- "foreground": "#e0def4"
- },
- "pressed": {
- "background": "#4e4b63",
- "border": "#423f55",
- "foreground": "#e0def4"
- },
- "active": {
- "background": "#47445b",
- "border": "#36334a",
- "foreground": "#e0def4"
- },
- "disabled": {
- "background": "#292739",
- "border": "#353347",
- "foreground": "#2f2b43"
- },
- "inverted": {
- "background": "#e0def4",
- "border": "#191724",
- "foreground": "#4b4860"
- }
- },
- "variant": {
- "default": {
- "background": "#292739",
- "border": "#423f55",
- "foreground": "#75718e"
- },
- "hovered": {
- "background": "#423f55",
- "border": "#423f55",
- "foreground": "#75718e"
- },
- "pressed": {
- "background": "#4e4b63",
- "border": "#423f55",
- "foreground": "#75718e"
- },
- "active": {
- "background": "#47445b",
- "border": "#36334a",
- "foreground": "#e0def4"
- },
- "disabled": {
- "background": "#292739",
- "border": "#353347",
- "foreground": "#2f2b43"
- },
- "inverted": {
- "background": "#e0def4",
- "border": "#191724",
- "foreground": "#4b4860"
- }
- },
- "on": {
- "default": {
- "background": "#1d1b2a",
- "border": "#232132",
- "foreground": "#e0def4"
- },
- "hovered": {
- "background": "#232132",
- "border": "#232132",
- "foreground": "#e0def4"
- },
- "pressed": {
- "background": "#2f2d40",
- "border": "#232132",
- "foreground": "#e0def4"
- },
- "active": {
- "background": "#403e53",
- "border": "#504d65",
- "foreground": "#e0def4"
- },
- "disabled": {
- "background": "#1d1b2a",
- "border": "#1e1c2c",
- "foreground": "#3b384f"
- },
- "inverted": {
- "background": "#e0def4",
- "border": "#191724",
- "foreground": "#3b394e"
- }
- },
- "accent": {
- "default": {
- "background": "#2f3739",
- "border": "#435255",
- "foreground": "#9cced7"
- },
- "hovered": {
- "background": "#435255",
- "border": "#435255",
- "foreground": "#9cced7"
- },
- "pressed": {
- "background": "#4e6164",
- "border": "#435255",
- "foreground": "#9cced7"
- },
- "active": {
- "background": "#5d757a",
- "border": "#6e8f94",
- "foreground": "#fbfdfd"
- },
- "disabled": {
- "background": "#2f3739",
- "border": "#3a4446",
- "foreground": "#85aeb5"
- },
- "inverted": {
- "background": "#fbfdfd",
- "border": "#171717",
- "foreground": "#587074"
- }
- },
- "positive": {
- "default": {
- "background": "#182e23",
- "border": "#254839",
- "foreground": "#5dc2a3"
- },
- "hovered": {
- "background": "#254839",
- "border": "#254839",
- "foreground": "#5dc2a3"
- },
- "pressed": {
- "background": "#2c5645",
- "border": "#254839",
- "foreground": "#5dc2a3"
- },
- "active": {
- "background": "#356b57",
- "border": "#40836c",
- "foreground": "#f9fdfb"
- },
- "disabled": {
- "background": "#182e23",
- "border": "#1e3b2e",
- "foreground": "#4ea287"
- },
- "inverted": {
- "background": "#f9fdfb",
- "border": "#000e00",
- "foreground": "#326552"
- }
- },
- "warning": {
- "default": {
- "background": "#50341a",
- "border": "#6d4d2b",
- "foreground": "#f5c177"
- },
- "hovered": {
- "background": "#6d4d2b",
- "border": "#6d4d2b",
- "foreground": "#f5c177"
- },
- "pressed": {
- "background": "#7e5a34",
- "border": "#6d4d2b",
- "foreground": "#f5c177"
- },
- "active": {
- "background": "#946e41",
- "border": "#b0854f",
- "foreground": "#fffcf9"
- },
- "disabled": {
- "background": "#50341a",
- "border": "#5e4023",
- "foreground": "#d2a263"
- },
- "inverted": {
- "background": "#fffcf9",
- "border": "#2c1600",
- "foreground": "#8e683c"
- }
- },
- "negative": {
- "default": {
- "background": "#431820",
- "border": "#612834",
- "foreground": "#ea6f92"
- },
- "hovered": {
- "background": "#612834",
- "border": "#612834",
- "foreground": "#ea6f92"
- },
- "pressed": {
- "background": "#71303f",
- "border": "#612834",
- "foreground": "#ea6f92"
- },
- "active": {
- "background": "#883c4f",
- "border": "#a44961",
- "foreground": "#fff9fa"
- },
- "disabled": {
- "background": "#431820",
- "border": "#52202a",
- "foreground": "#c75c79"
- },
- "inverted": {
- "background": "#fff9fa",
- "border": "#230000",
- "foreground": "#82384a"
- }
- }
- },
- "middle": {
- "base": {
- "default": {
- "background": "#1d1b2a",
- "border": "#232132",
- "foreground": "#e0def4"
- },
- "hovered": {
- "background": "#232132",
- "border": "#232132",
- "foreground": "#e0def4"
- },
- "pressed": {
- "background": "#2f2d40",
- "border": "#232132",
- "foreground": "#e0def4"
- },
- "active": {
- "background": "#403e53",
- "border": "#504d65",
- "foreground": "#e0def4"
- },
- "disabled": {
- "background": "#1d1b2a",
- "border": "#1e1c2c",
- "foreground": "#3b384f"
- },
- "inverted": {
- "background": "#e0def4",
- "border": "#191724",
- "foreground": "#3b394e"
- }
- },
- "variant": {
- "default": {
- "background": "#1d1b2a",
- "border": "#232132",
- "foreground": "#75718e"
- },
- "hovered": {
- "background": "#232132",
- "border": "#232132",
- "foreground": "#75718e"
- },
- "pressed": {
- "background": "#2f2d40",
- "border": "#232132",
- "foreground": "#75718e"
- },
- "active": {
- "background": "#403e53",
- "border": "#504d65",
- "foreground": "#e0def4"
- },
- "disabled": {
- "background": "#1d1b2a",
- "border": "#1e1c2c",
- "foreground": "#3b384f"
- },
- "inverted": {
- "background": "#e0def4",
- "border": "#191724",
- "foreground": "#3b394e"
- }
- },
- "on": {
- "default": {
- "background": "#191724",
- "border": "#1c1a29",
- "foreground": "#e0def4"
- },
- "hovered": {
- "background": "#1c1a29",
- "border": "#1c1a29",
- "foreground": "#e0def4"
- },
- "pressed": {
- "background": "#1d1b2b",
- "border": "#1c1a29",
- "foreground": "#e0def4"
- },
- "active": {
- "background": "#222031",
- "border": "#353347",
- "foreground": "#e0def4"
- },
- "disabled": {
- "background": "#191724",
- "border": "#1a1826",
- "foreground": "#4e4b63"
- },
- "inverted": {
- "background": "#e0def4",
- "border": "#191724",
- "foreground": "#1f1d2e"
- }
- },
- "accent": {
- "default": {
- "background": "#2f3739",
- "border": "#435255",
- "foreground": "#9cced7"
- },
- "hovered": {
- "background": "#435255",
- "border": "#435255",
- "foreground": "#9cced7"
- },
- "pressed": {
- "background": "#4e6164",
- "border": "#435255",
- "foreground": "#9cced7"
- },
- "active": {
- "background": "#5d757a",
- "border": "#6e8f94",
- "foreground": "#fbfdfd"
- },
- "disabled": {
- "background": "#2f3739",
- "border": "#3a4446",
- "foreground": "#85aeb5"
- },
- "inverted": {
- "background": "#fbfdfd",
- "border": "#171717",
- "foreground": "#587074"
- }
- },
- "positive": {
- "default": {
- "background": "#182e23",
- "border": "#254839",
- "foreground": "#5dc2a3"
- },
- "hovered": {
- "background": "#254839",
- "border": "#254839",
- "foreground": "#5dc2a3"
- },
- "pressed": {
- "background": "#2c5645",
- "border": "#254839",
- "foreground": "#5dc2a3"
- },
- "active": {
- "background": "#356b57",
- "border": "#40836c",
- "foreground": "#f9fdfb"
- },
- "disabled": {
- "background": "#182e23",
- "border": "#1e3b2e",
- "foreground": "#4ea287"
- },
- "inverted": {
- "background": "#f9fdfb",
- "border": "#000e00",
- "foreground": "#326552"
- }
- },
- "warning": {
- "default": {
- "background": "#50341a",
- "border": "#6d4d2b",
- "foreground": "#f5c177"
- },
- "hovered": {
- "background": "#6d4d2b",
- "border": "#6d4d2b",
- "foreground": "#f5c177"
- },
- "pressed": {
- "background": "#7e5a34",
- "border": "#6d4d2b",
- "foreground": "#f5c177"
- },
- "active": {
- "background": "#946e41",
- "border": "#b0854f",
- "foreground": "#fffcf9"
- },
- "disabled": {
- "background": "#50341a",
- "border": "#5e4023",
- "foreground": "#d2a263"
- },
- "inverted": {
- "background": "#fffcf9",
- "border": "#2c1600",
- "foreground": "#8e683c"
- }
- },
- "negative": {
- "default": {
- "background": "#431820",
- "border": "#612834",
- "foreground": "#ea6f92"
- },
- "hovered": {
- "background": "#612834",
- "border": "#612834",
- "foreground": "#ea6f92"
- },
- "pressed": {
- "background": "#71303f",
- "border": "#612834",
- "foreground": "#ea6f92"
- },
- "active": {
- "background": "#883c4f",
- "border": "#a44961",
- "foreground": "#fff9fa"
- },
- "disabled": {
- "background": "#431820",
- "border": "#52202a",
- "foreground": "#c75c79"
- },
- "inverted": {
- "background": "#fff9fa",
- "border": "#230000",
- "foreground": "#82384a"
- }
- }
- },
- "highest": {
- "base": {
- "default": {
- "background": "#191724",
- "border": "#1c1a29",
- "foreground": "#e0def4"
- },
- "hovered": {
- "background": "#1c1a29",
- "border": "#1c1a29",
- "foreground": "#e0def4"
- },
- "pressed": {
- "background": "#1d1b2b",
- "border": "#1c1a29",
- "foreground": "#e0def4"
- },
- "active": {
- "background": "#222031",
- "border": "#353347",
- "foreground": "#e0def4"
- },
- "disabled": {
- "background": "#191724",
- "border": "#1a1826",
- "foreground": "#4e4b63"
- },
- "inverted": {
- "background": "#e0def4",
- "border": "#191724",
- "foreground": "#1f1d2e"
- }
- },
- "variant": {
- "default": {
- "background": "#191724",
- "border": "#1c1a29",
- "foreground": "#75718e"
- },
- "hovered": {
- "background": "#1c1a29",
- "border": "#1c1a29",
- "foreground": "#75718e"
- },
- "pressed": {
- "background": "#1d1b2b",
- "border": "#1c1a29",
- "foreground": "#75718e"
- },
- "active": {
- "background": "#222031",
- "border": "#353347",
- "foreground": "#e0def4"
- },
- "disabled": {
- "background": "#191724",
- "border": "#1a1826",
- "foreground": "#4e4b63"
- },
- "inverted": {
- "background": "#e0def4",
- "border": "#191724",
- "foreground": "#1f1d2e"
- }
- },
- "on": {
- "default": {
- "background": "#1d1b2a",
- "border": "#232132",
- "foreground": "#e0def4"
- },
- "hovered": {
- "background": "#232132",
- "border": "#232132",
- "foreground": "#e0def4"
- },
- "pressed": {
- "background": "#2f2d40",
- "border": "#232132",
- "foreground": "#e0def4"
- },
- "active": {
- "background": "#403e53",
- "border": "#504d65",
- "foreground": "#e0def4"
- },
- "disabled": {
- "background": "#1d1b2a",
- "border": "#1e1c2c",
- "foreground": "#3b384f"
- },
- "inverted": {
- "background": "#e0def4",
- "border": "#191724",
- "foreground": "#3b394e"
- }
- },
- "accent": {
- "default": {
- "background": "#2f3739",
- "border": "#435255",
- "foreground": "#9cced7"
- },
- "hovered": {
- "background": "#435255",
- "border": "#435255",
- "foreground": "#9cced7"
- },
- "pressed": {
- "background": "#4e6164",
- "border": "#435255",
- "foreground": "#9cced7"
- },
- "active": {
- "background": "#5d757a",
- "border": "#6e8f94",
- "foreground": "#fbfdfd"
- },
- "disabled": {
- "background": "#2f3739",
- "border": "#3a4446",
- "foreground": "#85aeb5"
- },
- "inverted": {
- "background": "#fbfdfd",
- "border": "#171717",
- "foreground": "#587074"
- }
- },
- "positive": {
- "default": {
- "background": "#182e23",
- "border": "#254839",
- "foreground": "#5dc2a3"
- },
- "hovered": {
- "background": "#254839",
- "border": "#254839",
- "foreground": "#5dc2a3"
- },
- "pressed": {
- "background": "#2c5645",
- "border": "#254839",
- "foreground": "#5dc2a3"
- },
- "active": {
- "background": "#356b57",
- "border": "#40836c",
- "foreground": "#f9fdfb"
- },
- "disabled": {
- "background": "#182e23",
- "border": "#1e3b2e",
- "foreground": "#4ea287"
- },
- "inverted": {
- "background": "#f9fdfb",
- "border": "#000e00",
- "foreground": "#326552"
- }
- },
- "warning": {
- "default": {
- "background": "#50341a",
- "border": "#6d4d2b",
- "foreground": "#f5c177"
- },
- "hovered": {
- "background": "#6d4d2b",
- "border": "#6d4d2b",
- "foreground": "#f5c177"
- },
- "pressed": {
- "background": "#7e5a34",
- "border": "#6d4d2b",
- "foreground": "#f5c177"
- },
- "active": {
- "background": "#946e41",
- "border": "#b0854f",
- "foreground": "#fffcf9"
- },
- "disabled": {
- "background": "#50341a",
- "border": "#5e4023",
- "foreground": "#d2a263"
- },
- "inverted": {
- "background": "#fffcf9",
- "border": "#2c1600",
- "foreground": "#8e683c"
- }
- },
- "negative": {
- "default": {
- "background": "#431820",
- "border": "#612834",
- "foreground": "#ea6f92"
- },
- "hovered": {
- "background": "#612834",
- "border": "#612834",
- "foreground": "#ea6f92"
- },
- "pressed": {
- "background": "#71303f",
- "border": "#612834",
- "foreground": "#ea6f92"
- },
- "active": {
- "background": "#883c4f",
- "border": "#a44961",
- "foreground": "#fff9fa"
- },
- "disabled": {
- "background": "#431820",
- "border": "#52202a",
- "foreground": "#c75c79"
- },
- "inverted": {
- "background": "#fff9fa",
- "border": "#230000",
- "foreground": "#82384a"
- }
- }
- },
- "popover_shadow": {
- "blur": 4,
- "color": "#00000033",
- "offset": [
- 1,
- 2
- ]
- },
- "modal_shadow": {
- "blur": 16,
- "color": "#00000033",
- "offset": [
- 0,
- 2
- ]
- },
- "players": {
- "0": {
- "selection": "#9cced73d",
- "cursor": "#9cced7"
- },
- "1": {
- "selection": "#5dc2a33d",
- "cursor": "#5dc2a3"
- },
- "2": {
- "selection": "#9d76913d",
- "cursor": "#9d7691"
- },
- "3": {
- "selection": "#c4a7e63d",
- "cursor": "#c4a7e6"
- },
- "4": {
- "selection": "#c4a7e63d",
- "cursor": "#c4a7e6"
- },
- "5": {
- "selection": "#32748f3d",
- "cursor": "#32748f"
- },
- "6": {
- "selection": "#ea6f923d",
- "cursor": "#ea6f92"
- },
- "7": {
- "selection": "#f5c1773d",
- "cursor": "#f5c177"
- }
- },
- "syntax": {
- "comment": {
- "color": "#6e6a86"
- },
- "operator": {
- "color": "#31748f"
- },
- "punctuation": {
- "color": "#908caa"
- },
- "variable": {
- "color": "#e0def4"
- },
- "string": {
- "color": "#f6c177"
- },
- "type": {
- "color": "#9ccfd8"
- },
- "type.builtin": {
- "color": "#9ccfd8"
- },
- "boolean": {
- "color": "#ebbcba"
- },
- "function": {
- "color": "#ebbcba"
- },
- "keyword": {
- "color": "#31748f"
- },
- "tag": {
- "color": "#9ccfd8"
- },
- "function.method": {
- "color": "#ebbcba"
- },
- "title": {
- "color": "#f6c177"
- },
- "link_text": {
- "color": "#9ccfd8",
- "italic": false
- },
- "link_uri": {
- "color": "#ebbcba"
- }
- },
- "color_family": {
- "neutral": {
- "low": 11.568627450980392,
- "high": 91.37254901960785,
- "range": 79.80392156862746,
- "scaling_value": 1.2530712530712529
- },
- "red": {
- "low": 6.862745098039216,
- "high": 100,
- "range": 93.13725490196079,
- "scaling_value": 1.0736842105263158
- },
- "orange": {
- "low": 5.490196078431373,
- "high": 100,
- "range": 94.50980392156863,
- "scaling_value": 1.058091286307054
- },
- "yellow": {
- "low": 8.627450980392156,
- "high": 100,
- "range": 91.37254901960785,
- "scaling_value": 1.094420600858369
- },
- "green": {
- "low": 2.7450980392156863,
- "high": 100,
- "range": 97.25490196078431,
- "scaling_value": 1.028225806451613
- },
- "cyan": {
- "low": 0,
- "high": 100,
- "range": 100,
- "scaling_value": 1
- },
- "blue": {
- "low": 9.019607843137255,
- "high": 100,
- "range": 90.98039215686275,
- "scaling_value": 1.0991379310344827
- },
- "violet": {
- "low": 5.490196078431373,
- "high": 100,
- "range": 94.50980392156863,
- "scaling_value": 1.058091286307054
- },
- "magenta": {
- "low": 0,
- "high": 100,
- "range": 100,
- "scaling_value": 1
- }
- }
- }
- })
- .unwrap()
-}
-
-pub fn rose_pine_dawn() -> Theme {
- serde_json::from_value(json!({
- "name": "Rosé Pine Dawn",
- "is_light": true,
- "ramps": {},
- "lowest": {
- "base": {
- "default": {
- "background": "#dcd8d8",
- "border": "#dcd6d5",
- "foreground": "#575279"
- },
- "hovered": {
- "background": "#dcd6d5",
- "border": "#dcd6d5",
- "foreground": "#575279"
- },
- "pressed": {
- "background": "#efe6df",
- "border": "#dcd6d5",
- "foreground": "#575279"
- },
- "active": {
- "background": "#c1bac1",
- "border": "#a9a3b0",
- "foreground": "#575279"
- },
- "disabled": {
- "background": "#dcd8d8",
- "border": "#d0cccf",
- "foreground": "#938fa3"
- },
- "inverted": {
- "background": "#575279",
- "border": "#faf4ed",
- "foreground": "#c7c0c5"
- }
- },
- "variant": {
- "default": {
- "background": "#dcd8d8",
- "border": "#dcd6d5",
- "foreground": "#706c8c"
- },
- "hovered": {
- "background": "#dcd6d5",
- "border": "#dcd6d5",
- "foreground": "#706c8c"
- },
- "pressed": {
- "background": "#efe6df",
- "border": "#dcd6d5",
- "foreground": "#706c8c"
- },
- "active": {
- "background": "#c1bac1",
- "border": "#a9a3b0",
- "foreground": "#575279"
- },
- "disabled": {
- "background": "#dcd8d8",
- "border": "#d0cccf",
- "foreground": "#938fa3"
- },
- "inverted": {
- "background": "#575279",
- "border": "#faf4ed",
- "foreground": "#c7c0c5"
- }
- },
- "on": {
- "default": {
- "background": "#fef9f2",
- "border": "#e5e0df",
- "foreground": "#575279"
- },
- "hovered": {
- "background": "#e5e0df",
- "border": "#e5e0df",
- "foreground": "#575279"
- },
- "pressed": {
- "background": "#d4d0d2",
- "border": "#e5e0df",
- "foreground": "#575279"
- },
- "active": {
- "background": "#dbd5d4",
- "border": "#dbd3d1",
- "foreground": "#575279"
- },
- "disabled": {
- "background": "#fef9f2",
- "border": "#f6f1eb",
- "foreground": "#b1abb5"
- },
- "inverted": {
- "background": "#575279",
- "border": "#faf4ed",
- "foreground": "#d6d1d1"
- }
- },
- "accent": {
- "default": {
- "background": "#dde9eb",
- "border": "#c3d7db",
- "foreground": "#57949f"
- },
- "hovered": {
- "background": "#c3d7db",
- "border": "#c3d7db",
- "foreground": "#57949f"
- },
- "pressed": {
- "background": "#b6cfd3",
- "border": "#c3d7db",
- "foreground": "#57949f"
- },
- "active": {
- "background": "#a3c3c9",
- "border": "#8db6bd",
- "foreground": "#06090a"
- },
- "disabled": {
- "background": "#dde9eb",
- "border": "#d0e0e3",
- "foreground": "#72a5ae"
- },
- "inverted": {
- "background": "#06090a",
- "border": "#ffffff",
- "foreground": "#a8c7cd"
- }
- },
- "positive": {
- "default": {
- "background": "#dbeee7",
- "border": "#bee0d5",
- "foreground": "#3eaa8e"
- },
- "hovered": {
- "background": "#bee0d5",
- "border": "#bee0d5",
- "foreground": "#3eaa8e"
- },
- "pressed": {
- "background": "#b0dacb",
- "border": "#bee0d5",
- "foreground": "#3eaa8e"
- },
- "active": {
- "background": "#9bd0bf",
- "border": "#82c6b1",
- "foreground": "#060a09"
- },
- "disabled": {
- "background": "#dbeee7",
- "border": "#cde7de",
- "foreground": "#63b89f"
- },
- "inverted": {
- "background": "#060a09",
- "border": "#ffffff",
- "foreground": "#a1d4c3"
- }
- },
- "warning": {
- "default": {
- "background": "#ffebd6",
- "border": "#ffdab7",
- "foreground": "#e99d35"
- },
- "hovered": {
- "background": "#ffdab7",
- "border": "#ffdab7",
- "foreground": "#e99d35"
- },
- "pressed": {
- "background": "#fed2a6",
- "border": "#ffdab7",
- "foreground": "#e99d35"
- },
- "active": {
- "background": "#fbc891",
- "border": "#f7bc77",
- "foreground": "#330704"
- },
- "disabled": {
- "background": "#ffebd6",
- "border": "#ffe2c7",
- "foreground": "#f1ac57"
- },
- "inverted": {
- "background": "#330704",
- "border": "#ffffff",
- "foreground": "#fccb97"
- }
- },
- "negative": {
- "default": {
- "background": "#f1dfe3",
- "border": "#e6c6cd",
- "foreground": "#b4647a"
- },
- "hovered": {
- "background": "#e6c6cd",
- "border": "#e6c6cd",
- "foreground": "#b4647a"
- },
- "pressed": {
- "background": "#e0bac2",
- "border": "#e6c6cd",
- "foreground": "#b4647a"
- },
- "active": {
- "background": "#d8a8b3",
- "border": "#ce94a3",
- "foreground": "#0b0708"
- },
- "disabled": {
- "background": "#f1dfe3",
- "border": "#ecd2d8",
- "foreground": "#c17b8e"
- },
- "inverted": {
- "background": "#0b0708",
- "border": "#ffffff",
- "foreground": "#dbadb8"
- }
- }
- },
- "middle": {
- "base": {
- "default": {
- "background": "#fef9f2",
- "border": "#e5e0df",
- "foreground": "#575279"
- },
- "hovered": {
- "background": "#e5e0df",
- "border": "#e5e0df",
- "foreground": "#575279"
- },
- "pressed": {
- "background": "#d4d0d2",
- "border": "#e5e0df",
- "foreground": "#575279"
- },
- "active": {
- "background": "#dbd5d4",
- "border": "#dbd3d1",
- "foreground": "#575279"
- },
- "disabled": {
- "background": "#fef9f2",
- "border": "#f6f1eb",
- "foreground": "#b1abb5"
- },
- "inverted": {
- "background": "#575279",
- "border": "#faf4ed",
- "foreground": "#d6d1d1"
- }
- },
- "variant": {
- "default": {
- "background": "#fef9f2",
- "border": "#e5e0df",
- "foreground": "#706c8c"
- },
- "hovered": {
- "background": "#e5e0df",
- "border": "#e5e0df",
- "foreground": "#706c8c"
- },
- "pressed": {
- "background": "#d4d0d2",
- "border": "#e5e0df",
- "foreground": "#706c8c"
- },
- "active": {
- "background": "#dbd5d4",
- "border": "#dbd3d1",
- "foreground": "#575279"
- },
- "disabled": {
- "background": "#fef9f2",
- "border": "#f6f1eb",
- "foreground": "#b1abb5"
- },
- "inverted": {
- "background": "#575279",
- "border": "#faf4ed",
- "foreground": "#d6d1d1"
- }
- },
- "on": {
- "default": {
- "background": "#faf4ed",
- "border": "#fdf8f1",
- "foreground": "#575279"
- },
- "hovered": {
- "background": "#fdf8f1",
- "border": "#fdf8f1",
- "foreground": "#575279"
- },
- "pressed": {
- "background": "#fdf8f2",
- "border": "#fdf8f1",
- "foreground": "#575279"
- },
- "active": {
- "background": "#e6e1e0",
- "border": "#d0cccf",
- "foreground": "#575279"
- },
- "disabled": {
- "background": "#faf4ed",
- "border": "#fcf6ef",
- "foreground": "#efe6df"
- },
- "inverted": {
- "background": "#575279",
- "border": "#faf4ed",
- "foreground": "#ede9e5"
- }
- },
- "accent": {
- "default": {
- "background": "#dde9eb",
- "border": "#c3d7db",
- "foreground": "#57949f"
- },
- "hovered": {
- "background": "#c3d7db",
- "border": "#c3d7db",
- "foreground": "#57949f"
- },
- "pressed": {
- "background": "#b6cfd3",
- "border": "#c3d7db",
- "foreground": "#57949f"
- },
- "active": {
- "background": "#a3c3c9",
- "border": "#8db6bd",
- "foreground": "#06090a"
- },
- "disabled": {
- "background": "#dde9eb",
- "border": "#d0e0e3",
- "foreground": "#72a5ae"
- },
- "inverted": {
- "background": "#06090a",
- "border": "#ffffff",
- "foreground": "#a8c7cd"
- }
- },
- "positive": {
- "default": {
- "background": "#dbeee7",
- "border": "#bee0d5",
- "foreground": "#3eaa8e"
- },
- "hovered": {
- "background": "#bee0d5",
- "border": "#bee0d5",
- "foreground": "#3eaa8e"
- },
- "pressed": {
- "background": "#b0dacb",
- "border": "#bee0d5",
- "foreground": "#3eaa8e"
- },
- "active": {
- "background": "#9bd0bf",
- "border": "#82c6b1",
- "foreground": "#060a09"
- },
- "disabled": {
- "background": "#dbeee7",
- "border": "#cde7de",
- "foreground": "#63b89f"
- },
- "inverted": {
- "background": "#060a09",
- "border": "#ffffff",
- "foreground": "#a1d4c3"
- }
- },
- "warning": {
- "default": {
- "background": "#ffebd6",
- "border": "#ffdab7",
- "foreground": "#e99d35"
- },
- "hovered": {
- "background": "#ffdab7",
- "border": "#ffdab7",
- "foreground": "#e99d35"
- },
- "pressed": {
- "background": "#fed2a6",
- "border": "#ffdab7",
- "foreground": "#e99d35"
- },
- "active": {
- "background": "#fbc891",
- "border": "#f7bc77",
- "foreground": "#330704"
- },
- "disabled": {
- "background": "#ffebd6",
- "border": "#ffe2c7",
- "foreground": "#f1ac57"
- },
- "inverted": {
- "background": "#330704",
- "border": "#ffffff",
- "foreground": "#fccb97"
- }
- },
- "negative": {
- "default": {
- "background": "#f1dfe3",
- "border": "#e6c6cd",
- "foreground": "#b4647a"
- },
- "hovered": {
- "background": "#e6c6cd",
- "border": "#e6c6cd",
- "foreground": "#b4647a"
- },
- "pressed": {
- "background": "#e0bac2",
- "border": "#e6c6cd",
- "foreground": "#b4647a"
- },
- "active": {
- "background": "#d8a8b3",
- "border": "#ce94a3",
- "foreground": "#0b0708"
- },
- "disabled": {
- "background": "#f1dfe3",
- "border": "#ecd2d8",
- "foreground": "#c17b8e"
- },
- "inverted": {
- "background": "#0b0708",
- "border": "#ffffff",
- "foreground": "#dbadb8"
- }
- }
- },
- "highest": {
- "base": {
- "default": {
- "background": "#faf4ed",
- "border": "#fdf8f1",
- "foreground": "#575279"
- },
- "hovered": {
- "background": "#fdf8f1",
- "border": "#fdf8f1",
- "foreground": "#575279"
- },
- "pressed": {
- "background": "#fdf8f2",
- "border": "#fdf8f1",
- "foreground": "#575279"
- },
- "active": {
- "background": "#e6e1e0",
- "border": "#d0cccf",
- "foreground": "#575279"
- },
- "disabled": {
- "background": "#faf4ed",
- "border": "#fcf6ef",
- "foreground": "#efe6df"
- },
- "inverted": {
- "background": "#575279",
- "border": "#faf4ed",
- "foreground": "#ede9e5"
- }
- },
- "variant": {
- "default": {
- "background": "#faf4ed",
- "border": "#fdf8f1",
- "foreground": "#706c8c"
- },
- "hovered": {
- "background": "#fdf8f1",
- "border": "#fdf8f1",
- "foreground": "#706c8c"
- },
- "pressed": {
- "background": "#fdf8f2",
- "border": "#fdf8f1",
- "foreground": "#706c8c"
- },
- "active": {
- "background": "#e6e1e0",
- "border": "#d0cccf",
- "foreground": "#575279"
- },
- "disabled": {
- "background": "#faf4ed",
- "border": "#fcf6ef",
- "foreground": "#efe6df"
- },
- "inverted": {
- "background": "#575279",
- "border": "#faf4ed",
- "foreground": "#ede9e5"
- }
- },
- "on": {
- "default": {
- "background": "#fef9f2",
- "border": "#e5e0df",
- "foreground": "#575279"
- },
- "hovered": {
- "background": "#e5e0df",
- "border": "#e5e0df",
- "foreground": "#575279"
- },
- "pressed": {
- "background": "#d4d0d2",
- "border": "#e5e0df",
- "foreground": "#575279"
- },
- "active": {
- "background": "#dbd5d4",
- "border": "#dbd3d1",
- "foreground": "#575279"
- },
- "disabled": {
- "background": "#fef9f2",
- "border": "#f6f1eb",
- "foreground": "#b1abb5"
- },
- "inverted": {
- "background": "#575279",
- "border": "#faf4ed",
- "foreground": "#d6d1d1"
- }
- },
- "accent": {
- "default": {
- "background": "#dde9eb",
- "border": "#c3d7db",
- "foreground": "#57949f"
- },
- "hovered": {
- "background": "#c3d7db",
- "border": "#c3d7db",
- "foreground": "#57949f"
- },
- "pressed": {
- "background": "#b6cfd3",
- "border": "#c3d7db",
- "foreground": "#57949f"
- },
- "active": {
- "background": "#a3c3c9",
- "border": "#8db6bd",
- "foreground": "#06090a"
- },
- "disabled": {
- "background": "#dde9eb",
- "border": "#d0e0e3",
- "foreground": "#72a5ae"
- },
- "inverted": {
- "background": "#06090a",
- "border": "#ffffff",
- "foreground": "#a8c7cd"
- }
- },
- "positive": {
- "default": {
- "background": "#dbeee7",
- "border": "#bee0d5",
- "foreground": "#3eaa8e"
- },
- "hovered": {
- "background": "#bee0d5",
- "border": "#bee0d5",
- "foreground": "#3eaa8e"
- },
- "pressed": {
- "background": "#b0dacb",
- "border": "#bee0d5",
- "foreground": "#3eaa8e"
- },
- "active": {
- "background": "#9bd0bf",
- "border": "#82c6b1",
- "foreground": "#060a09"
- },
- "disabled": {
- "background": "#dbeee7",
- "border": "#cde7de",
- "foreground": "#63b89f"
- },
- "inverted": {
- "background": "#060a09",
- "border": "#ffffff",
- "foreground": "#a1d4c3"
- }
- },
- "warning": {
- "default": {
- "background": "#ffebd6",
- "border": "#ffdab7",
- "foreground": "#e99d35"
- },
- "hovered": {
- "background": "#ffdab7",
- "border": "#ffdab7",
- "foreground": "#e99d35"
- },
- "pressed": {
- "background": "#fed2a6",
- "border": "#ffdab7",
- "foreground": "#e99d35"
- },
- "active": {
- "background": "#fbc891",
- "border": "#f7bc77",
- "foreground": "#330704"
- },
- "disabled": {
- "background": "#ffebd6",
- "border": "#ffe2c7",
- "foreground": "#f1ac57"
- },
- "inverted": {
- "background": "#330704",
- "border": "#ffffff",
- "foreground": "#fccb97"
- }
- },
- "negative": {
- "default": {
- "background": "#f1dfe3",
- "border": "#e6c6cd",
- "foreground": "#b4647a"
- },
- "hovered": {
- "background": "#e6c6cd",
- "border": "#e6c6cd",
- "foreground": "#b4647a"
- },
- "pressed": {
- "background": "#e0bac2",
- "border": "#e6c6cd",
- "foreground": "#b4647a"
- },
- "active": {
- "background": "#d8a8b3",
- "border": "#ce94a3",
- "foreground": "#0b0708"
- },
- "disabled": {
- "background": "#f1dfe3",
- "border": "#ecd2d8",
- "foreground": "#c17b8e"
- },
- "inverted": {
- "background": "#0b0708",
- "border": "#ffffff",
- "foreground": "#dbadb8"
- }
- }
- },
- "popover_shadow": {
- "blur": 4,
- "color": "#2c2a4d33",
- "offset": [
- 1,
- 2
- ]
- },
- "modal_shadow": {
- "blur": 16,
- "color": "#2c2a4d33",
- "offset": [
- 0,
- 2
- ]
- },
- "players": {
- "0": {
- "selection": "#57949f3d",
- "cursor": "#57949f"
- },
- "1": {
- "selection": "#3eaa8e3d",
- "cursor": "#3eaa8e"
- },
- "2": {
- "selection": "#7c697f3d",
- "cursor": "#7c697f"
- },
- "3": {
- "selection": "#907aa93d",
- "cursor": "#907aa9"
- },
- "4": {
- "selection": "#907aa93d",
- "cursor": "#907aa9"
- },
- "5": {
- "selection": "#2a69833d",
- "cursor": "#2a6983"
- },
- "6": {
- "selection": "#b4647a3d",
- "cursor": "#b4647a"
- },
- "7": {
- "selection": "#e99d353d",
- "cursor": "#e99d35"
- }
- },
- "syntax": {
- "comment": {
- "color": "#9893a5"
- },
- "operator": {
- "color": "#286983"
- },
- "punctuation": {
- "color": "#797593"
- },
- "variable": {
- "color": "#575279"
- },
- "string": {
- "color": "#ea9d34"
- },
- "type": {
- "color": "#56949f"
- },
- "type.builtin": {
- "color": "#56949f"
- },
- "boolean": {
- "color": "#d7827e"
- },
- "function": {
- "color": "#d7827e"
- },
- "keyword": {
- "color": "#286983"
- },
- "tag": {
- "color": "#56949f"
- },
- "function.method": {
- "color": "#d7827e"
- },
- "title": {
- "color": "#ea9d34"
- },
- "link_text": {
- "color": "#56949f",
- "italic": false
- },
- "link_uri": {
- "color": "#d7827e"
- }
- },
- "color_family": {
- "neutral": {
- "low": 39.80392156862745,
- "high": 95.49019607843137,
- "range": 55.686274509803916,
- "scaling_value": 1.7957746478873242
- },
- "red": {
- "low": 0,
- "high": 100,
- "range": 100,
- "scaling_value": 1
- },
- "orange": {
- "low": 0,
- "high": 100,
- "range": 100,
- "scaling_value": 1
- },
- "yellow": {
- "low": 8.823529411764707,
- "high": 100,
- "range": 91.17647058823529,
- "scaling_value": 1.0967741935483872
- },
- "green": {
- "low": 0,
- "high": 100,
- "range": 100,
- "scaling_value": 1
- },
- "cyan": {
- "low": 0,
- "high": 100,
- "range": 100,
- "scaling_value": 1
- },
- "blue": {
- "low": 0,
- "high": 100,
- "range": 100,
- "scaling_value": 1
- },
- "violet": {
- "low": 0,
- "high": 100,
- "range": 100,
- "scaling_value": 1
- },
- "magenta": {
- "low": 0,
- "high": 100,
- "range": 100,
- "scaling_value": 1
- }
- }
- }))
- .unwrap()
-}
@@ -0,0 +1,2118 @@
+use gpui2::Rgba;
+use indexmap::IndexMap;
+
+use crate::scale::{ColorScaleName, ColorScaleSet, ColorScales};
+
+struct DefaultColorScaleSet {
+ scale: ColorScaleName,
+ light: [&'static str; 12],
+ light_alpha: [&'static str; 12],
+ dark: [&'static str; 12],
+ dark_alpha: [&'static str; 12],
+}
+
+impl From<DefaultColorScaleSet> for ColorScaleSet {
+ fn from(default: DefaultColorScaleSet) -> Self {
+ Self::new(
+ default.scale,
+ default
+ .light
+ .map(|color| Rgba::try_from(color).unwrap().into()),
+ default
+ .light_alpha
+ .map(|color| Rgba::try_from(color).unwrap().into()),
+ default
+ .dark
+ .map(|color| Rgba::try_from(color).unwrap().into()),
+ default
+ .dark_alpha
+ .map(|color| Rgba::try_from(color).unwrap().into()),
+ )
+ }
+}
+
+pub fn default_color_scales() -> ColorScales {
+ use ColorScaleName::*;
+
+ IndexMap::from_iter([
+ (Gray, gray().into()),
+ (Mauve, mauve().into()),
+ (Slate, slate().into()),
+ (Sage, sage().into()),
+ (Olive, olive().into()),
+ (Sand, sand().into()),
+ (Gold, gold().into()),
+ (Bronze, bronze().into()),
+ (Brown, brown().into()),
+ (Yellow, yellow().into()),
+ (Amber, amber().into()),
+ (Orange, orange().into()),
+ (Tomato, tomato().into()),
+ (Red, red().into()),
+ (Ruby, ruby().into()),
+ (Crimson, crimson().into()),
+ (Pink, pink().into()),
+ (Plum, plum().into()),
+ (Purple, purple().into()),
+ (Violet, violet().into()),
+ (Iris, iris().into()),
+ (Indigo, indigo().into()),
+ (Blue, blue().into()),
+ (Cyan, cyan().into()),
+ (Teal, teal().into()),
+ (Jade, jade().into()),
+ (Green, green().into()),
+ (Grass, grass().into()),
+ (Lime, lime().into()),
+ (Mint, mint().into()),
+ (Sky, sky().into()),
+ (Black, black().into()),
+ (White, white().into()),
+ ])
+}
+
+fn gray() -> DefaultColorScaleSet {
+ DefaultColorScaleSet {
+ scale: ColorScaleName::Gray,
+ light: [
+ "#fcfcfcff",
+ "#f9f9f9ff",
+ "#f0f0f0ff",
+ "#e8e8e8ff",
+ "#e0e0e0ff",
+ "#d9d9d9ff",
+ "#cececeff",
+ "#bbbbbbff",
+ "#8d8d8dff",
+ "#838383ff",
+ "#646464ff",
+ "#202020ff",
+ ],
+ light_alpha: [
+ "#00000003",
+ "#00000006",
+ "#0000000f",
+ "#00000017",
+ "#0000001f",
+ "#00000026",
+ "#00000031",
+ "#00000044",
+ "#00000072",
+ "#0000007c",
+ "#0000009b",
+ "#000000df",
+ ],
+ dark: [
+ "#111111ff",
+ "#191919ff",
+ "#222222ff",
+ "#2a2a2aff",
+ "#313131ff",
+ "#3a3a3aff",
+ "#484848ff",
+ "#606060ff",
+ "#6e6e6eff",
+ "#7b7b7bff",
+ "#b4b4b4ff",
+ "#eeeeeeff",
+ ],
+ dark_alpha: [
+ "#00000000",
+ "#ffffff09",
+ "#ffffff12",
+ "#ffffff1b",
+ "#ffffff22",
+ "#ffffff2c",
+ "#ffffff3b",
+ "#ffffff55",
+ "#ffffff64",
+ "#ffffff72",
+ "#ffffffaf",
+ "#ffffffed",
+ ],
+ }
+}
+
+fn mauve() -> DefaultColorScaleSet {
+ DefaultColorScaleSet {
+ scale: ColorScaleName::Mauve,
+ light: [
+ "#fdfcfdff",
+ "#faf9fbff",
+ "#f2eff3ff",
+ "#eae7ecff",
+ "#e3dfe6ff",
+ "#dbd8e0ff",
+ "#d0cdd7ff",
+ "#bcbac7ff",
+ "#8e8c99ff",
+ "#84828eff",
+ "#65636dff",
+ "#211f26ff",
+ ],
+ light_alpha: [
+ "#55005503",
+ "#2b005506",
+ "#30004010",
+ "#20003618",
+ "#20003820",
+ "#14003527",
+ "#10003332",
+ "#08003145",
+ "#05001d73",
+ "#0500197d",
+ "#0400119c",
+ "#020008e0",
+ ],
+ dark: [
+ "#121113ff",
+ "#1a191bff",
+ "#232225ff",
+ "#2b292dff",
+ "#323035ff",
+ "#3c393fff",
+ "#49474eff",
+ "#625f69ff",
+ "#6f6d78ff",
+ "#7c7a85ff",
+ "#b5b2bcff",
+ "#eeeef0ff",
+ ],
+ dark_alpha: [
+ "#00000000",
+ "#f5f4f609",
+ "#ebeaf814",
+ "#eee5f81d",
+ "#efe6fe25",
+ "#f1e6fd30",
+ "#eee9ff40",
+ "#eee7ff5d",
+ "#eae6fd6e",
+ "#ece9fd7c",
+ "#f5f1ffb7",
+ "#fdfdffef",
+ ],
+ }
+}
+
+fn slate() -> DefaultColorScaleSet {
+ DefaultColorScaleSet {
+ scale: ColorScaleName::Slate,
+ light: [
+ "#fcfcfdff",
+ "#f9f9fbff",
+ "#f0f0f3ff",
+ "#e8e8ecff",
+ "#e0e1e6ff",
+ "#d9d9e0ff",
+ "#cdced6ff",
+ "#b9bbc6ff",
+ "#8b8d98ff",
+ "#80838dff",
+ "#60646cff",
+ "#1c2024ff",
+ ],
+ light_alpha: [
+ "#00005503",
+ "#00005506",
+ "#0000330f",
+ "#00002d17",
+ "#0009321f",
+ "#00002f26",
+ "#00062e32",
+ "#00083046",
+ "#00051d74",
+ "#00071b7f",
+ "#0007149f",
+ "#000509e3",
+ ],
+ dark: [
+ "#111113ff",
+ "#18191bff",
+ "#212225ff",
+ "#272a2dff",
+ "#2e3135ff",
+ "#363a3fff",
+ "#43484eff",
+ "#5a6169ff",
+ "#696e77ff",
+ "#777b84ff",
+ "#b0b4baff",
+ "#edeef0ff",
+ ],
+ dark_alpha: [
+ "#00000000",
+ "#d8f4f609",
+ "#ddeaf814",
+ "#d3edf81d",
+ "#d9edfe25",
+ "#d6ebfd30",
+ "#d9edff40",
+ "#d9edff5d",
+ "#dfebfd6d",
+ "#e5edfd7b",
+ "#f1f7feb5",
+ "#fcfdffef",
+ ],
+ }
+}
+
+fn sage() -> DefaultColorScaleSet {
+ DefaultColorScaleSet {
+ scale: ColorScaleName::Sage,
+ light: [
+ "#fbfdfcff",
+ "#f7f9f8ff",
+ "#eef1f0ff",
+ "#e6e9e8ff",
+ "#dfe2e0ff",
+ "#d7dad9ff",
+ "#cbcfcdff",
+ "#b8bcbaff",
+ "#868e8bff",
+ "#7c8481ff",
+ "#5f6563ff",
+ "#1a211eff",
+ ],
+ light_alpha: [
+ "#00804004",
+ "#00402008",
+ "#002d1e11",
+ "#001f1519",
+ "#00180820",
+ "#00140d28",
+ "#00140a34",
+ "#000f0847",
+ "#00110b79",
+ "#00100a83",
+ "#000a07a0",
+ "#000805e5",
+ ],
+ dark: [
+ "#101211ff",
+ "#171918ff",
+ "#202221ff",
+ "#272a29ff",
+ "#2e3130ff",
+ "#373b39ff",
+ "#444947ff",
+ "#5b625fff",
+ "#63706bff",
+ "#717d79ff",
+ "#adb5b2ff",
+ "#eceeedff",
+ ],
+ dark_alpha: [
+ "#00000000",
+ "#f0f2f108",
+ "#f3f5f412",
+ "#f2fefd1a",
+ "#f1fbfa22",
+ "#edfbf42d",
+ "#edfcf73c",
+ "#ebfdf657",
+ "#dffdf266",
+ "#e5fdf674",
+ "#f4fefbb0",
+ "#fdfffeed",
+ ],
+ }
+}
+
+fn olive() -> DefaultColorScaleSet {
+ DefaultColorScaleSet {
+ scale: ColorScaleName::Olive,
+ light: [
+ "#fcfdfcff",
+ "#f8faf8ff",
+ "#eff1efff",
+ "#e7e9e7ff",
+ "#dfe2dfff",
+ "#d7dad7ff",
+ "#cccfccff",
+ "#b9bcb8ff",
+ "#898e87ff",
+ "#7f847dff",
+ "#60655fff",
+ "#1d211cff",
+ ],
+ light_alpha: [
+ "#00550003",
+ "#00490007",
+ "#00200010",
+ "#00160018",
+ "#00180020",
+ "#00140028",
+ "#000f0033",
+ "#040f0047",
+ "#050f0078",
+ "#040e0082",
+ "#020a00a0",
+ "#010600e3",
+ ],
+ dark: [
+ "#111210ff",
+ "#181917ff",
+ "#212220ff",
+ "#282a27ff",
+ "#2f312eff",
+ "#383a36ff",
+ "#454843ff",
+ "#5c625bff",
+ "#687066ff",
+ "#767d74ff",
+ "#afb5adff",
+ "#eceeecff",
+ ],
+ dark_alpha: [
+ "#00000000",
+ "#f1f2f008",
+ "#f4f5f312",
+ "#f3fef21a",
+ "#f2fbf122",
+ "#f4faed2c",
+ "#f2fced3b",
+ "#edfdeb57",
+ "#ebfde766",
+ "#f0fdec74",
+ "#f6fef4b0",
+ "#fdfffded",
+ ],
+ }
+}
+
+fn sand() -> DefaultColorScaleSet {
+ DefaultColorScaleSet {
+ scale: ColorScaleName::Sand,
+ light: [
+ "#fdfdfcff",
+ "#f9f9f8ff",
+ "#f1f0efff",
+ "#e9e8e6ff",
+ "#e2e1deff",
+ "#dad9d6ff",
+ "#cfcecaff",
+ "#bcbbb5ff",
+ "#8d8d86ff",
+ "#82827cff",
+ "#63635eff",
+ "#21201cff",
+ ],
+ light_alpha: [
+ "#55550003",
+ "#25250007",
+ "#20100010",
+ "#1f150019",
+ "#1f180021",
+ "#19130029",
+ "#19140035",
+ "#1915014a",
+ "#0f0f0079",
+ "#0c0c0083",
+ "#080800a1",
+ "#060500e3",
+ ],
+ dark: [
+ "#111110ff",
+ "#191918ff",
+ "#222221ff",
+ "#2a2a28ff",
+ "#31312eff",
+ "#3b3a37ff",
+ "#494844ff",
+ "#62605bff",
+ "#6f6d66ff",
+ "#7c7b74ff",
+ "#b5b3adff",
+ "#eeeeecff",
+ ],
+ dark_alpha: [
+ "#00000000",
+ "#f4f4f309",
+ "#f6f6f513",
+ "#fefef31b",
+ "#fbfbeb23",
+ "#fffaed2d",
+ "#fffbed3c",
+ "#fff9eb57",
+ "#fffae965",
+ "#fffdee73",
+ "#fffcf4b0",
+ "#fffffded",
+ ],
+ }
+}
+
+fn gold() -> DefaultColorScaleSet {
+ DefaultColorScaleSet {
+ scale: ColorScaleName::Gold,
+ light: [
+ "#fdfdfcff",
+ "#faf9f2ff",
+ "#f2f0e7ff",
+ "#eae6dbff",
+ "#e1dccfff",
+ "#d8d0bfff",
+ "#cbc0aaff",
+ "#b9a88dff",
+ "#978365ff",
+ "#8c7a5eff",
+ "#71624bff",
+ "#3b352bff",
+ ],
+ light_alpha: [
+ "#55550003",
+ "#9d8a000d",
+ "#75600018",
+ "#6b4e0024",
+ "#60460030",
+ "#64440040",
+ "#63420055",
+ "#633d0072",
+ "#5332009a",
+ "#492d00a1",
+ "#362100b4",
+ "#130c00d4",
+ ],
+ dark: [
+ "#121211ff",
+ "#1b1a17ff",
+ "#24231fff",
+ "#2d2b26ff",
+ "#38352eff",
+ "#444039ff",
+ "#544f46ff",
+ "#696256ff",
+ "#978365ff",
+ "#a39073ff",
+ "#cbb99fff",
+ "#e8e2d9ff",
+ ],
+ dark_alpha: [
+ "#91911102",
+ "#f9e29d0b",
+ "#f8ecbb15",
+ "#ffeec41e",
+ "#feecc22a",
+ "#feebcb37",
+ "#ffedcd48",
+ "#fdeaca5f",
+ "#ffdba690",
+ "#fedfb09d",
+ "#fee7c6c8",
+ "#fef7ede7",
+ ],
+ }
+}
+
+fn bronze() -> DefaultColorScaleSet {
+ DefaultColorScaleSet {
+ scale: ColorScaleName::Bronze,
+ light: [
+ "#fdfcfcff",
+ "#fdf7f5ff",
+ "#f6edeaff",
+ "#efe4dfff",
+ "#e7d9d3ff",
+ "#dfcdc5ff",
+ "#d3bcb3ff",
+ "#c2a499ff",
+ "#a18072ff",
+ "#957468ff",
+ "#7d5e54ff",
+ "#43302bff",
+ ],
+ light_alpha: [
+ "#55000003",
+ "#cc33000a",
+ "#92250015",
+ "#80280020",
+ "#7423002c",
+ "#7324003a",
+ "#6c1f004c",
+ "#671c0066",
+ "#551a008d",
+ "#4c150097",
+ "#3d0f00ab",
+ "#1d0600d4",
+ ],
+ dark: [
+ "#141110ff",
+ "#1c1917ff",
+ "#262220ff",
+ "#302a27ff",
+ "#3b3330ff",
+ "#493e3aff",
+ "#5a4c47ff",
+ "#6f5f58ff",
+ "#a18072ff",
+ "#ae8c7eff",
+ "#d4b3a5ff",
+ "#ede0d9ff",
+ ],
+ dark_alpha: [
+ "#d1110004",
+ "#fbbc910c",
+ "#faceb817",
+ "#facdb622",
+ "#ffd2c12d",
+ "#ffd1c03c",
+ "#fdd0c04f",
+ "#ffd6c565",
+ "#fec7b09b",
+ "#fecab5a9",
+ "#ffd7c6d1",
+ "#fff1e9ec",
+ ],
+ }
+}
+
+fn brown() -> DefaultColorScaleSet {
+ DefaultColorScaleSet {
+ scale: ColorScaleName::Brown,
+ light: [
+ "#fefdfcff",
+ "#fcf9f6ff",
+ "#f6eee7ff",
+ "#f0e4d9ff",
+ "#ebdacaff",
+ "#e4cdb7ff",
+ "#dcbc9fff",
+ "#cea37eff",
+ "#ad7f58ff",
+ "#a07553ff",
+ "#815e46ff",
+ "#3e332eff",
+ ],
+ light_alpha: [
+ "#aa550003",
+ "#aa550009",
+ "#a04b0018",
+ "#9b4a0026",
+ "#9f4d0035",
+ "#a04e0048",
+ "#a34e0060",
+ "#9f4a0081",
+ "#823c00a7",
+ "#723300ac",
+ "#522100b9",
+ "#140600d1",
+ ],
+ dark: [
+ "#12110fff",
+ "#1c1816ff",
+ "#28211dff",
+ "#322922ff",
+ "#3e3128ff",
+ "#4d3c2fff",
+ "#614a39ff",
+ "#7c5f46ff",
+ "#ad7f58ff",
+ "#b88c67ff",
+ "#dbb594ff",
+ "#f2e1caff",
+ ],
+ dark_alpha: [
+ "#91110002",
+ "#fba67c0c",
+ "#fcb58c19",
+ "#fbbb8a24",
+ "#fcb88931",
+ "#fdba8741",
+ "#ffbb8856",
+ "#ffbe8773",
+ "#feb87da8",
+ "#ffc18cb3",
+ "#fed1aad9",
+ "#feecd4f2",
+ ],
+ }
+}
+
+fn yellow() -> DefaultColorScaleSet {
+ DefaultColorScaleSet {
+ scale: ColorScaleName::Yellow,
+ light: [
+ "#fdfdf9ff",
+ "#fefce9ff",
+ "#fffab8ff",
+ "#fff394ff",
+ "#ffe770ff",
+ "#f3d768ff",
+ "#e4c767ff",
+ "#d5ae39ff",
+ "#ffe629ff",
+ "#ffdc00ff",
+ "#9e6c00ff",
+ "#473b1fff",
+ ],
+ light_alpha: [
+ "#aaaa0006",
+ "#f4dd0016",
+ "#ffee0047",
+ "#ffe3016b",
+ "#ffd5008f",
+ "#ebbc0097",
+ "#d2a10098",
+ "#c99700c6",
+ "#ffe100d6",
+ "#ffdc00ff",
+ "#9e6c00ff",
+ "#2e2000e0",
+ ],
+ dark: [
+ "#14120bff",
+ "#1b180fff",
+ "#2d2305ff",
+ "#362b00ff",
+ "#433500ff",
+ "#524202ff",
+ "#665417ff",
+ "#836a21ff",
+ "#ffe629ff",
+ "#ffff57ff",
+ "#f5e147ff",
+ "#f6eeb4ff",
+ ],
+ dark_alpha: [
+ "#d1510004",
+ "#f9b4000b",
+ "#ffaa001e",
+ "#fdb70028",
+ "#febb0036",
+ "#fec40046",
+ "#fdcb225c",
+ "#fdca327b",
+ "#ffe629ff",
+ "#ffff57ff",
+ "#fee949f5",
+ "#fef6baf6",
+ ],
+ }
+}
+
+fn amber() -> DefaultColorScaleSet {
+ DefaultColorScaleSet {
+ scale: ColorScaleName::Amber,
+ light: [
+ "#fefdfbff",
+ "#fefbe9ff",
+ "#fff7c2ff",
+ "#ffee9cff",
+ "#fbe577ff",
+ "#f3d673ff",
+ "#e9c162ff",
+ "#e2a336ff",
+ "#ffc53dff",
+ "#ffba18ff",
+ "#ab6400ff",
+ "#4f3422ff",
+ ],
+ light_alpha: [
+ "#c0800004",
+ "#f4d10016",
+ "#ffde003d",
+ "#ffd40063",
+ "#f8cf0088",
+ "#eab5008c",
+ "#dc9b009d",
+ "#da8a00c9",
+ "#ffb300c2",
+ "#ffb300e7",
+ "#ab6400ff",
+ "#341500dd",
+ ],
+ dark: [
+ "#16120cff",
+ "#1d180fff",
+ "#302008ff",
+ "#3f2700ff",
+ "#4d3000ff",
+ "#5c3d05ff",
+ "#714f19ff",
+ "#8f6424ff",
+ "#ffc53dff",
+ "#ffd60aff",
+ "#ffca16ff",
+ "#ffe7b3ff",
+ ],
+ dark_alpha: [
+ "#e63c0006",
+ "#fd9b000d",
+ "#fa820022",
+ "#fc820032",
+ "#fd8b0041",
+ "#fd9b0051",
+ "#ffab2567",
+ "#ffae3587",
+ "#ffc53dff",
+ "#ffd60aff",
+ "#ffca16ff",
+ "#ffe7b3ff",
+ ],
+ }
+}
+
+fn orange() -> DefaultColorScaleSet {
+ DefaultColorScaleSet {
+ scale: ColorScaleName::Orange,
+ light: [
+ "#fefcfbff",
+ "#fff7edff",
+ "#ffefd6ff",
+ "#ffdfb5ff",
+ "#ffd19aff",
+ "#ffc182ff",
+ "#f5ae73ff",
+ "#ec9455ff",
+ "#f76b15ff",
+ "#ef5f00ff",
+ "#cc4e00ff",
+ "#582d1dff",
+ ],
+ light_alpha: [
+ "#c0400004",
+ "#ff8e0012",
+ "#ff9c0029",
+ "#ff91014a",
+ "#ff8b0065",
+ "#ff81007d",
+ "#ed6c008c",
+ "#e35f00aa",
+ "#f65e00ea",
+ "#ef5f00ff",
+ "#cc4e00ff",
+ "#431200e2",
+ ],
+ dark: [
+ "#17120eff",
+ "#1e160fff",
+ "#331e0bff",
+ "#462100ff",
+ "#562800ff",
+ "#66350cff",
+ "#7e451dff",
+ "#a35829ff",
+ "#f76b15ff",
+ "#ff801fff",
+ "#ffa057ff",
+ "#ffe0c2ff",
+ ],
+ dark_alpha: [
+ "#ec360007",
+ "#fe6d000e",
+ "#fb6a0025",
+ "#ff590039",
+ "#ff61004a",
+ "#fd75045c",
+ "#ff832c75",
+ "#fe84389d",
+ "#fe6d15f7",
+ "#ff801fff",
+ "#ffa057ff",
+ "#ffe0c2ff",
+ ],
+ }
+}
+
+fn tomato() -> DefaultColorScaleSet {
+ DefaultColorScaleSet {
+ scale: ColorScaleName::Tomato,
+ light: [
+ "#fffcfcff",
+ "#fff8f7ff",
+ "#feebe7ff",
+ "#ffdcd3ff",
+ "#ffcdc2ff",
+ "#fdbdafff",
+ "#f5a898ff",
+ "#ec8e7bff",
+ "#e54d2eff",
+ "#dd4425ff",
+ "#d13415ff",
+ "#5c271fff",
+ ],
+ light_alpha: [
+ "#ff000003",
+ "#ff200008",
+ "#f52b0018",
+ "#ff35002c",
+ "#ff2e003d",
+ "#f92d0050",
+ "#e7280067",
+ "#db250084",
+ "#df2600d1",
+ "#d72400da",
+ "#cd2200ea",
+ "#460900e0",
+ ],
+ dark: [
+ "#181111ff",
+ "#1f1513ff",
+ "#391714ff",
+ "#4e1511ff",
+ "#5e1c16ff",
+ "#6e2920ff",
+ "#853a2dff",
+ "#ac4d39ff",
+ "#e54d2eff",
+ "#ec6142ff",
+ "#ff977dff",
+ "#fbd3cbff",
+ ],
+ dark_alpha: [
+ "#f1121208",
+ "#ff55330f",
+ "#ff35232b",
+ "#fd201142",
+ "#fe332153",
+ "#ff4f3864",
+ "#fd644a7d",
+ "#fe6d4ea7",
+ "#fe5431e4",
+ "#ff6847eb",
+ "#ff977dff",
+ "#ffd6cefb",
+ ],
+ }
+}
+
+fn red() -> DefaultColorScaleSet {
+ DefaultColorScaleSet {
+ scale: ColorScaleName::Red,
+ light: [
+ "#fffcfcff",
+ "#fff7f7ff",
+ "#feebecff",
+ "#ffdbdcff",
+ "#ffcdceff",
+ "#fdbdbeff",
+ "#f4a9aaff",
+ "#eb8e90ff",
+ "#e5484dff",
+ "#dc3e42ff",
+ "#ce2c31ff",
+ "#641723ff",
+ ],
+ light_alpha: [
+ "#ff000003",
+ "#ff000008",
+ "#f3000d14",
+ "#ff000824",
+ "#ff000632",
+ "#f8000442",
+ "#df000356",
+ "#d2000571",
+ "#db0007b7",
+ "#d10005c1",
+ "#c40006d3",
+ "#55000de8",
+ ],
+ dark: [
+ "#191111ff",
+ "#201314ff",
+ "#3b1219ff",
+ "#500f1cff",
+ "#611623ff",
+ "#72232dff",
+ "#8c333aff",
+ "#b54548ff",
+ "#e5484dff",
+ "#ec5d5eff",
+ "#ff9592ff",
+ "#ffd1d9ff",
+ ],
+ dark_alpha: [
+ "#f4121209",
+ "#f22f3e11",
+ "#ff173f2d",
+ "#fe0a3b44",
+ "#ff204756",
+ "#ff3e5668",
+ "#ff536184",
+ "#ff5d61b0",
+ "#fe4e54e4",
+ "#ff6465eb",
+ "#ff9592ff",
+ "#ffd1d9ff",
+ ],
+ }
+}
+
+fn ruby() -> DefaultColorScaleSet {
+ DefaultColorScaleSet {
+ scale: ColorScaleName::Ruby,
+ light: [
+ "#fffcfdff",
+ "#fff7f8ff",
+ "#feeaedff",
+ "#ffdce1ff",
+ "#ffced6ff",
+ "#f8bfc8ff",
+ "#efacb8ff",
+ "#e592a3ff",
+ "#e54666ff",
+ "#dc3b5dff",
+ "#ca244dff",
+ "#64172bff",
+ ],
+ light_alpha: [
+ "#ff005503",
+ "#ff002008",
+ "#f3002515",
+ "#ff002523",
+ "#ff002a31",
+ "#e4002440",
+ "#ce002553",
+ "#c300286d",
+ "#db002cb9",
+ "#d2002cc4",
+ "#c10030db",
+ "#550016e8",
+ ],
+ dark: [
+ "#191113ff",
+ "#1e1517ff",
+ "#3a141eff",
+ "#4e1325ff",
+ "#5e1a2eff",
+ "#6f2539ff",
+ "#883447ff",
+ "#b3445aff",
+ "#e54666ff",
+ "#ec5a72ff",
+ "#ff949dff",
+ "#fed2e1ff",
+ ],
+ dark_alpha: [
+ "#f4124a09",
+ "#fe5a7f0e",
+ "#ff235d2c",
+ "#fd195e42",
+ "#fe2d6b53",
+ "#ff447665",
+ "#ff577d80",
+ "#ff5c7cae",
+ "#fe4c70e4",
+ "#ff617beb",
+ "#ff949dff",
+ "#ffd3e2fe",
+ ],
+ }
+}
+
+fn crimson() -> DefaultColorScaleSet {
+ DefaultColorScaleSet {
+ scale: ColorScaleName::Crimson,
+ light: [
+ "#fffcfdff",
+ "#fef7f9ff",
+ "#ffe9f0ff",
+ "#fedce7ff",
+ "#faceddff",
+ "#f3bed1ff",
+ "#eaacc3ff",
+ "#e093b2ff",
+ "#e93d82ff",
+ "#df3478ff",
+ "#cb1d63ff",
+ "#621639ff",
+ ],
+ light_alpha: [
+ "#ff005503",
+ "#e0004008",
+ "#ff005216",
+ "#f8005123",
+ "#e5004f31",
+ "#d0004b41",
+ "#bf004753",
+ "#b6004a6c",
+ "#e2005bc2",
+ "#d70056cb",
+ "#c4004fe2",
+ "#530026e9",
+ ],
+ dark: [
+ "#191114ff",
+ "#201318ff",
+ "#381525ff",
+ "#4d122fff",
+ "#5c1839ff",
+ "#6d2545ff",
+ "#873356ff",
+ "#b0436eff",
+ "#e93d82ff",
+ "#ee518aff",
+ "#ff92adff",
+ "#fdd3e8ff",
+ ],
+ dark_alpha: [
+ "#f4126709",
+ "#f22f7a11",
+ "#fe2a8b2a",
+ "#fd158741",
+ "#fd278f51",
+ "#fe459763",
+ "#fd559b7f",
+ "#fe5b9bab",
+ "#fe418de8",
+ "#ff5693ed",
+ "#ff92adff",
+ "#ffd5eafd",
+ ],
+ }
+}
+
+fn pink() -> DefaultColorScaleSet {
+ DefaultColorScaleSet {
+ scale: ColorScaleName::Pink,
+ light: [
+ "#fffcfeff",
+ "#fef7fbff",
+ "#fee9f5ff",
+ "#fbdcefff",
+ "#f6cee7ff",
+ "#efbfddff",
+ "#e7acd0ff",
+ "#dd93c2ff",
+ "#d6409fff",
+ "#cf3897ff",
+ "#c2298aff",
+ "#651249ff",
+ ],
+ light_alpha: [
+ "#ff00aa03",
+ "#e0008008",
+ "#f4008c16",
+ "#e2008b23",
+ "#d1008331",
+ "#c0007840",
+ "#b6006f53",
+ "#af006f6c",
+ "#c8007fbf",
+ "#c2007ac7",
+ "#b60074d6",
+ "#59003bed",
+ ],
+ dark: [
+ "#191117ff",
+ "#21121dff",
+ "#37172fff",
+ "#4b143dff",
+ "#591c47ff",
+ "#692955ff",
+ "#833869ff",
+ "#a84885ff",
+ "#d6409fff",
+ "#de51a8ff",
+ "#ff8dccff",
+ "#fdd1eaff",
+ ],
+ dark_alpha: [
+ "#f412bc09",
+ "#f420bb12",
+ "#fe37cc29",
+ "#fc1ec43f",
+ "#fd35c24e",
+ "#fd51c75f",
+ "#fd62c87b",
+ "#ff68c8a2",
+ "#fe49bcd4",
+ "#ff5cc0dc",
+ "#ff8dccff",
+ "#ffd3ecfd",
+ ],
+ }
+}
+
+fn plum() -> DefaultColorScaleSet {
+ DefaultColorScaleSet {
+ scale: ColorScaleName::Plum,
+ light: [
+ "#fefcffff",
+ "#fdf7fdff",
+ "#fbebfbff",
+ "#f7def8ff",
+ "#f2d1f3ff",
+ "#e9c2ecff",
+ "#deade3ff",
+ "#cf91d8ff",
+ "#ab4abaff",
+ "#a144afff",
+ "#953ea3ff",
+ "#53195dff",
+ ],
+ light_alpha: [
+ "#aa00ff03",
+ "#c000c008",
+ "#cc00cc14",
+ "#c200c921",
+ "#b700bd2e",
+ "#a400b03d",
+ "#9900a852",
+ "#9000a56e",
+ "#89009eb5",
+ "#7f0092bb",
+ "#730086c1",
+ "#40004be6",
+ ],
+ dark: [
+ "#181118ff",
+ "#201320ff",
+ "#351a35ff",
+ "#451d47ff",
+ "#512454ff",
+ "#5e3061ff",
+ "#734079ff",
+ "#92549cff",
+ "#ab4abaff",
+ "#b658c4ff",
+ "#e796f3ff",
+ "#f4d4f4ff",
+ ],
+ dark_alpha: [
+ "#f112f108",
+ "#f22ff211",
+ "#fd4cfd27",
+ "#f646ff3a",
+ "#f455ff48",
+ "#f66dff56",
+ "#f07cfd70",
+ "#ee84ff95",
+ "#e961feb6",
+ "#ed70ffc0",
+ "#f19cfef3",
+ "#feddfef4",
+ ],
+ }
+}
+
+fn purple() -> DefaultColorScaleSet {
+ DefaultColorScaleSet {
+ scale: ColorScaleName::Purple,
+ light: [
+ "#fefcfeff",
+ "#fbf7feff",
+ "#f7edfeff",
+ "#f2e2fcff",
+ "#ead5f9ff",
+ "#e0c4f4ff",
+ "#d1afecff",
+ "#be93e4ff",
+ "#8e4ec6ff",
+ "#8347b9ff",
+ "#8145b5ff",
+ "#402060ff",
+ ],
+ light_alpha: [
+ "#aa00aa03",
+ "#8000e008",
+ "#8e00f112",
+ "#8d00e51d",
+ "#8000db2a",
+ "#7a01d03b",
+ "#6d00c350",
+ "#6600c06c",
+ "#5c00adb1",
+ "#53009eb8",
+ "#52009aba",
+ "#250049df",
+ ],
+ dark: [
+ "#18111bff",
+ "#1e1523ff",
+ "#301c3bff",
+ "#3d224eff",
+ "#48295cff",
+ "#54346bff",
+ "#664282ff",
+ "#8457aaff",
+ "#8e4ec6ff",
+ "#9a5cd0ff",
+ "#d19dffff",
+ "#ecd9faff",
+ ],
+ dark_alpha: [
+ "#b412f90b",
+ "#b744f714",
+ "#c150ff2d",
+ "#bb53fd42",
+ "#be5cfd51",
+ "#c16dfd61",
+ "#c378fd7a",
+ "#c47effa4",
+ "#b661ffc2",
+ "#bc6fffcd",
+ "#d19dffff",
+ "#f1ddfffa",
+ ],
+ }
+}
+
+fn violet() -> DefaultColorScaleSet {
+ DefaultColorScaleSet {
+ scale: ColorScaleName::Violet,
+ light: [
+ "#fdfcfeff",
+ "#faf8ffff",
+ "#f4f0feff",
+ "#ebe4ffff",
+ "#e1d9ffff",
+ "#d4cafeff",
+ "#c2b5f5ff",
+ "#aa99ecff",
+ "#6e56cfff",
+ "#654dc4ff",
+ "#6550b9ff",
+ "#2f265fff",
+ ],
+ light_alpha: [
+ "#5500aa03",
+ "#4900ff07",
+ "#4400ee0f",
+ "#4300ff1b",
+ "#3600ff26",
+ "#3100fb35",
+ "#2d01dd4a",
+ "#2b00d066",
+ "#2400b7a9",
+ "#2300abb2",
+ "#1f0099af",
+ "#0b0043d9",
+ ],
+ dark: [
+ "#14121fff",
+ "#1b1525ff",
+ "#291f43ff",
+ "#33255bff",
+ "#3c2e69ff",
+ "#473876ff",
+ "#56468bff",
+ "#6958adff",
+ "#6e56cfff",
+ "#7d66d9ff",
+ "#baa7ffff",
+ "#e2ddfeff",
+ ],
+ dark_alpha: [
+ "#4422ff0f",
+ "#853ff916",
+ "#8354fe36",
+ "#7d51fd50",
+ "#845ffd5f",
+ "#8f6cfd6d",
+ "#9879ff83",
+ "#977dfea8",
+ "#8668ffcc",
+ "#9176fed7",
+ "#baa7ffff",
+ "#e3defffe",
+ ],
+ }
+}
+
+fn iris() -> DefaultColorScaleSet {
+ DefaultColorScaleSet {
+ scale: ColorScaleName::Iris,
+ light: [
+ "#fdfdffff",
+ "#f8f8ffff",
+ "#f0f1feff",
+ "#e6e7ffff",
+ "#dadcffff",
+ "#cbcdffff",
+ "#b8baf8ff",
+ "#9b9ef0ff",
+ "#5b5bd6ff",
+ "#5151cdff",
+ "#5753c6ff",
+ "#272962ff",
+ ],
+ light_alpha: [
+ "#0000ff02",
+ "#0000ff07",
+ "#0011ee0f",
+ "#000bff19",
+ "#000eff25",
+ "#000aff34",
+ "#0008e647",
+ "#0008d964",
+ "#0000c0a4",
+ "#0000b6ae",
+ "#0600abac",
+ "#000246d8",
+ ],
+ dark: [
+ "#13131eff",
+ "#171625ff",
+ "#202248ff",
+ "#262a65ff",
+ "#303374ff",
+ "#3d3e82ff",
+ "#4a4a95ff",
+ "#5958b1ff",
+ "#5b5bd6ff",
+ "#6e6adeff",
+ "#b1a9ffff",
+ "#e0dffeff",
+ ],
+ dark_alpha: [
+ "#3636fe0e",
+ "#564bf916",
+ "#525bff3b",
+ "#4d58ff5a",
+ "#5b62fd6b",
+ "#6d6ffd7a",
+ "#7777fe8e",
+ "#7b7afeac",
+ "#6a6afed4",
+ "#7d79ffdc",
+ "#b1a9ffff",
+ "#e1e0fffe",
+ ],
+ }
+}
+
+fn indigo() -> DefaultColorScaleSet {
+ DefaultColorScaleSet {
+ scale: ColorScaleName::Indigo,
+ light: [
+ "#fdfdfeff",
+ "#f7f9ffff",
+ "#edf2feff",
+ "#e1e9ffff",
+ "#d2deffff",
+ "#c1d0ffff",
+ "#abbdf9ff",
+ "#8da4efff",
+ "#3e63ddff",
+ "#3358d4ff",
+ "#3a5bc7ff",
+ "#1f2d5cff",
+ ],
+ light_alpha: [
+ "#00008002",
+ "#0040ff08",
+ "#0047f112",
+ "#0044ff1e",
+ "#0044ff2d",
+ "#003eff3e",
+ "#0037ed54",
+ "#0034dc72",
+ "#0031d2c1",
+ "#002ec9cc",
+ "#002bb7c5",
+ "#001046e0",
+ ],
+ dark: [
+ "#11131fff",
+ "#141726ff",
+ "#182449ff",
+ "#1d2e62ff",
+ "#253974ff",
+ "#304384ff",
+ "#3a4f97ff",
+ "#435db1ff",
+ "#3e63ddff",
+ "#5472e4ff",
+ "#9eb1ffff",
+ "#d6e1ffff",
+ ],
+ dark_alpha: [
+ "#1133ff0f",
+ "#3354fa17",
+ "#2f62ff3c",
+ "#3566ff57",
+ "#4171fd6b",
+ "#5178fd7c",
+ "#5a7fff90",
+ "#5b81feac",
+ "#4671ffdb",
+ "#5c7efee3",
+ "#9eb1ffff",
+ "#d6e1ffff",
+ ],
+ }
+}
+
+fn blue() -> DefaultColorScaleSet {
+ DefaultColorScaleSet {
+ scale: ColorScaleName::Blue,
+ light: [
+ "#fbfdffff",
+ "#f4faffff",
+ "#e6f4feff",
+ "#d5efffff",
+ "#c2e5ffff",
+ "#acd8fcff",
+ "#8ec8f6ff",
+ "#5eb1efff",
+ "#0090ffff",
+ "#0588f0ff",
+ "#0d74ceff",
+ "#113264ff",
+ ],
+ light_alpha: [
+ "#0080ff04",
+ "#008cff0b",
+ "#008ff519",
+ "#009eff2a",
+ "#0093ff3d",
+ "#0088f653",
+ "#0083eb71",
+ "#0084e6a1",
+ "#0090ffff",
+ "#0086f0fa",
+ "#006dcbf2",
+ "#002359ee",
+ ],
+ dark: [
+ "#0d1520ff",
+ "#111927ff",
+ "#0d2847ff",
+ "#003362ff",
+ "#004074ff",
+ "#104d87ff",
+ "#205d9eff",
+ "#2870bdff",
+ "#0090ffff",
+ "#3b9effff",
+ "#70b8ffff",
+ "#c2e6ffff",
+ ],
+ dark_alpha: [
+ "#004df211",
+ "#1166fb18",
+ "#0077ff3a",
+ "#0075ff57",
+ "#0081fd6b",
+ "#0f89fd7f",
+ "#2a91fe98",
+ "#3094feb9",
+ "#0090ffff",
+ "#3b9effff",
+ "#70b8ffff",
+ "#c2e6ffff",
+ ],
+ }
+}
+
+fn cyan() -> DefaultColorScaleSet {
+ DefaultColorScaleSet {
+ scale: ColorScaleName::Cyan,
+ light: [
+ "#fafdfeff",
+ "#f2fafbff",
+ "#def7f9ff",
+ "#caf1f6ff",
+ "#b5e9f0ff",
+ "#9ddde7ff",
+ "#7dcedcff",
+ "#3db9cfff",
+ "#00a2c7ff",
+ "#0797b9ff",
+ "#107d98ff",
+ "#0d3c48ff",
+ ],
+ light_alpha: [
+ "#0099cc05",
+ "#009db10d",
+ "#00c2d121",
+ "#00bcd435",
+ "#01b4cc4a",
+ "#00a7c162",
+ "#009fbb82",
+ "#00a3c0c2",
+ "#00a2c7ff",
+ "#0094b7f8",
+ "#007491ef",
+ "#00323ef2",
+ ],
+ dark: [
+ "#0b161aff",
+ "#101b20ff",
+ "#082c36ff",
+ "#003848ff",
+ "#004558ff",
+ "#045468ff",
+ "#12677eff",
+ "#11809cff",
+ "#00a2c7ff",
+ "#23afd0ff",
+ "#4ccce6ff",
+ "#b6ecf7ff",
+ ],
+ dark_alpha: [
+ "#0091f70a",
+ "#02a7f211",
+ "#00befd28",
+ "#00baff3b",
+ "#00befd4d",
+ "#00c7fd5e",
+ "#14cdff75",
+ "#11cfff95",
+ "#00cfffc3",
+ "#28d6ffcd",
+ "#52e1fee5",
+ "#bbf3fef7",
+ ],
+ }
+}
+
+fn teal() -> DefaultColorScaleSet {
+ DefaultColorScaleSet {
+ scale: ColorScaleName::Teal,
+ light: [
+ "#fafefdff",
+ "#f3fbf9ff",
+ "#e0f8f3ff",
+ "#ccf3eaff",
+ "#b8eae0ff",
+ "#a1ded2ff",
+ "#83cdc1ff",
+ "#53b9abff",
+ "#12a594ff",
+ "#0d9b8aff",
+ "#008573ff",
+ "#0d3d38ff",
+ ],
+ light_alpha: [
+ "#00cc9905",
+ "#00aa800c",
+ "#00c69d1f",
+ "#00c39633",
+ "#00b49047",
+ "#00a6855e",
+ "#0099807c",
+ "#009783ac",
+ "#009e8ced",
+ "#009684f2",
+ "#008573ff",
+ "#00332df2",
+ ],
+ dark: [
+ "#0d1514ff",
+ "#111c1bff",
+ "#0d2d2aff",
+ "#023b37ff",
+ "#084843ff",
+ "#145750ff",
+ "#1c6961ff",
+ "#207e73ff",
+ "#12a594ff",
+ "#0eb39eff",
+ "#0bd8b6ff",
+ "#adf0ddff",
+ ],
+ dark_alpha: [
+ "#00deab05",
+ "#12fbe60c",
+ "#00ffe61e",
+ "#00ffe92d",
+ "#00ffea3b",
+ "#1cffe84b",
+ "#2efde85f",
+ "#32ffe775",
+ "#13ffe49f",
+ "#0dffe0ae",
+ "#0afed5d6",
+ "#b8ffebef",
+ ],
+ }
+}
+
+fn jade() -> DefaultColorScaleSet {
+ DefaultColorScaleSet {
+ scale: ColorScaleName::Jade,
+ light: [
+ "#fbfefdff",
+ "#f4fbf7ff",
+ "#e6f7edff",
+ "#d6f1e3ff",
+ "#c3e9d7ff",
+ "#acdec8ff",
+ "#8bceb6ff",
+ "#56ba9fff",
+ "#29a383ff",
+ "#26997bff",
+ "#208368ff",
+ "#1d3b31ff",
+ ],
+ light_alpha: [
+ "#00c08004",
+ "#00a3460b",
+ "#00ae4819",
+ "#00a85129",
+ "#00a2553c",
+ "#009a5753",
+ "#00945f74",
+ "#00976ea9",
+ "#00916bd6",
+ "#008764d9",
+ "#007152df",
+ "#002217e2",
+ ],
+ dark: [
+ "#0d1512ff",
+ "#121c18ff",
+ "#0f2e22ff",
+ "#0b3b2cff",
+ "#114837ff",
+ "#1b5745ff",
+ "#246854ff",
+ "#2a7e68ff",
+ "#29a383ff",
+ "#27b08bff",
+ "#1fd8a4ff",
+ "#adf0d4ff",
+ ],
+ dark_alpha: [
+ "#00de4505",
+ "#27fba60c",
+ "#02f99920",
+ "#00ffaa2d",
+ "#11ffb63b",
+ "#34ffc24b",
+ "#45fdc75e",
+ "#48ffcf75",
+ "#38feca9d",
+ "#31fec7ab",
+ "#21fec0d6",
+ "#b8ffe1ef",
+ ],
+ }
+}
+
+fn green() -> DefaultColorScaleSet {
+ DefaultColorScaleSet {
+ scale: ColorScaleName::Green,
+ light: [
+ "#fbfefcff",
+ "#f4fbf6ff",
+ "#e6f6ebff",
+ "#d6f1dfff",
+ "#c4e8d1ff",
+ "#adddc0ff",
+ "#8eceaaff",
+ "#5bb98bff",
+ "#30a46cff",
+ "#2b9a66ff",
+ "#218358ff",
+ "#193b2dff",
+ ],
+ light_alpha: [
+ "#00c04004",
+ "#00a32f0b",
+ "#00a43319",
+ "#00a83829",
+ "#019c393b",
+ "#00963c52",
+ "#00914071",
+ "#00924ba4",
+ "#008f4acf",
+ "#008647d4",
+ "#00713fde",
+ "#002616e6",
+ ],
+ dark: [
+ "#0e1512ff",
+ "#121b17ff",
+ "#132d21ff",
+ "#113b29ff",
+ "#174933ff",
+ "#20573eff",
+ "#28684aff",
+ "#2f7c57ff",
+ "#30a46cff",
+ "#33b074ff",
+ "#3dd68cff",
+ "#b1f1cbff",
+ ],
+ dark_alpha: [
+ "#00de4505",
+ "#29f99d0b",
+ "#22ff991e",
+ "#11ff992d",
+ "#2bffa23c",
+ "#44ffaa4b",
+ "#50fdac5e",
+ "#54ffad73",
+ "#44ffa49e",
+ "#43fea4ab",
+ "#46fea5d4",
+ "#bbffd7f0",
+ ],
+ }
+}
+
+fn grass() -> DefaultColorScaleSet {
+ DefaultColorScaleSet {
+ scale: ColorScaleName::Grass,
+ light: [
+ "#fbfefbff",
+ "#f5fbf5ff",
+ "#e9f6e9ff",
+ "#daf1dbff",
+ "#c9e8caff",
+ "#b2ddb5ff",
+ "#94ce9aff",
+ "#65ba74ff",
+ "#46a758ff",
+ "#3e9b4fff",
+ "#2a7e3bff",
+ "#203c25ff",
+ ],
+ light_alpha: [
+ "#00c00004",
+ "#0099000a",
+ "#00970016",
+ "#009f0725",
+ "#00930536",
+ "#008f0a4d",
+ "#018b0f6b",
+ "#008d199a",
+ "#008619b9",
+ "#007b17c1",
+ "#006514d5",
+ "#002006df",
+ ],
+ dark: [
+ "#0e1511ff",
+ "#141a15ff",
+ "#1b2a1eff",
+ "#1d3a24ff",
+ "#25482dff",
+ "#2d5736ff",
+ "#366740ff",
+ "#3e7949ff",
+ "#46a758ff",
+ "#53b365ff",
+ "#71d083ff",
+ "#c2f0c2ff",
+ ],
+ dark_alpha: [
+ "#00de1205",
+ "#5ef7780a",
+ "#70fe8c1b",
+ "#57ff802c",
+ "#68ff8b3b",
+ "#71ff8f4b",
+ "#77fd925d",
+ "#77fd9070",
+ "#65ff82a1",
+ "#72ff8dae",
+ "#89ff9fcd",
+ "#ceffceef",
+ ],
+ }
+}
+
+fn lime() -> DefaultColorScaleSet {
+ DefaultColorScaleSet {
+ scale: ColorScaleName::Lime,
+ light: [
+ "#fcfdfaff",
+ "#f8faf3ff",
+ "#eef6d6ff",
+ "#e2f0bdff",
+ "#d3e7a6ff",
+ "#c2da91ff",
+ "#abc978ff",
+ "#8db654ff",
+ "#bdee63ff",
+ "#b0e64cff",
+ "#5c7c2fff",
+ "#37401cff",
+ ],
+ light_alpha: [
+ "#66990005",
+ "#6b95000c",
+ "#96c80029",
+ "#8fc60042",
+ "#81bb0059",
+ "#72aa006e",
+ "#61990087",
+ "#559200ab",
+ "#93e4009c",
+ "#8fdc00b3",
+ "#375f00d0",
+ "#1e2900e3",
+ ],
+ dark: [
+ "#11130cff",
+ "#151a10ff",
+ "#1f2917ff",
+ "#29371dff",
+ "#334423ff",
+ "#3d522aff",
+ "#496231ff",
+ "#577538ff",
+ "#bdee63ff",
+ "#d4ff70ff",
+ "#bde56cff",
+ "#e3f7baff",
+ ],
+ dark_alpha: [
+ "#11bb0003",
+ "#78f7000a",
+ "#9bfd4c1a",
+ "#a7fe5c29",
+ "#affe6537",
+ "#b2fe6d46",
+ "#b6ff6f57",
+ "#b6fd6d6c",
+ "#caff69ed",
+ "#d4ff70ff",
+ "#d1fe77e4",
+ "#e9febff7",
+ ],
+ }
+}
+
+fn mint() -> DefaultColorScaleSet {
+ DefaultColorScaleSet {
+ scale: ColorScaleName::Mint,
+ light: [
+ "#f9fefdff",
+ "#f2fbf9ff",
+ "#ddf9f2ff",
+ "#c8f4e9ff",
+ "#b3ecdeff",
+ "#9ce0d0ff",
+ "#7ecfbdff",
+ "#4cbba5ff",
+ "#86ead4ff",
+ "#7de0cbff",
+ "#027864ff",
+ "#16433cff",
+ ],
+ light_alpha: [
+ "#00d5aa06",
+ "#00b18a0d",
+ "#00d29e22",
+ "#00cc9937",
+ "#00c0914c",
+ "#00b08663",
+ "#00a17d81",
+ "#009e7fb3",
+ "#00d3a579",
+ "#00c39982",
+ "#007763fd",
+ "#00312ae9",
+ ],
+ dark: [
+ "#0e1515ff",
+ "#0f1b1bff",
+ "#092c2bff",
+ "#003a38ff",
+ "#004744ff",
+ "#105650ff",
+ "#1e685fff",
+ "#277f70ff",
+ "#86ead4ff",
+ "#a8f5e5ff",
+ "#58d5baff",
+ "#c4f5e1ff",
+ ],
+ dark_alpha: [
+ "#00dede05",
+ "#00f9f90b",
+ "#00fff61d",
+ "#00fff42c",
+ "#00fff23a",
+ "#0effeb4a",
+ "#34fde55e",
+ "#41ffdf76",
+ "#92ffe7e9",
+ "#aefeedf5",
+ "#67ffded2",
+ "#cbfee9f5",
+ ],
+ }
+}
+
+fn sky() -> DefaultColorScaleSet {
+ DefaultColorScaleSet {
+ scale: ColorScaleName::Sky,
+ light: [
+ "#f9feffff",
+ "#f1fafdff",
+ "#e1f6fdff",
+ "#d1f0faff",
+ "#bee7f5ff",
+ "#a9daedff",
+ "#8dcae3ff",
+ "#60b3d7ff",
+ "#7ce2feff",
+ "#74daf8ff",
+ "#00749eff",
+ "#1d3e56ff",
+ ],
+ light_alpha: [
+ "#00d5ff06",
+ "#00a4db0e",
+ "#00b3ee1e",
+ "#00ace42e",
+ "#00a1d841",
+ "#0092ca56",
+ "#0089c172",
+ "#0085bf9f",
+ "#00c7fe83",
+ "#00bcf38b",
+ "#00749eff",
+ "#002540e2",
+ ],
+ dark: [
+ "#0d141fff",
+ "#111a27ff",
+ "#112840ff",
+ "#113555ff",
+ "#154467ff",
+ "#1b537bff",
+ "#1f6692ff",
+ "#197caeff",
+ "#7ce2feff",
+ "#a8eeffff",
+ "#75c7f0ff",
+ "#c2f3ffff",
+ ],
+ dark_alpha: [
+ "#0044ff0f",
+ "#1171fb18",
+ "#1184fc33",
+ "#128fff49",
+ "#1c9dfd5d",
+ "#28a5ff72",
+ "#2badfe8b",
+ "#1db2fea9",
+ "#7ce3fffe",
+ "#a8eeffff",
+ "#7cd3ffef",
+ "#c2f3ffff",
+ ],
+ }
+}
+
+fn black() -> DefaultColorScaleSet {
+ DefaultColorScaleSet {
+ scale: ColorScaleName::Black,
+ light: [
+ "#0000000d",
+ "#0000001a",
+ "#00000026",
+ "#00000033",
+ "#0000004d",
+ "#00000066",
+ "#00000080",
+ "#00000099",
+ "#000000b3",
+ "#000000cc",
+ "#000000e6",
+ "#000000f2",
+ ],
+ light_alpha: [
+ "#0000000d",
+ "#0000001a",
+ "#00000026",
+ "#00000033",
+ "#0000004d",
+ "#00000066",
+ "#00000080",
+ "#00000099",
+ "#000000b3",
+ "#000000cc",
+ "#000000e6",
+ "#000000f2",
+ ],
+ dark: [
+ "#0000000d",
+ "#0000001a",
+ "#00000026",
+ "#00000033",
+ "#0000004d",
+ "#00000066",
+ "#00000080",
+ "#00000099",
+ "#000000b3",
+ "#000000cc",
+ "#000000e6",
+ "#000000f2",
+ ],
+ dark_alpha: [
+ "#0000000d",
+ "#0000001a",
+ "#00000026",
+ "#00000033",
+ "#0000004d",
+ "#00000066",
+ "#00000080",
+ "#00000099",
+ "#000000b3",
+ "#000000cc",
+ "#000000e6",
+ "#000000f2",
+ ],
+ }
+}
+
+fn white() -> DefaultColorScaleSet {
+ DefaultColorScaleSet {
+ scale: ColorScaleName::White,
+ light: [
+ "#ffffff0d",
+ "#ffffff1a",
+ "#ffffff26",
+ "#ffffff33",
+ "#ffffff4d",
+ "#ffffff66",
+ "#ffffff80",
+ "#ffffff99",
+ "#ffffffb3",
+ "#ffffffcc",
+ "#ffffffe6",
+ "#fffffff2",
+ ],
+ light_alpha: [
+ "#ffffff0d",
+ "#ffffff1a",
+ "#ffffff26",
+ "#ffffff33",
+ "#ffffff4d",
+ "#ffffff66",
+ "#ffffff80",
+ "#ffffff99",
+ "#ffffffb3",
+ "#ffffffcc",
+ "#ffffffe6",
+ "#fffffff2",
+ ],
+ dark: [
+ "#ffffff0d",
+ "#ffffff1a",
+ "#ffffff26",
+ "#ffffff33",
+ "#ffffff4d",
+ "#ffffff66",
+ "#ffffff80",
+ "#ffffff99",
+ "#ffffffb3",
+ "#ffffffcc",
+ "#ffffffe6",
+ "#fffffff2",
+ ],
+ dark_alpha: [
+ "#ffffff0d",
+ "#ffffff1a",
+ "#ffffff26",
+ "#ffffff33",
+ "#ffffff4d",
+ "#ffffff66",
+ "#ffffff80",
+ "#ffffff99",
+ "#ffffffb3",
+ "#ffffffcc",
+ "#ffffffe6",
+ "#fffffff2",
+ ],
+ }
+}
@@ -1,7 +1,4 @@
-use crate::{
- themes::{one_dark, rose_pine, rose_pine_dawn, rose_pine_moon, sandcastle},
- Theme, ThemeMetadata,
-};
+use crate::{themes, Theme, ThemeMetadata};
use anyhow::{anyhow, Result};
use gpui2::SharedString;
use std::{collections::HashMap, sync::Arc};
@@ -41,11 +38,45 @@ impl Default for ThemeRegistry {
};
this.insert_themes([
- one_dark(),
- rose_pine(),
- rose_pine_dawn(),
- rose_pine_moon(),
- sandcastle(),
+ themes::andromeda(),
+ themes::atelier_cave_dark(),
+ themes::atelier_cave_light(),
+ themes::atelier_dune_dark(),
+ themes::atelier_dune_light(),
+ themes::atelier_estuary_dark(),
+ themes::atelier_estuary_light(),
+ themes::atelier_forest_dark(),
+ themes::atelier_forest_light(),
+ themes::atelier_heath_dark(),
+ themes::atelier_heath_light(),
+ themes::atelier_lakeside_dark(),
+ themes::atelier_lakeside_light(),
+ themes::atelier_plateau_dark(),
+ themes::atelier_plateau_light(),
+ themes::atelier_savanna_dark(),
+ themes::atelier_savanna_light(),
+ themes::atelier_seaside_dark(),
+ themes::atelier_seaside_light(),
+ themes::atelier_sulphurpool_dark(),
+ themes::atelier_sulphurpool_light(),
+ themes::ayu_dark(),
+ themes::ayu_light(),
+ themes::ayu_mirage(),
+ themes::gruvbox_dark(),
+ themes::gruvbox_dark_hard(),
+ themes::gruvbox_dark_soft(),
+ themes::gruvbox_light(),
+ themes::gruvbox_light_hard(),
+ themes::gruvbox_light_soft(),
+ themes::one_dark(),
+ themes::one_light(),
+ themes::rose_pine(),
+ themes::rose_pine_dawn(),
+ themes::rose_pine_moon(),
+ themes::sandcastle(),
+ themes::solarized_dark(),
+ themes::solarized_light(),
+ themes::summercamp(),
]);
this
@@ -0,0 +1,164 @@
+use gpui2::{AppContext, Hsla};
+use indexmap::IndexMap;
+
+use crate::{theme, Appearance};
+
+#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub enum ColorScaleName {
+ Gray,
+ Mauve,
+ Slate,
+ Sage,
+ Olive,
+ Sand,
+ Gold,
+ Bronze,
+ Brown,
+ Yellow,
+ Amber,
+ Orange,
+ Tomato,
+ Red,
+ Ruby,
+ Crimson,
+ Pink,
+ Plum,
+ Purple,
+ Violet,
+ Iris,
+ Indigo,
+ Blue,
+ Cyan,
+ Teal,
+ Jade,
+ Green,
+ Grass,
+ Lime,
+ Mint,
+ Sky,
+ Black,
+ White,
+}
+
+impl std::fmt::Display for ColorScaleName {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ write!(
+ f,
+ "{}",
+ match self {
+ Self::Gray => "Gray",
+ Self::Mauve => "Mauve",
+ Self::Slate => "Slate",
+ Self::Sage => "Sage",
+ Self::Olive => "Olive",
+ Self::Sand => "Sand",
+ Self::Gold => "Gold",
+ Self::Bronze => "Bronze",
+ Self::Brown => "Brown",
+ Self::Yellow => "Yellow",
+ Self::Amber => "Amber",
+ Self::Orange => "Orange",
+ Self::Tomato => "Tomato",
+ Self::Red => "Red",
+ Self::Ruby => "Ruby",
+ Self::Crimson => "Crimson",
+ Self::Pink => "Pink",
+ Self::Plum => "Plum",
+ Self::Purple => "Purple",
+ Self::Violet => "Violet",
+ Self::Iris => "Iris",
+ Self::Indigo => "Indigo",
+ Self::Blue => "Blue",
+ Self::Cyan => "Cyan",
+ Self::Teal => "Teal",
+ Self::Jade => "Jade",
+ Self::Green => "Green",
+ Self::Grass => "Grass",
+ Self::Lime => "Lime",
+ Self::Mint => "Mint",
+ Self::Sky => "Sky",
+ Self::Black => "Black",
+ Self::White => "White",
+ }
+ )
+ }
+}
+
+pub type ColorScale = [Hsla; 12];
+
+pub type ColorScales = IndexMap<ColorScaleName, ColorScaleSet>;
+
+/// A one-based step in a [`ColorScale`].
+pub type ColorScaleStep = usize;
+
+pub struct ColorScaleSet {
+ name: ColorScaleName,
+ light: ColorScale,
+ dark: ColorScale,
+ light_alpha: ColorScale,
+ dark_alpha: ColorScale,
+}
+
+impl ColorScaleSet {
+ pub fn new(
+ name: ColorScaleName,
+ light: ColorScale,
+ light_alpha: ColorScale,
+ dark: ColorScale,
+ dark_alpha: ColorScale,
+ ) -> Self {
+ Self {
+ name,
+ light,
+ light_alpha,
+ dark,
+ dark_alpha,
+ }
+ }
+
+ pub fn name(&self) -> String {
+ self.name.to_string()
+ }
+
+ pub fn light(&self, step: ColorScaleStep) -> Hsla {
+ self.light[step - 1]
+ }
+
+ pub fn light_alpha(&self, step: ColorScaleStep) -> Hsla {
+ self.light_alpha[step - 1]
+ }
+
+ pub fn dark(&self, step: ColorScaleStep) -> Hsla {
+ self.dark[step - 1]
+ }
+
+ pub fn dark_alpha(&self, step: ColorScaleStep) -> Hsla {
+ self.dark_alpha[step - 1]
+ }
+
+ fn current_appearance(cx: &AppContext) -> Appearance {
+ let theme = theme(cx);
+ if theme.metadata.is_light {
+ Appearance::Light
+ } else {
+ Appearance::Dark
+ }
+ }
+
+ pub fn step(&self, cx: &AppContext, step: ColorScaleStep) -> Hsla {
+ let appearance = Self::current_appearance(cx);
+
+ match appearance {
+ Appearance::Light => self.light(step),
+ Appearance::Dark => self.dark(step),
+ }
+ }
+
+ pub fn step_alpha(&self, cx: &AppContext, step: ColorScaleStep) -> Hsla {
+ let appearance = Self::current_appearance(cx);
+ match appearance {
+ Appearance::Light => self.light_alpha(step),
+ Appearance::Dark => self.dark_alpha(step),
+ }
+ }
+}
@@ -1,14 +1,24 @@
+mod default;
mod registry;
+mod scale;
mod settings;
mod themes;
+pub use default::*;
pub use registry::*;
+pub use scale::*;
pub use settings::*;
use gpui2::{AppContext, HighlightStyle, Hsla, SharedString};
use settings2::Settings;
use std::sync::Arc;
+#[derive(Debug, Clone, PartialEq)]
+pub enum Appearance {
+ Light,
+ Dark,
+}
+
pub fn init(cx: &mut AppContext) {
cx.set_global(ThemeRegistry::default());
ThemeSettings::register(cx);
@@ -18,6 +28,10 @@ pub fn active_theme<'a>(cx: &'a AppContext) -> &'a Arc<Theme> {
&ThemeSettings::get_global(cx).active_theme
}
+pub fn theme(cx: &AppContext) -> Arc<Theme> {
+ active_theme(cx).clone()
+}
+
pub struct Theme {
pub metadata: ThemeMetadata,
@@ -0,0 +1,130 @@
+use gpui2::rgba;
+
+use crate::{PlayerTheme, SyntaxTheme, Theme, ThemeMetadata};
+
+pub fn andromeda() -> Theme {
+ Theme {
+ metadata: ThemeMetadata {
+ name: "Andromeda".into(),
+ is_light: false,
+ },
+ transparent: rgba(0x00000000).into(),
+ mac_os_traffic_light_red: rgba(0xec695eff).into(),
+ mac_os_traffic_light_yellow: rgba(0xf4bf4eff).into(),
+ mac_os_traffic_light_green: rgba(0x61c553ff).into(),
+ border: rgba(0x2b2f38ff).into(),
+ border_variant: rgba(0x2b2f38ff).into(),
+ border_focused: rgba(0x183934ff).into(),
+ border_transparent: rgba(0x00000000).into(),
+ elevated_surface: rgba(0x262933ff).into(),
+ surface: rgba(0x21242bff).into(),
+ background: rgba(0x262933ff).into(),
+ filled_element: rgba(0x262933ff).into(),
+ filled_element_hover: rgba(0xffffff1e).into(),
+ filled_element_active: rgba(0xffffff28).into(),
+ filled_element_selected: rgba(0x12231fff).into(),
+ filled_element_disabled: rgba(0x00000000).into(),
+ ghost_element: rgba(0x00000000).into(),
+ ghost_element_hover: rgba(0xffffff14).into(),
+ ghost_element_active: rgba(0xffffff1e).into(),
+ ghost_element_selected: rgba(0x12231fff).into(),
+ ghost_element_disabled: rgba(0x00000000).into(),
+ text: rgba(0xf7f7f8ff).into(),
+ text_muted: rgba(0xaca8aeff).into(),
+ text_placeholder: rgba(0xf82871ff).into(),
+ text_disabled: rgba(0x6b6b73ff).into(),
+ text_accent: rgba(0x10a793ff).into(),
+ icon_muted: rgba(0xaca8aeff).into(),
+ syntax: SyntaxTheme {
+ highlights: vec![
+ ("emphasis".into(), rgba(0x10a793ff).into()),
+ ("punctuation.bracket".into(), rgba(0xd8d5dbff).into()),
+ ("attribute".into(), rgba(0x10a793ff).into()),
+ ("variable".into(), rgba(0xf7f7f8ff).into()),
+ ("predictive".into(), rgba(0x315f70ff).into()),
+ ("property".into(), rgba(0x10a793ff).into()),
+ ("variant".into(), rgba(0x10a793ff).into()),
+ ("embedded".into(), rgba(0xf7f7f8ff).into()),
+ ("string.special".into(), rgba(0xf29c14ff).into()),
+ ("keyword".into(), rgba(0x10a793ff).into()),
+ ("tag".into(), rgba(0x10a793ff).into()),
+ ("enum".into(), rgba(0xf29c14ff).into()),
+ ("link_text".into(), rgba(0xf29c14ff).into()),
+ ("primary".into(), rgba(0xf7f7f8ff).into()),
+ ("punctuation".into(), rgba(0xd8d5dbff).into()),
+ ("punctuation.special".into(), rgba(0xd8d5dbff).into()),
+ ("function".into(), rgba(0xfee56cff).into()),
+ ("number".into(), rgba(0x96df71ff).into()),
+ ("preproc".into(), rgba(0xf7f7f8ff).into()),
+ ("operator".into(), rgba(0xf29c14ff).into()),
+ ("constructor".into(), rgba(0x10a793ff).into()),
+ ("string.escape".into(), rgba(0xafabb1ff).into()),
+ ("string.special.symbol".into(), rgba(0xf29c14ff).into()),
+ ("string".into(), rgba(0xf29c14ff).into()),
+ ("comment".into(), rgba(0xafabb1ff).into()),
+ ("hint".into(), rgba(0x618399ff).into()),
+ ("type".into(), rgba(0x08e7c5ff).into()),
+ ("label".into(), rgba(0x10a793ff).into()),
+ ("comment.doc".into(), rgba(0xafabb1ff).into()),
+ ("text.literal".into(), rgba(0xf29c14ff).into()),
+ ("constant".into(), rgba(0x96df71ff).into()),
+ ("string.regex".into(), rgba(0xf29c14ff).into()),
+ ("emphasis.strong".into(), rgba(0x10a793ff).into()),
+ ("title".into(), rgba(0xf7f7f8ff).into()),
+ ("punctuation.delimiter".into(), rgba(0xd8d5dbff).into()),
+ ("link_uri".into(), rgba(0x96df71ff).into()),
+ ("boolean".into(), rgba(0x96df71ff).into()),
+ ("punctuation.list_marker".into(), rgba(0xd8d5dbff).into()),
+ ],
+ },
+ status_bar: rgba(0x262933ff).into(),
+ title_bar: rgba(0x262933ff).into(),
+ toolbar: rgba(0x1e2025ff).into(),
+ tab_bar: rgba(0x21242bff).into(),
+ editor: rgba(0x1e2025ff).into(),
+ editor_subheader: rgba(0x21242bff).into(),
+ editor_active_line: rgba(0x21242bff).into(),
+ terminal: rgba(0x1e2025ff).into(),
+ image_fallback_background: rgba(0x262933ff).into(),
+ git_created: rgba(0x96df71ff).into(),
+ git_modified: rgba(0x10a793ff).into(),
+ git_deleted: rgba(0xf82871ff).into(),
+ git_conflict: rgba(0xfee56cff).into(),
+ git_ignored: rgba(0x6b6b73ff).into(),
+ git_renamed: rgba(0xfee56cff).into(),
+ players: [
+ PlayerTheme {
+ cursor: rgba(0x10a793ff).into(),
+ selection: rgba(0x10a7933d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x96df71ff).into(),
+ selection: rgba(0x96df713d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xc74cecff).into(),
+ selection: rgba(0xc74cec3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xf29c14ff).into(),
+ selection: rgba(0xf29c143d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x893ea6ff).into(),
+ selection: rgba(0x893ea63d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x08e7c5ff).into(),
+ selection: rgba(0x08e7c53d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xf82871ff).into(),
+ selection: rgba(0xf828713d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xfee56cff).into(),
+ selection: rgba(0xfee56c3d).into(),
+ },
+ ],
+ }
+}
@@ -0,0 +1,136 @@
+use gpui2::rgba;
+
+use crate::{PlayerTheme, SyntaxTheme, Theme, ThemeMetadata};
+
+pub fn atelier_cave_dark() -> Theme {
+ Theme {
+ metadata: ThemeMetadata {
+ name: "Atelier Cave Dark".into(),
+ is_light: false,
+ },
+ transparent: rgba(0x00000000).into(),
+ mac_os_traffic_light_red: rgba(0xec695eff).into(),
+ mac_os_traffic_light_yellow: rgba(0xf4bf4eff).into(),
+ mac_os_traffic_light_green: rgba(0x61c553ff).into(),
+ border: rgba(0x56505eff).into(),
+ border_variant: rgba(0x56505eff).into(),
+ border_focused: rgba(0x222953ff).into(),
+ border_transparent: rgba(0x00000000).into(),
+ elevated_surface: rgba(0x3a353fff).into(),
+ surface: rgba(0x221f26ff).into(),
+ background: rgba(0x3a353fff).into(),
+ filled_element: rgba(0x3a353fff).into(),
+ filled_element_hover: rgba(0xffffff1e).into(),
+ filled_element_active: rgba(0xffffff28).into(),
+ filled_element_selected: rgba(0x161a35ff).into(),
+ filled_element_disabled: rgba(0x00000000).into(),
+ ghost_element: rgba(0x00000000).into(),
+ ghost_element_hover: rgba(0xffffff14).into(),
+ ghost_element_active: rgba(0xffffff1e).into(),
+ ghost_element_selected: rgba(0x161a35ff).into(),
+ ghost_element_disabled: rgba(0x00000000).into(),
+ text: rgba(0xefecf4ff).into(),
+ text_muted: rgba(0x898591ff).into(),
+ text_placeholder: rgba(0xbe4677ff).into(),
+ text_disabled: rgba(0x756f7eff).into(),
+ text_accent: rgba(0x566ddaff).into(),
+ icon_muted: rgba(0x898591ff).into(),
+ syntax: SyntaxTheme {
+ highlights: vec![
+ ("comment.doc".into(), rgba(0x8b8792ff).into()),
+ ("tag".into(), rgba(0x566ddaff).into()),
+ ("link_text".into(), rgba(0xaa563bff).into()),
+ ("constructor".into(), rgba(0x566ddaff).into()),
+ ("punctuation".into(), rgba(0xe2dfe7ff).into()),
+ ("punctuation.special".into(), rgba(0xbf3fbfff).into()),
+ ("string.special.symbol".into(), rgba(0x299292ff).into()),
+ ("string.escape".into(), rgba(0x8b8792ff).into()),
+ ("emphasis".into(), rgba(0x566ddaff).into()),
+ ("type".into(), rgba(0xa06d3aff).into()),
+ ("punctuation.delimiter".into(), rgba(0x8b8792ff).into()),
+ ("variant".into(), rgba(0xa06d3aff).into()),
+ ("variable.special".into(), rgba(0x9559e7ff).into()),
+ ("text.literal".into(), rgba(0xaa563bff).into()),
+ ("punctuation.list_marker".into(), rgba(0xe2dfe7ff).into()),
+ ("comment".into(), rgba(0x655f6dff).into()),
+ ("function.method".into(), rgba(0x576cdbff).into()),
+ ("property".into(), rgba(0xbe4677ff).into()),
+ ("operator".into(), rgba(0x8b8792ff).into()),
+ ("emphasis.strong".into(), rgba(0x566ddaff).into()),
+ ("label".into(), rgba(0x566ddaff).into()),
+ ("enum".into(), rgba(0xaa563bff).into()),
+ ("number".into(), rgba(0xaa563bff).into()),
+ ("primary".into(), rgba(0xe2dfe7ff).into()),
+ ("keyword".into(), rgba(0x9559e7ff).into()),
+ (
+ "function.special.definition".into(),
+ rgba(0xa06d3aff).into(),
+ ),
+ ("punctuation.bracket".into(), rgba(0x8b8792ff).into()),
+ ("constant".into(), rgba(0x2b9292ff).into()),
+ ("string.special".into(), rgba(0xbf3fbfff).into()),
+ ("title".into(), rgba(0xefecf4ff).into()),
+ ("preproc".into(), rgba(0xefecf4ff).into()),
+ ("link_uri".into(), rgba(0x2b9292ff).into()),
+ ("string".into(), rgba(0x299292ff).into()),
+ ("embedded".into(), rgba(0xefecf4ff).into()),
+ ("hint".into(), rgba(0x706897ff).into()),
+ ("boolean".into(), rgba(0x2b9292ff).into()),
+ ("variable".into(), rgba(0xe2dfe7ff).into()),
+ ("predictive".into(), rgba(0x615787ff).into()),
+ ("string.regex".into(), rgba(0x388bc6ff).into()),
+ ("function".into(), rgba(0x576cdbff).into()),
+ ("attribute".into(), rgba(0x566ddaff).into()),
+ ],
+ },
+ status_bar: rgba(0x3a353fff).into(),
+ title_bar: rgba(0x3a353fff).into(),
+ toolbar: rgba(0x19171cff).into(),
+ tab_bar: rgba(0x221f26ff).into(),
+ editor: rgba(0x19171cff).into(),
+ editor_subheader: rgba(0x221f26ff).into(),
+ editor_active_line: rgba(0x221f26ff).into(),
+ terminal: rgba(0x19171cff).into(),
+ image_fallback_background: rgba(0x3a353fff).into(),
+ git_created: rgba(0x2b9292ff).into(),
+ git_modified: rgba(0x566ddaff).into(),
+ git_deleted: rgba(0xbe4677ff).into(),
+ git_conflict: rgba(0xa06d3aff).into(),
+ git_ignored: rgba(0x756f7eff).into(),
+ git_renamed: rgba(0xa06d3aff).into(),
+ players: [
+ PlayerTheme {
+ cursor: rgba(0x566ddaff).into(),
+ selection: rgba(0x566dda3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x2b9292ff).into(),
+ selection: rgba(0x2b92923d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xbf41bfff).into(),
+ selection: rgba(0xbf41bf3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xaa563bff).into(),
+ selection: rgba(0xaa563b3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x955ae6ff).into(),
+ selection: rgba(0x955ae63d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x3a8bc6ff).into(),
+ selection: rgba(0x3a8bc63d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xbe4677ff).into(),
+ selection: rgba(0xbe46773d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xa06d3aff).into(),
+ selection: rgba(0xa06d3a3d).into(),
+ },
+ ],
+ }
+}
@@ -0,0 +1,136 @@
+use gpui2::rgba;
+
+use crate::{PlayerTheme, SyntaxTheme, Theme, ThemeMetadata};
+
+pub fn atelier_cave_light() -> Theme {
+ Theme {
+ metadata: ThemeMetadata {
+ name: "Atelier Cave Light".into(),
+ is_light: true,
+ },
+ transparent: rgba(0x00000000).into(),
+ mac_os_traffic_light_red: rgba(0xec695eff).into(),
+ mac_os_traffic_light_yellow: rgba(0xf4bf4eff).into(),
+ mac_os_traffic_light_green: rgba(0x61c553ff).into(),
+ border: rgba(0x8f8b96ff).into(),
+ border_variant: rgba(0x8f8b96ff).into(),
+ border_focused: rgba(0xc8c7f2ff).into(),
+ border_transparent: rgba(0x00000000).into(),
+ elevated_surface: rgba(0xbfbcc5ff).into(),
+ surface: rgba(0xe6e3ebff).into(),
+ background: rgba(0xbfbcc5ff).into(),
+ filled_element: rgba(0xbfbcc5ff).into(),
+ filled_element_hover: rgba(0xffffff1e).into(),
+ filled_element_active: rgba(0xffffff28).into(),
+ filled_element_selected: rgba(0xe1e0f9ff).into(),
+ filled_element_disabled: rgba(0x00000000).into(),
+ ghost_element: rgba(0x00000000).into(),
+ ghost_element_hover: rgba(0xffffff14).into(),
+ ghost_element_active: rgba(0xffffff1e).into(),
+ ghost_element_selected: rgba(0xe1e0f9ff).into(),
+ ghost_element_disabled: rgba(0x00000000).into(),
+ text: rgba(0x19171cff).into(),
+ text_muted: rgba(0x5a5462ff).into(),
+ text_placeholder: rgba(0xbd4677ff).into(),
+ text_disabled: rgba(0x6e6876ff).into(),
+ text_accent: rgba(0x586cdaff).into(),
+ icon_muted: rgba(0x5a5462ff).into(),
+ syntax: SyntaxTheme {
+ highlights: vec![
+ ("link_text".into(), rgba(0xaa573cff).into()),
+ ("string".into(), rgba(0x299292ff).into()),
+ ("emphasis".into(), rgba(0x586cdaff).into()),
+ ("label".into(), rgba(0x586cdaff).into()),
+ ("property".into(), rgba(0xbe4677ff).into()),
+ ("emphasis.strong".into(), rgba(0x586cdaff).into()),
+ ("constant".into(), rgba(0x2b9292ff).into()),
+ (
+ "function.special.definition".into(),
+ rgba(0xa06d3aff).into(),
+ ),
+ ("embedded".into(), rgba(0x19171cff).into()),
+ ("punctuation.special".into(), rgba(0xbf3fbfff).into()),
+ ("function".into(), rgba(0x576cdbff).into()),
+ ("tag".into(), rgba(0x586cdaff).into()),
+ ("number".into(), rgba(0xaa563bff).into()),
+ ("primary".into(), rgba(0x26232aff).into()),
+ ("text.literal".into(), rgba(0xaa573cff).into()),
+ ("variant".into(), rgba(0xa06d3aff).into()),
+ ("type".into(), rgba(0xa06d3aff).into()),
+ ("punctuation".into(), rgba(0x26232aff).into()),
+ ("string.escape".into(), rgba(0x585260ff).into()),
+ ("keyword".into(), rgba(0x9559e7ff).into()),
+ ("title".into(), rgba(0x19171cff).into()),
+ ("constructor".into(), rgba(0x586cdaff).into()),
+ ("punctuation.list_marker".into(), rgba(0x26232aff).into()),
+ ("string.special".into(), rgba(0xbf3fbfff).into()),
+ ("operator".into(), rgba(0x585260ff).into()),
+ ("function.method".into(), rgba(0x576cdbff).into()),
+ ("link_uri".into(), rgba(0x2b9292ff).into()),
+ ("variable.special".into(), rgba(0x9559e7ff).into()),
+ ("hint".into(), rgba(0x776d9dff).into()),
+ ("punctuation.bracket".into(), rgba(0x585260ff).into()),
+ ("string.special.symbol".into(), rgba(0x299292ff).into()),
+ ("predictive".into(), rgba(0x887fafff).into()),
+ ("attribute".into(), rgba(0x586cdaff).into()),
+ ("enum".into(), rgba(0xaa573cff).into()),
+ ("preproc".into(), rgba(0x19171cff).into()),
+ ("boolean".into(), rgba(0x2b9292ff).into()),
+ ("variable".into(), rgba(0x26232aff).into()),
+ ("comment.doc".into(), rgba(0x585260ff).into()),
+ ("string.regex".into(), rgba(0x388bc6ff).into()),
+ ("punctuation.delimiter".into(), rgba(0x585260ff).into()),
+ ("comment".into(), rgba(0x7d7787ff).into()),
+ ],
+ },
+ status_bar: rgba(0xbfbcc5ff).into(),
+ title_bar: rgba(0xbfbcc5ff).into(),
+ toolbar: rgba(0xefecf4ff).into(),
+ tab_bar: rgba(0xe6e3ebff).into(),
+ editor: rgba(0xefecf4ff).into(),
+ editor_subheader: rgba(0xe6e3ebff).into(),
+ editor_active_line: rgba(0xe6e3ebff).into(),
+ terminal: rgba(0xefecf4ff).into(),
+ image_fallback_background: rgba(0xbfbcc5ff).into(),
+ git_created: rgba(0x2b9292ff).into(),
+ git_modified: rgba(0x586cdaff).into(),
+ git_deleted: rgba(0xbd4677ff).into(),
+ git_conflict: rgba(0xa06e3bff).into(),
+ git_ignored: rgba(0x6e6876ff).into(),
+ git_renamed: rgba(0xa06e3bff).into(),
+ players: [
+ PlayerTheme {
+ cursor: rgba(0x586cdaff).into(),
+ selection: rgba(0x586cda3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x2b9292ff).into(),
+ selection: rgba(0x2b92923d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xbf41bfff).into(),
+ selection: rgba(0xbf41bf3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xaa573cff).into(),
+ selection: rgba(0xaa573c3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x955ae6ff).into(),
+ selection: rgba(0x955ae63d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x3a8bc6ff).into(),
+ selection: rgba(0x3a8bc63d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xbd4677ff).into(),
+ selection: rgba(0xbd46773d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xa06e3bff).into(),
+ selection: rgba(0xa06e3b3d).into(),
+ },
+ ],
+ }
+}
@@ -0,0 +1,136 @@
+use gpui2::rgba;
+
+use crate::{PlayerTheme, SyntaxTheme, Theme, ThemeMetadata};
+
+pub fn atelier_dune_dark() -> Theme {
+ Theme {
+ metadata: ThemeMetadata {
+ name: "Atelier Dune Dark".into(),
+ is_light: false,
+ },
+ transparent: rgba(0x00000000).into(),
+ mac_os_traffic_light_red: rgba(0xec695eff).into(),
+ mac_os_traffic_light_yellow: rgba(0xf4bf4eff).into(),
+ mac_os_traffic_light_green: rgba(0x61c553ff).into(),
+ border: rgba(0x6c695cff).into(),
+ border_variant: rgba(0x6c695cff).into(),
+ border_focused: rgba(0x262f56ff).into(),
+ border_transparent: rgba(0x00000000).into(),
+ elevated_surface: rgba(0x45433bff).into(),
+ surface: rgba(0x262622ff).into(),
+ background: rgba(0x45433bff).into(),
+ filled_element: rgba(0x45433bff).into(),
+ filled_element_hover: rgba(0xffffff1e).into(),
+ filled_element_active: rgba(0xffffff28).into(),
+ filled_element_selected: rgba(0x171e38ff).into(),
+ filled_element_disabled: rgba(0x00000000).into(),
+ ghost_element: rgba(0x00000000).into(),
+ ghost_element_hover: rgba(0xffffff14).into(),
+ ghost_element_active: rgba(0xffffff1e).into(),
+ ghost_element_selected: rgba(0x171e38ff).into(),
+ ghost_element_disabled: rgba(0x00000000).into(),
+ text: rgba(0xfefbecff).into(),
+ text_muted: rgba(0xa4a08bff).into(),
+ text_placeholder: rgba(0xd73837ff).into(),
+ text_disabled: rgba(0x8f8b77ff).into(),
+ text_accent: rgba(0x6684e0ff).into(),
+ icon_muted: rgba(0xa4a08bff).into(),
+ syntax: SyntaxTheme {
+ highlights: vec![
+ ("constructor".into(), rgba(0x6684e0ff).into()),
+ ("punctuation".into(), rgba(0xe8e4cfff).into()),
+ ("punctuation.delimiter".into(), rgba(0xa6a28cff).into()),
+ ("string.special".into(), rgba(0xd43451ff).into()),
+ ("string.escape".into(), rgba(0xa6a28cff).into()),
+ ("comment".into(), rgba(0x7d7a68ff).into()),
+ ("enum".into(), rgba(0xb65611ff).into()),
+ ("variable.special".into(), rgba(0xb854d4ff).into()),
+ ("primary".into(), rgba(0xe8e4cfff).into()),
+ ("comment.doc".into(), rgba(0xa6a28cff).into()),
+ ("label".into(), rgba(0x6684e0ff).into()),
+ ("operator".into(), rgba(0xa6a28cff).into()),
+ ("string".into(), rgba(0x5fac38ff).into()),
+ ("variant".into(), rgba(0xae9512ff).into()),
+ ("variable".into(), rgba(0xe8e4cfff).into()),
+ ("function.method".into(), rgba(0x6583e1ff).into()),
+ (
+ "function.special.definition".into(),
+ rgba(0xae9512ff).into(),
+ ),
+ ("string.regex".into(), rgba(0x1ead82ff).into()),
+ ("emphasis.strong".into(), rgba(0x6684e0ff).into()),
+ ("punctuation.special".into(), rgba(0xd43451ff).into()),
+ ("punctuation.bracket".into(), rgba(0xa6a28cff).into()),
+ ("link_text".into(), rgba(0xb65611ff).into()),
+ ("link_uri".into(), rgba(0x5fac39ff).into()),
+ ("boolean".into(), rgba(0x5fac39ff).into()),
+ ("hint".into(), rgba(0xb17272ff).into()),
+ ("tag".into(), rgba(0x6684e0ff).into()),
+ ("function".into(), rgba(0x6583e1ff).into()),
+ ("title".into(), rgba(0xfefbecff).into()),
+ ("property".into(), rgba(0xd73737ff).into()),
+ ("type".into(), rgba(0xae9512ff).into()),
+ ("constant".into(), rgba(0x5fac39ff).into()),
+ ("attribute".into(), rgba(0x6684e0ff).into()),
+ ("predictive".into(), rgba(0x9c6262ff).into()),
+ ("string.special.symbol".into(), rgba(0x5fac38ff).into()),
+ ("punctuation.list_marker".into(), rgba(0xe8e4cfff).into()),
+ ("emphasis".into(), rgba(0x6684e0ff).into()),
+ ("keyword".into(), rgba(0xb854d4ff).into()),
+ ("text.literal".into(), rgba(0xb65611ff).into()),
+ ("number".into(), rgba(0xb65610ff).into()),
+ ("preproc".into(), rgba(0xfefbecff).into()),
+ ("embedded".into(), rgba(0xfefbecff).into()),
+ ],
+ },
+ status_bar: rgba(0x45433bff).into(),
+ title_bar: rgba(0x45433bff).into(),
+ toolbar: rgba(0x20201dff).into(),
+ tab_bar: rgba(0x262622ff).into(),
+ editor: rgba(0x20201dff).into(),
+ editor_subheader: rgba(0x262622ff).into(),
+ editor_active_line: rgba(0x262622ff).into(),
+ terminal: rgba(0x20201dff).into(),
+ image_fallback_background: rgba(0x45433bff).into(),
+ git_created: rgba(0x5fac39ff).into(),
+ git_modified: rgba(0x6684e0ff).into(),
+ git_deleted: rgba(0xd73837ff).into(),
+ git_conflict: rgba(0xae9414ff).into(),
+ git_ignored: rgba(0x8f8b77ff).into(),
+ git_renamed: rgba(0xae9414ff).into(),
+ players: [
+ PlayerTheme {
+ cursor: rgba(0x6684e0ff).into(),
+ selection: rgba(0x6684e03d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x5fac39ff).into(),
+ selection: rgba(0x5fac393d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xd43651ff).into(),
+ selection: rgba(0xd436513d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xb65611ff).into(),
+ selection: rgba(0xb656113d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xb854d3ff).into(),
+ selection: rgba(0xb854d33d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x20ad83ff).into(),
+ selection: rgba(0x20ad833d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xd73837ff).into(),
+ selection: rgba(0xd738373d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xae9414ff).into(),
+ selection: rgba(0xae94143d).into(),
+ },
+ ],
+ }
+}
@@ -0,0 +1,136 @@
+use gpui2::rgba;
+
+use crate::{PlayerTheme, SyntaxTheme, Theme, ThemeMetadata};
+
+pub fn atelier_dune_light() -> Theme {
+ Theme {
+ metadata: ThemeMetadata {
+ name: "Atelier Dune Light".into(),
+ is_light: true,
+ },
+ transparent: rgba(0x00000000).into(),
+ mac_os_traffic_light_red: rgba(0xec695eff).into(),
+ mac_os_traffic_light_yellow: rgba(0xf4bf4eff).into(),
+ mac_os_traffic_light_green: rgba(0x61c553ff).into(),
+ border: rgba(0xa8a48eff).into(),
+ border_variant: rgba(0xa8a48eff).into(),
+ border_focused: rgba(0xcdd1f5ff).into(),
+ border_transparent: rgba(0x00000000).into(),
+ elevated_surface: rgba(0xcecab4ff).into(),
+ surface: rgba(0xeeebd7ff).into(),
+ background: rgba(0xcecab4ff).into(),
+ filled_element: rgba(0xcecab4ff).into(),
+ filled_element_hover: rgba(0xffffff1e).into(),
+ filled_element_active: rgba(0xffffff28).into(),
+ filled_element_selected: rgba(0xe3e5faff).into(),
+ filled_element_disabled: rgba(0x00000000).into(),
+ ghost_element: rgba(0x00000000).into(),
+ ghost_element_hover: rgba(0xffffff14).into(),
+ ghost_element_active: rgba(0xffffff1e).into(),
+ ghost_element_selected: rgba(0xe3e5faff).into(),
+ ghost_element_disabled: rgba(0x00000000).into(),
+ text: rgba(0x20201dff).into(),
+ text_muted: rgba(0x706d5fff).into(),
+ text_placeholder: rgba(0xd73737ff).into(),
+ text_disabled: rgba(0x878471ff).into(),
+ text_accent: rgba(0x6684dfff).into(),
+ icon_muted: rgba(0x706d5fff).into(),
+ syntax: SyntaxTheme {
+ highlights: vec![
+ ("primary".into(), rgba(0x292824ff).into()),
+ ("comment".into(), rgba(0x999580ff).into()),
+ ("type".into(), rgba(0xae9512ff).into()),
+ ("variant".into(), rgba(0xae9512ff).into()),
+ ("label".into(), rgba(0x6684dfff).into()),
+ ("function.method".into(), rgba(0x6583e1ff).into()),
+ ("variable.special".into(), rgba(0xb854d4ff).into()),
+ ("string.regex".into(), rgba(0x1ead82ff).into()),
+ ("property".into(), rgba(0xd73737ff).into()),
+ ("keyword".into(), rgba(0xb854d4ff).into()),
+ ("number".into(), rgba(0xb65610ff).into()),
+ ("punctuation.list_marker".into(), rgba(0x292824ff).into()),
+ (
+ "function.special.definition".into(),
+ rgba(0xae9512ff).into(),
+ ),
+ ("punctuation.special".into(), rgba(0xd43451ff).into()),
+ ("punctuation".into(), rgba(0x292824ff).into()),
+ ("punctuation.delimiter".into(), rgba(0x6e6b5eff).into()),
+ ("tag".into(), rgba(0x6684dfff).into()),
+ ("link_text".into(), rgba(0xb65712ff).into()),
+ ("boolean".into(), rgba(0x61ac39ff).into()),
+ ("hint".into(), rgba(0xb37979ff).into()),
+ ("operator".into(), rgba(0x6e6b5eff).into()),
+ ("constant".into(), rgba(0x61ac39ff).into()),
+ ("function".into(), rgba(0x6583e1ff).into()),
+ ("text.literal".into(), rgba(0xb65712ff).into()),
+ ("string.special.symbol".into(), rgba(0x5fac38ff).into()),
+ ("attribute".into(), rgba(0x6684dfff).into()),
+ ("emphasis".into(), rgba(0x6684dfff).into()),
+ ("preproc".into(), rgba(0x20201dff).into()),
+ ("comment.doc".into(), rgba(0x6e6b5eff).into()),
+ ("punctuation.bracket".into(), rgba(0x6e6b5eff).into()),
+ ("string".into(), rgba(0x5fac38ff).into()),
+ ("enum".into(), rgba(0xb65712ff).into()),
+ ("variable".into(), rgba(0x292824ff).into()),
+ ("string.special".into(), rgba(0xd43451ff).into()),
+ ("embedded".into(), rgba(0x20201dff).into()),
+ ("emphasis.strong".into(), rgba(0x6684dfff).into()),
+ ("predictive".into(), rgba(0xc88a8aff).into()),
+ ("title".into(), rgba(0x20201dff).into()),
+ ("constructor".into(), rgba(0x6684dfff).into()),
+ ("link_uri".into(), rgba(0x61ac39ff).into()),
+ ("string.escape".into(), rgba(0x6e6b5eff).into()),
+ ],
+ },
+ status_bar: rgba(0xcecab4ff).into(),
+ title_bar: rgba(0xcecab4ff).into(),
+ toolbar: rgba(0xfefbecff).into(),
+ tab_bar: rgba(0xeeebd7ff).into(),
+ editor: rgba(0xfefbecff).into(),
+ editor_subheader: rgba(0xeeebd7ff).into(),
+ editor_active_line: rgba(0xeeebd7ff).into(),
+ terminal: rgba(0xfefbecff).into(),
+ image_fallback_background: rgba(0xcecab4ff).into(),
+ git_created: rgba(0x61ac39ff).into(),
+ git_modified: rgba(0x6684dfff).into(),
+ git_deleted: rgba(0xd73737ff).into(),
+ git_conflict: rgba(0xae9414ff).into(),
+ git_ignored: rgba(0x878471ff).into(),
+ git_renamed: rgba(0xae9414ff).into(),
+ players: [
+ PlayerTheme {
+ cursor: rgba(0x6684dfff).into(),
+ selection: rgba(0x6684df3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x61ac39ff).into(),
+ selection: rgba(0x61ac393d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xd43652ff).into(),
+ selection: rgba(0xd436523d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xb65712ff).into(),
+ selection: rgba(0xb657123d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xb755d3ff).into(),
+ selection: rgba(0xb755d33d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x21ad82ff).into(),
+ selection: rgba(0x21ad823d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xd73737ff).into(),
+ selection: rgba(0xd737373d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xae9414ff).into(),
+ selection: rgba(0xae94143d).into(),
+ },
+ ],
+ }
+}
@@ -0,0 +1,136 @@
+use gpui2::rgba;
+
+use crate::{PlayerTheme, SyntaxTheme, Theme, ThemeMetadata};
+
+pub fn atelier_estuary_dark() -> Theme {
+ Theme {
+ metadata: ThemeMetadata {
+ name: "Atelier Estuary Dark".into(),
+ is_light: false,
+ },
+ transparent: rgba(0x00000000).into(),
+ mac_os_traffic_light_red: rgba(0xec695eff).into(),
+ mac_os_traffic_light_yellow: rgba(0xf4bf4eff).into(),
+ mac_os_traffic_light_green: rgba(0x61c553ff).into(),
+ border: rgba(0x5d5c4cff).into(),
+ border_variant: rgba(0x5d5c4cff).into(),
+ border_focused: rgba(0x1c3927ff).into(),
+ border_transparent: rgba(0x00000000).into(),
+ elevated_surface: rgba(0x424136ff).into(),
+ surface: rgba(0x2c2b23ff).into(),
+ background: rgba(0x424136ff).into(),
+ filled_element: rgba(0x424136ff).into(),
+ filled_element_hover: rgba(0xffffff1e).into(),
+ filled_element_active: rgba(0xffffff28).into(),
+ filled_element_selected: rgba(0x142319ff).into(),
+ filled_element_disabled: rgba(0x00000000).into(),
+ ghost_element: rgba(0x00000000).into(),
+ ghost_element_hover: rgba(0xffffff14).into(),
+ ghost_element_active: rgba(0xffffff1e).into(),
+ ghost_element_selected: rgba(0x142319ff).into(),
+ ghost_element_disabled: rgba(0x00000000).into(),
+ text: rgba(0xf4f3ecff).into(),
+ text_muted: rgba(0x91907fff).into(),
+ text_placeholder: rgba(0xba6136ff).into(),
+ text_disabled: rgba(0x7d7c6aff).into(),
+ text_accent: rgba(0x36a165ff).into(),
+ icon_muted: rgba(0x91907fff).into(),
+ syntax: SyntaxTheme {
+ highlights: vec![
+ ("string.special.symbol".into(), rgba(0x7c9725ff).into()),
+ ("comment".into(), rgba(0x6c6b5aff).into()),
+ ("operator".into(), rgba(0x929181ff).into()),
+ ("punctuation.delimiter".into(), rgba(0x929181ff).into()),
+ ("keyword".into(), rgba(0x5f9182ff).into()),
+ ("punctuation.special".into(), rgba(0x9d6b7bff).into()),
+ ("preproc".into(), rgba(0xf4f3ecff).into()),
+ ("title".into(), rgba(0xf4f3ecff).into()),
+ ("string.escape".into(), rgba(0x929181ff).into()),
+ ("boolean".into(), rgba(0x7d9726ff).into()),
+ ("punctuation.bracket".into(), rgba(0x929181ff).into()),
+ ("emphasis.strong".into(), rgba(0x36a165ff).into()),
+ ("string".into(), rgba(0x7c9725ff).into()),
+ ("constant".into(), rgba(0x7d9726ff).into()),
+ ("link_text".into(), rgba(0xae7214ff).into()),
+ ("tag".into(), rgba(0x36a165ff).into()),
+ ("hint".into(), rgba(0x6f815aff).into()),
+ ("punctuation".into(), rgba(0xe7e6dfff).into()),
+ ("string.regex".into(), rgba(0x5a9d47ff).into()),
+ ("variant".into(), rgba(0xa5980cff).into()),
+ ("type".into(), rgba(0xa5980cff).into()),
+ ("attribute".into(), rgba(0x36a165ff).into()),
+ ("emphasis".into(), rgba(0x36a165ff).into()),
+ ("enum".into(), rgba(0xae7214ff).into()),
+ ("number".into(), rgba(0xae7312ff).into()),
+ ("property".into(), rgba(0xba6135ff).into()),
+ ("predictive".into(), rgba(0x5f724cff).into()),
+ (
+ "function.special.definition".into(),
+ rgba(0xa5980cff).into(),
+ ),
+ ("link_uri".into(), rgba(0x7d9726ff).into()),
+ ("variable.special".into(), rgba(0x5f9182ff).into()),
+ ("text.literal".into(), rgba(0xae7214ff).into()),
+ ("label".into(), rgba(0x36a165ff).into()),
+ ("primary".into(), rgba(0xe7e6dfff).into()),
+ ("variable".into(), rgba(0xe7e6dfff).into()),
+ ("embedded".into(), rgba(0xf4f3ecff).into()),
+ ("function.method".into(), rgba(0x35a166ff).into()),
+ ("comment.doc".into(), rgba(0x929181ff).into()),
+ ("string.special".into(), rgba(0x9d6b7bff).into()),
+ ("constructor".into(), rgba(0x36a165ff).into()),
+ ("punctuation.list_marker".into(), rgba(0xe7e6dfff).into()),
+ ("function".into(), rgba(0x35a166ff).into()),
+ ],
+ },
+ status_bar: rgba(0x424136ff).into(),
+ title_bar: rgba(0x424136ff).into(),
+ toolbar: rgba(0x22221bff).into(),
+ tab_bar: rgba(0x2c2b23ff).into(),
+ editor: rgba(0x22221bff).into(),
+ editor_subheader: rgba(0x2c2b23ff).into(),
+ editor_active_line: rgba(0x2c2b23ff).into(),
+ terminal: rgba(0x22221bff).into(),
+ image_fallback_background: rgba(0x424136ff).into(),
+ git_created: rgba(0x7d9726ff).into(),
+ git_modified: rgba(0x36a165ff).into(),
+ git_deleted: rgba(0xba6136ff).into(),
+ git_conflict: rgba(0xa5980fff).into(),
+ git_ignored: rgba(0x7d7c6aff).into(),
+ git_renamed: rgba(0xa5980fff).into(),
+ players: [
+ PlayerTheme {
+ cursor: rgba(0x36a165ff).into(),
+ selection: rgba(0x36a1653d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x7d9726ff).into(),
+ selection: rgba(0x7d97263d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x9d6b7bff).into(),
+ selection: rgba(0x9d6b7b3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xae7214ff).into(),
+ selection: rgba(0xae72143d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x5f9182ff).into(),
+ selection: rgba(0x5f91823d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x5a9d47ff).into(),
+ selection: rgba(0x5a9d473d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xba6136ff).into(),
+ selection: rgba(0xba61363d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xa5980fff).into(),
+ selection: rgba(0xa5980f3d).into(),
+ },
+ ],
+ }
+}
@@ -0,0 +1,136 @@
+use gpui2::rgba;
+
+use crate::{PlayerTheme, SyntaxTheme, Theme, ThemeMetadata};
+
+pub fn atelier_estuary_light() -> Theme {
+ Theme {
+ metadata: ThemeMetadata {
+ name: "Atelier Estuary Light".into(),
+ is_light: true,
+ },
+ transparent: rgba(0x00000000).into(),
+ mac_os_traffic_light_red: rgba(0xec695eff).into(),
+ mac_os_traffic_light_yellow: rgba(0xf4bf4eff).into(),
+ mac_os_traffic_light_green: rgba(0x61c553ff).into(),
+ border: rgba(0x969585ff).into(),
+ border_variant: rgba(0x969585ff).into(),
+ border_focused: rgba(0xbbddc6ff).into(),
+ border_transparent: rgba(0x00000000).into(),
+ elevated_surface: rgba(0xc5c4b9ff).into(),
+ surface: rgba(0xebeae3ff).into(),
+ background: rgba(0xc5c4b9ff).into(),
+ filled_element: rgba(0xc5c4b9ff).into(),
+ filled_element_hover: rgba(0xffffff1e).into(),
+ filled_element_active: rgba(0xffffff28).into(),
+ filled_element_selected: rgba(0xd9ecdfff).into(),
+ filled_element_disabled: rgba(0x00000000).into(),
+ ghost_element: rgba(0x00000000).into(),
+ ghost_element_hover: rgba(0xffffff14).into(),
+ ghost_element_active: rgba(0xffffff1e).into(),
+ ghost_element_selected: rgba(0xd9ecdfff).into(),
+ ghost_element_disabled: rgba(0x00000000).into(),
+ text: rgba(0x22221bff).into(),
+ text_muted: rgba(0x61604fff).into(),
+ text_placeholder: rgba(0xba6336ff).into(),
+ text_disabled: rgba(0x767463ff).into(),
+ text_accent: rgba(0x37a165ff).into(),
+ icon_muted: rgba(0x61604fff).into(),
+ syntax: SyntaxTheme {
+ highlights: vec![
+ ("string.special".into(), rgba(0x9d6b7bff).into()),
+ ("link_text".into(), rgba(0xae7214ff).into()),
+ ("emphasis.strong".into(), rgba(0x37a165ff).into()),
+ ("tag".into(), rgba(0x37a165ff).into()),
+ ("primary".into(), rgba(0x302f27ff).into()),
+ ("emphasis".into(), rgba(0x37a165ff).into()),
+ ("hint".into(), rgba(0x758961ff).into()),
+ ("title".into(), rgba(0x22221bff).into()),
+ ("string.regex".into(), rgba(0x5a9d47ff).into()),
+ ("attribute".into(), rgba(0x37a165ff).into()),
+ ("string.escape".into(), rgba(0x5f5e4eff).into()),
+ ("embedded".into(), rgba(0x22221bff).into()),
+ ("punctuation.bracket".into(), rgba(0x5f5e4eff).into()),
+ (
+ "function.special.definition".into(),
+ rgba(0xa5980cff).into(),
+ ),
+ ("operator".into(), rgba(0x5f5e4eff).into()),
+ ("constant".into(), rgba(0x7c9728ff).into()),
+ ("comment.doc".into(), rgba(0x5f5e4eff).into()),
+ ("label".into(), rgba(0x37a165ff).into()),
+ ("variable".into(), rgba(0x302f27ff).into()),
+ ("punctuation".into(), rgba(0x302f27ff).into()),
+ ("punctuation.delimiter".into(), rgba(0x5f5e4eff).into()),
+ ("comment".into(), rgba(0x878573ff).into()),
+ ("punctuation.special".into(), rgba(0x9d6b7bff).into()),
+ ("string.special.symbol".into(), rgba(0x7c9725ff).into()),
+ ("enum".into(), rgba(0xae7214ff).into()),
+ ("variable.special".into(), rgba(0x5f9182ff).into()),
+ ("link_uri".into(), rgba(0x7c9728ff).into()),
+ ("punctuation.list_marker".into(), rgba(0x302f27ff).into()),
+ ("number".into(), rgba(0xae7312ff).into()),
+ ("function".into(), rgba(0x35a166ff).into()),
+ ("text.literal".into(), rgba(0xae7214ff).into()),
+ ("boolean".into(), rgba(0x7c9728ff).into()),
+ ("predictive".into(), rgba(0x879a72ff).into()),
+ ("type".into(), rgba(0xa5980cff).into()),
+ ("constructor".into(), rgba(0x37a165ff).into()),
+ ("property".into(), rgba(0xba6135ff).into()),
+ ("keyword".into(), rgba(0x5f9182ff).into()),
+ ("function.method".into(), rgba(0x35a166ff).into()),
+ ("variant".into(), rgba(0xa5980cff).into()),
+ ("string".into(), rgba(0x7c9725ff).into()),
+ ("preproc".into(), rgba(0x22221bff).into()),
+ ],
+ },
+ status_bar: rgba(0xc5c4b9ff).into(),
+ title_bar: rgba(0xc5c4b9ff).into(),
+ toolbar: rgba(0xf4f3ecff).into(),
+ tab_bar: rgba(0xebeae3ff).into(),
+ editor: rgba(0xf4f3ecff).into(),
+ editor_subheader: rgba(0xebeae3ff).into(),
+ editor_active_line: rgba(0xebeae3ff).into(),
+ terminal: rgba(0xf4f3ecff).into(),
+ image_fallback_background: rgba(0xc5c4b9ff).into(),
+ git_created: rgba(0x7c9728ff).into(),
+ git_modified: rgba(0x37a165ff).into(),
+ git_deleted: rgba(0xba6336ff).into(),
+ git_conflict: rgba(0xa5980fff).into(),
+ git_ignored: rgba(0x767463ff).into(),
+ git_renamed: rgba(0xa5980fff).into(),
+ players: [
+ PlayerTheme {
+ cursor: rgba(0x37a165ff).into(),
+ selection: rgba(0x37a1653d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x7c9728ff).into(),
+ selection: rgba(0x7c97283d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x9d6b7bff).into(),
+ selection: rgba(0x9d6b7b3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xae7214ff).into(),
+ selection: rgba(0xae72143d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x5f9182ff).into(),
+ selection: rgba(0x5f91823d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x5c9d49ff).into(),
+ selection: rgba(0x5c9d493d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xba6336ff).into(),
+ selection: rgba(0xba63363d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xa5980fff).into(),
+ selection: rgba(0xa5980f3d).into(),
+ },
+ ],
+ }
+}
@@ -0,0 +1,136 @@
+use gpui2::rgba;
+
+use crate::{PlayerTheme, SyntaxTheme, Theme, ThemeMetadata};
+
+pub fn atelier_forest_dark() -> Theme {
+ Theme {
+ metadata: ThemeMetadata {
+ name: "Atelier Forest Dark".into(),
+ is_light: false,
+ },
+ transparent: rgba(0x00000000).into(),
+ mac_os_traffic_light_red: rgba(0xec695eff).into(),
+ mac_os_traffic_light_yellow: rgba(0xf4bf4eff).into(),
+ mac_os_traffic_light_green: rgba(0x61c553ff).into(),
+ border: rgba(0x665f5cff).into(),
+ border_variant: rgba(0x665f5cff).into(),
+ border_focused: rgba(0x182d5bff).into(),
+ border_transparent: rgba(0x00000000).into(),
+ elevated_surface: rgba(0x443c39ff).into(),
+ surface: rgba(0x27211eff).into(),
+ background: rgba(0x443c39ff).into(),
+ filled_element: rgba(0x443c39ff).into(),
+ filled_element_hover: rgba(0xffffff1e).into(),
+ filled_element_active: rgba(0xffffff28).into(),
+ filled_element_selected: rgba(0x0f1c3dff).into(),
+ filled_element_disabled: rgba(0x00000000).into(),
+ ghost_element: rgba(0x00000000).into(),
+ ghost_element_hover: rgba(0xffffff14).into(),
+ ghost_element_active: rgba(0xffffff1e).into(),
+ ghost_element_selected: rgba(0x0f1c3dff).into(),
+ ghost_element_disabled: rgba(0x00000000).into(),
+ text: rgba(0xf0eeedff).into(),
+ text_muted: rgba(0xa79f9dff).into(),
+ text_placeholder: rgba(0xf22c3fff).into(),
+ text_disabled: rgba(0x8e8683ff).into(),
+ text_accent: rgba(0x407ee6ff).into(),
+ icon_muted: rgba(0xa79f9dff).into(),
+ syntax: SyntaxTheme {
+ highlights: vec![
+ ("link_uri".into(), rgba(0x7a9726ff).into()),
+ ("punctuation.list_marker".into(), rgba(0xe6e2e0ff).into()),
+ ("type".into(), rgba(0xc38417ff).into()),
+ ("punctuation.bracket".into(), rgba(0xa8a19fff).into()),
+ ("punctuation".into(), rgba(0xe6e2e0ff).into()),
+ ("preproc".into(), rgba(0xf0eeedff).into()),
+ ("punctuation.special".into(), rgba(0xc33ff3ff).into()),
+ ("variable.special".into(), rgba(0x6666eaff).into()),
+ ("tag".into(), rgba(0x407ee6ff).into()),
+ ("constructor".into(), rgba(0x407ee6ff).into()),
+ ("title".into(), rgba(0xf0eeedff).into()),
+ ("hint".into(), rgba(0xa77087ff).into()),
+ ("constant".into(), rgba(0x7a9726ff).into()),
+ ("number".into(), rgba(0xdf521fff).into()),
+ ("emphasis.strong".into(), rgba(0x407ee6ff).into()),
+ ("boolean".into(), rgba(0x7a9726ff).into()),
+ ("comment".into(), rgba(0x766e6bff).into()),
+ ("string.special".into(), rgba(0xc33ff3ff).into()),
+ ("text.literal".into(), rgba(0xdf5321ff).into()),
+ ("string.regex".into(), rgba(0x3c96b8ff).into()),
+ ("enum".into(), rgba(0xdf5321ff).into()),
+ ("operator".into(), rgba(0xa8a19fff).into()),
+ ("embedded".into(), rgba(0xf0eeedff).into()),
+ ("string.special.symbol".into(), rgba(0x7a9725ff).into()),
+ ("predictive".into(), rgba(0x8f5b70ff).into()),
+ ("comment.doc".into(), rgba(0xa8a19fff).into()),
+ ("variant".into(), rgba(0xc38417ff).into()),
+ ("label".into(), rgba(0x407ee6ff).into()),
+ ("property".into(), rgba(0xf22c40ff).into()),
+ ("keyword".into(), rgba(0x6666eaff).into()),
+ ("function".into(), rgba(0x3f7ee7ff).into()),
+ ("string.escape".into(), rgba(0xa8a19fff).into()),
+ ("string".into(), rgba(0x7a9725ff).into()),
+ ("primary".into(), rgba(0xe6e2e0ff).into()),
+ ("function.method".into(), rgba(0x3f7ee7ff).into()),
+ ("link_text".into(), rgba(0xdf5321ff).into()),
+ ("attribute".into(), rgba(0x407ee6ff).into()),
+ ("emphasis".into(), rgba(0x407ee6ff).into()),
+ (
+ "function.special.definition".into(),
+ rgba(0xc38417ff).into(),
+ ),
+ ("variable".into(), rgba(0xe6e2e0ff).into()),
+ ("punctuation.delimiter".into(), rgba(0xa8a19fff).into()),
+ ],
+ },
+ status_bar: rgba(0x443c39ff).into(),
+ title_bar: rgba(0x443c39ff).into(),
+ toolbar: rgba(0x1b1918ff).into(),
+ tab_bar: rgba(0x27211eff).into(),
+ editor: rgba(0x1b1918ff).into(),
+ editor_subheader: rgba(0x27211eff).into(),
+ editor_active_line: rgba(0x27211eff).into(),
+ terminal: rgba(0x1b1918ff).into(),
+ image_fallback_background: rgba(0x443c39ff).into(),
+ git_created: rgba(0x7a9726ff).into(),
+ git_modified: rgba(0x407ee6ff).into(),
+ git_deleted: rgba(0xf22c3fff).into(),
+ git_conflict: rgba(0xc38418ff).into(),
+ git_ignored: rgba(0x8e8683ff).into(),
+ git_renamed: rgba(0xc38418ff).into(),
+ players: [
+ PlayerTheme {
+ cursor: rgba(0x407ee6ff).into(),
+ selection: rgba(0x407ee63d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x7a9726ff).into(),
+ selection: rgba(0x7a97263d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xc340f2ff).into(),
+ selection: rgba(0xc340f23d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xdf5321ff).into(),
+ selection: rgba(0xdf53213d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x6565e9ff).into(),
+ selection: rgba(0x6565e93d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x3d97b8ff).into(),
+ selection: rgba(0x3d97b83d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xf22c3fff).into(),
+ selection: rgba(0xf22c3f3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xc38418ff).into(),
+ selection: rgba(0xc384183d).into(),
+ },
+ ],
+ }
+}
@@ -0,0 +1,136 @@
+use gpui2::rgba;
+
+use crate::{PlayerTheme, SyntaxTheme, Theme, ThemeMetadata};
+
+pub fn atelier_forest_light() -> Theme {
+ Theme {
+ metadata: ThemeMetadata {
+ name: "Atelier Forest Light".into(),
+ is_light: true,
+ },
+ transparent: rgba(0x00000000).into(),
+ mac_os_traffic_light_red: rgba(0xec695eff).into(),
+ mac_os_traffic_light_yellow: rgba(0xf4bf4eff).into(),
+ mac_os_traffic_light_green: rgba(0x61c553ff).into(),
+ border: rgba(0xaaa3a1ff).into(),
+ border_variant: rgba(0xaaa3a1ff).into(),
+ border_focused: rgba(0xc6cef7ff).into(),
+ border_transparent: rgba(0x00000000).into(),
+ elevated_surface: rgba(0xccc7c5ff).into(),
+ surface: rgba(0xe9e6e4ff).into(),
+ background: rgba(0xccc7c5ff).into(),
+ filled_element: rgba(0xccc7c5ff).into(),
+ filled_element_hover: rgba(0xffffff1e).into(),
+ filled_element_active: rgba(0xffffff28).into(),
+ filled_element_selected: rgba(0xdfe3fbff).into(),
+ filled_element_disabled: rgba(0x00000000).into(),
+ ghost_element: rgba(0x00000000).into(),
+ ghost_element_hover: rgba(0xffffff14).into(),
+ ghost_element_active: rgba(0xffffff1e).into(),
+ ghost_element_selected: rgba(0xdfe3fbff).into(),
+ ghost_element_disabled: rgba(0x00000000).into(),
+ text: rgba(0x1b1918ff).into(),
+ text_muted: rgba(0x6a6360ff).into(),
+ text_placeholder: rgba(0xf22e40ff).into(),
+ text_disabled: rgba(0x837b78ff).into(),
+ text_accent: rgba(0x407ee6ff).into(),
+ icon_muted: rgba(0x6a6360ff).into(),
+ syntax: SyntaxTheme {
+ highlights: vec![
+ ("punctuation.special".into(), rgba(0xc33ff3ff).into()),
+ ("text.literal".into(), rgba(0xdf5421ff).into()),
+ ("string.escape".into(), rgba(0x68615eff).into()),
+ ("string.regex".into(), rgba(0x3c96b8ff).into()),
+ ("number".into(), rgba(0xdf521fff).into()),
+ ("preproc".into(), rgba(0x1b1918ff).into()),
+ ("keyword".into(), rgba(0x6666eaff).into()),
+ ("variable.special".into(), rgba(0x6666eaff).into()),
+ ("punctuation.delimiter".into(), rgba(0x68615eff).into()),
+ ("emphasis.strong".into(), rgba(0x407ee6ff).into()),
+ ("boolean".into(), rgba(0x7a9728ff).into()),
+ ("variant".into(), rgba(0xc38417ff).into()),
+ ("predictive".into(), rgba(0xbe899eff).into()),
+ ("tag".into(), rgba(0x407ee6ff).into()),
+ ("property".into(), rgba(0xf22c40ff).into()),
+ ("enum".into(), rgba(0xdf5421ff).into()),
+ ("attribute".into(), rgba(0x407ee6ff).into()),
+ ("function.method".into(), rgba(0x3f7ee7ff).into()),
+ ("function".into(), rgba(0x3f7ee7ff).into()),
+ ("emphasis".into(), rgba(0x407ee6ff).into()),
+ ("primary".into(), rgba(0x2c2421ff).into()),
+ ("variable".into(), rgba(0x2c2421ff).into()),
+ ("constant".into(), rgba(0x7a9728ff).into()),
+ ("title".into(), rgba(0x1b1918ff).into()),
+ ("comment.doc".into(), rgba(0x68615eff).into()),
+ ("constructor".into(), rgba(0x407ee6ff).into()),
+ ("type".into(), rgba(0xc38417ff).into()),
+ ("punctuation.list_marker".into(), rgba(0x2c2421ff).into()),
+ ("punctuation".into(), rgba(0x2c2421ff).into()),
+ ("string".into(), rgba(0x7a9725ff).into()),
+ ("label".into(), rgba(0x407ee6ff).into()),
+ ("string.special".into(), rgba(0xc33ff3ff).into()),
+ ("embedded".into(), rgba(0x1b1918ff).into()),
+ ("link_text".into(), rgba(0xdf5421ff).into()),
+ ("punctuation.bracket".into(), rgba(0x68615eff).into()),
+ ("comment".into(), rgba(0x9c9491ff).into()),
+ (
+ "function.special.definition".into(),
+ rgba(0xc38417ff).into(),
+ ),
+ ("link_uri".into(), rgba(0x7a9728ff).into()),
+ ("operator".into(), rgba(0x68615eff).into()),
+ ("hint".into(), rgba(0xa67287ff).into()),
+ ("string.special.symbol".into(), rgba(0x7a9725ff).into()),
+ ],
+ },
+ status_bar: rgba(0xccc7c5ff).into(),
+ title_bar: rgba(0xccc7c5ff).into(),
+ toolbar: rgba(0xf0eeedff).into(),
+ tab_bar: rgba(0xe9e6e4ff).into(),
+ editor: rgba(0xf0eeedff).into(),
+ editor_subheader: rgba(0xe9e6e4ff).into(),
+ editor_active_line: rgba(0xe9e6e4ff).into(),
+ terminal: rgba(0xf0eeedff).into(),
+ image_fallback_background: rgba(0xccc7c5ff).into(),
+ git_created: rgba(0x7a9728ff).into(),
+ git_modified: rgba(0x407ee6ff).into(),
+ git_deleted: rgba(0xf22e40ff).into(),
+ git_conflict: rgba(0xc38419ff).into(),
+ git_ignored: rgba(0x837b78ff).into(),
+ git_renamed: rgba(0xc38419ff).into(),
+ players: [
+ PlayerTheme {
+ cursor: rgba(0x407ee6ff).into(),
+ selection: rgba(0x407ee63d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x7a9728ff).into(),
+ selection: rgba(0x7a97283d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xc340f2ff).into(),
+ selection: rgba(0xc340f23d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xdf5421ff).into(),
+ selection: rgba(0xdf54213d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x6765e9ff).into(),
+ selection: rgba(0x6765e93d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x3e96b8ff).into(),
+ selection: rgba(0x3e96b83d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xf22e40ff).into(),
+ selection: rgba(0xf22e403d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xc38419ff).into(),
+ selection: rgba(0xc384193d).into(),
+ },
+ ],
+ }
+}
@@ -0,0 +1,136 @@
+use gpui2::rgba;
+
+use crate::{PlayerTheme, SyntaxTheme, Theme, ThemeMetadata};
+
+pub fn atelier_heath_dark() -> Theme {
+ Theme {
+ metadata: ThemeMetadata {
+ name: "Atelier Heath Dark".into(),
+ is_light: false,
+ },
+ transparent: rgba(0x00000000).into(),
+ mac_os_traffic_light_red: rgba(0xec695eff).into(),
+ mac_os_traffic_light_yellow: rgba(0xf4bf4eff).into(),
+ mac_os_traffic_light_green: rgba(0x61c553ff).into(),
+ border: rgba(0x675b67ff).into(),
+ border_variant: rgba(0x675b67ff).into(),
+ border_focused: rgba(0x192961ff).into(),
+ border_transparent: rgba(0x00000000).into(),
+ elevated_surface: rgba(0x433a43ff).into(),
+ surface: rgba(0x252025ff).into(),
+ background: rgba(0x433a43ff).into(),
+ filled_element: rgba(0x433a43ff).into(),
+ filled_element_hover: rgba(0xffffff1e).into(),
+ filled_element_active: rgba(0xffffff28).into(),
+ filled_element_selected: rgba(0x0d1a43ff).into(),
+ filled_element_disabled: rgba(0x00000000).into(),
+ ghost_element: rgba(0x00000000).into(),
+ ghost_element_hover: rgba(0xffffff14).into(),
+ ghost_element_active: rgba(0xffffff1e).into(),
+ ghost_element_selected: rgba(0x0d1a43ff).into(),
+ ghost_element_disabled: rgba(0x00000000).into(),
+ text: rgba(0xf7f3f7ff).into(),
+ text_muted: rgba(0xa899a8ff).into(),
+ text_placeholder: rgba(0xca3f2bff).into(),
+ text_disabled: rgba(0x908190ff).into(),
+ text_accent: rgba(0x5169ebff).into(),
+ icon_muted: rgba(0xa899a8ff).into(),
+ syntax: SyntaxTheme {
+ highlights: vec![
+ ("preproc".into(), rgba(0xf7f3f7ff).into()),
+ ("number".into(), rgba(0xa65825ff).into()),
+ ("boolean".into(), rgba(0x918b3aff).into()),
+ ("embedded".into(), rgba(0xf7f3f7ff).into()),
+ ("variable.special".into(), rgba(0x7b58bfff).into()),
+ ("operator".into(), rgba(0xab9babff).into()),
+ ("punctuation.delimiter".into(), rgba(0xab9babff).into()),
+ ("primary".into(), rgba(0xd8cad8ff).into()),
+ ("punctuation.bracket".into(), rgba(0xab9babff).into()),
+ ("comment.doc".into(), rgba(0xab9babff).into()),
+ ("variant".into(), rgba(0xbb8a34ff).into()),
+ ("attribute".into(), rgba(0x5169ebff).into()),
+ ("property".into(), rgba(0xca3f2aff).into()),
+ ("keyword".into(), rgba(0x7b58bfff).into()),
+ ("hint".into(), rgba(0x8d70a8ff).into()),
+ ("string.special.symbol".into(), rgba(0x918b3aff).into()),
+ ("punctuation.special".into(), rgba(0xcc32ccff).into()),
+ ("link_uri".into(), rgba(0x918b3aff).into()),
+ ("link_text".into(), rgba(0xa65827ff).into()),
+ ("enum".into(), rgba(0xa65827ff).into()),
+ ("function".into(), rgba(0x506aecff).into()),
+ (
+ "function.special.definition".into(),
+ rgba(0xbb8a34ff).into(),
+ ),
+ ("constant".into(), rgba(0x918b3aff).into()),
+ ("title".into(), rgba(0xf7f3f7ff).into()),
+ ("string.regex".into(), rgba(0x149393ff).into()),
+ ("variable".into(), rgba(0xd8cad8ff).into()),
+ ("comment".into(), rgba(0x776977ff).into()),
+ ("predictive".into(), rgba(0x75588fff).into()),
+ ("function.method".into(), rgba(0x506aecff).into()),
+ ("type".into(), rgba(0xbb8a34ff).into()),
+ ("punctuation".into(), rgba(0xd8cad8ff).into()),
+ ("emphasis".into(), rgba(0x5169ebff).into()),
+ ("emphasis.strong".into(), rgba(0x5169ebff).into()),
+ ("tag".into(), rgba(0x5169ebff).into()),
+ ("text.literal".into(), rgba(0xa65827ff).into()),
+ ("string".into(), rgba(0x918b3aff).into()),
+ ("string.escape".into(), rgba(0xab9babff).into()),
+ ("constructor".into(), rgba(0x5169ebff).into()),
+ ("label".into(), rgba(0x5169ebff).into()),
+ ("punctuation.list_marker".into(), rgba(0xd8cad8ff).into()),
+ ("string.special".into(), rgba(0xcc32ccff).into()),
+ ],
+ },
+ status_bar: rgba(0x433a43ff).into(),
+ title_bar: rgba(0x433a43ff).into(),
+ toolbar: rgba(0x1b181bff).into(),
+ tab_bar: rgba(0x252025ff).into(),
+ editor: rgba(0x1b181bff).into(),
+ editor_subheader: rgba(0x252025ff).into(),
+ editor_active_line: rgba(0x252025ff).into(),
+ terminal: rgba(0x1b181bff).into(),
+ image_fallback_background: rgba(0x433a43ff).into(),
+ git_created: rgba(0x918b3aff).into(),
+ git_modified: rgba(0x5169ebff).into(),
+ git_deleted: rgba(0xca3f2bff).into(),
+ git_conflict: rgba(0xbb8a35ff).into(),
+ git_ignored: rgba(0x908190ff).into(),
+ git_renamed: rgba(0xbb8a35ff).into(),
+ players: [
+ PlayerTheme {
+ cursor: rgba(0x5169ebff).into(),
+ selection: rgba(0x5169eb3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x918b3aff).into(),
+ selection: rgba(0x918b3a3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xcc34ccff).into(),
+ selection: rgba(0xcc34cc3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xa65827ff).into(),
+ selection: rgba(0xa658273d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x7b58bfff).into(),
+ selection: rgba(0x7b58bf3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x189393ff).into(),
+ selection: rgba(0x1893933d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xca3f2bff).into(),
+ selection: rgba(0xca3f2b3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xbb8a35ff).into(),
+ selection: rgba(0xbb8a353d).into(),
+ },
+ ],
+ }
+}
@@ -0,0 +1,136 @@
+use gpui2::rgba;
+
+use crate::{PlayerTheme, SyntaxTheme, Theme, ThemeMetadata};
+
+pub fn atelier_heath_light() -> Theme {
+ Theme {
+ metadata: ThemeMetadata {
+ name: "Atelier Heath Light".into(),
+ is_light: true,
+ },
+ transparent: rgba(0x00000000).into(),
+ mac_os_traffic_light_red: rgba(0xec695eff).into(),
+ mac_os_traffic_light_yellow: rgba(0xf4bf4eff).into(),
+ mac_os_traffic_light_green: rgba(0x61c553ff).into(),
+ border: rgba(0xad9dadff).into(),
+ border_variant: rgba(0xad9dadff).into(),
+ border_focused: rgba(0xcac7faff).into(),
+ border_transparent: rgba(0x00000000).into(),
+ elevated_surface: rgba(0xc6b8c6ff).into(),
+ surface: rgba(0xe0d5e0ff).into(),
+ background: rgba(0xc6b8c6ff).into(),
+ filled_element: rgba(0xc6b8c6ff).into(),
+ filled_element_hover: rgba(0xffffff1e).into(),
+ filled_element_active: rgba(0xffffff28).into(),
+ filled_element_selected: rgba(0xe2dffcff).into(),
+ filled_element_disabled: rgba(0x00000000).into(),
+ ghost_element: rgba(0x00000000).into(),
+ ghost_element_hover: rgba(0xffffff14).into(),
+ ghost_element_active: rgba(0xffffff1e).into(),
+ ghost_element_selected: rgba(0xe2dffcff).into(),
+ ghost_element_disabled: rgba(0x00000000).into(),
+ text: rgba(0x1b181bff).into(),
+ text_muted: rgba(0x6b5e6bff).into(),
+ text_placeholder: rgba(0xca402bff).into(),
+ text_disabled: rgba(0x857785ff).into(),
+ text_accent: rgba(0x5169ebff).into(),
+ icon_muted: rgba(0x6b5e6bff).into(),
+ syntax: SyntaxTheme {
+ highlights: vec![
+ ("enum".into(), rgba(0xa65927ff).into()),
+ ("string.escape".into(), rgba(0x695d69ff).into()),
+ ("link_uri".into(), rgba(0x918b3bff).into()),
+ ("function.method".into(), rgba(0x506aecff).into()),
+ ("comment.doc".into(), rgba(0x695d69ff).into()),
+ ("property".into(), rgba(0xca3f2aff).into()),
+ ("string.special".into(), rgba(0xcc32ccff).into()),
+ ("tag".into(), rgba(0x5169ebff).into()),
+ ("embedded".into(), rgba(0x1b181bff).into()),
+ ("primary".into(), rgba(0x292329ff).into()),
+ ("punctuation".into(), rgba(0x292329ff).into()),
+ ("punctuation.special".into(), rgba(0xcc32ccff).into()),
+ ("type".into(), rgba(0xbb8a34ff).into()),
+ ("number".into(), rgba(0xa65825ff).into()),
+ ("function".into(), rgba(0x506aecff).into()),
+ ("preproc".into(), rgba(0x1b181bff).into()),
+ ("punctuation.bracket".into(), rgba(0x695d69ff).into()),
+ ("punctuation.delimiter".into(), rgba(0x695d69ff).into()),
+ ("variable".into(), rgba(0x292329ff).into()),
+ (
+ "function.special.definition".into(),
+ rgba(0xbb8a34ff).into(),
+ ),
+ ("label".into(), rgba(0x5169ebff).into()),
+ ("constructor".into(), rgba(0x5169ebff).into()),
+ ("emphasis.strong".into(), rgba(0x5169ebff).into()),
+ ("constant".into(), rgba(0x918b3bff).into()),
+ ("keyword".into(), rgba(0x7b58bfff).into()),
+ ("variable.special".into(), rgba(0x7b58bfff).into()),
+ ("variant".into(), rgba(0xbb8a34ff).into()),
+ ("title".into(), rgba(0x1b181bff).into()),
+ ("attribute".into(), rgba(0x5169ebff).into()),
+ ("comment".into(), rgba(0x9e8f9eff).into()),
+ ("string.special.symbol".into(), rgba(0x918b3aff).into()),
+ ("predictive".into(), rgba(0xa487bfff).into()),
+ ("link_text".into(), rgba(0xa65927ff).into()),
+ ("punctuation.list_marker".into(), rgba(0x292329ff).into()),
+ ("boolean".into(), rgba(0x918b3bff).into()),
+ ("text.literal".into(), rgba(0xa65927ff).into()),
+ ("emphasis".into(), rgba(0x5169ebff).into()),
+ ("string.regex".into(), rgba(0x149393ff).into()),
+ ("hint".into(), rgba(0x8c70a6ff).into()),
+ ("string".into(), rgba(0x918b3aff).into()),
+ ("operator".into(), rgba(0x695d69ff).into()),
+ ],
+ },
+ status_bar: rgba(0xc6b8c6ff).into(),
+ title_bar: rgba(0xc6b8c6ff).into(),
+ toolbar: rgba(0xf7f3f7ff).into(),
+ tab_bar: rgba(0xe0d5e0ff).into(),
+ editor: rgba(0xf7f3f7ff).into(),
+ editor_subheader: rgba(0xe0d5e0ff).into(),
+ editor_active_line: rgba(0xe0d5e0ff).into(),
+ terminal: rgba(0xf7f3f7ff).into(),
+ image_fallback_background: rgba(0xc6b8c6ff).into(),
+ git_created: rgba(0x918b3bff).into(),
+ git_modified: rgba(0x5169ebff).into(),
+ git_deleted: rgba(0xca402bff).into(),
+ git_conflict: rgba(0xbb8a35ff).into(),
+ git_ignored: rgba(0x857785ff).into(),
+ git_renamed: rgba(0xbb8a35ff).into(),
+ players: [
+ PlayerTheme {
+ cursor: rgba(0x5169ebff).into(),
+ selection: rgba(0x5169eb3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x918b3bff).into(),
+ selection: rgba(0x918b3b3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xcc34ccff).into(),
+ selection: rgba(0xcc34cc3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xa65927ff).into(),
+ selection: rgba(0xa659273d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x7a5ac0ff).into(),
+ selection: rgba(0x7a5ac03d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x189393ff).into(),
+ selection: rgba(0x1893933d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xca402bff).into(),
+ selection: rgba(0xca402b3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xbb8a35ff).into(),
+ selection: rgba(0xbb8a353d).into(),
+ },
+ ],
+ }
+}
@@ -0,0 +1,136 @@
+use gpui2::rgba;
+
+use crate::{PlayerTheme, SyntaxTheme, Theme, ThemeMetadata};
+
+pub fn atelier_lakeside_dark() -> Theme {
+ Theme {
+ metadata: ThemeMetadata {
+ name: "Atelier Lakeside Dark".into(),
+ is_light: false,
+ },
+ transparent: rgba(0x00000000).into(),
+ mac_os_traffic_light_red: rgba(0xec695eff).into(),
+ mac_os_traffic_light_yellow: rgba(0xf4bf4eff).into(),
+ mac_os_traffic_light_green: rgba(0x61c553ff).into(),
+ border: rgba(0x4f6a78ff).into(),
+ border_variant: rgba(0x4f6a78ff).into(),
+ border_focused: rgba(0x1a2f3cff).into(),
+ border_transparent: rgba(0x00000000).into(),
+ elevated_surface: rgba(0x33444dff).into(),
+ surface: rgba(0x1c2529ff).into(),
+ background: rgba(0x33444dff).into(),
+ filled_element: rgba(0x33444dff).into(),
+ filled_element_hover: rgba(0xffffff1e).into(),
+ filled_element_active: rgba(0xffffff28).into(),
+ filled_element_selected: rgba(0x121c24ff).into(),
+ filled_element_disabled: rgba(0x00000000).into(),
+ ghost_element: rgba(0x00000000).into(),
+ ghost_element_hover: rgba(0xffffff14).into(),
+ ghost_element_active: rgba(0xffffff1e).into(),
+ ghost_element_selected: rgba(0x121c24ff).into(),
+ ghost_element_disabled: rgba(0x00000000).into(),
+ text: rgba(0xebf8ffff).into(),
+ text_muted: rgba(0x7c9fb3ff).into(),
+ text_placeholder: rgba(0xd22e72ff).into(),
+ text_disabled: rgba(0x688c9dff).into(),
+ text_accent: rgba(0x267eadff).into(),
+ icon_muted: rgba(0x7c9fb3ff).into(),
+ syntax: SyntaxTheme {
+ highlights: vec![
+ ("punctuation.bracket".into(), rgba(0x7ea2b4ff).into()),
+ ("punctuation.special".into(), rgba(0xb72cd2ff).into()),
+ ("property".into(), rgba(0xd22c72ff).into()),
+ ("function.method".into(), rgba(0x247eadff).into()),
+ ("comment".into(), rgba(0x5a7b8cff).into()),
+ ("constructor".into(), rgba(0x267eadff).into()),
+ ("boolean".into(), rgba(0x558c3aff).into()),
+ ("hint".into(), rgba(0x52809aff).into()),
+ ("label".into(), rgba(0x267eadff).into()),
+ ("string.special".into(), rgba(0xb72cd2ff).into()),
+ ("title".into(), rgba(0xebf8ffff).into()),
+ ("punctuation.list_marker".into(), rgba(0xc1e4f6ff).into()),
+ ("emphasis.strong".into(), rgba(0x267eadff).into()),
+ ("enum".into(), rgba(0x935b25ff).into()),
+ ("type".into(), rgba(0x8a8a0eff).into()),
+ ("tag".into(), rgba(0x267eadff).into()),
+ ("punctuation.delimiter".into(), rgba(0x7ea2b4ff).into()),
+ ("primary".into(), rgba(0xc1e4f6ff).into()),
+ ("link_text".into(), rgba(0x935b25ff).into()),
+ ("variable".into(), rgba(0xc1e4f6ff).into()),
+ ("variable.special".into(), rgba(0x6a6ab7ff).into()),
+ ("string.special.symbol".into(), rgba(0x558c3aff).into()),
+ ("link_uri".into(), rgba(0x558c3aff).into()),
+ ("function".into(), rgba(0x247eadff).into()),
+ ("predictive".into(), rgba(0x426f88ff).into()),
+ ("punctuation".into(), rgba(0xc1e4f6ff).into()),
+ ("string.escape".into(), rgba(0x7ea2b4ff).into()),
+ ("keyword".into(), rgba(0x6a6ab7ff).into()),
+ ("attribute".into(), rgba(0x267eadff).into()),
+ ("string.regex".into(), rgba(0x2c8f6eff).into()),
+ ("embedded".into(), rgba(0xebf8ffff).into()),
+ ("emphasis".into(), rgba(0x267eadff).into()),
+ ("string".into(), rgba(0x558c3aff).into()),
+ ("operator".into(), rgba(0x7ea2b4ff).into()),
+ ("text.literal".into(), rgba(0x935b25ff).into()),
+ ("constant".into(), rgba(0x558c3aff).into()),
+ ("comment.doc".into(), rgba(0x7ea2b4ff).into()),
+ ("number".into(), rgba(0x935c24ff).into()),
+ ("preproc".into(), rgba(0xebf8ffff).into()),
+ (
+ "function.special.definition".into(),
+ rgba(0x8a8a0eff).into(),
+ ),
+ ("variant".into(), rgba(0x8a8a0eff).into()),
+ ],
+ },
+ status_bar: rgba(0x33444dff).into(),
+ title_bar: rgba(0x33444dff).into(),
+ toolbar: rgba(0x161b1dff).into(),
+ tab_bar: rgba(0x1c2529ff).into(),
+ editor: rgba(0x161b1dff).into(),
+ editor_subheader: rgba(0x1c2529ff).into(),
+ editor_active_line: rgba(0x1c2529ff).into(),
+ terminal: rgba(0x161b1dff).into(),
+ image_fallback_background: rgba(0x33444dff).into(),
+ git_created: rgba(0x558c3aff).into(),
+ git_modified: rgba(0x267eadff).into(),
+ git_deleted: rgba(0xd22e72ff).into(),
+ git_conflict: rgba(0x8a8a10ff).into(),
+ git_ignored: rgba(0x688c9dff).into(),
+ git_renamed: rgba(0x8a8a10ff).into(),
+ players: [
+ PlayerTheme {
+ cursor: rgba(0x267eadff).into(),
+ selection: rgba(0x267ead3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x558c3aff).into(),
+ selection: rgba(0x558c3a3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xb72ed2ff).into(),
+ selection: rgba(0xb72ed23d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x935b25ff).into(),
+ selection: rgba(0x935b253d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x6a6ab7ff).into(),
+ selection: rgba(0x6a6ab73d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x2d8f6fff).into(),
+ selection: rgba(0x2d8f6f3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xd22e72ff).into(),
+ selection: rgba(0xd22e723d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x8a8a10ff).into(),
+ selection: rgba(0x8a8a103d).into(),
+ },
+ ],
+ }
+}
@@ -0,0 +1,136 @@
+use gpui2::rgba;
+
+use crate::{PlayerTheme, SyntaxTheme, Theme, ThemeMetadata};
+
+pub fn atelier_lakeside_light() -> Theme {
+ Theme {
+ metadata: ThemeMetadata {
+ name: "Atelier Lakeside Light".into(),
+ is_light: true,
+ },
+ transparent: rgba(0x00000000).into(),
+ mac_os_traffic_light_red: rgba(0xec695eff).into(),
+ mac_os_traffic_light_yellow: rgba(0xf4bf4eff).into(),
+ mac_os_traffic_light_green: rgba(0x61c553ff).into(),
+ border: rgba(0x80a4b6ff).into(),
+ border_variant: rgba(0x80a4b6ff).into(),
+ border_focused: rgba(0xb9cee0ff).into(),
+ border_transparent: rgba(0x00000000).into(),
+ elevated_surface: rgba(0xa6cadcff).into(),
+ surface: rgba(0xcdeaf9ff).into(),
+ background: rgba(0xa6cadcff).into(),
+ filled_element: rgba(0xa6cadcff).into(),
+ filled_element_hover: rgba(0xffffff1e).into(),
+ filled_element_active: rgba(0xffffff28).into(),
+ filled_element_selected: rgba(0xd8e4eeff).into(),
+ filled_element_disabled: rgba(0x00000000).into(),
+ ghost_element: rgba(0x00000000).into(),
+ ghost_element_hover: rgba(0xffffff14).into(),
+ ghost_element_active: rgba(0xffffff1e).into(),
+ ghost_element_selected: rgba(0xd8e4eeff).into(),
+ ghost_element_disabled: rgba(0x00000000).into(),
+ text: rgba(0x161b1dff).into(),
+ text_muted: rgba(0x526f7dff).into(),
+ text_placeholder: rgba(0xd22e71ff).into(),
+ text_disabled: rgba(0x628496ff).into(),
+ text_accent: rgba(0x267eadff).into(),
+ icon_muted: rgba(0x526f7dff).into(),
+ syntax: SyntaxTheme {
+ highlights: vec![
+ ("emphasis".into(), rgba(0x267eadff).into()),
+ ("number".into(), rgba(0x935c24ff).into()),
+ ("embedded".into(), rgba(0x161b1dff).into()),
+ ("link_text".into(), rgba(0x935c25ff).into()),
+ ("string".into(), rgba(0x558c3aff).into()),
+ ("constructor".into(), rgba(0x267eadff).into()),
+ ("punctuation.list_marker".into(), rgba(0x1f292eff).into()),
+ ("string.special".into(), rgba(0xb72cd2ff).into()),
+ ("title".into(), rgba(0x161b1dff).into()),
+ ("variant".into(), rgba(0x8a8a0eff).into()),
+ ("tag".into(), rgba(0x267eadff).into()),
+ ("attribute".into(), rgba(0x267eadff).into()),
+ ("keyword".into(), rgba(0x6a6ab7ff).into()),
+ ("enum".into(), rgba(0x935c25ff).into()),
+ ("function".into(), rgba(0x247eadff).into()),
+ ("string.escape".into(), rgba(0x516d7bff).into()),
+ ("operator".into(), rgba(0x516d7bff).into()),
+ ("function.method".into(), rgba(0x247eadff).into()),
+ (
+ "function.special.definition".into(),
+ rgba(0x8a8a0eff).into(),
+ ),
+ ("punctuation.delimiter".into(), rgba(0x516d7bff).into()),
+ ("comment".into(), rgba(0x7094a7ff).into()),
+ ("primary".into(), rgba(0x1f292eff).into()),
+ ("punctuation.bracket".into(), rgba(0x516d7bff).into()),
+ ("variable".into(), rgba(0x1f292eff).into()),
+ ("emphasis.strong".into(), rgba(0x267eadff).into()),
+ ("predictive".into(), rgba(0x6a97b2ff).into()),
+ ("punctuation.special".into(), rgba(0xb72cd2ff).into()),
+ ("hint".into(), rgba(0x5a87a0ff).into()),
+ ("text.literal".into(), rgba(0x935c25ff).into()),
+ ("string.special.symbol".into(), rgba(0x558c3aff).into()),
+ ("comment.doc".into(), rgba(0x516d7bff).into()),
+ ("constant".into(), rgba(0x568c3bff).into()),
+ ("boolean".into(), rgba(0x568c3bff).into()),
+ ("preproc".into(), rgba(0x161b1dff).into()),
+ ("variable.special".into(), rgba(0x6a6ab7ff).into()),
+ ("link_uri".into(), rgba(0x568c3bff).into()),
+ ("string.regex".into(), rgba(0x2c8f6eff).into()),
+ ("punctuation".into(), rgba(0x1f292eff).into()),
+ ("property".into(), rgba(0xd22c72ff).into()),
+ ("label".into(), rgba(0x267eadff).into()),
+ ("type".into(), rgba(0x8a8a0eff).into()),
+ ],
+ },
+ status_bar: rgba(0xa6cadcff).into(),
+ title_bar: rgba(0xa6cadcff).into(),
+ toolbar: rgba(0xebf8ffff).into(),
+ tab_bar: rgba(0xcdeaf9ff).into(),
+ editor: rgba(0xebf8ffff).into(),
+ editor_subheader: rgba(0xcdeaf9ff).into(),
+ editor_active_line: rgba(0xcdeaf9ff).into(),
+ terminal: rgba(0xebf8ffff).into(),
+ image_fallback_background: rgba(0xa6cadcff).into(),
+ git_created: rgba(0x568c3bff).into(),
+ git_modified: rgba(0x267eadff).into(),
+ git_deleted: rgba(0xd22e71ff).into(),
+ git_conflict: rgba(0x8a8a10ff).into(),
+ git_ignored: rgba(0x628496ff).into(),
+ git_renamed: rgba(0x8a8a10ff).into(),
+ players: [
+ PlayerTheme {
+ cursor: rgba(0x267eadff).into(),
+ selection: rgba(0x267ead3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x568c3bff).into(),
+ selection: rgba(0x568c3b3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xb72ed2ff).into(),
+ selection: rgba(0xb72ed23d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x935c25ff).into(),
+ selection: rgba(0x935c253d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x6c6ab7ff).into(),
+ selection: rgba(0x6c6ab73d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x2e8f6eff).into(),
+ selection: rgba(0x2e8f6e3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xd22e71ff).into(),
+ selection: rgba(0xd22e713d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x8a8a10ff).into(),
+ selection: rgba(0x8a8a103d).into(),
+ },
+ ],
+ }
+}
@@ -0,0 +1,136 @@
+use gpui2::rgba;
+
+use crate::{PlayerTheme, SyntaxTheme, Theme, ThemeMetadata};
+
+pub fn atelier_plateau_dark() -> Theme {
+ Theme {
+ metadata: ThemeMetadata {
+ name: "Atelier Plateau Dark".into(),
+ is_light: false,
+ },
+ transparent: rgba(0x00000000).into(),
+ mac_os_traffic_light_red: rgba(0xec695eff).into(),
+ mac_os_traffic_light_yellow: rgba(0xf4bf4eff).into(),
+ mac_os_traffic_light_green: rgba(0x61c553ff).into(),
+ border: rgba(0x564e4eff).into(),
+ border_variant: rgba(0x564e4eff).into(),
+ border_focused: rgba(0x2c2b45ff).into(),
+ border_transparent: rgba(0x00000000).into(),
+ elevated_surface: rgba(0x3b3535ff).into(),
+ surface: rgba(0x252020ff).into(),
+ background: rgba(0x3b3535ff).into(),
+ filled_element: rgba(0x3b3535ff).into(),
+ filled_element_hover: rgba(0xffffff1e).into(),
+ filled_element_active: rgba(0xffffff28).into(),
+ filled_element_selected: rgba(0x1c1b29ff).into(),
+ filled_element_disabled: rgba(0x00000000).into(),
+ ghost_element: rgba(0x00000000).into(),
+ ghost_element_hover: rgba(0xffffff14).into(),
+ ghost_element_active: rgba(0xffffff1e).into(),
+ ghost_element_selected: rgba(0x1c1b29ff).into(),
+ ghost_element_disabled: rgba(0x00000000).into(),
+ text: rgba(0xf4ececff).into(),
+ text_muted: rgba(0x898383ff).into(),
+ text_placeholder: rgba(0xca4848ff).into(),
+ text_disabled: rgba(0x756e6eff).into(),
+ text_accent: rgba(0x7272caff).into(),
+ icon_muted: rgba(0x898383ff).into(),
+ syntax: SyntaxTheme {
+ highlights: vec![
+ ("variant".into(), rgba(0xa06d3aff).into()),
+ ("label".into(), rgba(0x7272caff).into()),
+ ("punctuation.delimiter".into(), rgba(0x8a8585ff).into()),
+ ("string.regex".into(), rgba(0x5485b6ff).into()),
+ ("variable.special".into(), rgba(0x8464c4ff).into()),
+ ("string".into(), rgba(0x4b8b8bff).into()),
+ ("property".into(), rgba(0xca4848ff).into()),
+ ("hint".into(), rgba(0x8a647aff).into()),
+ ("comment.doc".into(), rgba(0x8a8585ff).into()),
+ ("attribute".into(), rgba(0x7272caff).into()),
+ ("tag".into(), rgba(0x7272caff).into()),
+ ("constructor".into(), rgba(0x7272caff).into()),
+ ("boolean".into(), rgba(0x4b8b8bff).into()),
+ ("preproc".into(), rgba(0xf4ececff).into()),
+ ("constant".into(), rgba(0x4b8b8bff).into()),
+ ("punctuation.special".into(), rgba(0xbd5187ff).into()),
+ ("function.method".into(), rgba(0x7272caff).into()),
+ ("comment".into(), rgba(0x655d5dff).into()),
+ ("variable".into(), rgba(0xe7dfdfff).into()),
+ ("primary".into(), rgba(0xe7dfdfff).into()),
+ ("title".into(), rgba(0xf4ececff).into()),
+ ("emphasis".into(), rgba(0x7272caff).into()),
+ ("emphasis.strong".into(), rgba(0x7272caff).into()),
+ ("function".into(), rgba(0x7272caff).into()),
+ ("type".into(), rgba(0xa06d3aff).into()),
+ ("operator".into(), rgba(0x8a8585ff).into()),
+ ("embedded".into(), rgba(0xf4ececff).into()),
+ ("predictive".into(), rgba(0x795369ff).into()),
+ ("punctuation".into(), rgba(0xe7dfdfff).into()),
+ ("link_text".into(), rgba(0xb4593bff).into()),
+ ("enum".into(), rgba(0xb4593bff).into()),
+ ("string.special".into(), rgba(0xbd5187ff).into()),
+ ("text.literal".into(), rgba(0xb4593bff).into()),
+ ("string.escape".into(), rgba(0x8a8585ff).into()),
+ (
+ "function.special.definition".into(),
+ rgba(0xa06d3aff).into(),
+ ),
+ ("keyword".into(), rgba(0x8464c4ff).into()),
+ ("link_uri".into(), rgba(0x4b8b8bff).into()),
+ ("number".into(), rgba(0xb4593bff).into()),
+ ("punctuation.bracket".into(), rgba(0x8a8585ff).into()),
+ ("string.special.symbol".into(), rgba(0x4b8b8bff).into()),
+ ("punctuation.list_marker".into(), rgba(0xe7dfdfff).into()),
+ ],
+ },
+ status_bar: rgba(0x3b3535ff).into(),
+ title_bar: rgba(0x3b3535ff).into(),
+ toolbar: rgba(0x1b1818ff).into(),
+ tab_bar: rgba(0x252020ff).into(),
+ editor: rgba(0x1b1818ff).into(),
+ editor_subheader: rgba(0x252020ff).into(),
+ editor_active_line: rgba(0x252020ff).into(),
+ terminal: rgba(0x1b1818ff).into(),
+ image_fallback_background: rgba(0x3b3535ff).into(),
+ git_created: rgba(0x4b8b8bff).into(),
+ git_modified: rgba(0x7272caff).into(),
+ git_deleted: rgba(0xca4848ff).into(),
+ git_conflict: rgba(0xa06d3aff).into(),
+ git_ignored: rgba(0x756e6eff).into(),
+ git_renamed: rgba(0xa06d3aff).into(),
+ players: [
+ PlayerTheme {
+ cursor: rgba(0x7272caff).into(),
+ selection: rgba(0x7272ca3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x4b8b8bff).into(),
+ selection: rgba(0x4b8b8b3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xbd5187ff).into(),
+ selection: rgba(0xbd51873d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xb4593bff).into(),
+ selection: rgba(0xb4593b3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x8464c4ff).into(),
+ selection: rgba(0x8464c43d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x5485b6ff).into(),
+ selection: rgba(0x5485b63d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xca4848ff).into(),
+ selection: rgba(0xca48483d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xa06d3aff).into(),
+ selection: rgba(0xa06d3a3d).into(),
+ },
+ ],
+ }
+}
@@ -0,0 +1,136 @@
+use gpui2::rgba;
+
+use crate::{PlayerTheme, SyntaxTheme, Theme, ThemeMetadata};
+
+pub fn atelier_plateau_light() -> Theme {
+ Theme {
+ metadata: ThemeMetadata {
+ name: "Atelier Plateau Light".into(),
+ is_light: true,
+ },
+ transparent: rgba(0x00000000).into(),
+ mac_os_traffic_light_red: rgba(0xec695eff).into(),
+ mac_os_traffic_light_yellow: rgba(0xf4bf4eff).into(),
+ mac_os_traffic_light_green: rgba(0x61c553ff).into(),
+ border: rgba(0x8e8989ff).into(),
+ border_variant: rgba(0x8e8989ff).into(),
+ border_focused: rgba(0xcecaecff).into(),
+ border_transparent: rgba(0x00000000).into(),
+ elevated_surface: rgba(0xc1bbbbff).into(),
+ surface: rgba(0xebe3e3ff).into(),
+ background: rgba(0xc1bbbbff).into(),
+ filled_element: rgba(0xc1bbbbff).into(),
+ filled_element_hover: rgba(0xffffff1e).into(),
+ filled_element_active: rgba(0xffffff28).into(),
+ filled_element_selected: rgba(0xe4e1f5ff).into(),
+ filled_element_disabled: rgba(0x00000000).into(),
+ ghost_element: rgba(0x00000000).into(),
+ ghost_element_hover: rgba(0xffffff14).into(),
+ ghost_element_active: rgba(0xffffff1e).into(),
+ ghost_element_selected: rgba(0xe4e1f5ff).into(),
+ ghost_element_disabled: rgba(0x00000000).into(),
+ text: rgba(0x1b1818ff).into(),
+ text_muted: rgba(0x5a5252ff).into(),
+ text_placeholder: rgba(0xca4a4aff).into(),
+ text_disabled: rgba(0x6e6666ff).into(),
+ text_accent: rgba(0x7272caff).into(),
+ icon_muted: rgba(0x5a5252ff).into(),
+ syntax: SyntaxTheme {
+ highlights: vec![
+ ("text.literal".into(), rgba(0xb45a3cff).into()),
+ ("punctuation.special".into(), rgba(0xbd5187ff).into()),
+ ("variant".into(), rgba(0xa06d3aff).into()),
+ ("punctuation".into(), rgba(0x292424ff).into()),
+ ("string.escape".into(), rgba(0x585050ff).into()),
+ ("emphasis".into(), rgba(0x7272caff).into()),
+ ("title".into(), rgba(0x1b1818ff).into()),
+ ("constructor".into(), rgba(0x7272caff).into()),
+ ("variable".into(), rgba(0x292424ff).into()),
+ ("predictive".into(), rgba(0xa27a91ff).into()),
+ ("label".into(), rgba(0x7272caff).into()),
+ ("function.method".into(), rgba(0x7272caff).into()),
+ ("link_uri".into(), rgba(0x4c8b8bff).into()),
+ ("punctuation.delimiter".into(), rgba(0x585050ff).into()),
+ ("link_text".into(), rgba(0xb45a3cff).into()),
+ ("hint".into(), rgba(0x91697fff).into()),
+ ("emphasis.strong".into(), rgba(0x7272caff).into()),
+ ("attribute".into(), rgba(0x7272caff).into()),
+ ("boolean".into(), rgba(0x4c8b8bff).into()),
+ ("string.special.symbol".into(), rgba(0x4b8b8bff).into()),
+ ("string".into(), rgba(0x4b8b8bff).into()),
+ ("type".into(), rgba(0xa06d3aff).into()),
+ ("string.regex".into(), rgba(0x5485b6ff).into()),
+ ("comment.doc".into(), rgba(0x585050ff).into()),
+ ("string.special".into(), rgba(0xbd5187ff).into()),
+ ("property".into(), rgba(0xca4848ff).into()),
+ ("preproc".into(), rgba(0x1b1818ff).into()),
+ ("embedded".into(), rgba(0x1b1818ff).into()),
+ ("comment".into(), rgba(0x7e7777ff).into()),
+ ("primary".into(), rgba(0x292424ff).into()),
+ ("number".into(), rgba(0xb4593bff).into()),
+ ("function".into(), rgba(0x7272caff).into()),
+ ("punctuation.bracket".into(), rgba(0x585050ff).into()),
+ ("tag".into(), rgba(0x7272caff).into()),
+ ("punctuation.list_marker".into(), rgba(0x292424ff).into()),
+ (
+ "function.special.definition".into(),
+ rgba(0xa06d3aff).into(),
+ ),
+ ("enum".into(), rgba(0xb45a3cff).into()),
+ ("keyword".into(), rgba(0x8464c4ff).into()),
+ ("operator".into(), rgba(0x585050ff).into()),
+ ("variable.special".into(), rgba(0x8464c4ff).into()),
+ ("constant".into(), rgba(0x4c8b8bff).into()),
+ ],
+ },
+ status_bar: rgba(0xc1bbbbff).into(),
+ title_bar: rgba(0xc1bbbbff).into(),
+ toolbar: rgba(0xf4ececff).into(),
+ tab_bar: rgba(0xebe3e3ff).into(),
+ editor: rgba(0xf4ececff).into(),
+ editor_subheader: rgba(0xebe3e3ff).into(),
+ editor_active_line: rgba(0xebe3e3ff).into(),
+ terminal: rgba(0xf4ececff).into(),
+ image_fallback_background: rgba(0xc1bbbbff).into(),
+ git_created: rgba(0x4c8b8bff).into(),
+ git_modified: rgba(0x7272caff).into(),
+ git_deleted: rgba(0xca4a4aff).into(),
+ git_conflict: rgba(0xa06e3bff).into(),
+ git_ignored: rgba(0x6e6666ff).into(),
+ git_renamed: rgba(0xa06e3bff).into(),
+ players: [
+ PlayerTheme {
+ cursor: rgba(0x7272caff).into(),
+ selection: rgba(0x7272ca3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x4c8b8bff).into(),
+ selection: rgba(0x4c8b8b3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xbd5186ff).into(),
+ selection: rgba(0xbd51863d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xb45a3cff).into(),
+ selection: rgba(0xb45a3c3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x8464c4ff).into(),
+ selection: rgba(0x8464c43d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x5485b5ff).into(),
+ selection: rgba(0x5485b53d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xca4a4aff).into(),
+ selection: rgba(0xca4a4a3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xa06e3bff).into(),
+ selection: rgba(0xa06e3b3d).into(),
+ },
+ ],
+ }
+}
@@ -0,0 +1,136 @@
+use gpui2::rgba;
+
+use crate::{PlayerTheme, SyntaxTheme, Theme, ThemeMetadata};
+
+pub fn atelier_savanna_dark() -> Theme {
+ Theme {
+ metadata: ThemeMetadata {
+ name: "Atelier Savanna Dark".into(),
+ is_light: false,
+ },
+ transparent: rgba(0x00000000).into(),
+ mac_os_traffic_light_red: rgba(0xec695eff).into(),
+ mac_os_traffic_light_yellow: rgba(0xf4bf4eff).into(),
+ mac_os_traffic_light_green: rgba(0x61c553ff).into(),
+ border: rgba(0x505e55ff).into(),
+ border_variant: rgba(0x505e55ff).into(),
+ border_focused: rgba(0x1f3233ff).into(),
+ border_transparent: rgba(0x00000000).into(),
+ elevated_surface: rgba(0x353f39ff).into(),
+ surface: rgba(0x1f2621ff).into(),
+ background: rgba(0x353f39ff).into(),
+ filled_element: rgba(0x353f39ff).into(),
+ filled_element_hover: rgba(0xffffff1e).into(),
+ filled_element_active: rgba(0xffffff28).into(),
+ filled_element_selected: rgba(0x151e20ff).into(),
+ filled_element_disabled: rgba(0x00000000).into(),
+ ghost_element: rgba(0x00000000).into(),
+ ghost_element_hover: rgba(0xffffff14).into(),
+ ghost_element_active: rgba(0xffffff1e).into(),
+ ghost_element_selected: rgba(0x151e20ff).into(),
+ ghost_element_disabled: rgba(0x00000000).into(),
+ text: rgba(0xecf4eeff).into(),
+ text_muted: rgba(0x859188ff).into(),
+ text_placeholder: rgba(0xb16038ff).into(),
+ text_disabled: rgba(0x6f7e74ff).into(),
+ text_accent: rgba(0x468b8fff).into(),
+ icon_muted: rgba(0x859188ff).into(),
+ syntax: SyntaxTheme {
+ highlights: vec![
+ ("function.method".into(), rgba(0x468b8fff).into()),
+ ("title".into(), rgba(0xecf4eeff).into()),
+ ("label".into(), rgba(0x468b8fff).into()),
+ ("text.literal".into(), rgba(0x9f703bff).into()),
+ ("boolean".into(), rgba(0x479962ff).into()),
+ ("punctuation.list_marker".into(), rgba(0xdfe7e2ff).into()),
+ ("string.escape".into(), rgba(0x87928aff).into()),
+ ("string.special".into(), rgba(0x857368ff).into()),
+ ("punctuation.delimiter".into(), rgba(0x87928aff).into()),
+ ("tag".into(), rgba(0x468b8fff).into()),
+ ("property".into(), rgba(0xb16038ff).into()),
+ ("preproc".into(), rgba(0xecf4eeff).into()),
+ ("primary".into(), rgba(0xdfe7e2ff).into()),
+ ("link_uri".into(), rgba(0x479962ff).into()),
+ ("comment".into(), rgba(0x5f6d64ff).into()),
+ ("type".into(), rgba(0xa07d3aff).into()),
+ ("hint".into(), rgba(0x607e76ff).into()),
+ ("punctuation".into(), rgba(0xdfe7e2ff).into()),
+ ("string.special.symbol".into(), rgba(0x479962ff).into()),
+ ("emphasis.strong".into(), rgba(0x468b8fff).into()),
+ ("keyword".into(), rgba(0x55859bff).into()),
+ ("comment.doc".into(), rgba(0x87928aff).into()),
+ ("punctuation.bracket".into(), rgba(0x87928aff).into()),
+ ("constant".into(), rgba(0x479962ff).into()),
+ ("link_text".into(), rgba(0x9f703bff).into()),
+ ("number".into(), rgba(0x9f703bff).into()),
+ ("function".into(), rgba(0x468b8fff).into()),
+ ("variable".into(), rgba(0xdfe7e2ff).into()),
+ ("emphasis".into(), rgba(0x468b8fff).into()),
+ ("punctuation.special".into(), rgba(0x857368ff).into()),
+ ("constructor".into(), rgba(0x468b8fff).into()),
+ ("variable.special".into(), rgba(0x55859bff).into()),
+ ("operator".into(), rgba(0x87928aff).into()),
+ ("enum".into(), rgba(0x9f703bff).into()),
+ ("string.regex".into(), rgba(0x1b9aa0ff).into()),
+ ("attribute".into(), rgba(0x468b8fff).into()),
+ ("predictive".into(), rgba(0x506d66ff).into()),
+ ("string".into(), rgba(0x479962ff).into()),
+ ("embedded".into(), rgba(0xecf4eeff).into()),
+ ("variant".into(), rgba(0xa07d3aff).into()),
+ (
+ "function.special.definition".into(),
+ rgba(0xa07d3aff).into(),
+ ),
+ ],
+ },
+ status_bar: rgba(0x353f39ff).into(),
+ title_bar: rgba(0x353f39ff).into(),
+ toolbar: rgba(0x171c19ff).into(),
+ tab_bar: rgba(0x1f2621ff).into(),
+ editor: rgba(0x171c19ff).into(),
+ editor_subheader: rgba(0x1f2621ff).into(),
+ editor_active_line: rgba(0x1f2621ff).into(),
+ terminal: rgba(0x171c19ff).into(),
+ image_fallback_background: rgba(0x353f39ff).into(),
+ git_created: rgba(0x479962ff).into(),
+ git_modified: rgba(0x468b8fff).into(),
+ git_deleted: rgba(0xb16038ff).into(),
+ git_conflict: rgba(0xa07d3aff).into(),
+ git_ignored: rgba(0x6f7e74ff).into(),
+ git_renamed: rgba(0xa07d3aff).into(),
+ players: [
+ PlayerTheme {
+ cursor: rgba(0x468b8fff).into(),
+ selection: rgba(0x468b8f3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x479962ff).into(),
+ selection: rgba(0x4799623d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x857368ff).into(),
+ selection: rgba(0x8573683d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x9f703bff).into(),
+ selection: rgba(0x9f703b3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x55859bff).into(),
+ selection: rgba(0x55859b3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x1d9aa0ff).into(),
+ selection: rgba(0x1d9aa03d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xb16038ff).into(),
+ selection: rgba(0xb160383d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xa07d3aff).into(),
+ selection: rgba(0xa07d3a3d).into(),
+ },
+ ],
+ }
+}
@@ -0,0 +1,136 @@
+use gpui2::rgba;
+
+use crate::{PlayerTheme, SyntaxTheme, Theme, ThemeMetadata};
+
+pub fn atelier_savanna_light() -> Theme {
+ Theme {
+ metadata: ThemeMetadata {
+ name: "Atelier Savanna Light".into(),
+ is_light: true,
+ },
+ transparent: rgba(0x00000000).into(),
+ mac_os_traffic_light_red: rgba(0xec695eff).into(),
+ mac_os_traffic_light_yellow: rgba(0xf4bf4eff).into(),
+ mac_os_traffic_light_green: rgba(0x61c553ff).into(),
+ border: rgba(0x8b968eff).into(),
+ border_variant: rgba(0x8b968eff).into(),
+ border_focused: rgba(0xbed4d6ff).into(),
+ border_transparent: rgba(0x00000000).into(),
+ elevated_surface: rgba(0xbcc5bfff).into(),
+ surface: rgba(0xe3ebe6ff).into(),
+ background: rgba(0xbcc5bfff).into(),
+ filled_element: rgba(0xbcc5bfff).into(),
+ filled_element_hover: rgba(0xffffff1e).into(),
+ filled_element_active: rgba(0xffffff28).into(),
+ filled_element_selected: rgba(0xdae7e8ff).into(),
+ filled_element_disabled: rgba(0x00000000).into(),
+ ghost_element: rgba(0x00000000).into(),
+ ghost_element_hover: rgba(0xffffff14).into(),
+ ghost_element_active: rgba(0xffffff1e).into(),
+ ghost_element_selected: rgba(0xdae7e8ff).into(),
+ ghost_element_disabled: rgba(0x00000000).into(),
+ text: rgba(0x171c19ff).into(),
+ text_muted: rgba(0x546259ff).into(),
+ text_placeholder: rgba(0xb16139ff).into(),
+ text_disabled: rgba(0x68766dff).into(),
+ text_accent: rgba(0x488b90ff).into(),
+ icon_muted: rgba(0x546259ff).into(),
+ syntax: SyntaxTheme {
+ highlights: vec![
+ ("text.literal".into(), rgba(0x9f713cff).into()),
+ ("string".into(), rgba(0x479962ff).into()),
+ ("punctuation.special".into(), rgba(0x857368ff).into()),
+ ("type".into(), rgba(0xa07d3aff).into()),
+ ("enum".into(), rgba(0x9f713cff).into()),
+ ("title".into(), rgba(0x171c19ff).into()),
+ ("comment".into(), rgba(0x77877cff).into()),
+ ("predictive".into(), rgba(0x75958bff).into()),
+ ("punctuation.list_marker".into(), rgba(0x232a25ff).into()),
+ ("string.special.symbol".into(), rgba(0x479962ff).into()),
+ ("constructor".into(), rgba(0x488b90ff).into()),
+ ("variable".into(), rgba(0x232a25ff).into()),
+ ("label".into(), rgba(0x488b90ff).into()),
+ ("attribute".into(), rgba(0x488b90ff).into()),
+ ("constant".into(), rgba(0x499963ff).into()),
+ ("function".into(), rgba(0x468b8fff).into()),
+ ("variable.special".into(), rgba(0x55859bff).into()),
+ ("keyword".into(), rgba(0x55859bff).into()),
+ ("number".into(), rgba(0x9f703bff).into()),
+ ("boolean".into(), rgba(0x499963ff).into()),
+ ("embedded".into(), rgba(0x171c19ff).into()),
+ ("string.special".into(), rgba(0x857368ff).into()),
+ ("emphasis.strong".into(), rgba(0x488b90ff).into()),
+ ("string.regex".into(), rgba(0x1b9aa0ff).into()),
+ ("hint".into(), rgba(0x66847cff).into()),
+ ("preproc".into(), rgba(0x171c19ff).into()),
+ ("link_uri".into(), rgba(0x499963ff).into()),
+ ("variant".into(), rgba(0xa07d3aff).into()),
+ ("function.method".into(), rgba(0x468b8fff).into()),
+ ("punctuation.bracket".into(), rgba(0x526057ff).into()),
+ ("punctuation.delimiter".into(), rgba(0x526057ff).into()),
+ ("punctuation".into(), rgba(0x232a25ff).into()),
+ ("primary".into(), rgba(0x232a25ff).into()),
+ ("string.escape".into(), rgba(0x526057ff).into()),
+ ("property".into(), rgba(0xb16038ff).into()),
+ ("operator".into(), rgba(0x526057ff).into()),
+ ("comment.doc".into(), rgba(0x526057ff).into()),
+ (
+ "function.special.definition".into(),
+ rgba(0xa07d3aff).into(),
+ ),
+ ("link_text".into(), rgba(0x9f713cff).into()),
+ ("tag".into(), rgba(0x488b90ff).into()),
+ ("emphasis".into(), rgba(0x488b90ff).into()),
+ ],
+ },
+ status_bar: rgba(0xbcc5bfff).into(),
+ title_bar: rgba(0xbcc5bfff).into(),
+ toolbar: rgba(0xecf4eeff).into(),
+ tab_bar: rgba(0xe3ebe6ff).into(),
+ editor: rgba(0xecf4eeff).into(),
+ editor_subheader: rgba(0xe3ebe6ff).into(),
+ editor_active_line: rgba(0xe3ebe6ff).into(),
+ terminal: rgba(0xecf4eeff).into(),
+ image_fallback_background: rgba(0xbcc5bfff).into(),
+ git_created: rgba(0x499963ff).into(),
+ git_modified: rgba(0x488b90ff).into(),
+ git_deleted: rgba(0xb16139ff).into(),
+ git_conflict: rgba(0xa07d3bff).into(),
+ git_ignored: rgba(0x68766dff).into(),
+ git_renamed: rgba(0xa07d3bff).into(),
+ players: [
+ PlayerTheme {
+ cursor: rgba(0x488b90ff).into(),
+ selection: rgba(0x488b903d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x499963ff).into(),
+ selection: rgba(0x4999633d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x857368ff).into(),
+ selection: rgba(0x8573683d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x9f713cff).into(),
+ selection: rgba(0x9f713c3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x55859bff).into(),
+ selection: rgba(0x55859b3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x1e9aa0ff).into(),
+ selection: rgba(0x1e9aa03d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xb16139ff).into(),
+ selection: rgba(0xb161393d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xa07d3bff).into(),
+ selection: rgba(0xa07d3b3d).into(),
+ },
+ ],
+ }
+}
@@ -0,0 +1,136 @@
+use gpui2::rgba;
+
+use crate::{PlayerTheme, SyntaxTheme, Theme, ThemeMetadata};
+
+pub fn atelier_seaside_dark() -> Theme {
+ Theme {
+ metadata: ThemeMetadata {
+ name: "Atelier Seaside Dark".into(),
+ is_light: false,
+ },
+ transparent: rgba(0x00000000).into(),
+ mac_os_traffic_light_red: rgba(0xec695eff).into(),
+ mac_os_traffic_light_yellow: rgba(0xf4bf4eff).into(),
+ mac_os_traffic_light_green: rgba(0x61c553ff).into(),
+ border: rgba(0x5c6c5cff).into(),
+ border_variant: rgba(0x5c6c5cff).into(),
+ border_focused: rgba(0x102667ff).into(),
+ border_transparent: rgba(0x00000000).into(),
+ elevated_surface: rgba(0x3b453bff).into(),
+ surface: rgba(0x1f231fff).into(),
+ background: rgba(0x3b453bff).into(),
+ filled_element: rgba(0x3b453bff).into(),
+ filled_element_hover: rgba(0xffffff1e).into(),
+ filled_element_active: rgba(0xffffff28).into(),
+ filled_element_selected: rgba(0x051949ff).into(),
+ filled_element_disabled: rgba(0x00000000).into(),
+ ghost_element: rgba(0x00000000).into(),
+ ghost_element_hover: rgba(0xffffff14).into(),
+ ghost_element_active: rgba(0xffffff1e).into(),
+ ghost_element_selected: rgba(0x051949ff).into(),
+ ghost_element_disabled: rgba(0x00000000).into(),
+ text: rgba(0xf3faf3ff).into(),
+ text_muted: rgba(0x8ba48bff).into(),
+ text_placeholder: rgba(0xe61c3bff).into(),
+ text_disabled: rgba(0x778f77ff).into(),
+ text_accent: rgba(0x3e62f4ff).into(),
+ icon_muted: rgba(0x8ba48bff).into(),
+ syntax: SyntaxTheme {
+ highlights: vec![
+ ("comment".into(), rgba(0x687d68ff).into()),
+ ("predictive".into(), rgba(0x00788bff).into()),
+ ("string.special".into(), rgba(0xe618c3ff).into()),
+ ("string.regex".into(), rgba(0x1899b3ff).into()),
+ ("boolean".into(), rgba(0x2aa329ff).into()),
+ ("string".into(), rgba(0x28a328ff).into()),
+ ("operator".into(), rgba(0x8ca68cff).into()),
+ ("primary".into(), rgba(0xcfe8cfff).into()),
+ ("number".into(), rgba(0x87711cff).into()),
+ ("punctuation.special".into(), rgba(0xe618c3ff).into()),
+ ("link_text".into(), rgba(0x87711dff).into()),
+ ("title".into(), rgba(0xf3faf3ff).into()),
+ ("comment.doc".into(), rgba(0x8ca68cff).into()),
+ ("label".into(), rgba(0x3e62f4ff).into()),
+ ("preproc".into(), rgba(0xf3faf3ff).into()),
+ ("punctuation.bracket".into(), rgba(0x8ca68cff).into()),
+ ("punctuation.delimiter".into(), rgba(0x8ca68cff).into()),
+ ("function.method".into(), rgba(0x3d62f5ff).into()),
+ ("tag".into(), rgba(0x3e62f4ff).into()),
+ ("embedded".into(), rgba(0xf3faf3ff).into()),
+ ("text.literal".into(), rgba(0x87711dff).into()),
+ ("punctuation".into(), rgba(0xcfe8cfff).into()),
+ ("string.special.symbol".into(), rgba(0x28a328ff).into()),
+ ("link_uri".into(), rgba(0x2aa329ff).into()),
+ ("keyword".into(), rgba(0xac2aeeff).into()),
+ ("function".into(), rgba(0x3d62f5ff).into()),
+ ("string.escape".into(), rgba(0x8ca68cff).into()),
+ ("variant".into(), rgba(0x98981bff).into()),
+ (
+ "function.special.definition".into(),
+ rgba(0x98981bff).into(),
+ ),
+ ("constructor".into(), rgba(0x3e62f4ff).into()),
+ ("constant".into(), rgba(0x2aa329ff).into()),
+ ("hint".into(), rgba(0x008b9fff).into()),
+ ("type".into(), rgba(0x98981bff).into()),
+ ("emphasis".into(), rgba(0x3e62f4ff).into()),
+ ("variable".into(), rgba(0xcfe8cfff).into()),
+ ("emphasis.strong".into(), rgba(0x3e62f4ff).into()),
+ ("attribute".into(), rgba(0x3e62f4ff).into()),
+ ("enum".into(), rgba(0x87711dff).into()),
+ ("property".into(), rgba(0xe6183bff).into()),
+ ("punctuation.list_marker".into(), rgba(0xcfe8cfff).into()),
+ ("variable.special".into(), rgba(0xac2aeeff).into()),
+ ],
+ },
+ status_bar: rgba(0x3b453bff).into(),
+ title_bar: rgba(0x3b453bff).into(),
+ toolbar: rgba(0x131513ff).into(),
+ tab_bar: rgba(0x1f231fff).into(),
+ editor: rgba(0x131513ff).into(),
+ editor_subheader: rgba(0x1f231fff).into(),
+ editor_active_line: rgba(0x1f231fff).into(),
+ terminal: rgba(0x131513ff).into(),
+ image_fallback_background: rgba(0x3b453bff).into(),
+ git_created: rgba(0x2aa329ff).into(),
+ git_modified: rgba(0x3e62f4ff).into(),
+ git_deleted: rgba(0xe61c3bff).into(),
+ git_conflict: rgba(0x98981bff).into(),
+ git_ignored: rgba(0x778f77ff).into(),
+ git_renamed: rgba(0x98981bff).into(),
+ players: [
+ PlayerTheme {
+ cursor: rgba(0x3e62f4ff).into(),
+ selection: rgba(0x3e62f43d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x2aa329ff).into(),
+ selection: rgba(0x2aa3293d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xe61cc3ff).into(),
+ selection: rgba(0xe61cc33d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x87711dff).into(),
+ selection: rgba(0x87711d3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xac2dedff).into(),
+ selection: rgba(0xac2ded3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x1b99b3ff).into(),
+ selection: rgba(0x1b99b33d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xe61c3bff).into(),
+ selection: rgba(0xe61c3b3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x98981bff).into(),
+ selection: rgba(0x98981b3d).into(),
+ },
+ ],
+ }
+}
@@ -0,0 +1,136 @@
+use gpui2::rgba;
+
+use crate::{PlayerTheme, SyntaxTheme, Theme, ThemeMetadata};
+
+pub fn atelier_seaside_light() -> Theme {
+ Theme {
+ metadata: ThemeMetadata {
+ name: "Atelier Seaside Light".into(),
+ is_light: true,
+ },
+ transparent: rgba(0x00000000).into(),
+ mac_os_traffic_light_red: rgba(0xec695eff).into(),
+ mac_os_traffic_light_yellow: rgba(0xf4bf4eff).into(),
+ mac_os_traffic_light_green: rgba(0x61c553ff).into(),
+ border: rgba(0x8ea88eff).into(),
+ border_variant: rgba(0x8ea88eff).into(),
+ border_focused: rgba(0xc9c4fdff).into(),
+ border_transparent: rgba(0x00000000).into(),
+ elevated_surface: rgba(0xb4ceb4ff).into(),
+ surface: rgba(0xdaeedaff).into(),
+ background: rgba(0xb4ceb4ff).into(),
+ filled_element: rgba(0xb4ceb4ff).into(),
+ filled_element_hover: rgba(0xffffff1e).into(),
+ filled_element_active: rgba(0xffffff28).into(),
+ filled_element_selected: rgba(0xe1ddfeff).into(),
+ filled_element_disabled: rgba(0x00000000).into(),
+ ghost_element: rgba(0x00000000).into(),
+ ghost_element_hover: rgba(0xffffff14).into(),
+ ghost_element_active: rgba(0xffffff1e).into(),
+ ghost_element_selected: rgba(0xe1ddfeff).into(),
+ ghost_element_disabled: rgba(0x00000000).into(),
+ text: rgba(0x131513ff).into(),
+ text_muted: rgba(0x5f705fff).into(),
+ text_placeholder: rgba(0xe61c3dff).into(),
+ text_disabled: rgba(0x718771ff).into(),
+ text_accent: rgba(0x3e61f4ff).into(),
+ icon_muted: rgba(0x5f705fff).into(),
+ syntax: SyntaxTheme {
+ highlights: vec![
+ ("string.escape".into(), rgba(0x5e6e5eff).into()),
+ ("boolean".into(), rgba(0x2aa32aff).into()),
+ ("string.special".into(), rgba(0xe618c3ff).into()),
+ ("comment".into(), rgba(0x809980ff).into()),
+ ("number".into(), rgba(0x87711cff).into()),
+ ("comment.doc".into(), rgba(0x5e6e5eff).into()),
+ ("tag".into(), rgba(0x3e61f4ff).into()),
+ ("string.special.symbol".into(), rgba(0x28a328ff).into()),
+ ("primary".into(), rgba(0x242924ff).into()),
+ ("string".into(), rgba(0x28a328ff).into()),
+ ("enum".into(), rgba(0x87711fff).into()),
+ ("operator".into(), rgba(0x5e6e5eff).into()),
+ ("string.regex".into(), rgba(0x1899b3ff).into()),
+ ("keyword".into(), rgba(0xac2aeeff).into()),
+ ("emphasis".into(), rgba(0x3e61f4ff).into()),
+ ("link_uri".into(), rgba(0x2aa32aff).into()),
+ ("constant".into(), rgba(0x2aa32aff).into()),
+ ("constructor".into(), rgba(0x3e61f4ff).into()),
+ ("link_text".into(), rgba(0x87711fff).into()),
+ ("emphasis.strong".into(), rgba(0x3e61f4ff).into()),
+ ("punctuation.list_marker".into(), rgba(0x242924ff).into()),
+ ("punctuation.delimiter".into(), rgba(0x5e6e5eff).into()),
+ ("punctuation.special".into(), rgba(0xe618c3ff).into()),
+ ("variant".into(), rgba(0x98981bff).into()),
+ ("predictive".into(), rgba(0x00a2b5ff).into()),
+ ("attribute".into(), rgba(0x3e61f4ff).into()),
+ ("preproc".into(), rgba(0x131513ff).into()),
+ ("embedded".into(), rgba(0x131513ff).into()),
+ ("punctuation".into(), rgba(0x242924ff).into()),
+ ("label".into(), rgba(0x3e61f4ff).into()),
+ ("function.method".into(), rgba(0x3d62f5ff).into()),
+ ("property".into(), rgba(0xe6183bff).into()),
+ ("title".into(), rgba(0x131513ff).into()),
+ ("variable".into(), rgba(0x242924ff).into()),
+ ("function".into(), rgba(0x3d62f5ff).into()),
+ ("variable.special".into(), rgba(0xac2aeeff).into()),
+ ("type".into(), rgba(0x98981bff).into()),
+ ("text.literal".into(), rgba(0x87711fff).into()),
+ ("hint".into(), rgba(0x008fa1ff).into()),
+ (
+ "function.special.definition".into(),
+ rgba(0x98981bff).into(),
+ ),
+ ("punctuation.bracket".into(), rgba(0x5e6e5eff).into()),
+ ],
+ },
+ status_bar: rgba(0xb4ceb4ff).into(),
+ title_bar: rgba(0xb4ceb4ff).into(),
+ toolbar: rgba(0xf3faf3ff).into(),
+ tab_bar: rgba(0xdaeedaff).into(),
+ editor: rgba(0xf3faf3ff).into(),
+ editor_subheader: rgba(0xdaeedaff).into(),
+ editor_active_line: rgba(0xdaeedaff).into(),
+ terminal: rgba(0xf3faf3ff).into(),
+ image_fallback_background: rgba(0xb4ceb4ff).into(),
+ git_created: rgba(0x2aa32aff).into(),
+ git_modified: rgba(0x3e61f4ff).into(),
+ git_deleted: rgba(0xe61c3dff).into(),
+ git_conflict: rgba(0x98981cff).into(),
+ git_ignored: rgba(0x718771ff).into(),
+ git_renamed: rgba(0x98981cff).into(),
+ players: [
+ PlayerTheme {
+ cursor: rgba(0x3e61f4ff).into(),
+ selection: rgba(0x3e61f43d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x2aa32aff).into(),
+ selection: rgba(0x2aa32a3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xe61cc2ff).into(),
+ selection: rgba(0xe61cc23d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x87711fff).into(),
+ selection: rgba(0x87711f3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xac2dedff).into(),
+ selection: rgba(0xac2ded3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x1c99b3ff).into(),
+ selection: rgba(0x1c99b33d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xe61c3dff).into(),
+ selection: rgba(0xe61c3d3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x98981cff).into(),
+ selection: rgba(0x98981c3d).into(),
+ },
+ ],
+ }
+}
@@ -0,0 +1,136 @@
+use gpui2::rgba;
+
+use crate::{PlayerTheme, SyntaxTheme, Theme, ThemeMetadata};
+
+pub fn atelier_sulphurpool_dark() -> Theme {
+ Theme {
+ metadata: ThemeMetadata {
+ name: "Atelier Sulphurpool Dark".into(),
+ is_light: false,
+ },
+ transparent: rgba(0x00000000).into(),
+ mac_os_traffic_light_red: rgba(0xec695eff).into(),
+ mac_os_traffic_light_yellow: rgba(0xf4bf4eff).into(),
+ mac_os_traffic_light_green: rgba(0x61c553ff).into(),
+ border: rgba(0x5b6385ff).into(),
+ border_variant: rgba(0x5b6385ff).into(),
+ border_focused: rgba(0x203348ff).into(),
+ border_transparent: rgba(0x00000000).into(),
+ elevated_surface: rgba(0x3e4769ff).into(),
+ surface: rgba(0x262f51ff).into(),
+ background: rgba(0x3e4769ff).into(),
+ filled_element: rgba(0x3e4769ff).into(),
+ filled_element_hover: rgba(0xffffff1e).into(),
+ filled_element_active: rgba(0xffffff28).into(),
+ filled_element_selected: rgba(0x161f2bff).into(),
+ filled_element_disabled: rgba(0x00000000).into(),
+ ghost_element: rgba(0x00000000).into(),
+ ghost_element_hover: rgba(0xffffff14).into(),
+ ghost_element_active: rgba(0xffffff1e).into(),
+ ghost_element_selected: rgba(0x161f2bff).into(),
+ ghost_element_disabled: rgba(0x00000000).into(),
+ text: rgba(0xf5f7ffff).into(),
+ text_muted: rgba(0x959bb2ff).into(),
+ text_placeholder: rgba(0xc94922ff).into(),
+ text_disabled: rgba(0x7e849eff).into(),
+ text_accent: rgba(0x3e8ed0ff).into(),
+ icon_muted: rgba(0x959bb2ff).into(),
+ syntax: SyntaxTheme {
+ highlights: vec![
+ ("title".into(), rgba(0xf5f7ffff).into()),
+ ("constructor".into(), rgba(0x3e8ed0ff).into()),
+ ("type".into(), rgba(0xc08b2fff).into()),
+ ("punctuation.list_marker".into(), rgba(0xdfe2f1ff).into()),
+ ("property".into(), rgba(0xc94821ff).into()),
+ ("link_uri".into(), rgba(0xac9739ff).into()),
+ ("string.escape".into(), rgba(0x979db4ff).into()),
+ ("constant".into(), rgba(0xac9739ff).into()),
+ ("embedded".into(), rgba(0xf5f7ffff).into()),
+ ("punctuation.special".into(), rgba(0x9b6279ff).into()),
+ ("punctuation.bracket".into(), rgba(0x979db4ff).into()),
+ ("preproc".into(), rgba(0xf5f7ffff).into()),
+ ("emphasis.strong".into(), rgba(0x3e8ed0ff).into()),
+ ("emphasis".into(), rgba(0x3e8ed0ff).into()),
+ ("enum".into(), rgba(0xc76a29ff).into()),
+ ("boolean".into(), rgba(0xac9739ff).into()),
+ ("primary".into(), rgba(0xdfe2f1ff).into()),
+ ("function.method".into(), rgba(0x3d8fd1ff).into()),
+ (
+ "function.special.definition".into(),
+ rgba(0xc08b2fff).into(),
+ ),
+ ("comment.doc".into(), rgba(0x979db4ff).into()),
+ ("string".into(), rgba(0xac9738ff).into()),
+ ("text.literal".into(), rgba(0xc76a29ff).into()),
+ ("operator".into(), rgba(0x979db4ff).into()),
+ ("number".into(), rgba(0xc76a28ff).into()),
+ ("string.special".into(), rgba(0x9b6279ff).into()),
+ ("punctuation.delimiter".into(), rgba(0x979db4ff).into()),
+ ("tag".into(), rgba(0x3e8ed0ff).into()),
+ ("string.special.symbol".into(), rgba(0xac9738ff).into()),
+ ("variable".into(), rgba(0xdfe2f1ff).into()),
+ ("attribute".into(), rgba(0x3e8ed0ff).into()),
+ ("punctuation".into(), rgba(0xdfe2f1ff).into()),
+ ("string.regex".into(), rgba(0x21a2c9ff).into()),
+ ("keyword".into(), rgba(0x6679ccff).into()),
+ ("label".into(), rgba(0x3e8ed0ff).into()),
+ ("hint".into(), rgba(0x6c81a5ff).into()),
+ ("function".into(), rgba(0x3d8fd1ff).into()),
+ ("link_text".into(), rgba(0xc76a29ff).into()),
+ ("variant".into(), rgba(0xc08b2fff).into()),
+ ("variable.special".into(), rgba(0x6679ccff).into()),
+ ("predictive".into(), rgba(0x58709aff).into()),
+ ("comment".into(), rgba(0x6a7293ff).into()),
+ ],
+ },
+ status_bar: rgba(0x3e4769ff).into(),
+ title_bar: rgba(0x3e4769ff).into(),
+ toolbar: rgba(0x202646ff).into(),
+ tab_bar: rgba(0x262f51ff).into(),
+ editor: rgba(0x202646ff).into(),
+ editor_subheader: rgba(0x262f51ff).into(),
+ editor_active_line: rgba(0x262f51ff).into(),
+ terminal: rgba(0x202646ff).into(),
+ image_fallback_background: rgba(0x3e4769ff).into(),
+ git_created: rgba(0xac9739ff).into(),
+ git_modified: rgba(0x3e8ed0ff).into(),
+ git_deleted: rgba(0xc94922ff).into(),
+ git_conflict: rgba(0xc08b30ff).into(),
+ git_ignored: rgba(0x7e849eff).into(),
+ git_renamed: rgba(0xc08b30ff).into(),
+ players: [
+ PlayerTheme {
+ cursor: rgba(0x3e8ed0ff).into(),
+ selection: rgba(0x3e8ed03d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xac9739ff).into(),
+ selection: rgba(0xac97393d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x9b6279ff).into(),
+ selection: rgba(0x9b62793d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xc76a29ff).into(),
+ selection: rgba(0xc76a293d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x6679ccff).into(),
+ selection: rgba(0x6679cc3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x24a1c9ff).into(),
+ selection: rgba(0x24a1c93d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xc94922ff).into(),
+ selection: rgba(0xc949223d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xc08b30ff).into(),
+ selection: rgba(0xc08b303d).into(),
+ },
+ ],
+ }
+}
@@ -0,0 +1,136 @@
+use gpui2::rgba;
+
+use crate::{PlayerTheme, SyntaxTheme, Theme, ThemeMetadata};
+
+pub fn atelier_sulphurpool_light() -> Theme {
+ Theme {
+ metadata: ThemeMetadata {
+ name: "Atelier Sulphurpool Light".into(),
+ is_light: true,
+ },
+ transparent: rgba(0x00000000).into(),
+ mac_os_traffic_light_red: rgba(0xec695eff).into(),
+ mac_os_traffic_light_yellow: rgba(0xf4bf4eff).into(),
+ mac_os_traffic_light_green: rgba(0x61c553ff).into(),
+ border: rgba(0x9a9fb6ff).into(),
+ border_variant: rgba(0x9a9fb6ff).into(),
+ border_focused: rgba(0xc2d5efff).into(),
+ border_transparent: rgba(0x00000000).into(),
+ elevated_surface: rgba(0xc1c5d8ff).into(),
+ surface: rgba(0xe5e8f5ff).into(),
+ background: rgba(0xc1c5d8ff).into(),
+ filled_element: rgba(0xc1c5d8ff).into(),
+ filled_element_hover: rgba(0xffffff1e).into(),
+ filled_element_active: rgba(0xffffff28).into(),
+ filled_element_selected: rgba(0xdde7f6ff).into(),
+ filled_element_disabled: rgba(0x00000000).into(),
+ ghost_element: rgba(0x00000000).into(),
+ ghost_element_hover: rgba(0xffffff14).into(),
+ ghost_element_active: rgba(0xffffff1e).into(),
+ ghost_element_selected: rgba(0xdde7f6ff).into(),
+ ghost_element_disabled: rgba(0x00000000).into(),
+ text: rgba(0x202646ff).into(),
+ text_muted: rgba(0x5f6789ff).into(),
+ text_placeholder: rgba(0xc94922ff).into(),
+ text_disabled: rgba(0x767d9aff).into(),
+ text_accent: rgba(0x3e8fd0ff).into(),
+ icon_muted: rgba(0x5f6789ff).into(),
+ syntax: SyntaxTheme {
+ highlights: vec![
+ ("string.special".into(), rgba(0x9b6279ff).into()),
+ ("string.regex".into(), rgba(0x21a2c9ff).into()),
+ ("embedded".into(), rgba(0x202646ff).into()),
+ ("string".into(), rgba(0xac9738ff).into()),
+ (
+ "function.special.definition".into(),
+ rgba(0xc08b2fff).into(),
+ ),
+ ("hint".into(), rgba(0x7087b2ff).into()),
+ ("function.method".into(), rgba(0x3d8fd1ff).into()),
+ ("punctuation.list_marker".into(), rgba(0x293256ff).into()),
+ ("punctuation".into(), rgba(0x293256ff).into()),
+ ("constant".into(), rgba(0xac9739ff).into()),
+ ("label".into(), rgba(0x3e8fd0ff).into()),
+ ("comment.doc".into(), rgba(0x5d6587ff).into()),
+ ("property".into(), rgba(0xc94821ff).into()),
+ ("punctuation.bracket".into(), rgba(0x5d6587ff).into()),
+ ("constructor".into(), rgba(0x3e8fd0ff).into()),
+ ("variable.special".into(), rgba(0x6679ccff).into()),
+ ("emphasis".into(), rgba(0x3e8fd0ff).into()),
+ ("link_text".into(), rgba(0xc76a29ff).into()),
+ ("keyword".into(), rgba(0x6679ccff).into()),
+ ("primary".into(), rgba(0x293256ff).into()),
+ ("comment".into(), rgba(0x898ea4ff).into()),
+ ("title".into(), rgba(0x202646ff).into()),
+ ("link_uri".into(), rgba(0xac9739ff).into()),
+ ("text.literal".into(), rgba(0xc76a29ff).into()),
+ ("operator".into(), rgba(0x5d6587ff).into()),
+ ("number".into(), rgba(0xc76a28ff).into()),
+ ("preproc".into(), rgba(0x202646ff).into()),
+ ("attribute".into(), rgba(0x3e8fd0ff).into()),
+ ("emphasis.strong".into(), rgba(0x3e8fd0ff).into()),
+ ("string.escape".into(), rgba(0x5d6587ff).into()),
+ ("tag".into(), rgba(0x3e8fd0ff).into()),
+ ("variable".into(), rgba(0x293256ff).into()),
+ ("predictive".into(), rgba(0x8599beff).into()),
+ ("enum".into(), rgba(0xc76a29ff).into()),
+ ("string.special.symbol".into(), rgba(0xac9738ff).into()),
+ ("punctuation.delimiter".into(), rgba(0x5d6587ff).into()),
+ ("function".into(), rgba(0x3d8fd1ff).into()),
+ ("type".into(), rgba(0xc08b2fff).into()),
+ ("punctuation.special".into(), rgba(0x9b6279ff).into()),
+ ("variant".into(), rgba(0xc08b2fff).into()),
+ ("boolean".into(), rgba(0xac9739ff).into()),
+ ],
+ },
+ status_bar: rgba(0xc1c5d8ff).into(),
+ title_bar: rgba(0xc1c5d8ff).into(),
+ toolbar: rgba(0xf5f7ffff).into(),
+ tab_bar: rgba(0xe5e8f5ff).into(),
+ editor: rgba(0xf5f7ffff).into(),
+ editor_subheader: rgba(0xe5e8f5ff).into(),
+ editor_active_line: rgba(0xe5e8f5ff).into(),
+ terminal: rgba(0xf5f7ffff).into(),
+ image_fallback_background: rgba(0xc1c5d8ff).into(),
+ git_created: rgba(0xac9739ff).into(),
+ git_modified: rgba(0x3e8fd0ff).into(),
+ git_deleted: rgba(0xc94922ff).into(),
+ git_conflict: rgba(0xc08b30ff).into(),
+ git_ignored: rgba(0x767d9aff).into(),
+ git_renamed: rgba(0xc08b30ff).into(),
+ players: [
+ PlayerTheme {
+ cursor: rgba(0x3e8fd0ff).into(),
+ selection: rgba(0x3e8fd03d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xac9739ff).into(),
+ selection: rgba(0xac97393d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x9b6279ff).into(),
+ selection: rgba(0x9b62793d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xc76a29ff).into(),
+ selection: rgba(0xc76a293d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x6679cbff).into(),
+ selection: rgba(0x6679cb3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x24a1c9ff).into(),
+ selection: rgba(0x24a1c93d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xc94922ff).into(),
+ selection: rgba(0xc949223d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xc08b30ff).into(),
+ selection: rgba(0xc08b303d).into(),
+ },
+ ],
+ }
+}
@@ -0,0 +1,130 @@
+use gpui2::rgba;
+
+use crate::{PlayerTheme, SyntaxTheme, Theme, ThemeMetadata};
+
+pub fn ayu_dark() -> Theme {
+ Theme {
+ metadata: ThemeMetadata {
+ name: "Ayu Dark".into(),
+ is_light: false,
+ },
+ transparent: rgba(0x00000000).into(),
+ mac_os_traffic_light_red: rgba(0xec695eff).into(),
+ mac_os_traffic_light_yellow: rgba(0xf4bf4eff).into(),
+ mac_os_traffic_light_green: rgba(0x61c553ff).into(),
+ border: rgba(0x3f4043ff).into(),
+ border_variant: rgba(0x3f4043ff).into(),
+ border_focused: rgba(0x1b4a6eff).into(),
+ border_transparent: rgba(0x00000000).into(),
+ elevated_surface: rgba(0x313337ff).into(),
+ surface: rgba(0x1f2127ff).into(),
+ background: rgba(0x313337ff).into(),
+ filled_element: rgba(0x313337ff).into(),
+ filled_element_hover: rgba(0xffffff1e).into(),
+ filled_element_active: rgba(0xffffff28).into(),
+ filled_element_selected: rgba(0x0d2f4eff).into(),
+ filled_element_disabled: rgba(0x00000000).into(),
+ ghost_element: rgba(0x00000000).into(),
+ ghost_element_hover: rgba(0xffffff14).into(),
+ ghost_element_active: rgba(0xffffff1e).into(),
+ ghost_element_selected: rgba(0x0d2f4eff).into(),
+ ghost_element_disabled: rgba(0x00000000).into(),
+ text: rgba(0xbfbdb6ff).into(),
+ text_muted: rgba(0x8a8986ff).into(),
+ text_placeholder: rgba(0xef7177ff).into(),
+ text_disabled: rgba(0x696a6aff).into(),
+ text_accent: rgba(0x5ac1feff).into(),
+ icon_muted: rgba(0x8a8986ff).into(),
+ syntax: SyntaxTheme {
+ highlights: vec![
+ ("emphasis".into(), rgba(0x5ac1feff).into()),
+ ("punctuation.bracket".into(), rgba(0xa6a5a0ff).into()),
+ ("constructor".into(), rgba(0x5ac1feff).into()),
+ ("predictive".into(), rgba(0x5a728bff).into()),
+ ("emphasis.strong".into(), rgba(0x5ac1feff).into()),
+ ("string.regex".into(), rgba(0x95e6cbff).into()),
+ ("tag".into(), rgba(0x5ac1feff).into()),
+ ("punctuation".into(), rgba(0xa6a5a0ff).into()),
+ ("number".into(), rgba(0xd2a6ffff).into()),
+ ("punctuation.special".into(), rgba(0xd2a6ffff).into()),
+ ("primary".into(), rgba(0xbfbdb6ff).into()),
+ ("boolean".into(), rgba(0xd2a6ffff).into()),
+ ("variant".into(), rgba(0x5ac1feff).into()),
+ ("link_uri".into(), rgba(0xaad84cff).into()),
+ ("comment.doc".into(), rgba(0x8c8b88ff).into()),
+ ("title".into(), rgba(0xbfbdb6ff).into()),
+ ("text.literal".into(), rgba(0xfe8f40ff).into()),
+ ("link_text".into(), rgba(0xfe8f40ff).into()),
+ ("punctuation.delimiter".into(), rgba(0xa6a5a0ff).into()),
+ ("string.escape".into(), rgba(0x8c8b88ff).into()),
+ ("hint".into(), rgba(0x628b80ff).into()),
+ ("type".into(), rgba(0x59c2ffff).into()),
+ ("variable".into(), rgba(0xbfbdb6ff).into()),
+ ("label".into(), rgba(0x5ac1feff).into()),
+ ("enum".into(), rgba(0xfe8f40ff).into()),
+ ("operator".into(), rgba(0xf29668ff).into()),
+ ("function".into(), rgba(0xffb353ff).into()),
+ ("preproc".into(), rgba(0xbfbdb6ff).into()),
+ ("embedded".into(), rgba(0xbfbdb6ff).into()),
+ ("string".into(), rgba(0xa9d94bff).into()),
+ ("attribute".into(), rgba(0x5ac1feff).into()),
+ ("keyword".into(), rgba(0xff8f3fff).into()),
+ ("string.special.symbol".into(), rgba(0xfe8f40ff).into()),
+ ("comment".into(), rgba(0xabb5be8c).into()),
+ ("property".into(), rgba(0x5ac1feff).into()),
+ ("punctuation.list_marker".into(), rgba(0xa6a5a0ff).into()),
+ ("constant".into(), rgba(0xd2a6ffff).into()),
+ ("string.special".into(), rgba(0xe5b572ff).into()),
+ ],
+ },
+ status_bar: rgba(0x313337ff).into(),
+ title_bar: rgba(0x313337ff).into(),
+ toolbar: rgba(0x0d1016ff).into(),
+ tab_bar: rgba(0x1f2127ff).into(),
+ editor: rgba(0x0d1016ff).into(),
+ editor_subheader: rgba(0x1f2127ff).into(),
+ editor_active_line: rgba(0x1f2127ff).into(),
+ terminal: rgba(0x0d1016ff).into(),
+ image_fallback_background: rgba(0x313337ff).into(),
+ git_created: rgba(0xaad84cff).into(),
+ git_modified: rgba(0x5ac1feff).into(),
+ git_deleted: rgba(0xef7177ff).into(),
+ git_conflict: rgba(0xfeb454ff).into(),
+ git_ignored: rgba(0x696a6aff).into(),
+ git_renamed: rgba(0xfeb454ff).into(),
+ players: [
+ PlayerTheme {
+ cursor: rgba(0x5ac1feff).into(),
+ selection: rgba(0x5ac1fe3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xaad84cff).into(),
+ selection: rgba(0xaad84c3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x39bae5ff).into(),
+ selection: rgba(0x39bae53d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xfe8f40ff).into(),
+ selection: rgba(0xfe8f403d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xd2a6feff).into(),
+ selection: rgba(0xd2a6fe3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x95e5cbff).into(),
+ selection: rgba(0x95e5cb3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xef7177ff).into(),
+ selection: rgba(0xef71773d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xfeb454ff).into(),
+ selection: rgba(0xfeb4543d).into(),
+ },
+ ],
+ }
+}
@@ -0,0 +1,130 @@
+use gpui2::rgba;
+
+use crate::{PlayerTheme, SyntaxTheme, Theme, ThemeMetadata};
+
+pub fn ayu_light() -> Theme {
+ Theme {
+ metadata: ThemeMetadata {
+ name: "Ayu Light".into(),
+ is_light: true,
+ },
+ transparent: rgba(0x00000000).into(),
+ mac_os_traffic_light_red: rgba(0xec695eff).into(),
+ mac_os_traffic_light_yellow: rgba(0xf4bf4eff).into(),
+ mac_os_traffic_light_green: rgba(0x61c553ff).into(),
+ border: rgba(0xcfd1d2ff).into(),
+ border_variant: rgba(0xcfd1d2ff).into(),
+ border_focused: rgba(0xc4daf6ff).into(),
+ border_transparent: rgba(0x00000000).into(),
+ elevated_surface: rgba(0xdcdddeff).into(),
+ surface: rgba(0xececedff).into(),
+ background: rgba(0xdcdddeff).into(),
+ filled_element: rgba(0xdcdddeff).into(),
+ filled_element_hover: rgba(0xffffff1e).into(),
+ filled_element_active: rgba(0xffffff28).into(),
+ filled_element_selected: rgba(0xdeebfaff).into(),
+ filled_element_disabled: rgba(0x00000000).into(),
+ ghost_element: rgba(0x00000000).into(),
+ ghost_element_hover: rgba(0xffffff14).into(),
+ ghost_element_active: rgba(0xffffff1e).into(),
+ ghost_element_selected: rgba(0xdeebfaff).into(),
+ ghost_element_disabled: rgba(0x00000000).into(),
+ text: rgba(0x5c6166ff).into(),
+ text_muted: rgba(0x8b8e92ff).into(),
+ text_placeholder: rgba(0xef7271ff).into(),
+ text_disabled: rgba(0xa9acaeff).into(),
+ text_accent: rgba(0x3b9ee5ff).into(),
+ icon_muted: rgba(0x8b8e92ff).into(),
+ syntax: SyntaxTheme {
+ highlights: vec![
+ ("string".into(), rgba(0x86b300ff).into()),
+ ("enum".into(), rgba(0xf98d3fff).into()),
+ ("comment".into(), rgba(0x787b8099).into()),
+ ("comment.doc".into(), rgba(0x898d90ff).into()),
+ ("emphasis".into(), rgba(0x3b9ee5ff).into()),
+ ("keyword".into(), rgba(0xfa8d3eff).into()),
+ ("string.regex".into(), rgba(0x4bbf98ff).into()),
+ ("text.literal".into(), rgba(0xf98d3fff).into()),
+ ("string.escape".into(), rgba(0x898d90ff).into()),
+ ("link_text".into(), rgba(0xf98d3fff).into()),
+ ("punctuation".into(), rgba(0x73777bff).into()),
+ ("constructor".into(), rgba(0x3b9ee5ff).into()),
+ ("constant".into(), rgba(0xa37accff).into()),
+ ("variable".into(), rgba(0x5c6166ff).into()),
+ ("primary".into(), rgba(0x5c6166ff).into()),
+ ("emphasis.strong".into(), rgba(0x3b9ee5ff).into()),
+ ("string.special".into(), rgba(0xe6ba7eff).into()),
+ ("number".into(), rgba(0xa37accff).into()),
+ ("preproc".into(), rgba(0x5c6166ff).into()),
+ ("punctuation.delimiter".into(), rgba(0x73777bff).into()),
+ ("string.special.symbol".into(), rgba(0xf98d3fff).into()),
+ ("boolean".into(), rgba(0xa37accff).into()),
+ ("property".into(), rgba(0x3b9ee5ff).into()),
+ ("title".into(), rgba(0x5c6166ff).into()),
+ ("hint".into(), rgba(0x8ca7c2ff).into()),
+ ("predictive".into(), rgba(0x9eb9d3ff).into()),
+ ("operator".into(), rgba(0xed9365ff).into()),
+ ("type".into(), rgba(0x389ee6ff).into()),
+ ("function".into(), rgba(0xf2ad48ff).into()),
+ ("variant".into(), rgba(0x3b9ee5ff).into()),
+ ("label".into(), rgba(0x3b9ee5ff).into()),
+ ("punctuation.list_marker".into(), rgba(0x73777bff).into()),
+ ("punctuation.bracket".into(), rgba(0x73777bff).into()),
+ ("embedded".into(), rgba(0x5c6166ff).into()),
+ ("punctuation.special".into(), rgba(0xa37accff).into()),
+ ("attribute".into(), rgba(0x3b9ee5ff).into()),
+ ("tag".into(), rgba(0x3b9ee5ff).into()),
+ ("link_uri".into(), rgba(0x85b304ff).into()),
+ ],
+ },
+ status_bar: rgba(0xdcdddeff).into(),
+ title_bar: rgba(0xdcdddeff).into(),
+ toolbar: rgba(0xfcfcfcff).into(),
+ tab_bar: rgba(0xececedff).into(),
+ editor: rgba(0xfcfcfcff).into(),
+ editor_subheader: rgba(0xececedff).into(),
+ editor_active_line: rgba(0xececedff).into(),
+ terminal: rgba(0xfcfcfcff).into(),
+ image_fallback_background: rgba(0xdcdddeff).into(),
+ git_created: rgba(0x85b304ff).into(),
+ git_modified: rgba(0x3b9ee5ff).into(),
+ git_deleted: rgba(0xef7271ff).into(),
+ git_conflict: rgba(0xf1ad49ff).into(),
+ git_ignored: rgba(0xa9acaeff).into(),
+ git_renamed: rgba(0xf1ad49ff).into(),
+ players: [
+ PlayerTheme {
+ cursor: rgba(0x3b9ee5ff).into(),
+ selection: rgba(0x3b9ee53d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x85b304ff).into(),
+ selection: rgba(0x85b3043d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x55b4d3ff).into(),
+ selection: rgba(0x55b4d33d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xf98d3fff).into(),
+ selection: rgba(0xf98d3f3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xa37accff).into(),
+ selection: rgba(0xa37acc3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x4dbf99ff).into(),
+ selection: rgba(0x4dbf993d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xef7271ff).into(),
+ selection: rgba(0xef72713d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xf1ad49ff).into(),
+ selection: rgba(0xf1ad493d).into(),
+ },
+ ],
+ }
+}
@@ -0,0 +1,130 @@
+use gpui2::rgba;
+
+use crate::{PlayerTheme, SyntaxTheme, Theme, ThemeMetadata};
+
+pub fn ayu_mirage() -> Theme {
+ Theme {
+ metadata: ThemeMetadata {
+ name: "Ayu Mirage".into(),
+ is_light: false,
+ },
+ transparent: rgba(0x00000000).into(),
+ mac_os_traffic_light_red: rgba(0xec695eff).into(),
+ mac_os_traffic_light_yellow: rgba(0xf4bf4eff).into(),
+ mac_os_traffic_light_green: rgba(0x61c553ff).into(),
+ border: rgba(0x53565dff).into(),
+ border_variant: rgba(0x53565dff).into(),
+ border_focused: rgba(0x24556fff).into(),
+ border_transparent: rgba(0x00000000).into(),
+ elevated_surface: rgba(0x464a52ff).into(),
+ surface: rgba(0x353944ff).into(),
+ background: rgba(0x464a52ff).into(),
+ filled_element: rgba(0x464a52ff).into(),
+ filled_element_hover: rgba(0xffffff1e).into(),
+ filled_element_active: rgba(0xffffff28).into(),
+ filled_element_selected: rgba(0x123950ff).into(),
+ filled_element_disabled: rgba(0x00000000).into(),
+ ghost_element: rgba(0x00000000).into(),
+ ghost_element_hover: rgba(0xffffff14).into(),
+ ghost_element_active: rgba(0xffffff1e).into(),
+ ghost_element_selected: rgba(0x123950ff).into(),
+ ghost_element_disabled: rgba(0x00000000).into(),
+ text: rgba(0xcccac2ff).into(),
+ text_muted: rgba(0x9a9a98ff).into(),
+ text_placeholder: rgba(0xf18779ff).into(),
+ text_disabled: rgba(0x7b7d7fff).into(),
+ text_accent: rgba(0x72cffeff).into(),
+ icon_muted: rgba(0x9a9a98ff).into(),
+ syntax: SyntaxTheme {
+ highlights: vec![
+ ("text.literal".into(), rgba(0xfead66ff).into()),
+ ("link_text".into(), rgba(0xfead66ff).into()),
+ ("function".into(), rgba(0xffd173ff).into()),
+ ("punctuation.delimiter".into(), rgba(0xb4b3aeff).into()),
+ ("property".into(), rgba(0x72cffeff).into()),
+ ("title".into(), rgba(0xcccac2ff).into()),
+ ("boolean".into(), rgba(0xdfbfffff).into()),
+ ("link_uri".into(), rgba(0xd5fe80ff).into()),
+ ("label".into(), rgba(0x72cffeff).into()),
+ ("primary".into(), rgba(0xcccac2ff).into()),
+ ("number".into(), rgba(0xdfbfffff).into()),
+ ("variant".into(), rgba(0x72cffeff).into()),
+ ("enum".into(), rgba(0xfead66ff).into()),
+ ("string.special.symbol".into(), rgba(0xfead66ff).into()),
+ ("operator".into(), rgba(0xf29e74ff).into()),
+ ("punctuation.special".into(), rgba(0xdfbfffff).into()),
+ ("constructor".into(), rgba(0x72cffeff).into()),
+ ("type".into(), rgba(0x73cfffff).into()),
+ ("emphasis.strong".into(), rgba(0x72cffeff).into()),
+ ("embedded".into(), rgba(0xcccac2ff).into()),
+ ("comment".into(), rgba(0xb8cfe680).into()),
+ ("tag".into(), rgba(0x72cffeff).into()),
+ ("keyword".into(), rgba(0xffad65ff).into()),
+ ("punctuation".into(), rgba(0xb4b3aeff).into()),
+ ("preproc".into(), rgba(0xcccac2ff).into()),
+ ("hint".into(), rgba(0x7399a3ff).into()),
+ ("string.special".into(), rgba(0xffdfb3ff).into()),
+ ("attribute".into(), rgba(0x72cffeff).into()),
+ ("string.regex".into(), rgba(0x95e6cbff).into()),
+ ("predictive".into(), rgba(0x6d839bff).into()),
+ ("comment.doc".into(), rgba(0x9b9b99ff).into()),
+ ("emphasis".into(), rgba(0x72cffeff).into()),
+ ("string".into(), rgba(0xd4fe7fff).into()),
+ ("constant".into(), rgba(0xdfbfffff).into()),
+ ("string.escape".into(), rgba(0x9b9b99ff).into()),
+ ("variable".into(), rgba(0xcccac2ff).into()),
+ ("punctuation.bracket".into(), rgba(0xb4b3aeff).into()),
+ ("punctuation.list_marker".into(), rgba(0xb4b3aeff).into()),
+ ],
+ },
+ status_bar: rgba(0x464a52ff).into(),
+ title_bar: rgba(0x464a52ff).into(),
+ toolbar: rgba(0x242835ff).into(),
+ tab_bar: rgba(0x353944ff).into(),
+ editor: rgba(0x242835ff).into(),
+ editor_subheader: rgba(0x353944ff).into(),
+ editor_active_line: rgba(0x353944ff).into(),
+ terminal: rgba(0x242835ff).into(),
+ image_fallback_background: rgba(0x464a52ff).into(),
+ git_created: rgba(0xd5fe80ff).into(),
+ git_modified: rgba(0x72cffeff).into(),
+ git_deleted: rgba(0xf18779ff).into(),
+ git_conflict: rgba(0xfecf72ff).into(),
+ git_ignored: rgba(0x7b7d7fff).into(),
+ git_renamed: rgba(0xfecf72ff).into(),
+ players: [
+ PlayerTheme {
+ cursor: rgba(0x72cffeff).into(),
+ selection: rgba(0x72cffe3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xd5fe80ff).into(),
+ selection: rgba(0xd5fe803d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x5bcde5ff).into(),
+ selection: rgba(0x5bcde53d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xfead66ff).into(),
+ selection: rgba(0xfead663d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xdebffeff).into(),
+ selection: rgba(0xdebffe3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x95e5cbff).into(),
+ selection: rgba(0x95e5cb3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xf18779ff).into(),
+ selection: rgba(0xf187793d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xfecf72ff).into(),
+ selection: rgba(0xfecf723d).into(),
+ },
+ ],
+ }
+}
@@ -0,0 +1,131 @@
+use gpui2::rgba;
+
+use crate::{PlayerTheme, SyntaxTheme, Theme, ThemeMetadata};
+
+pub fn gruvbox_dark() -> Theme {
+ Theme {
+ metadata: ThemeMetadata {
+ name: "Gruvbox Dark".into(),
+ is_light: false,
+ },
+ transparent: rgba(0x00000000).into(),
+ mac_os_traffic_light_red: rgba(0xec695eff).into(),
+ mac_os_traffic_light_yellow: rgba(0xf4bf4eff).into(),
+ mac_os_traffic_light_green: rgba(0x61c553ff).into(),
+ border: rgba(0x5b534dff).into(),
+ border_variant: rgba(0x5b534dff).into(),
+ border_focused: rgba(0x303a36ff).into(),
+ border_transparent: rgba(0x00000000).into(),
+ elevated_surface: rgba(0x4c4642ff).into(),
+ surface: rgba(0x3a3735ff).into(),
+ background: rgba(0x4c4642ff).into(),
+ filled_element: rgba(0x4c4642ff).into(),
+ filled_element_hover: rgba(0xffffff1e).into(),
+ filled_element_active: rgba(0xffffff28).into(),
+ filled_element_selected: rgba(0x1e2321ff).into(),
+ filled_element_disabled: rgba(0x00000000).into(),
+ ghost_element: rgba(0x00000000).into(),
+ ghost_element_hover: rgba(0xffffff14).into(),
+ ghost_element_active: rgba(0xffffff1e).into(),
+ ghost_element_selected: rgba(0x1e2321ff).into(),
+ ghost_element_disabled: rgba(0x00000000).into(),
+ text: rgba(0xfbf1c7ff).into(),
+ text_muted: rgba(0xc5b597ff).into(),
+ text_placeholder: rgba(0xfb4a35ff).into(),
+ text_disabled: rgba(0x998b78ff).into(),
+ text_accent: rgba(0x83a598ff).into(),
+ icon_muted: rgba(0xc5b597ff).into(),
+ syntax: SyntaxTheme {
+ highlights: vec![
+ ("operator".into(), rgba(0x8ec07cff).into()),
+ ("string.special.symbol".into(), rgba(0x8ec07cff).into()),
+ ("emphasis.strong".into(), rgba(0x83a598ff).into()),
+ ("attribute".into(), rgba(0x83a598ff).into()),
+ ("property".into(), rgba(0xebdbb2ff).into()),
+ ("comment.doc".into(), rgba(0xc6b697ff).into()),
+ ("emphasis".into(), rgba(0x83a598ff).into()),
+ ("variant".into(), rgba(0x83a598ff).into()),
+ ("text.literal".into(), rgba(0x83a598ff).into()),
+ ("keyword".into(), rgba(0xfb4833ff).into()),
+ ("primary".into(), rgba(0xebdbb2ff).into()),
+ ("variable".into(), rgba(0x83a598ff).into()),
+ ("enum".into(), rgba(0xfe7f18ff).into()),
+ ("constructor".into(), rgba(0x83a598ff).into()),
+ ("punctuation".into(), rgba(0xd5c4a1ff).into()),
+ ("link_uri".into(), rgba(0xd3869bff).into()),
+ ("hint".into(), rgba(0x8c957dff).into()),
+ ("string.regex".into(), rgba(0xfe7f18ff).into()),
+ ("punctuation.delimiter".into(), rgba(0xe5d5adff).into()),
+ ("string".into(), rgba(0xb8bb25ff).into()),
+ ("punctuation.special".into(), rgba(0xe5d5adff).into()),
+ ("link_text".into(), rgba(0x8ec07cff).into()),
+ ("tag".into(), rgba(0x8ec07cff).into()),
+ ("string.escape".into(), rgba(0xc6b697ff).into()),
+ ("label".into(), rgba(0x83a598ff).into()),
+ ("constant".into(), rgba(0xfabd2eff).into()),
+ ("type".into(), rgba(0xfabd2eff).into()),
+ ("number".into(), rgba(0xd3869bff).into()),
+ ("string.special".into(), rgba(0xd3869bff).into()),
+ ("function.builtin".into(), rgba(0xfb4833ff).into()),
+ ("boolean".into(), rgba(0xd3869bff).into()),
+ ("embedded".into(), rgba(0x8ec07cff).into()),
+ ("title".into(), rgba(0xb8bb25ff).into()),
+ ("function".into(), rgba(0xb8bb25ff).into()),
+ ("punctuation.bracket".into(), rgba(0xa89984ff).into()),
+ ("comment".into(), rgba(0xa89984ff).into()),
+ ("preproc".into(), rgba(0xfbf1c7ff).into()),
+ ("predictive".into(), rgba(0x717363ff).into()),
+ ("punctuation.list_marker".into(), rgba(0xebdbb2ff).into()),
+ ],
+ },
+ status_bar: rgba(0x4c4642ff).into(),
+ title_bar: rgba(0x4c4642ff).into(),
+ toolbar: rgba(0x282828ff).into(),
+ tab_bar: rgba(0x3a3735ff).into(),
+ editor: rgba(0x282828ff).into(),
+ editor_subheader: rgba(0x3a3735ff).into(),
+ editor_active_line: rgba(0x3a3735ff).into(),
+ terminal: rgba(0x282828ff).into(),
+ image_fallback_background: rgba(0x4c4642ff).into(),
+ git_created: rgba(0xb7bb26ff).into(),
+ git_modified: rgba(0x83a598ff).into(),
+ git_deleted: rgba(0xfb4a35ff).into(),
+ git_conflict: rgba(0xf9bd2fff).into(),
+ git_ignored: rgba(0x998b78ff).into(),
+ git_renamed: rgba(0xf9bd2fff).into(),
+ players: [
+ PlayerTheme {
+ cursor: rgba(0x83a598ff).into(),
+ selection: rgba(0x83a5983d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xb7bb26ff).into(),
+ selection: rgba(0xb7bb263d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xa89984ff).into(),
+ selection: rgba(0xa899843d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xfd801bff).into(),
+ selection: rgba(0xfd801b3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xd3869bff).into(),
+ selection: rgba(0xd3869b3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x8ec07cff).into(),
+ selection: rgba(0x8ec07c3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xfb4a35ff).into(),
+ selection: rgba(0xfb4a353d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xf9bd2fff).into(),
+ selection: rgba(0xf9bd2f3d).into(),
+ },
+ ],
+ }
+}
@@ -0,0 +1,131 @@
+use gpui2::rgba;
+
+use crate::{PlayerTheme, SyntaxTheme, Theme, ThemeMetadata};
+
+pub fn gruvbox_dark_hard() -> Theme {
+ Theme {
+ metadata: ThemeMetadata {
+ name: "Gruvbox Dark Hard".into(),
+ is_light: false,
+ },
+ transparent: rgba(0x00000000).into(),
+ mac_os_traffic_light_red: rgba(0xec695eff).into(),
+ mac_os_traffic_light_yellow: rgba(0xf4bf4eff).into(),
+ mac_os_traffic_light_green: rgba(0x61c553ff).into(),
+ border: rgba(0x5b534dff).into(),
+ border_variant: rgba(0x5b534dff).into(),
+ border_focused: rgba(0x303a36ff).into(),
+ border_transparent: rgba(0x00000000).into(),
+ elevated_surface: rgba(0x4c4642ff).into(),
+ surface: rgba(0x393634ff).into(),
+ background: rgba(0x4c4642ff).into(),
+ filled_element: rgba(0x4c4642ff).into(),
+ filled_element_hover: rgba(0xffffff1e).into(),
+ filled_element_active: rgba(0xffffff28).into(),
+ filled_element_selected: rgba(0x1e2321ff).into(),
+ filled_element_disabled: rgba(0x00000000).into(),
+ ghost_element: rgba(0x00000000).into(),
+ ghost_element_hover: rgba(0xffffff14).into(),
+ ghost_element_active: rgba(0xffffff1e).into(),
+ ghost_element_selected: rgba(0x1e2321ff).into(),
+ ghost_element_disabled: rgba(0x00000000).into(),
+ text: rgba(0xfbf1c7ff).into(),
+ text_muted: rgba(0xc5b597ff).into(),
+ text_placeholder: rgba(0xfb4a35ff).into(),
+ text_disabled: rgba(0x998b78ff).into(),
+ text_accent: rgba(0x83a598ff).into(),
+ icon_muted: rgba(0xc5b597ff).into(),
+ syntax: SyntaxTheme {
+ highlights: vec![
+ ("primary".into(), rgba(0xebdbb2ff).into()),
+ ("label".into(), rgba(0x83a598ff).into()),
+ ("punctuation.delimiter".into(), rgba(0xe5d5adff).into()),
+ ("variant".into(), rgba(0x83a598ff).into()),
+ ("type".into(), rgba(0xfabd2eff).into()),
+ ("string.regex".into(), rgba(0xfe7f18ff).into()),
+ ("function.builtin".into(), rgba(0xfb4833ff).into()),
+ ("title".into(), rgba(0xb8bb25ff).into()),
+ ("string".into(), rgba(0xb8bb25ff).into()),
+ ("operator".into(), rgba(0x8ec07cff).into()),
+ ("embedded".into(), rgba(0x8ec07cff).into()),
+ ("punctuation.bracket".into(), rgba(0xa89984ff).into()),
+ ("string.special".into(), rgba(0xd3869bff).into()),
+ ("attribute".into(), rgba(0x83a598ff).into()),
+ ("comment".into(), rgba(0xa89984ff).into()),
+ ("link_text".into(), rgba(0x8ec07cff).into()),
+ ("punctuation.special".into(), rgba(0xe5d5adff).into()),
+ ("punctuation.list_marker".into(), rgba(0xebdbb2ff).into()),
+ ("comment.doc".into(), rgba(0xc6b697ff).into()),
+ ("preproc".into(), rgba(0xfbf1c7ff).into()),
+ ("text.literal".into(), rgba(0x83a598ff).into()),
+ ("function".into(), rgba(0xb8bb25ff).into()),
+ ("predictive".into(), rgba(0x717363ff).into()),
+ ("emphasis.strong".into(), rgba(0x83a598ff).into()),
+ ("punctuation".into(), rgba(0xd5c4a1ff).into()),
+ ("string.special.symbol".into(), rgba(0x8ec07cff).into()),
+ ("property".into(), rgba(0xebdbb2ff).into()),
+ ("keyword".into(), rgba(0xfb4833ff).into()),
+ ("constructor".into(), rgba(0x83a598ff).into()),
+ ("tag".into(), rgba(0x8ec07cff).into()),
+ ("variable".into(), rgba(0x83a598ff).into()),
+ ("enum".into(), rgba(0xfe7f18ff).into()),
+ ("hint".into(), rgba(0x8c957dff).into()),
+ ("number".into(), rgba(0xd3869bff).into()),
+ ("constant".into(), rgba(0xfabd2eff).into()),
+ ("boolean".into(), rgba(0xd3869bff).into()),
+ ("link_uri".into(), rgba(0xd3869bff).into()),
+ ("string.escape".into(), rgba(0xc6b697ff).into()),
+ ("emphasis".into(), rgba(0x83a598ff).into()),
+ ],
+ },
+ status_bar: rgba(0x4c4642ff).into(),
+ title_bar: rgba(0x4c4642ff).into(),
+ toolbar: rgba(0x1d2021ff).into(),
+ tab_bar: rgba(0x393634ff).into(),
+ editor: rgba(0x1d2021ff).into(),
+ editor_subheader: rgba(0x393634ff).into(),
+ editor_active_line: rgba(0x393634ff).into(),
+ terminal: rgba(0x1d2021ff).into(),
+ image_fallback_background: rgba(0x4c4642ff).into(),
+ git_created: rgba(0xb7bb26ff).into(),
+ git_modified: rgba(0x83a598ff).into(),
+ git_deleted: rgba(0xfb4a35ff).into(),
+ git_conflict: rgba(0xf9bd2fff).into(),
+ git_ignored: rgba(0x998b78ff).into(),
+ git_renamed: rgba(0xf9bd2fff).into(),
+ players: [
+ PlayerTheme {
+ cursor: rgba(0x83a598ff).into(),
+ selection: rgba(0x83a5983d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xb7bb26ff).into(),
+ selection: rgba(0xb7bb263d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xa89984ff).into(),
+ selection: rgba(0xa899843d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xfd801bff).into(),
+ selection: rgba(0xfd801b3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xd3869bff).into(),
+ selection: rgba(0xd3869b3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x8ec07cff).into(),
+ selection: rgba(0x8ec07c3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xfb4a35ff).into(),
+ selection: rgba(0xfb4a353d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xf9bd2fff).into(),
+ selection: rgba(0xf9bd2f3d).into(),
+ },
+ ],
+ }
+}
@@ -0,0 +1,131 @@
+use gpui2::rgba;
+
+use crate::{PlayerTheme, SyntaxTheme, Theme, ThemeMetadata};
+
+pub fn gruvbox_dark_soft() -> Theme {
+ Theme {
+ metadata: ThemeMetadata {
+ name: "Gruvbox Dark Soft".into(),
+ is_light: false,
+ },
+ transparent: rgba(0x00000000).into(),
+ mac_os_traffic_light_red: rgba(0xec695eff).into(),
+ mac_os_traffic_light_yellow: rgba(0xf4bf4eff).into(),
+ mac_os_traffic_light_green: rgba(0x61c553ff).into(),
+ border: rgba(0x5b534dff).into(),
+ border_variant: rgba(0x5b534dff).into(),
+ border_focused: rgba(0x303a36ff).into(),
+ border_transparent: rgba(0x00000000).into(),
+ elevated_surface: rgba(0x4c4642ff).into(),
+ surface: rgba(0x3b3735ff).into(),
+ background: rgba(0x4c4642ff).into(),
+ filled_element: rgba(0x4c4642ff).into(),
+ filled_element_hover: rgba(0xffffff1e).into(),
+ filled_element_active: rgba(0xffffff28).into(),
+ filled_element_selected: rgba(0x1e2321ff).into(),
+ filled_element_disabled: rgba(0x00000000).into(),
+ ghost_element: rgba(0x00000000).into(),
+ ghost_element_hover: rgba(0xffffff14).into(),
+ ghost_element_active: rgba(0xffffff1e).into(),
+ ghost_element_selected: rgba(0x1e2321ff).into(),
+ ghost_element_disabled: rgba(0x00000000).into(),
+ text: rgba(0xfbf1c7ff).into(),
+ text_muted: rgba(0xc5b597ff).into(),
+ text_placeholder: rgba(0xfb4a35ff).into(),
+ text_disabled: rgba(0x998b78ff).into(),
+ text_accent: rgba(0x83a598ff).into(),
+ icon_muted: rgba(0xc5b597ff).into(),
+ syntax: SyntaxTheme {
+ highlights: vec![
+ ("punctuation.special".into(), rgba(0xe5d5adff).into()),
+ ("attribute".into(), rgba(0x83a598ff).into()),
+ ("preproc".into(), rgba(0xfbf1c7ff).into()),
+ ("keyword".into(), rgba(0xfb4833ff).into()),
+ ("emphasis".into(), rgba(0x83a598ff).into()),
+ ("punctuation.delimiter".into(), rgba(0xe5d5adff).into()),
+ ("punctuation.bracket".into(), rgba(0xa89984ff).into()),
+ ("comment".into(), rgba(0xa89984ff).into()),
+ ("text.literal".into(), rgba(0x83a598ff).into()),
+ ("predictive".into(), rgba(0x717363ff).into()),
+ ("link_text".into(), rgba(0x8ec07cff).into()),
+ ("variant".into(), rgba(0x83a598ff).into()),
+ ("label".into(), rgba(0x83a598ff).into()),
+ ("function".into(), rgba(0xb8bb25ff).into()),
+ ("string.regex".into(), rgba(0xfe7f18ff).into()),
+ ("boolean".into(), rgba(0xd3869bff).into()),
+ ("number".into(), rgba(0xd3869bff).into()),
+ ("string.escape".into(), rgba(0xc6b697ff).into()),
+ ("constructor".into(), rgba(0x83a598ff).into()),
+ ("link_uri".into(), rgba(0xd3869bff).into()),
+ ("string.special.symbol".into(), rgba(0x8ec07cff).into()),
+ ("type".into(), rgba(0xfabd2eff).into()),
+ ("function.builtin".into(), rgba(0xfb4833ff).into()),
+ ("title".into(), rgba(0xb8bb25ff).into()),
+ ("primary".into(), rgba(0xebdbb2ff).into()),
+ ("tag".into(), rgba(0x8ec07cff).into()),
+ ("constant".into(), rgba(0xfabd2eff).into()),
+ ("emphasis.strong".into(), rgba(0x83a598ff).into()),
+ ("string.special".into(), rgba(0xd3869bff).into()),
+ ("hint".into(), rgba(0x8c957dff).into()),
+ ("comment.doc".into(), rgba(0xc6b697ff).into()),
+ ("property".into(), rgba(0xebdbb2ff).into()),
+ ("embedded".into(), rgba(0x8ec07cff).into()),
+ ("operator".into(), rgba(0x8ec07cff).into()),
+ ("punctuation".into(), rgba(0xd5c4a1ff).into()),
+ ("variable".into(), rgba(0x83a598ff).into()),
+ ("enum".into(), rgba(0xfe7f18ff).into()),
+ ("punctuation.list_marker".into(), rgba(0xebdbb2ff).into()),
+ ("string".into(), rgba(0xb8bb25ff).into()),
+ ],
+ },
+ status_bar: rgba(0x4c4642ff).into(),
+ title_bar: rgba(0x4c4642ff).into(),
+ toolbar: rgba(0x32302fff).into(),
+ tab_bar: rgba(0x3b3735ff).into(),
+ editor: rgba(0x32302fff).into(),
+ editor_subheader: rgba(0x3b3735ff).into(),
+ editor_active_line: rgba(0x3b3735ff).into(),
+ terminal: rgba(0x32302fff).into(),
+ image_fallback_background: rgba(0x4c4642ff).into(),
+ git_created: rgba(0xb7bb26ff).into(),
+ git_modified: rgba(0x83a598ff).into(),
+ git_deleted: rgba(0xfb4a35ff).into(),
+ git_conflict: rgba(0xf9bd2fff).into(),
+ git_ignored: rgba(0x998b78ff).into(),
+ git_renamed: rgba(0xf9bd2fff).into(),
+ players: [
+ PlayerTheme {
+ cursor: rgba(0x83a598ff).into(),
+ selection: rgba(0x83a5983d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xb7bb26ff).into(),
+ selection: rgba(0xb7bb263d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xa89984ff).into(),
+ selection: rgba(0xa899843d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xfd801bff).into(),
+ selection: rgba(0xfd801b3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xd3869bff).into(),
+ selection: rgba(0xd3869b3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x8ec07cff).into(),
+ selection: rgba(0x8ec07c3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xfb4a35ff).into(),
+ selection: rgba(0xfb4a353d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xf9bd2fff).into(),
+ selection: rgba(0xf9bd2f3d).into(),
+ },
+ ],
+ }
+}
@@ -0,0 +1,131 @@
+use gpui2::rgba;
+
+use crate::{PlayerTheme, SyntaxTheme, Theme, ThemeMetadata};
+
+pub fn gruvbox_light() -> Theme {
+ Theme {
+ metadata: ThemeMetadata {
+ name: "Gruvbox Light".into(),
+ is_light: true,
+ },
+ transparent: rgba(0x00000000).into(),
+ mac_os_traffic_light_red: rgba(0xec695eff).into(),
+ mac_os_traffic_light_yellow: rgba(0xf4bf4eff).into(),
+ mac_os_traffic_light_green: rgba(0x61c553ff).into(),
+ border: rgba(0xc8b899ff).into(),
+ border_variant: rgba(0xc8b899ff).into(),
+ border_focused: rgba(0xadc5ccff).into(),
+ border_transparent: rgba(0x00000000).into(),
+ elevated_surface: rgba(0xd9c8a4ff).into(),
+ surface: rgba(0xecddb4ff).into(),
+ background: rgba(0xd9c8a4ff).into(),
+ filled_element: rgba(0xd9c8a4ff).into(),
+ filled_element_hover: rgba(0xffffff1e).into(),
+ filled_element_active: rgba(0xffffff28).into(),
+ filled_element_selected: rgba(0xd2dee2ff).into(),
+ filled_element_disabled: rgba(0x00000000).into(),
+ ghost_element: rgba(0x00000000).into(),
+ ghost_element_hover: rgba(0xffffff14).into(),
+ ghost_element_active: rgba(0xffffff1e).into(),
+ ghost_element_selected: rgba(0xd2dee2ff).into(),
+ ghost_element_disabled: rgba(0x00000000).into(),
+ text: rgba(0x282828ff).into(),
+ text_muted: rgba(0x5f5650ff).into(),
+ text_placeholder: rgba(0x9d0308ff).into(),
+ text_disabled: rgba(0x897b6eff).into(),
+ text_accent: rgba(0x0b6678ff).into(),
+ icon_muted: rgba(0x5f5650ff).into(),
+ syntax: SyntaxTheme {
+ highlights: vec![
+ ("number".into(), rgba(0x8f3e71ff).into()),
+ ("link_text".into(), rgba(0x427b58ff).into()),
+ ("string.special".into(), rgba(0x8f3e71ff).into()),
+ ("string.special.symbol".into(), rgba(0x427b58ff).into()),
+ ("function".into(), rgba(0x79740eff).into()),
+ ("title".into(), rgba(0x79740eff).into()),
+ ("emphasis".into(), rgba(0x0b6678ff).into()),
+ ("punctuation".into(), rgba(0x3c3836ff).into()),
+ ("string.escape".into(), rgba(0x5d544eff).into()),
+ ("type".into(), rgba(0xb57613ff).into()),
+ ("string".into(), rgba(0x79740eff).into()),
+ ("keyword".into(), rgba(0x9d0006ff).into()),
+ ("tag".into(), rgba(0x427b58ff).into()),
+ ("primary".into(), rgba(0x282828ff).into()),
+ ("link_uri".into(), rgba(0x8f3e71ff).into()),
+ ("comment.doc".into(), rgba(0x5d544eff).into()),
+ ("boolean".into(), rgba(0x8f3e71ff).into()),
+ ("embedded".into(), rgba(0x427b58ff).into()),
+ ("hint".into(), rgba(0x677562ff).into()),
+ ("emphasis.strong".into(), rgba(0x0b6678ff).into()),
+ ("operator".into(), rgba(0x427b58ff).into()),
+ ("label".into(), rgba(0x0b6678ff).into()),
+ ("comment".into(), rgba(0x7c6f64ff).into()),
+ ("function.builtin".into(), rgba(0x9d0006ff).into()),
+ ("punctuation.bracket".into(), rgba(0x665c54ff).into()),
+ ("text.literal".into(), rgba(0x066578ff).into()),
+ ("string.regex".into(), rgba(0xaf3a02ff).into()),
+ ("property".into(), rgba(0x282828ff).into()),
+ ("attribute".into(), rgba(0x0b6678ff).into()),
+ ("punctuation.delimiter".into(), rgba(0x413d3aff).into()),
+ ("constructor".into(), rgba(0x0b6678ff).into()),
+ ("variable".into(), rgba(0x066578ff).into()),
+ ("constant".into(), rgba(0xb57613ff).into()),
+ ("preproc".into(), rgba(0x282828ff).into()),
+ ("punctuation.special".into(), rgba(0x413d3aff).into()),
+ ("punctuation.list_marker".into(), rgba(0x282828ff).into()),
+ ("variant".into(), rgba(0x0b6678ff).into()),
+ ("predictive".into(), rgba(0x7c9780ff).into()),
+ ("enum".into(), rgba(0xaf3a02ff).into()),
+ ],
+ },
+ status_bar: rgba(0xd9c8a4ff).into(),
+ title_bar: rgba(0xd9c8a4ff).into(),
+ toolbar: rgba(0xfbf1c7ff).into(),
+ tab_bar: rgba(0xecddb4ff).into(),
+ editor: rgba(0xfbf1c7ff).into(),
+ editor_subheader: rgba(0xecddb4ff).into(),
+ editor_active_line: rgba(0xecddb4ff).into(),
+ terminal: rgba(0xfbf1c7ff).into(),
+ image_fallback_background: rgba(0xd9c8a4ff).into(),
+ git_created: rgba(0x797410ff).into(),
+ git_modified: rgba(0x0b6678ff).into(),
+ git_deleted: rgba(0x9d0308ff).into(),
+ git_conflict: rgba(0xb57615ff).into(),
+ git_ignored: rgba(0x897b6eff).into(),
+ git_renamed: rgba(0xb57615ff).into(),
+ players: [
+ PlayerTheme {
+ cursor: rgba(0x0b6678ff).into(),
+ selection: rgba(0x0b66783d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x797410ff).into(),
+ selection: rgba(0x7974103d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x7c6f64ff).into(),
+ selection: rgba(0x7c6f643d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xaf3a04ff).into(),
+ selection: rgba(0xaf3a043d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x8f3f70ff).into(),
+ selection: rgba(0x8f3f703d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x437b59ff).into(),
+ selection: rgba(0x437b593d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x9d0308ff).into(),
+ selection: rgba(0x9d03083d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xb57615ff).into(),
+ selection: rgba(0xb576153d).into(),
+ },
+ ],
+ }
+}
@@ -0,0 +1,131 @@
+use gpui2::rgba;
+
+use crate::{PlayerTheme, SyntaxTheme, Theme, ThemeMetadata};
+
+pub fn gruvbox_light_hard() -> Theme {
+ Theme {
+ metadata: ThemeMetadata {
+ name: "Gruvbox Light Hard".into(),
+ is_light: true,
+ },
+ transparent: rgba(0x00000000).into(),
+ mac_os_traffic_light_red: rgba(0xec695eff).into(),
+ mac_os_traffic_light_yellow: rgba(0xf4bf4eff).into(),
+ mac_os_traffic_light_green: rgba(0x61c553ff).into(),
+ border: rgba(0xc8b899ff).into(),
+ border_variant: rgba(0xc8b899ff).into(),
+ border_focused: rgba(0xadc5ccff).into(),
+ border_transparent: rgba(0x00000000).into(),
+ elevated_surface: rgba(0xd9c8a4ff).into(),
+ surface: rgba(0xecddb5ff).into(),
+ background: rgba(0xd9c8a4ff).into(),
+ filled_element: rgba(0xd9c8a4ff).into(),
+ filled_element_hover: rgba(0xffffff1e).into(),
+ filled_element_active: rgba(0xffffff28).into(),
+ filled_element_selected: rgba(0xd2dee2ff).into(),
+ filled_element_disabled: rgba(0x00000000).into(),
+ ghost_element: rgba(0x00000000).into(),
+ ghost_element_hover: rgba(0xffffff14).into(),
+ ghost_element_active: rgba(0xffffff1e).into(),
+ ghost_element_selected: rgba(0xd2dee2ff).into(),
+ ghost_element_disabled: rgba(0x00000000).into(),
+ text: rgba(0x282828ff).into(),
+ text_muted: rgba(0x5f5650ff).into(),
+ text_placeholder: rgba(0x9d0308ff).into(),
+ text_disabled: rgba(0x897b6eff).into(),
+ text_accent: rgba(0x0b6678ff).into(),
+ icon_muted: rgba(0x5f5650ff).into(),
+ syntax: SyntaxTheme {
+ highlights: vec![
+ ("label".into(), rgba(0x0b6678ff).into()),
+ ("hint".into(), rgba(0x677562ff).into()),
+ ("boolean".into(), rgba(0x8f3e71ff).into()),
+ ("function.builtin".into(), rgba(0x9d0006ff).into()),
+ ("constant".into(), rgba(0xb57613ff).into()),
+ ("preproc".into(), rgba(0x282828ff).into()),
+ ("predictive".into(), rgba(0x7c9780ff).into()),
+ ("string".into(), rgba(0x79740eff).into()),
+ ("comment.doc".into(), rgba(0x5d544eff).into()),
+ ("function".into(), rgba(0x79740eff).into()),
+ ("title".into(), rgba(0x79740eff).into()),
+ ("text.literal".into(), rgba(0x066578ff).into()),
+ ("punctuation.bracket".into(), rgba(0x665c54ff).into()),
+ ("string.escape".into(), rgba(0x5d544eff).into()),
+ ("punctuation.delimiter".into(), rgba(0x413d3aff).into()),
+ ("string.special.symbol".into(), rgba(0x427b58ff).into()),
+ ("type".into(), rgba(0xb57613ff).into()),
+ ("constructor".into(), rgba(0x0b6678ff).into()),
+ ("property".into(), rgba(0x282828ff).into()),
+ ("comment".into(), rgba(0x7c6f64ff).into()),
+ ("enum".into(), rgba(0xaf3a02ff).into()),
+ ("emphasis".into(), rgba(0x0b6678ff).into()),
+ ("embedded".into(), rgba(0x427b58ff).into()),
+ ("operator".into(), rgba(0x427b58ff).into()),
+ ("attribute".into(), rgba(0x0b6678ff).into()),
+ ("emphasis.strong".into(), rgba(0x0b6678ff).into()),
+ ("link_text".into(), rgba(0x427b58ff).into()),
+ ("punctuation.special".into(), rgba(0x413d3aff).into()),
+ ("punctuation.list_marker".into(), rgba(0x282828ff).into()),
+ ("variant".into(), rgba(0x0b6678ff).into()),
+ ("primary".into(), rgba(0x282828ff).into()),
+ ("number".into(), rgba(0x8f3e71ff).into()),
+ ("tag".into(), rgba(0x427b58ff).into()),
+ ("keyword".into(), rgba(0x9d0006ff).into()),
+ ("link_uri".into(), rgba(0x8f3e71ff).into()),
+ ("string.regex".into(), rgba(0xaf3a02ff).into()),
+ ("variable".into(), rgba(0x066578ff).into()),
+ ("string.special".into(), rgba(0x8f3e71ff).into()),
+ ("punctuation".into(), rgba(0x3c3836ff).into()),
+ ],
+ },
+ status_bar: rgba(0xd9c8a4ff).into(),
+ title_bar: rgba(0xd9c8a4ff).into(),
+ toolbar: rgba(0xf9f5d7ff).into(),
+ tab_bar: rgba(0xecddb5ff).into(),
+ editor: rgba(0xf9f5d7ff).into(),
+ editor_subheader: rgba(0xecddb5ff).into(),
+ editor_active_line: rgba(0xecddb5ff).into(),
+ terminal: rgba(0xf9f5d7ff).into(),
+ image_fallback_background: rgba(0xd9c8a4ff).into(),
+ git_created: rgba(0x797410ff).into(),
+ git_modified: rgba(0x0b6678ff).into(),
+ git_deleted: rgba(0x9d0308ff).into(),
+ git_conflict: rgba(0xb57615ff).into(),
+ git_ignored: rgba(0x897b6eff).into(),
+ git_renamed: rgba(0xb57615ff).into(),
+ players: [
+ PlayerTheme {
+ cursor: rgba(0x0b6678ff).into(),
+ selection: rgba(0x0b66783d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x797410ff).into(),
+ selection: rgba(0x7974103d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x7c6f64ff).into(),
+ selection: rgba(0x7c6f643d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xaf3a04ff).into(),
+ selection: rgba(0xaf3a043d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x8f3f70ff).into(),
+ selection: rgba(0x8f3f703d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x437b59ff).into(),
+ selection: rgba(0x437b593d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x9d0308ff).into(),
+ selection: rgba(0x9d03083d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xb57615ff).into(),
+ selection: rgba(0xb576153d).into(),
+ },
+ ],
+ }
+}
@@ -0,0 +1,131 @@
+use gpui2::rgba;
+
+use crate::{PlayerTheme, SyntaxTheme, Theme, ThemeMetadata};
+
+pub fn gruvbox_light_soft() -> Theme {
+ Theme {
+ metadata: ThemeMetadata {
+ name: "Gruvbox Light Soft".into(),
+ is_light: true,
+ },
+ transparent: rgba(0x00000000).into(),
+ mac_os_traffic_light_red: rgba(0xec695eff).into(),
+ mac_os_traffic_light_yellow: rgba(0xf4bf4eff).into(),
+ mac_os_traffic_light_green: rgba(0x61c553ff).into(),
+ border: rgba(0xc8b899ff).into(),
+ border_variant: rgba(0xc8b899ff).into(),
+ border_focused: rgba(0xadc5ccff).into(),
+ border_transparent: rgba(0x00000000).into(),
+ elevated_surface: rgba(0xd9c8a4ff).into(),
+ surface: rgba(0xecdcb3ff).into(),
+ background: rgba(0xd9c8a4ff).into(),
+ filled_element: rgba(0xd9c8a4ff).into(),
+ filled_element_hover: rgba(0xffffff1e).into(),
+ filled_element_active: rgba(0xffffff28).into(),
+ filled_element_selected: rgba(0xd2dee2ff).into(),
+ filled_element_disabled: rgba(0x00000000).into(),
+ ghost_element: rgba(0x00000000).into(),
+ ghost_element_hover: rgba(0xffffff14).into(),
+ ghost_element_active: rgba(0xffffff1e).into(),
+ ghost_element_selected: rgba(0xd2dee2ff).into(),
+ ghost_element_disabled: rgba(0x00000000).into(),
+ text: rgba(0x282828ff).into(),
+ text_muted: rgba(0x5f5650ff).into(),
+ text_placeholder: rgba(0x9d0308ff).into(),
+ text_disabled: rgba(0x897b6eff).into(),
+ text_accent: rgba(0x0b6678ff).into(),
+ icon_muted: rgba(0x5f5650ff).into(),
+ syntax: SyntaxTheme {
+ highlights: vec![
+ ("preproc".into(), rgba(0x282828ff).into()),
+ ("punctuation.list_marker".into(), rgba(0x282828ff).into()),
+ ("string".into(), rgba(0x79740eff).into()),
+ ("constant".into(), rgba(0xb57613ff).into()),
+ ("keyword".into(), rgba(0x9d0006ff).into()),
+ ("string.special.symbol".into(), rgba(0x427b58ff).into()),
+ ("comment.doc".into(), rgba(0x5d544eff).into()),
+ ("hint".into(), rgba(0x677562ff).into()),
+ ("number".into(), rgba(0x8f3e71ff).into()),
+ ("enum".into(), rgba(0xaf3a02ff).into()),
+ ("emphasis".into(), rgba(0x0b6678ff).into()),
+ ("operator".into(), rgba(0x427b58ff).into()),
+ ("comment".into(), rgba(0x7c6f64ff).into()),
+ ("embedded".into(), rgba(0x427b58ff).into()),
+ ("type".into(), rgba(0xb57613ff).into()),
+ ("title".into(), rgba(0x79740eff).into()),
+ ("constructor".into(), rgba(0x0b6678ff).into()),
+ ("punctuation.delimiter".into(), rgba(0x413d3aff).into()),
+ ("function".into(), rgba(0x79740eff).into()),
+ ("link_uri".into(), rgba(0x8f3e71ff).into()),
+ ("emphasis.strong".into(), rgba(0x0b6678ff).into()),
+ ("boolean".into(), rgba(0x8f3e71ff).into()),
+ ("function.builtin".into(), rgba(0x9d0006ff).into()),
+ ("predictive".into(), rgba(0x7c9780ff).into()),
+ ("string.regex".into(), rgba(0xaf3a02ff).into()),
+ ("tag".into(), rgba(0x427b58ff).into()),
+ ("text.literal".into(), rgba(0x066578ff).into()),
+ ("punctuation".into(), rgba(0x3c3836ff).into()),
+ ("punctuation.bracket".into(), rgba(0x665c54ff).into()),
+ ("variable".into(), rgba(0x066578ff).into()),
+ ("attribute".into(), rgba(0x0b6678ff).into()),
+ ("string.special".into(), rgba(0x8f3e71ff).into()),
+ ("label".into(), rgba(0x0b6678ff).into()),
+ ("string.escape".into(), rgba(0x5d544eff).into()),
+ ("link_text".into(), rgba(0x427b58ff).into()),
+ ("punctuation.special".into(), rgba(0x413d3aff).into()),
+ ("property".into(), rgba(0x282828ff).into()),
+ ("variant".into(), rgba(0x0b6678ff).into()),
+ ("primary".into(), rgba(0x282828ff).into()),
+ ],
+ },
+ status_bar: rgba(0xd9c8a4ff).into(),
+ title_bar: rgba(0xd9c8a4ff).into(),
+ toolbar: rgba(0xf2e5bcff).into(),
+ tab_bar: rgba(0xecdcb3ff).into(),
+ editor: rgba(0xf2e5bcff).into(),
+ editor_subheader: rgba(0xecdcb3ff).into(),
+ editor_active_line: rgba(0xecdcb3ff).into(),
+ terminal: rgba(0xf2e5bcff).into(),
+ image_fallback_background: rgba(0xd9c8a4ff).into(),
+ git_created: rgba(0x797410ff).into(),
+ git_modified: rgba(0x0b6678ff).into(),
+ git_deleted: rgba(0x9d0308ff).into(),
+ git_conflict: rgba(0xb57615ff).into(),
+ git_ignored: rgba(0x897b6eff).into(),
+ git_renamed: rgba(0xb57615ff).into(),
+ players: [
+ PlayerTheme {
+ cursor: rgba(0x0b6678ff).into(),
+ selection: rgba(0x0b66783d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x797410ff).into(),
+ selection: rgba(0x7974103d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x7c6f64ff).into(),
+ selection: rgba(0x7c6f643d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xaf3a04ff).into(),
+ selection: rgba(0xaf3a043d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x8f3f70ff).into(),
+ selection: rgba(0x8f3f703d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x437b59ff).into(),
+ selection: rgba(0x437b593d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x9d0308ff).into(),
+ selection: rgba(0x9d03083d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xb57615ff).into(),
+ selection: rgba(0xb576153d).into(),
+ },
+ ],
+ }
+}
@@ -1,7 +1,79 @@
+mod andromeda;
+mod atelier_cave_dark;
+mod atelier_cave_light;
+mod atelier_dune_dark;
+mod atelier_dune_light;
+mod atelier_estuary_dark;
+mod atelier_estuary_light;
+mod atelier_forest_dark;
+mod atelier_forest_light;
+mod atelier_heath_dark;
+mod atelier_heath_light;
+mod atelier_lakeside_dark;
+mod atelier_lakeside_light;
+mod atelier_plateau_dark;
+mod atelier_plateau_light;
+mod atelier_savanna_dark;
+mod atelier_savanna_light;
+mod atelier_seaside_dark;
+mod atelier_seaside_light;
+mod atelier_sulphurpool_dark;
+mod atelier_sulphurpool_light;
+mod ayu_dark;
+mod ayu_light;
+mod ayu_mirage;
+mod gruvbox_dark;
+mod gruvbox_dark_hard;
+mod gruvbox_dark_soft;
+mod gruvbox_light;
+mod gruvbox_light_hard;
+mod gruvbox_light_soft;
mod one_dark;
+mod one_light;
mod rose_pine;
+mod rose_pine_dawn;
+mod rose_pine_moon;
mod sandcastle;
+mod solarized_dark;
+mod solarized_light;
+mod summercamp;
+pub use andromeda::*;
+pub use atelier_cave_dark::*;
+pub use atelier_cave_light::*;
+pub use atelier_dune_dark::*;
+pub use atelier_dune_light::*;
+pub use atelier_estuary_dark::*;
+pub use atelier_estuary_light::*;
+pub use atelier_forest_dark::*;
+pub use atelier_forest_light::*;
+pub use atelier_heath_dark::*;
+pub use atelier_heath_light::*;
+pub use atelier_lakeside_dark::*;
+pub use atelier_lakeside_light::*;
+pub use atelier_plateau_dark::*;
+pub use atelier_plateau_light::*;
+pub use atelier_savanna_dark::*;
+pub use atelier_savanna_light::*;
+pub use atelier_seaside_dark::*;
+pub use atelier_seaside_light::*;
+pub use atelier_sulphurpool_dark::*;
+pub use atelier_sulphurpool_light::*;
+pub use ayu_dark::*;
+pub use ayu_light::*;
+pub use ayu_mirage::*;
+pub use gruvbox_dark::*;
+pub use gruvbox_dark_hard::*;
+pub use gruvbox_dark_soft::*;
+pub use gruvbox_light::*;
+pub use gruvbox_light_hard::*;
+pub use gruvbox_light_soft::*;
pub use one_dark::*;
+pub use one_light::*;
pub use rose_pine::*;
+pub use rose_pine_dawn::*;
+pub use rose_pine_moon::*;
pub use sandcastle::*;
+pub use solarized_dark::*;
+pub use solarized_light::*;
+pub use summercamp::*;
@@ -37,45 +37,45 @@ pub fn one_dark() -> Theme {
icon_muted: rgba(0x838994ff).into(),
syntax: SyntaxTheme {
highlights: vec![
- ("link_uri".into(), rgba(0x6eb4bfff).into()),
- ("number".into(), rgba(0xbf956aff).into()),
- ("property".into(), rgba(0xd07277ff).into()),
- ("boolean".into(), rgba(0xbf956aff).into()),
- ("label".into(), rgba(0x74ade8ff).into()),
- ("punctuation.list_marker".into(), rgba(0xd07277ff).into()),
("keyword".into(), rgba(0xb477cfff).into()),
- ("punctuation.delimiter".into(), rgba(0xb2b9c6ff).into()),
- ("string.special".into(), rgba(0xbf956aff).into()),
- ("constant".into(), rgba(0xdfc184ff).into()),
- ("punctuation".into(), rgba(0xacb2beff).into()),
- ("variable.special".into(), rgba(0xbf956aff).into()),
- ("preproc".into(), rgba(0xc8ccd4ff).into()),
- ("enum".into(), rgba(0xd07277ff).into()),
- ("attribute".into(), rgba(0x74ade8ff).into()),
- ("emphasis.strong".into(), rgba(0xbf956aff).into()),
- ("title".into(), rgba(0xd07277ff).into()),
- ("hint".into(), rgba(0x5a6f89ff).into()),
- ("emphasis".into(), rgba(0x74ade8ff).into()),
- ("string.regex".into(), rgba(0xbf956aff).into()),
- ("link_text".into(), rgba(0x73ade9ff).into()),
- ("string".into(), rgba(0xa1c181ff).into()),
("comment.doc".into(), rgba(0x878e98ff).into()),
- ("punctuation.special".into(), rgba(0xb1574bff).into()),
- ("primary".into(), rgba(0xacb2beff).into()),
- ("operator".into(), rgba(0x6eb4bfff).into()),
+ ("variant".into(), rgba(0x73ade9ff).into()),
+ ("property".into(), rgba(0xd07277ff).into()),
("function".into(), rgba(0x73ade9ff).into()),
- ("string.special.symbol".into(), rgba(0xbf956aff).into()),
("type".into(), rgba(0x6eb4bfff).into()),
- ("variant".into(), rgba(0x73ade9ff).into()),
("tag".into(), rgba(0x74ade8ff).into()),
- ("punctuation.bracket".into(), rgba(0xb2b9c6ff).into()),
- ("embedded".into(), rgba(0xc8ccd4ff).into()),
("string.escape".into(), rgba(0x878e98ff).into()),
- ("variable".into(), rgba(0xc8ccd4ff).into()),
- ("predictive".into(), rgba(0x5a6a87ff).into()),
+ ("punctuation.bracket".into(), rgba(0xb2b9c6ff).into()),
+ ("hint".into(), rgba(0x5a6f89ff).into()),
+ ("punctuation".into(), rgba(0xacb2beff).into()),
("comment".into(), rgba(0x5d636fff).into()),
- ("text.literal".into(), rgba(0xa1c181ff).into()),
+ ("emphasis".into(), rgba(0x74ade8ff).into()),
+ ("punctuation.special".into(), rgba(0xb1574bff).into()),
+ ("link_uri".into(), rgba(0x6eb4bfff).into()),
+ ("string.regex".into(), rgba(0xbf956aff).into()),
("constructor".into(), rgba(0x73ade9ff).into()),
+ ("operator".into(), rgba(0x6eb4bfff).into()),
+ ("constant".into(), rgba(0xdfc184ff).into()),
+ ("string.special".into(), rgba(0xbf956aff).into()),
+ ("emphasis.strong".into(), rgba(0xbf956aff).into()),
+ ("string.special.symbol".into(), rgba(0xbf956aff).into()),
+ ("primary".into(), rgba(0xacb2beff).into()),
+ ("preproc".into(), rgba(0xc8ccd4ff).into()),
+ ("string".into(), rgba(0xa1c181ff).into()),
+ ("punctuation.delimiter".into(), rgba(0xb2b9c6ff).into()),
+ ("embedded".into(), rgba(0xc8ccd4ff).into()),
+ ("enum".into(), rgba(0xd07277ff).into()),
+ ("variable.special".into(), rgba(0xbf956aff).into()),
+ ("text.literal".into(), rgba(0xa1c181ff).into()),
+ ("attribute".into(), rgba(0x74ade8ff).into()),
+ ("link_text".into(), rgba(0x73ade9ff).into()),
+ ("title".into(), rgba(0xd07277ff).into()),
+ ("predictive".into(), rgba(0x5a6a87ff).into()),
+ ("number".into(), rgba(0xbf956aff).into()),
+ ("label".into(), rgba(0x74ade8ff).into()),
+ ("variable".into(), rgba(0xc8ccd4ff).into()),
+ ("boolean".into(), rgba(0xbf956aff).into()),
+ ("punctuation.list_marker".into(), rgba(0xd07277ff).into()),
],
},
status_bar: rgba(0x3b414dff).into(),
@@ -0,0 +1,131 @@
+use gpui2::rgba;
+
+use crate::{PlayerTheme, SyntaxTheme, Theme, ThemeMetadata};
+
+pub fn one_light() -> Theme {
+ Theme {
+ metadata: ThemeMetadata {
+ name: "One Light".into(),
+ is_light: true,
+ },
+ transparent: rgba(0x00000000).into(),
+ mac_os_traffic_light_red: rgba(0xec695eff).into(),
+ mac_os_traffic_light_yellow: rgba(0xf4bf4eff).into(),
+ mac_os_traffic_light_green: rgba(0x61c553ff).into(),
+ border: rgba(0xc9c9caff).into(),
+ border_variant: rgba(0xc9c9caff).into(),
+ border_focused: rgba(0xcbcdf6ff).into(),
+ border_transparent: rgba(0x00000000).into(),
+ elevated_surface: rgba(0xdcdcddff).into(),
+ surface: rgba(0xebebecff).into(),
+ background: rgba(0xdcdcddff).into(),
+ filled_element: rgba(0xdcdcddff).into(),
+ filled_element_hover: rgba(0xffffff1e).into(),
+ filled_element_active: rgba(0xffffff28).into(),
+ filled_element_selected: rgba(0xe2e2faff).into(),
+ filled_element_disabled: rgba(0x00000000).into(),
+ ghost_element: rgba(0x00000000).into(),
+ ghost_element_hover: rgba(0xffffff14).into(),
+ ghost_element_active: rgba(0xffffff1e).into(),
+ ghost_element_selected: rgba(0xe2e2faff).into(),
+ ghost_element_disabled: rgba(0x00000000).into(),
+ text: rgba(0x383a41ff).into(),
+ text_muted: rgba(0x7e8087ff).into(),
+ text_placeholder: rgba(0xd36151ff).into(),
+ text_disabled: rgba(0xa1a1a3ff).into(),
+ text_accent: rgba(0x5c78e2ff).into(),
+ icon_muted: rgba(0x7e8087ff).into(),
+ syntax: SyntaxTheme {
+ highlights: vec![
+ ("string.special.symbol".into(), rgba(0xad6e26ff).into()),
+ ("hint".into(), rgba(0x9294beff).into()),
+ ("link_uri".into(), rgba(0x3882b7ff).into()),
+ ("type".into(), rgba(0x3882b7ff).into()),
+ ("string.regex".into(), rgba(0xad6e26ff).into()),
+ ("constant".into(), rgba(0x669f59ff).into()),
+ ("function".into(), rgba(0x5b79e3ff).into()),
+ ("string.special".into(), rgba(0xad6e26ff).into()),
+ ("punctuation.bracket".into(), rgba(0x4d4f52ff).into()),
+ ("variable".into(), rgba(0x383a41ff).into()),
+ ("punctuation".into(), rgba(0x383a41ff).into()),
+ ("property".into(), rgba(0xd3604fff).into()),
+ ("string".into(), rgba(0x649f57ff).into()),
+ ("predictive".into(), rgba(0x9b9ec6ff).into()),
+ ("attribute".into(), rgba(0x5c78e2ff).into()),
+ ("number".into(), rgba(0xad6e25ff).into()),
+ ("constructor".into(), rgba(0x5c78e2ff).into()),
+ ("embedded".into(), rgba(0x383a41ff).into()),
+ ("title".into(), rgba(0xd3604fff).into()),
+ ("tag".into(), rgba(0x5c78e2ff).into()),
+ ("boolean".into(), rgba(0xad6e25ff).into()),
+ ("punctuation.list_marker".into(), rgba(0xd3604fff).into()),
+ ("variant".into(), rgba(0x5b79e3ff).into()),
+ ("emphasis".into(), rgba(0x5c78e2ff).into()),
+ ("link_text".into(), rgba(0x5b79e3ff).into()),
+ ("comment".into(), rgba(0xa2a3a7ff).into()),
+ ("punctuation.special".into(), rgba(0xb92b46ff).into()),
+ ("emphasis.strong".into(), rgba(0xad6e25ff).into()),
+ ("primary".into(), rgba(0x383a41ff).into()),
+ ("punctuation.delimiter".into(), rgba(0x4d4f52ff).into()),
+ ("label".into(), rgba(0x5c78e2ff).into()),
+ ("keyword".into(), rgba(0xa449abff).into()),
+ ("string.escape".into(), rgba(0x7c7e86ff).into()),
+ ("text.literal".into(), rgba(0x649f57ff).into()),
+ ("variable.special".into(), rgba(0xad6e25ff).into()),
+ ("comment.doc".into(), rgba(0x7c7e86ff).into()),
+ ("enum".into(), rgba(0xd3604fff).into()),
+ ("operator".into(), rgba(0x3882b7ff).into()),
+ ("preproc".into(), rgba(0x383a41ff).into()),
+ ],
+ },
+ status_bar: rgba(0xdcdcddff).into(),
+ title_bar: rgba(0xdcdcddff).into(),
+ toolbar: rgba(0xfafafaff).into(),
+ tab_bar: rgba(0xebebecff).into(),
+ editor: rgba(0xfafafaff).into(),
+ editor_subheader: rgba(0xebebecff).into(),
+ editor_active_line: rgba(0xebebecff).into(),
+ terminal: rgba(0xfafafaff).into(),
+ image_fallback_background: rgba(0xdcdcddff).into(),
+ git_created: rgba(0x669f59ff).into(),
+ git_modified: rgba(0x5c78e2ff).into(),
+ git_deleted: rgba(0xd36151ff).into(),
+ git_conflict: rgba(0xdec184ff).into(),
+ git_ignored: rgba(0xa1a1a3ff).into(),
+ git_renamed: rgba(0xdec184ff).into(),
+ players: [
+ PlayerTheme {
+ cursor: rgba(0x5c78e2ff).into(),
+ selection: rgba(0x5c78e23d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x669f59ff).into(),
+ selection: rgba(0x669f593d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x984ea5ff).into(),
+ selection: rgba(0x984ea53d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xad6e26ff).into(),
+ selection: rgba(0xad6e263d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xa349abff).into(),
+ selection: rgba(0xa349ab3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x3a82b7ff).into(),
+ selection: rgba(0x3a82b73d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xd36151ff).into(),
+ selection: rgba(0xd361513d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xdec184ff).into(),
+ selection: rgba(0xdec1843d).into(),
+ },
+ ],
+ }
+}
@@ -37,46 +37,46 @@ pub fn rose_pine() -> Theme {
icon_muted: rgba(0x74708dff).into(),
syntax: SyntaxTheme {
highlights: vec![
- ("text.literal".into(), rgba(0xc4a7e6ff).into()),
- ("string".into(), rgba(0xf5c177ff).into()),
- ("enum".into(), rgba(0xc4a7e6ff).into()),
- ("number".into(), rgba(0x5cc1a3ff).into()),
- ("attribute".into(), rgba(0x9bced6ff).into()),
- ("property".into(), rgba(0x9bced6ff).into()),
- ("function".into(), rgba(0xebbcbaff).into()),
- ("embedded".into(), rgba(0xe0def4ff).into()),
("punctuation.delimiter".into(), rgba(0x9d99b6ff).into()),
- ("variant".into(), rgba(0x9bced6ff).into()),
- ("operator".into(), rgba(0x30738fff).into()),
- ("comment".into(), rgba(0x6e6a86ff).into()),
- ("type.builtin".into(), rgba(0x9ccfd8ff).into()),
- ("label".into(), rgba(0x9bced6ff).into()),
+ ("number".into(), rgba(0x5cc1a3ff).into()),
+ ("punctuation.special".into(), rgba(0x9d99b6ff).into()),
("string.escape".into(), rgba(0x76728fff).into()),
- ("type".into(), rgba(0x9ccfd8ff).into()),
- ("constructor".into(), rgba(0x9bced6ff).into()),
- ("punctuation.bracket".into(), rgba(0x9d99b6ff).into()),
- ("function.method".into(), rgba(0xebbcbaff).into()),
- ("tag".into(), rgba(0x9ccfd8ff).into()),
- ("link_text".into(), rgba(0x9ccfd8ff).into()),
- ("string.special".into(), rgba(0xc4a7e6ff).into()),
+ ("title".into(), rgba(0xf5c177ff).into()),
+ ("constant".into(), rgba(0x5cc1a3ff).into()),
("string.regex".into(), rgba(0xc4a7e6ff).into()),
- ("preproc".into(), rgba(0xe0def4ff).into()),
- ("emphasis.strong".into(), rgba(0x9bced6ff).into()),
- ("emphasis".into(), rgba(0x9bced6ff).into()),
+ ("type.builtin".into(), rgba(0x9ccfd8ff).into()),
("comment.doc".into(), rgba(0x76728fff).into()),
- ("boolean".into(), rgba(0xebbcbaff).into()),
- ("punctuation.list_marker".into(), rgba(0x9d99b6ff).into()),
- ("hint".into(), rgba(0x5e768cff).into()),
- ("title".into(), rgba(0xf5c177ff).into()),
- ("variable".into(), rgba(0xe0def4ff).into()),
- ("string.special.symbol".into(), rgba(0xc4a7e6ff).into()),
("primary".into(), rgba(0xe0def4ff).into()),
- ("predictive".into(), rgba(0x556b81ff).into()),
+ ("string.special".into(), rgba(0xc4a7e6ff).into()),
("punctuation".into(), rgba(0x908caaff).into()),
- ("constant".into(), rgba(0x5cc1a3ff).into()),
- ("punctuation.special".into(), rgba(0x9d99b6ff).into()),
+ ("string.special.symbol".into(), rgba(0xc4a7e6ff).into()),
+ ("variant".into(), rgba(0x9bced6ff).into()),
+ ("function.method".into(), rgba(0xebbcbaff).into()),
+ ("comment".into(), rgba(0x6e6a86ff).into()),
+ ("boolean".into(), rgba(0xebbcbaff).into()),
+ ("preproc".into(), rgba(0xe0def4ff).into()),
("link_uri".into(), rgba(0xebbcbaff).into()),
+ ("hint".into(), rgba(0x5e768cff).into()),
+ ("attribute".into(), rgba(0x9bced6ff).into()),
+ ("text.literal".into(), rgba(0xc4a7e6ff).into()),
+ ("punctuation.list_marker".into(), rgba(0x9d99b6ff).into()),
+ ("operator".into(), rgba(0x30738fff).into()),
+ ("emphasis.strong".into(), rgba(0x9bced6ff).into()),
("keyword".into(), rgba(0x30738fff).into()),
+ ("enum".into(), rgba(0xc4a7e6ff).into()),
+ ("tag".into(), rgba(0x9ccfd8ff).into()),
+ ("constructor".into(), rgba(0x9bced6ff).into()),
+ ("function".into(), rgba(0xebbcbaff).into()),
+ ("string".into(), rgba(0xf5c177ff).into()),
+ ("type".into(), rgba(0x9ccfd8ff).into()),
+ ("emphasis".into(), rgba(0x9bced6ff).into()),
+ ("link_text".into(), rgba(0x9ccfd8ff).into()),
+ ("property".into(), rgba(0x9bced6ff).into()),
+ ("predictive".into(), rgba(0x556b81ff).into()),
+ ("punctuation.bracket".into(), rgba(0x9d99b6ff).into()),
+ ("embedded".into(), rgba(0xe0def4ff).into()),
+ ("variable".into(), rgba(0xe0def4ff).into()),
+ ("label".into(), rgba(0x9bced6ff).into()),
],
},
status_bar: rgba(0x292738ff).into(),
@@ -130,261 +130,3 @@ pub fn rose_pine() -> Theme {
],
}
}
-
-pub fn rose_pine_dawn() -> Theme {
- Theme {
- metadata: ThemeMetadata {
- name: "Rosé Pine Dawn".into(),
- is_light: true,
- },
- transparent: rgba(0x00000000).into(),
- mac_os_traffic_light_red: rgba(0xec695eff).into(),
- mac_os_traffic_light_yellow: rgba(0xf4bf4eff).into(),
- mac_os_traffic_light_green: rgba(0x61c553ff).into(),
- border: rgba(0xdcd6d5ff).into(),
- border_variant: rgba(0xdcd6d5ff).into(),
- border_focused: rgba(0xc3d7dbff).into(),
- border_transparent: rgba(0x00000000).into(),
- elevated_surface: rgba(0xdcd8d8ff).into(),
- surface: rgba(0xfef9f2ff).into(),
- background: rgba(0xdcd8d8ff).into(),
- filled_element: rgba(0xdcd8d8ff).into(),
- filled_element_hover: rgba(0xffffff1e).into(),
- filled_element_active: rgba(0xffffff28).into(),
- filled_element_selected: rgba(0xdde9ebff).into(),
- filled_element_disabled: rgba(0x00000000).into(),
- ghost_element: rgba(0x00000000).into(),
- ghost_element_hover: rgba(0xffffff14).into(),
- ghost_element_active: rgba(0xffffff1e).into(),
- ghost_element_selected: rgba(0xdde9ebff).into(),
- ghost_element_disabled: rgba(0x00000000).into(),
- text: rgba(0x575279ff).into(),
- text_muted: rgba(0x706c8cff).into(),
- text_placeholder: rgba(0xb4647aff).into(),
- text_disabled: rgba(0x938fa3ff).into(),
- text_accent: rgba(0x57949fff).into(),
- icon_muted: rgba(0x706c8cff).into(),
- syntax: SyntaxTheme {
- highlights: vec![
- ("type".into(), rgba(0x55949fff).into()),
- ("keyword".into(), rgba(0x276983ff).into()),
- ("link_text".into(), rgba(0x55949fff).into()),
- ("embedded".into(), rgba(0x575279ff).into()),
- ("type.builtin".into(), rgba(0x55949fff).into()),
- ("punctuation.delimiter".into(), rgba(0x635e82ff).into()),
- ("text.literal".into(), rgba(0x9079a9ff).into()),
- ("variant".into(), rgba(0x57949fff).into()),
- ("string".into(), rgba(0xea9d34ff).into()),
- ("hint".into(), rgba(0x7a92aaff).into()),
- ("punctuation.special".into(), rgba(0x635e82ff).into()),
- ("string.special".into(), rgba(0x9079a9ff).into()),
- ("string.regex".into(), rgba(0x9079a9ff).into()),
- ("operator".into(), rgba(0x276983ff).into()),
- ("boolean".into(), rgba(0xd7827dff).into()),
- ("constructor".into(), rgba(0x57949fff).into()),
- ("punctuation".into(), rgba(0x797593ff).into()),
- ("label".into(), rgba(0x57949fff).into()),
- ("variable".into(), rgba(0x575279ff).into()),
- ("tag".into(), rgba(0x55949fff).into()),
- ("primary".into(), rgba(0x575279ff).into()),
- ("link_uri".into(), rgba(0xd7827dff).into()),
- ("punctuation.list_marker".into(), rgba(0x635e82ff).into()),
- ("string.escape".into(), rgba(0x6e6a8bff).into()),
- ("punctuation.bracket".into(), rgba(0x635e82ff).into()),
- ("function".into(), rgba(0xd7827dff).into()),
- ("preproc".into(), rgba(0x575279ff).into()),
- ("function.method".into(), rgba(0xd7827dff).into()),
- ("predictive".into(), rgba(0xa2acbeff).into()),
- ("comment.doc".into(), rgba(0x6e6a8bff).into()),
- ("comment".into(), rgba(0x9893a5ff).into()),
- ("number".into(), rgba(0x3daa8eff).into()),
- ("emphasis".into(), rgba(0x57949fff).into()),
- ("title".into(), rgba(0xea9d34ff).into()),
- ("enum".into(), rgba(0x9079a9ff).into()),
- ("string.special.symbol".into(), rgba(0x9079a9ff).into()),
- ("constant".into(), rgba(0x3daa8eff).into()),
- ("emphasis.strong".into(), rgba(0x57949fff).into()),
- ("property".into(), rgba(0x57949fff).into()),
- ("attribute".into(), rgba(0x57949fff).into()),
- ],
- },
- status_bar: rgba(0xdcd8d8ff).into(),
- title_bar: rgba(0xdcd8d8ff).into(),
- toolbar: rgba(0xfaf4edff).into(),
- tab_bar: rgba(0xfef9f2ff).into(),
- editor: rgba(0xfaf4edff).into(),
- editor_subheader: rgba(0xfef9f2ff).into(),
- editor_active_line: rgba(0xfef9f2ff).into(),
- terminal: rgba(0xfaf4edff).into(),
- image_fallback_background: rgba(0xdcd8d8ff).into(),
- git_created: rgba(0x3daa8eff).into(),
- git_modified: rgba(0x57949fff).into(),
- git_deleted: rgba(0xb4647aff).into(),
- git_conflict: rgba(0xe99d35ff).into(),
- git_ignored: rgba(0x938fa3ff).into(),
- git_renamed: rgba(0xe99d35ff).into(),
- players: [
- PlayerTheme {
- cursor: rgba(0x57949fff).into(),
- selection: rgba(0x57949f3d).into(),
- },
- PlayerTheme {
- cursor: rgba(0x3daa8eff).into(),
- selection: rgba(0x3daa8e3d).into(),
- },
- PlayerTheme {
- cursor: rgba(0x7c697fff).into(),
- selection: rgba(0x7c697f3d).into(),
- },
- PlayerTheme {
- cursor: rgba(0x9079a9ff).into(),
- selection: rgba(0x9079a93d).into(),
- },
- PlayerTheme {
- cursor: rgba(0x9079a9ff).into(),
- selection: rgba(0x9079a93d).into(),
- },
- PlayerTheme {
- cursor: rgba(0x296983ff).into(),
- selection: rgba(0x2969833d).into(),
- },
- PlayerTheme {
- cursor: rgba(0xb4647aff).into(),
- selection: rgba(0xb4647a3d).into(),
- },
- PlayerTheme {
- cursor: rgba(0xe99d35ff).into(),
- selection: rgba(0xe99d353d).into(),
- },
- ],
- }
-}
-
-pub fn rose_pine_moon() -> Theme {
- Theme {
- metadata: ThemeMetadata {
- name: "Rosé Pine Moon".into(),
- is_light: false,
- },
- transparent: rgba(0x00000000).into(),
- mac_os_traffic_light_red: rgba(0xec695eff).into(),
- mac_os_traffic_light_yellow: rgba(0xf4bf4eff).into(),
- mac_os_traffic_light_green: rgba(0x61c553ff).into(),
- border: rgba(0x504c68ff).into(),
- border_variant: rgba(0x504c68ff).into(),
- border_focused: rgba(0x435255ff).into(),
- border_transparent: rgba(0x00000000).into(),
- elevated_surface: rgba(0x38354eff).into(),
- surface: rgba(0x28253cff).into(),
- background: rgba(0x38354eff).into(),
- filled_element: rgba(0x38354eff).into(),
- filled_element_hover: rgba(0xffffff1e).into(),
- filled_element_active: rgba(0xffffff28).into(),
- filled_element_selected: rgba(0x2f3639ff).into(),
- filled_element_disabled: rgba(0x00000000).into(),
- ghost_element: rgba(0x00000000).into(),
- ghost_element_hover: rgba(0xffffff14).into(),
- ghost_element_active: rgba(0xffffff1e).into(),
- ghost_element_selected: rgba(0x2f3639ff).into(),
- ghost_element_disabled: rgba(0x00000000).into(),
- text: rgba(0xe0def4ff).into(),
- text_muted: rgba(0x85819eff).into(),
- text_placeholder: rgba(0xea6e92ff).into(),
- text_disabled: rgba(0x605d7aff).into(),
- text_accent: rgba(0x9bced6ff).into(),
- icon_muted: rgba(0x85819eff).into(),
- syntax: SyntaxTheme {
- highlights: vec![
- ("embedded".into(), rgba(0xe0def4ff).into()),
- ("link_uri".into(), rgba(0xea9a97ff).into()),
- ("primary".into(), rgba(0xe0def4ff).into()),
- ("punctuation.delimiter".into(), rgba(0xaeabc6ff).into()),
- ("string.escape".into(), rgba(0x8682a0ff).into()),
- ("attribute".into(), rgba(0x9bced6ff).into()),
- ("constant".into(), rgba(0x5cc1a3ff).into()),
- ("keyword".into(), rgba(0x3d8fb0ff).into()),
- ("predictive".into(), rgba(0x516b83ff).into()),
- ("label".into(), rgba(0x9bced6ff).into()),
- ("comment.doc".into(), rgba(0x8682a0ff).into()),
- ("emphasis".into(), rgba(0x9bced6ff).into()),
- ("string".into(), rgba(0xf5c177ff).into()),
- ("type".into(), rgba(0x9ccfd8ff).into()),
- ("string.special".into(), rgba(0xc4a7e6ff).into()),
- ("function".into(), rgba(0xea9a97ff).into()),
- ("constructor".into(), rgba(0x9bced6ff).into()),
- ("comment".into(), rgba(0x6e6a86ff).into()),
- ("preproc".into(), rgba(0xe0def4ff).into()),
- ("enum".into(), rgba(0xc4a7e6ff).into()),
- ("punctuation.bracket".into(), rgba(0xaeabc6ff).into()),
- ("number".into(), rgba(0x5cc1a3ff).into()),
- ("hint".into(), rgba(0x728aa2ff).into()),
- ("variant".into(), rgba(0x9bced6ff).into()),
- ("link_text".into(), rgba(0x9ccfd8ff).into()),
- ("property".into(), rgba(0x9bced6ff).into()),
- ("punctuation.list_marker".into(), rgba(0xaeabc6ff).into()),
- ("operator".into(), rgba(0x3d8fb0ff).into()),
- ("title".into(), rgba(0xf5c177ff).into()),
- ("punctuation".into(), rgba(0x908caaff).into()),
- ("string.regex".into(), rgba(0xc4a7e6ff).into()),
- ("tag".into(), rgba(0x9ccfd8ff).into()),
- ("emphasis.strong".into(), rgba(0x9bced6ff).into()),
- ("text.literal".into(), rgba(0xc4a7e6ff).into()),
- ("punctuation.special".into(), rgba(0xaeabc6ff).into()),
- ("boolean".into(), rgba(0xea9a97ff).into()),
- ("type.builtin".into(), rgba(0x9ccfd8ff).into()),
- ("function.method".into(), rgba(0xea9a97ff).into()),
- ("variable".into(), rgba(0xe0def4ff).into()),
- ("string.special.symbol".into(), rgba(0xc4a7e6ff).into()),
- ],
- },
- status_bar: rgba(0x38354eff).into(),
- title_bar: rgba(0x38354eff).into(),
- toolbar: rgba(0x232136ff).into(),
- tab_bar: rgba(0x28253cff).into(),
- editor: rgba(0x232136ff).into(),
- editor_subheader: rgba(0x28253cff).into(),
- editor_active_line: rgba(0x28253cff).into(),
- terminal: rgba(0x232136ff).into(),
- image_fallback_background: rgba(0x38354eff).into(),
- git_created: rgba(0x5cc1a3ff).into(),
- git_modified: rgba(0x9bced6ff).into(),
- git_deleted: rgba(0xea6e92ff).into(),
- git_conflict: rgba(0xf5c177ff).into(),
- git_ignored: rgba(0x605d7aff).into(),
- git_renamed: rgba(0xf5c177ff).into(),
- players: [
- PlayerTheme {
- cursor: rgba(0x9bced6ff).into(),
- selection: rgba(0x9bced63d).into(),
- },
- PlayerTheme {
- cursor: rgba(0x5cc1a3ff).into(),
- selection: rgba(0x5cc1a33d).into(),
- },
- PlayerTheme {
- cursor: rgba(0xa683a0ff).into(),
- selection: rgba(0xa683a03d).into(),
- },
- PlayerTheme {
- cursor: rgba(0xc4a7e6ff).into(),
- selection: rgba(0xc4a7e63d).into(),
- },
- PlayerTheme {
- cursor: rgba(0xc4a7e6ff).into(),
- selection: rgba(0xc4a7e63d).into(),
- },
- PlayerTheme {
- cursor: rgba(0x3e8fb0ff).into(),
- selection: rgba(0x3e8fb03d).into(),
- },
- PlayerTheme {
- cursor: rgba(0xea6e92ff).into(),
- selection: rgba(0xea6e923d).into(),
- },
- PlayerTheme {
- cursor: rgba(0xf5c177ff).into(),
- selection: rgba(0xf5c1773d).into(),
- },
- ],
- }
-}
@@ -0,0 +1,132 @@
+use gpui2::rgba;
+
+use crate::{PlayerTheme, SyntaxTheme, Theme, ThemeMetadata};
+
+pub fn rose_pine_dawn() -> Theme {
+ Theme {
+ metadata: ThemeMetadata {
+ name: "Rosé Pine Dawn".into(),
+ is_light: true,
+ },
+ transparent: rgba(0x00000000).into(),
+ mac_os_traffic_light_red: rgba(0xec695eff).into(),
+ mac_os_traffic_light_yellow: rgba(0xf4bf4eff).into(),
+ mac_os_traffic_light_green: rgba(0x61c553ff).into(),
+ border: rgba(0xdcd6d5ff).into(),
+ border_variant: rgba(0xdcd6d5ff).into(),
+ border_focused: rgba(0xc3d7dbff).into(),
+ border_transparent: rgba(0x00000000).into(),
+ elevated_surface: rgba(0xdcd8d8ff).into(),
+ surface: rgba(0xfef9f2ff).into(),
+ background: rgba(0xdcd8d8ff).into(),
+ filled_element: rgba(0xdcd8d8ff).into(),
+ filled_element_hover: rgba(0xffffff1e).into(),
+ filled_element_active: rgba(0xffffff28).into(),
+ filled_element_selected: rgba(0xdde9ebff).into(),
+ filled_element_disabled: rgba(0x00000000).into(),
+ ghost_element: rgba(0x00000000).into(),
+ ghost_element_hover: rgba(0xffffff14).into(),
+ ghost_element_active: rgba(0xffffff1e).into(),
+ ghost_element_selected: rgba(0xdde9ebff).into(),
+ ghost_element_disabled: rgba(0x00000000).into(),
+ text: rgba(0x575279ff).into(),
+ text_muted: rgba(0x706c8cff).into(),
+ text_placeholder: rgba(0xb4647aff).into(),
+ text_disabled: rgba(0x938fa3ff).into(),
+ text_accent: rgba(0x57949fff).into(),
+ icon_muted: rgba(0x706c8cff).into(),
+ syntax: SyntaxTheme {
+ highlights: vec![
+ ("primary".into(), rgba(0x575279ff).into()),
+ ("attribute".into(), rgba(0x57949fff).into()),
+ ("operator".into(), rgba(0x276983ff).into()),
+ ("boolean".into(), rgba(0xd7827dff).into()),
+ ("tag".into(), rgba(0x55949fff).into()),
+ ("enum".into(), rgba(0x9079a9ff).into()),
+ ("embedded".into(), rgba(0x575279ff).into()),
+ ("label".into(), rgba(0x57949fff).into()),
+ ("function.method".into(), rgba(0xd7827dff).into()),
+ ("punctuation.list_marker".into(), rgba(0x635e82ff).into()),
+ ("punctuation.delimiter".into(), rgba(0x635e82ff).into()),
+ ("string".into(), rgba(0xea9d34ff).into()),
+ ("type".into(), rgba(0x55949fff).into()),
+ ("string.regex".into(), rgba(0x9079a9ff).into()),
+ ("variable".into(), rgba(0x575279ff).into()),
+ ("constructor".into(), rgba(0x57949fff).into()),
+ ("punctuation.bracket".into(), rgba(0x635e82ff).into()),
+ ("emphasis".into(), rgba(0x57949fff).into()),
+ ("comment.doc".into(), rgba(0x6e6a8bff).into()),
+ ("comment".into(), rgba(0x9893a5ff).into()),
+ ("keyword".into(), rgba(0x276983ff).into()),
+ ("preproc".into(), rgba(0x575279ff).into()),
+ ("string.special".into(), rgba(0x9079a9ff).into()),
+ ("string.escape".into(), rgba(0x6e6a8bff).into()),
+ ("constant".into(), rgba(0x3daa8eff).into()),
+ ("property".into(), rgba(0x57949fff).into()),
+ ("punctuation.special".into(), rgba(0x635e82ff).into()),
+ ("text.literal".into(), rgba(0x9079a9ff).into()),
+ ("type.builtin".into(), rgba(0x55949fff).into()),
+ ("string.special.symbol".into(), rgba(0x9079a9ff).into()),
+ ("link_uri".into(), rgba(0xd7827dff).into()),
+ ("number".into(), rgba(0x3daa8eff).into()),
+ ("emphasis.strong".into(), rgba(0x57949fff).into()),
+ ("function".into(), rgba(0xd7827dff).into()),
+ ("title".into(), rgba(0xea9d34ff).into()),
+ ("punctuation".into(), rgba(0x797593ff).into()),
+ ("link_text".into(), rgba(0x55949fff).into()),
+ ("variant".into(), rgba(0x57949fff).into()),
+ ("predictive".into(), rgba(0xa2acbeff).into()),
+ ("hint".into(), rgba(0x7a92aaff).into()),
+ ],
+ },
+ status_bar: rgba(0xdcd8d8ff).into(),
+ title_bar: rgba(0xdcd8d8ff).into(),
+ toolbar: rgba(0xfaf4edff).into(),
+ tab_bar: rgba(0xfef9f2ff).into(),
+ editor: rgba(0xfaf4edff).into(),
+ editor_subheader: rgba(0xfef9f2ff).into(),
+ editor_active_line: rgba(0xfef9f2ff).into(),
+ terminal: rgba(0xfaf4edff).into(),
+ image_fallback_background: rgba(0xdcd8d8ff).into(),
+ git_created: rgba(0x3daa8eff).into(),
+ git_modified: rgba(0x57949fff).into(),
+ git_deleted: rgba(0xb4647aff).into(),
+ git_conflict: rgba(0xe99d35ff).into(),
+ git_ignored: rgba(0x938fa3ff).into(),
+ git_renamed: rgba(0xe99d35ff).into(),
+ players: [
+ PlayerTheme {
+ cursor: rgba(0x57949fff).into(),
+ selection: rgba(0x57949f3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x3daa8eff).into(),
+ selection: rgba(0x3daa8e3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x7c697fff).into(),
+ selection: rgba(0x7c697f3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x9079a9ff).into(),
+ selection: rgba(0x9079a93d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x9079a9ff).into(),
+ selection: rgba(0x9079a93d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x296983ff).into(),
+ selection: rgba(0x2969833d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xb4647aff).into(),
+ selection: rgba(0xb4647a3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xe99d35ff).into(),
+ selection: rgba(0xe99d353d).into(),
+ },
+ ],
+ }
+}
@@ -0,0 +1,132 @@
+use gpui2::rgba;
+
+use crate::{PlayerTheme, SyntaxTheme, Theme, ThemeMetadata};
+
+pub fn rose_pine_moon() -> Theme {
+ Theme {
+ metadata: ThemeMetadata {
+ name: "Rosé Pine Moon".into(),
+ is_light: false,
+ },
+ transparent: rgba(0x00000000).into(),
+ mac_os_traffic_light_red: rgba(0xec695eff).into(),
+ mac_os_traffic_light_yellow: rgba(0xf4bf4eff).into(),
+ mac_os_traffic_light_green: rgba(0x61c553ff).into(),
+ border: rgba(0x504c68ff).into(),
+ border_variant: rgba(0x504c68ff).into(),
+ border_focused: rgba(0x435255ff).into(),
+ border_transparent: rgba(0x00000000).into(),
+ elevated_surface: rgba(0x38354eff).into(),
+ surface: rgba(0x28253cff).into(),
+ background: rgba(0x38354eff).into(),
+ filled_element: rgba(0x38354eff).into(),
+ filled_element_hover: rgba(0xffffff1e).into(),
+ filled_element_active: rgba(0xffffff28).into(),
+ filled_element_selected: rgba(0x2f3639ff).into(),
+ filled_element_disabled: rgba(0x00000000).into(),
+ ghost_element: rgba(0x00000000).into(),
+ ghost_element_hover: rgba(0xffffff14).into(),
+ ghost_element_active: rgba(0xffffff1e).into(),
+ ghost_element_selected: rgba(0x2f3639ff).into(),
+ ghost_element_disabled: rgba(0x00000000).into(),
+ text: rgba(0xe0def4ff).into(),
+ text_muted: rgba(0x85819eff).into(),
+ text_placeholder: rgba(0xea6e92ff).into(),
+ text_disabled: rgba(0x605d7aff).into(),
+ text_accent: rgba(0x9bced6ff).into(),
+ icon_muted: rgba(0x85819eff).into(),
+ syntax: SyntaxTheme {
+ highlights: vec![
+ ("type.builtin".into(), rgba(0x9ccfd8ff).into()),
+ ("variable".into(), rgba(0xe0def4ff).into()),
+ ("punctuation".into(), rgba(0x908caaff).into()),
+ ("number".into(), rgba(0x5cc1a3ff).into()),
+ ("comment".into(), rgba(0x6e6a86ff).into()),
+ ("string.special".into(), rgba(0xc4a7e6ff).into()),
+ ("string.escape".into(), rgba(0x8682a0ff).into()),
+ ("function.method".into(), rgba(0xea9a97ff).into()),
+ ("predictive".into(), rgba(0x516b83ff).into()),
+ ("punctuation.delimiter".into(), rgba(0xaeabc6ff).into()),
+ ("primary".into(), rgba(0xe0def4ff).into()),
+ ("link_text".into(), rgba(0x9ccfd8ff).into()),
+ ("string.regex".into(), rgba(0xc4a7e6ff).into()),
+ ("constructor".into(), rgba(0x9bced6ff).into()),
+ ("constant".into(), rgba(0x5cc1a3ff).into()),
+ ("emphasis.strong".into(), rgba(0x9bced6ff).into()),
+ ("function".into(), rgba(0xea9a97ff).into()),
+ ("hint".into(), rgba(0x728aa2ff).into()),
+ ("preproc".into(), rgba(0xe0def4ff).into()),
+ ("property".into(), rgba(0x9bced6ff).into()),
+ ("punctuation.list_marker".into(), rgba(0xaeabc6ff).into()),
+ ("emphasis".into(), rgba(0x9bced6ff).into()),
+ ("attribute".into(), rgba(0x9bced6ff).into()),
+ ("title".into(), rgba(0xf5c177ff).into()),
+ ("keyword".into(), rgba(0x3d8fb0ff).into()),
+ ("string".into(), rgba(0xf5c177ff).into()),
+ ("text.literal".into(), rgba(0xc4a7e6ff).into()),
+ ("embedded".into(), rgba(0xe0def4ff).into()),
+ ("comment.doc".into(), rgba(0x8682a0ff).into()),
+ ("variant".into(), rgba(0x9bced6ff).into()),
+ ("label".into(), rgba(0x9bced6ff).into()),
+ ("punctuation.special".into(), rgba(0xaeabc6ff).into()),
+ ("string.special.symbol".into(), rgba(0xc4a7e6ff).into()),
+ ("tag".into(), rgba(0x9ccfd8ff).into()),
+ ("enum".into(), rgba(0xc4a7e6ff).into()),
+ ("boolean".into(), rgba(0xea9a97ff).into()),
+ ("punctuation.bracket".into(), rgba(0xaeabc6ff).into()),
+ ("operator".into(), rgba(0x3d8fb0ff).into()),
+ ("type".into(), rgba(0x9ccfd8ff).into()),
+ ("link_uri".into(), rgba(0xea9a97ff).into()),
+ ],
+ },
+ status_bar: rgba(0x38354eff).into(),
+ title_bar: rgba(0x38354eff).into(),
+ toolbar: rgba(0x232136ff).into(),
+ tab_bar: rgba(0x28253cff).into(),
+ editor: rgba(0x232136ff).into(),
+ editor_subheader: rgba(0x28253cff).into(),
+ editor_active_line: rgba(0x28253cff).into(),
+ terminal: rgba(0x232136ff).into(),
+ image_fallback_background: rgba(0x38354eff).into(),
+ git_created: rgba(0x5cc1a3ff).into(),
+ git_modified: rgba(0x9bced6ff).into(),
+ git_deleted: rgba(0xea6e92ff).into(),
+ git_conflict: rgba(0xf5c177ff).into(),
+ git_ignored: rgba(0x605d7aff).into(),
+ git_renamed: rgba(0xf5c177ff).into(),
+ players: [
+ PlayerTheme {
+ cursor: rgba(0x9bced6ff).into(),
+ selection: rgba(0x9bced63d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x5cc1a3ff).into(),
+ selection: rgba(0x5cc1a33d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xa683a0ff).into(),
+ selection: rgba(0xa683a03d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xc4a7e6ff).into(),
+ selection: rgba(0xc4a7e63d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xc4a7e6ff).into(),
+ selection: rgba(0xc4a7e63d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x3e8fb0ff).into(),
+ selection: rgba(0x3e8fb03d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xea6e92ff).into(),
+ selection: rgba(0xea6e923d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xf5c177ff).into(),
+ selection: rgba(0xf5c1773d).into(),
+ },
+ ],
+ }
+}
@@ -37,44 +37,44 @@ pub fn sandcastle() -> Theme {
icon_muted: rgba(0xa69782ff).into(),
syntax: SyntaxTheme {
highlights: vec![
- ("string.special.symbol".into(), rgba(0xa07d3aff).into()),
- ("enum".into(), rgba(0xa07d3aff).into()),
+ ("comment".into(), rgba(0xa89984ff).into()),
+ ("type".into(), rgba(0x83a598ff).into()),
+ ("preproc".into(), rgba(0xfdf4c1ff).into()),
("punctuation.bracket".into(), rgba(0xd5c5a1ff).into()),
("hint".into(), rgba(0x727d68ff).into()),
- ("punctuation.delimiter".into(), rgba(0xd5c5a1ff).into()),
- ("comment".into(), rgba(0xa89984ff).into()),
- ("embedded".into(), rgba(0xfdf4c1ff).into()),
+ ("link_uri".into(), rgba(0x83a598ff).into()),
+ ("text.literal".into(), rgba(0xa07d3aff).into()),
+ ("enum".into(), rgba(0xa07d3aff).into()),
+ ("string.special".into(), rgba(0xa07d3aff).into()),
("string".into(), rgba(0xa07d3aff).into()),
- ("string.escape".into(), rgba(0xa89984ff).into()),
- ("comment.doc".into(), rgba(0xa89984ff).into()),
- ("variant".into(), rgba(0x518b8bff).into()),
+ ("punctuation.special".into(), rgba(0xd5c5a1ff).into()),
+ ("keyword".into(), rgba(0x518b8bff).into()),
+ ("constructor".into(), rgba(0x518b8bff).into()),
("predictive".into(), rgba(0x5c6152ff).into()),
- ("link_text".into(), rgba(0xa07d3aff).into()),
- ("attribute".into(), rgba(0x518b8bff).into()),
("title".into(), rgba(0xfdf4c1ff).into()),
+ ("variable".into(), rgba(0xfdf4c1ff).into()),
("emphasis.strong".into(), rgba(0x518b8bff).into()),
("primary".into(), rgba(0xfdf4c1ff).into()),
+ ("emphasis".into(), rgba(0x518b8bff).into()),
+ ("punctuation".into(), rgba(0xd5c5a1ff).into()),
+ ("constant".into(), rgba(0x83a598ff).into()),
+ ("link_text".into(), rgba(0xa07d3aff).into()),
+ ("punctuation.delimiter".into(), rgba(0xd5c5a1ff).into()),
+ ("embedded".into(), rgba(0xfdf4c1ff).into()),
+ ("string.special.symbol".into(), rgba(0xa07d3aff).into()),
+ ("tag".into(), rgba(0x518b8bff).into()),
("punctuation.list_marker".into(), rgba(0xd5c5a1ff).into()),
+ ("operator".into(), rgba(0xa07d3aff).into()),
("boolean".into(), rgba(0x83a598ff).into()),
("function".into(), rgba(0xa07d3aff).into()),
- ("punctuation.special".into(), rgba(0xd5c5a1ff).into()),
- ("string.special".into(), rgba(0xa07d3aff).into()),
- ("string.regex".into(), rgba(0xa07d3aff).into()),
- ("tag".into(), rgba(0x518b8bff).into()),
- ("keyword".into(), rgba(0x518b8bff).into()),
- ("type".into(), rgba(0x83a598ff).into()),
- ("text.literal".into(), rgba(0xa07d3aff).into()),
- ("link_uri".into(), rgba(0x83a598ff).into()),
+ ("attribute".into(), rgba(0x518b8bff).into()),
+ ("number".into(), rgba(0x83a598ff).into()),
+ ("string.escape".into(), rgba(0xa89984ff).into()),
+ ("comment.doc".into(), rgba(0xa89984ff).into()),
("label".into(), rgba(0x518b8bff).into()),
+ ("string.regex".into(), rgba(0xa07d3aff).into()),
("property".into(), rgba(0x518b8bff).into()),
- ("number".into(), rgba(0x83a598ff).into()),
- ("constructor".into(), rgba(0x518b8bff).into()),
- ("preproc".into(), rgba(0xfdf4c1ff).into()),
- ("emphasis".into(), rgba(0x518b8bff).into()),
- ("variable".into(), rgba(0xfdf4c1ff).into()),
- ("operator".into(), rgba(0xa07d3aff).into()),
- ("punctuation".into(), rgba(0xd5c5a1ff).into()),
- ("constant".into(), rgba(0x83a598ff).into()),
+ ("variant".into(), rgba(0x518b8bff).into()),
],
},
status_bar: rgba(0x333944ff).into(),
@@ -0,0 +1,130 @@
+use gpui2::rgba;
+
+use crate::{PlayerTheme, SyntaxTheme, Theme, ThemeMetadata};
+
+pub fn solarized_dark() -> Theme {
+ Theme {
+ metadata: ThemeMetadata {
+ name: "Solarized Dark".into(),
+ is_light: false,
+ },
+ transparent: rgba(0x00000000).into(),
+ mac_os_traffic_light_red: rgba(0xec695eff).into(),
+ mac_os_traffic_light_yellow: rgba(0xf4bf4eff).into(),
+ mac_os_traffic_light_green: rgba(0x61c553ff).into(),
+ border: rgba(0x2b4e58ff).into(),
+ border_variant: rgba(0x2b4e58ff).into(),
+ border_focused: rgba(0x1b3149ff).into(),
+ border_transparent: rgba(0x00000000).into(),
+ elevated_surface: rgba(0x073743ff).into(),
+ surface: rgba(0x04313bff).into(),
+ background: rgba(0x073743ff).into(),
+ filled_element: rgba(0x073743ff).into(),
+ filled_element_hover: rgba(0xffffff1e).into(),
+ filled_element_active: rgba(0xffffff28).into(),
+ filled_element_selected: rgba(0x141f2cff).into(),
+ filled_element_disabled: rgba(0x00000000).into(),
+ ghost_element: rgba(0x00000000).into(),
+ ghost_element_hover: rgba(0xffffff14).into(),
+ ghost_element_active: rgba(0xffffff1e).into(),
+ ghost_element_selected: rgba(0x141f2cff).into(),
+ ghost_element_disabled: rgba(0x00000000).into(),
+ text: rgba(0xfdf6e3ff).into(),
+ text_muted: rgba(0x93a1a1ff).into(),
+ text_placeholder: rgba(0xdc3330ff).into(),
+ text_disabled: rgba(0x6f8389ff).into(),
+ text_accent: rgba(0x278ad1ff).into(),
+ icon_muted: rgba(0x93a1a1ff).into(),
+ syntax: SyntaxTheme {
+ highlights: vec![
+ ("punctuation.special".into(), rgba(0xefe9d6ff).into()),
+ ("string".into(), rgba(0xcb4b16ff).into()),
+ ("variant".into(), rgba(0x278ad1ff).into()),
+ ("variable".into(), rgba(0xfdf6e3ff).into()),
+ ("string.special.symbol".into(), rgba(0xcb4b16ff).into()),
+ ("primary".into(), rgba(0xfdf6e3ff).into()),
+ ("type".into(), rgba(0x2ba198ff).into()),
+ ("boolean".into(), rgba(0x849903ff).into()),
+ ("string.special".into(), rgba(0xcb4b16ff).into()),
+ ("label".into(), rgba(0x278ad1ff).into()),
+ ("link_uri".into(), rgba(0x849903ff).into()),
+ ("constructor".into(), rgba(0x278ad1ff).into()),
+ ("hint".into(), rgba(0x4f8297ff).into()),
+ ("preproc".into(), rgba(0xfdf6e3ff).into()),
+ ("text.literal".into(), rgba(0xcb4b16ff).into()),
+ ("string.escape".into(), rgba(0x99a5a4ff).into()),
+ ("link_text".into(), rgba(0xcb4b16ff).into()),
+ ("comment".into(), rgba(0x99a5a4ff).into()),
+ ("enum".into(), rgba(0xcb4b16ff).into()),
+ ("constant".into(), rgba(0x849903ff).into()),
+ ("comment.doc".into(), rgba(0x99a5a4ff).into()),
+ ("emphasis".into(), rgba(0x278ad1ff).into()),
+ ("predictive".into(), rgba(0x3f718bff).into()),
+ ("attribute".into(), rgba(0x278ad1ff).into()),
+ ("punctuation.delimiter".into(), rgba(0xefe9d6ff).into()),
+ ("function".into(), rgba(0xb58902ff).into()),
+ ("emphasis.strong".into(), rgba(0x278ad1ff).into()),
+ ("tag".into(), rgba(0x278ad1ff).into()),
+ ("string.regex".into(), rgba(0xcb4b16ff).into()),
+ ("property".into(), rgba(0x278ad1ff).into()),
+ ("keyword".into(), rgba(0x278ad1ff).into()),
+ ("number".into(), rgba(0x849903ff).into()),
+ ("embedded".into(), rgba(0xfdf6e3ff).into()),
+ ("operator".into(), rgba(0xcb4b16ff).into()),
+ ("punctuation".into(), rgba(0xefe9d6ff).into()),
+ ("punctuation.bracket".into(), rgba(0xefe9d6ff).into()),
+ ("title".into(), rgba(0xfdf6e3ff).into()),
+ ("punctuation.list_marker".into(), rgba(0xefe9d6ff).into()),
+ ],
+ },
+ status_bar: rgba(0x073743ff).into(),
+ title_bar: rgba(0x073743ff).into(),
+ toolbar: rgba(0x002a35ff).into(),
+ tab_bar: rgba(0x04313bff).into(),
+ editor: rgba(0x002a35ff).into(),
+ editor_subheader: rgba(0x04313bff).into(),
+ editor_active_line: rgba(0x04313bff).into(),
+ terminal: rgba(0x002a35ff).into(),
+ image_fallback_background: rgba(0x073743ff).into(),
+ git_created: rgba(0x849903ff).into(),
+ git_modified: rgba(0x278ad1ff).into(),
+ git_deleted: rgba(0xdc3330ff).into(),
+ git_conflict: rgba(0xb58902ff).into(),
+ git_ignored: rgba(0x6f8389ff).into(),
+ git_renamed: rgba(0xb58902ff).into(),
+ players: [
+ PlayerTheme {
+ cursor: rgba(0x278ad1ff).into(),
+ selection: rgba(0x278ad13d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x849903ff).into(),
+ selection: rgba(0x8499033d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xd33781ff).into(),
+ selection: rgba(0xd337813d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xcb4b16ff).into(),
+ selection: rgba(0xcb4b163d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x6c71c4ff).into(),
+ selection: rgba(0x6c71c43d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x2ba198ff).into(),
+ selection: rgba(0x2ba1983d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xdc3330ff).into(),
+ selection: rgba(0xdc33303d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xb58902ff).into(),
+ selection: rgba(0xb589023d).into(),
+ },
+ ],
+ }
+}
@@ -0,0 +1,130 @@
+use gpui2::rgba;
+
+use crate::{PlayerTheme, SyntaxTheme, Theme, ThemeMetadata};
+
+pub fn solarized_light() -> Theme {
+ Theme {
+ metadata: ThemeMetadata {
+ name: "Solarized Light".into(),
+ is_light: true,
+ },
+ transparent: rgba(0x00000000).into(),
+ mac_os_traffic_light_red: rgba(0xec695eff).into(),
+ mac_os_traffic_light_yellow: rgba(0xf4bf4eff).into(),
+ mac_os_traffic_light_green: rgba(0x61c553ff).into(),
+ border: rgba(0x9faaa8ff).into(),
+ border_variant: rgba(0x9faaa8ff).into(),
+ border_focused: rgba(0xbfd3efff).into(),
+ border_transparent: rgba(0x00000000).into(),
+ elevated_surface: rgba(0xcfd0c4ff).into(),
+ surface: rgba(0xf3eddaff).into(),
+ background: rgba(0xcfd0c4ff).into(),
+ filled_element: rgba(0xcfd0c4ff).into(),
+ filled_element_hover: rgba(0xffffff1e).into(),
+ filled_element_active: rgba(0xffffff28).into(),
+ filled_element_selected: rgba(0xdbe6f6ff).into(),
+ filled_element_disabled: rgba(0x00000000).into(),
+ ghost_element: rgba(0x00000000).into(),
+ ghost_element_hover: rgba(0xffffff14).into(),
+ ghost_element_active: rgba(0xffffff1e).into(),
+ ghost_element_selected: rgba(0xdbe6f6ff).into(),
+ ghost_element_disabled: rgba(0x00000000).into(),
+ text: rgba(0x002a35ff).into(),
+ text_muted: rgba(0x34555eff).into(),
+ text_placeholder: rgba(0xdc3330ff).into(),
+ text_disabled: rgba(0x6a7f86ff).into(),
+ text_accent: rgba(0x288bd1ff).into(),
+ icon_muted: rgba(0x34555eff).into(),
+ syntax: SyntaxTheme {
+ highlights: vec![
+ ("string.escape".into(), rgba(0x30525bff).into()),
+ ("boolean".into(), rgba(0x849903ff).into()),
+ ("comment.doc".into(), rgba(0x30525bff).into()),
+ ("string.special".into(), rgba(0xcb4b17ff).into()),
+ ("punctuation".into(), rgba(0x04333eff).into()),
+ ("emphasis".into(), rgba(0x288bd1ff).into()),
+ ("type".into(), rgba(0x2ba198ff).into()),
+ ("preproc".into(), rgba(0x002a35ff).into()),
+ ("emphasis.strong".into(), rgba(0x288bd1ff).into()),
+ ("constant".into(), rgba(0x849903ff).into()),
+ ("title".into(), rgba(0x002a35ff).into()),
+ ("operator".into(), rgba(0xcb4b17ff).into()),
+ ("punctuation.bracket".into(), rgba(0x04333eff).into()),
+ ("link_uri".into(), rgba(0x849903ff).into()),
+ ("label".into(), rgba(0x288bd1ff).into()),
+ ("enum".into(), rgba(0xcb4b17ff).into()),
+ ("property".into(), rgba(0x288bd1ff).into()),
+ ("predictive".into(), rgba(0x679aafff).into()),
+ ("punctuation.special".into(), rgba(0x04333eff).into()),
+ ("text.literal".into(), rgba(0xcb4b17ff).into()),
+ ("string".into(), rgba(0xcb4b17ff).into()),
+ ("string.regex".into(), rgba(0xcb4b17ff).into()),
+ ("variable".into(), rgba(0x002a35ff).into()),
+ ("tag".into(), rgba(0x288bd1ff).into()),
+ ("string.special.symbol".into(), rgba(0xcb4b17ff).into()),
+ ("link_text".into(), rgba(0xcb4b17ff).into()),
+ ("punctuation.list_marker".into(), rgba(0x04333eff).into()),
+ ("keyword".into(), rgba(0x288bd1ff).into()),
+ ("constructor".into(), rgba(0x288bd1ff).into()),
+ ("attribute".into(), rgba(0x288bd1ff).into()),
+ ("variant".into(), rgba(0x288bd1ff).into()),
+ ("function".into(), rgba(0xb58903ff).into()),
+ ("primary".into(), rgba(0x002a35ff).into()),
+ ("hint".into(), rgba(0x5789a3ff).into()),
+ ("comment".into(), rgba(0x30525bff).into()),
+ ("number".into(), rgba(0x849903ff).into()),
+ ("punctuation.delimiter".into(), rgba(0x04333eff).into()),
+ ("embedded".into(), rgba(0x002a35ff).into()),
+ ],
+ },
+ status_bar: rgba(0xcfd0c4ff).into(),
+ title_bar: rgba(0xcfd0c4ff).into(),
+ toolbar: rgba(0xfdf6e3ff).into(),
+ tab_bar: rgba(0xf3eddaff).into(),
+ editor: rgba(0xfdf6e3ff).into(),
+ editor_subheader: rgba(0xf3eddaff).into(),
+ editor_active_line: rgba(0xf3eddaff).into(),
+ terminal: rgba(0xfdf6e3ff).into(),
+ image_fallback_background: rgba(0xcfd0c4ff).into(),
+ git_created: rgba(0x849903ff).into(),
+ git_modified: rgba(0x288bd1ff).into(),
+ git_deleted: rgba(0xdc3330ff).into(),
+ git_conflict: rgba(0xb58903ff).into(),
+ git_ignored: rgba(0x6a7f86ff).into(),
+ git_renamed: rgba(0xb58903ff).into(),
+ players: [
+ PlayerTheme {
+ cursor: rgba(0x288bd1ff).into(),
+ selection: rgba(0x288bd13d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x849903ff).into(),
+ selection: rgba(0x8499033d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xd33781ff).into(),
+ selection: rgba(0xd337813d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xcb4b17ff).into(),
+ selection: rgba(0xcb4b173d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x6c71c3ff).into(),
+ selection: rgba(0x6c71c33d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x2ba198ff).into(),
+ selection: rgba(0x2ba1983d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xdc3330ff).into(),
+ selection: rgba(0xdc33303d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xb58903ff).into(),
+ selection: rgba(0xb589033d).into(),
+ },
+ ],
+ }
+}
@@ -0,0 +1,130 @@
+use gpui2::rgba;
+
+use crate::{PlayerTheme, SyntaxTheme, Theme, ThemeMetadata};
+
+pub fn summercamp() -> Theme {
+ Theme {
+ metadata: ThemeMetadata {
+ name: "Summercamp".into(),
+ is_light: false,
+ },
+ transparent: rgba(0x00000000).into(),
+ mac_os_traffic_light_red: rgba(0xec695eff).into(),
+ mac_os_traffic_light_yellow: rgba(0xf4bf4eff).into(),
+ mac_os_traffic_light_green: rgba(0x61c553ff).into(),
+ border: rgba(0x302c21ff).into(),
+ border_variant: rgba(0x302c21ff).into(),
+ border_focused: rgba(0x193760ff).into(),
+ border_transparent: rgba(0x00000000).into(),
+ elevated_surface: rgba(0x2a261cff).into(),
+ surface: rgba(0x231f16ff).into(),
+ background: rgba(0x2a261cff).into(),
+ filled_element: rgba(0x2a261cff).into(),
+ filled_element_hover: rgba(0xffffff1e).into(),
+ filled_element_active: rgba(0xffffff28).into(),
+ filled_element_selected: rgba(0x0e2242ff).into(),
+ filled_element_disabled: rgba(0x00000000).into(),
+ ghost_element: rgba(0x00000000).into(),
+ ghost_element_hover: rgba(0xffffff14).into(),
+ ghost_element_active: rgba(0xffffff1e).into(),
+ ghost_element_selected: rgba(0x0e2242ff).into(),
+ ghost_element_disabled: rgba(0x00000000).into(),
+ text: rgba(0xf8f5deff).into(),
+ text_muted: rgba(0x736e55ff).into(),
+ text_placeholder: rgba(0xe35041ff).into(),
+ text_disabled: rgba(0x4c4735ff).into(),
+ text_accent: rgba(0x499befff).into(),
+ icon_muted: rgba(0x736e55ff).into(),
+ syntax: SyntaxTheme {
+ highlights: vec![
+ ("predictive".into(), rgba(0x78434aff).into()),
+ ("title".into(), rgba(0xf8f5deff).into()),
+ ("primary".into(), rgba(0xf8f5deff).into()),
+ ("punctuation.special".into(), rgba(0xbfbb9bff).into()),
+ ("constant".into(), rgba(0x5dea5aff).into()),
+ ("string.regex".into(), rgba(0xfaa11cff).into()),
+ ("tag".into(), rgba(0x499befff).into()),
+ ("preproc".into(), rgba(0xf8f5deff).into()),
+ ("comment".into(), rgba(0x777159ff).into()),
+ ("punctuation.bracket".into(), rgba(0xbfbb9bff).into()),
+ ("constructor".into(), rgba(0x499befff).into()),
+ ("type".into(), rgba(0x5aeabbff).into()),
+ ("variable".into(), rgba(0xf8f5deff).into()),
+ ("operator".into(), rgba(0xfaa11cff).into()),
+ ("boolean".into(), rgba(0x5dea5aff).into()),
+ ("attribute".into(), rgba(0x499befff).into()),
+ ("link_text".into(), rgba(0xfaa11cff).into()),
+ ("string.escape".into(), rgba(0x777159ff).into()),
+ ("string.special".into(), rgba(0xfaa11cff).into()),
+ ("string.special.symbol".into(), rgba(0xfaa11cff).into()),
+ ("hint".into(), rgba(0x246e61ff).into()),
+ ("link_uri".into(), rgba(0x5dea5aff).into()),
+ ("comment.doc".into(), rgba(0x777159ff).into()),
+ ("emphasis".into(), rgba(0x499befff).into()),
+ ("punctuation".into(), rgba(0xbfbb9bff).into()),
+ ("text.literal".into(), rgba(0xfaa11cff).into()),
+ ("number".into(), rgba(0x5dea5aff).into()),
+ ("punctuation.delimiter".into(), rgba(0xbfbb9bff).into()),
+ ("label".into(), rgba(0x499befff).into()),
+ ("function".into(), rgba(0xf1fe28ff).into()),
+ ("property".into(), rgba(0x499befff).into()),
+ ("keyword".into(), rgba(0x499befff).into()),
+ ("embedded".into(), rgba(0xf8f5deff).into()),
+ ("string".into(), rgba(0xfaa11cff).into()),
+ ("punctuation.list_marker".into(), rgba(0xbfbb9bff).into()),
+ ("enum".into(), rgba(0xfaa11cff).into()),
+ ("emphasis.strong".into(), rgba(0x499befff).into()),
+ ("variant".into(), rgba(0x499befff).into()),
+ ],
+ },
+ status_bar: rgba(0x2a261cff).into(),
+ title_bar: rgba(0x2a261cff).into(),
+ toolbar: rgba(0x1b1810ff).into(),
+ tab_bar: rgba(0x231f16ff).into(),
+ editor: rgba(0x1b1810ff).into(),
+ editor_subheader: rgba(0x231f16ff).into(),
+ editor_active_line: rgba(0x231f16ff).into(),
+ terminal: rgba(0x1b1810ff).into(),
+ image_fallback_background: rgba(0x2a261cff).into(),
+ git_created: rgba(0x5dea5aff).into(),
+ git_modified: rgba(0x499befff).into(),
+ git_deleted: rgba(0xe35041ff).into(),
+ git_conflict: rgba(0xf1fe28ff).into(),
+ git_ignored: rgba(0x4c4735ff).into(),
+ git_renamed: rgba(0xf1fe28ff).into(),
+ players: [
+ PlayerTheme {
+ cursor: rgba(0x499befff).into(),
+ selection: rgba(0x499bef3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x5dea5aff).into(),
+ selection: rgba(0x5dea5a3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xf59be6ff).into(),
+ selection: rgba(0xf59be63d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xfaa11cff).into(),
+ selection: rgba(0xfaa11c3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xfe8080ff).into(),
+ selection: rgba(0xfe80803d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0x5aeabbff).into(),
+ selection: rgba(0x5aeabb3d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xe35041ff).into(),
+ selection: rgba(0xe350413d).into(),
+ },
+ PlayerTheme {
+ cursor: rgba(0xf1fe28ff).into(),
+ selection: rgba(0xf1fe283d).into(),
+ },
+ ],
+ }
+}
@@ -9,6 +9,7 @@ publish = false
[dependencies]
anyhow.workspace = true
clap = { version = "4.4", features = ["derive", "string"] }
+convert_case = "0.6.0"
gpui2 = { path = "../gpui2" }
log.workspace = true
rust-embed.workspace = true
@@ -1,16 +1,25 @@
+mod theme_printer;
+
use std::borrow::Cow;
use std::collections::HashMap;
use std::fmt::{self, Debug};
+use std::fs::File;
+use std::io::Write;
+use std::path::PathBuf;
+use std::str::FromStr;
use anyhow::{anyhow, Context, Result};
use clap::Parser;
-use gpui2::{hsla, rgb, serde_json, AssetSource, Hsla, Rgba, SharedString};
+use convert_case::{Case, Casing};
+use gpui2::{hsla, rgb, serde_json, AssetSource, Hsla, SharedString};
use log::LevelFilter;
use rust_embed::RustEmbed;
use serde::de::Visitor;
use serde::{Deserialize, Deserializer};
use simplelog::SimpleLogger;
-use theme2::{PlayerTheme, SyntaxTheme, ThemeMetadata};
+use theme2::{PlayerTheme, SyntaxTheme};
+
+use crate::theme_printer::ThemePrinter;
#[derive(Parser)]
#[command(author, version, about, long_about = None)]
@@ -22,13 +31,71 @@ struct Args {
fn main() -> Result<()> {
SimpleLogger::init(LevelFilter::Info, Default::default()).expect("could not initialize logger");
- let args = Args::parse();
+ // let args = Args::parse();
+
+ let themes_path = PathBuf::from_str("crates/theme2/src/themes")?;
+
+ let mut theme_modules = Vec::new();
+
+ for theme_path in Assets.list("themes/")? {
+ let (_, theme_name) = theme_path.split_once("themes/").unwrap();
+
+ if theme_name == ".gitkeep" {
+ continue;
+ }
+
+ let (json_theme, legacy_theme) = load_theme(&theme_path)?;
+
+ let theme = convert_theme(json_theme, legacy_theme)?;
+
+ let theme_slug = theme
+ .metadata
+ .name
+ .as_ref()
+ .replace("é", "e")
+ .to_case(Case::Snake);
+
+ let mut output_file = File::create(themes_path.join(format!("{theme_slug}.rs")))?;
+
+ let theme_module = format!(
+ r#"
+ use gpui2::rgba;
- let (json_theme, legacy_theme) = load_theme(args.theme)?;
+ use crate::{{PlayerTheme, SyntaxTheme, Theme, ThemeMetadata}};
- let theme = convert_theme(json_theme, legacy_theme)?;
+ pub fn {theme_slug}() -> Theme {{
+ {theme_definition}
+ }}
+ "#,
+ theme_definition = format!("{:#?}", ThemePrinter::new(theme))
+ );
- println!("{:#?}", ThemePrinter(theme));
+ output_file.write_all(theme_module.as_bytes())?;
+
+ theme_modules.push(theme_slug);
+ }
+
+ let mut mod_rs_file = File::create(themes_path.join(format!("mod.rs")))?;
+
+ let mod_rs_contents = format!(
+ r#"
+ {mod_statements}
+
+ {use_statements}
+ "#,
+ mod_statements = theme_modules
+ .iter()
+ .map(|module| format!("mod {module};"))
+ .collect::<Vec<_>>()
+ .join("\n"),
+ use_statements = theme_modules
+ .iter()
+ .map(|module| format!("pub use {module}::*;"))
+ .collect::<Vec<_>>()
+ .join("\n")
+ );
+
+ mod_rs_file.write_all(mod_rs_contents.as_bytes())?;
Ok(())
}
@@ -184,9 +251,9 @@ struct JsonSyntaxStyle {
}
/// Loads the [`Theme`] with the given name.
-fn load_theme(name: String) -> Result<(JsonTheme, LegacyTheme)> {
- let theme_contents = Assets::get(&format!("themes/{name}.json"))
- .with_context(|| format!("theme file not found: '{name}'"))?;
+fn load_theme(theme_path: &str) -> Result<(JsonTheme, LegacyTheme)> {
+ let theme_contents =
+ Assets::get(theme_path).with_context(|| format!("theme file not found: '{theme_path}'"))?;
let json_theme: JsonTheme = serde_json::from_str(std::str::from_utf8(&theme_contents.data)?)
.context("failed to parse legacy theme")?;
@@ -321,167 +388,3 @@ where
}
deserializer.deserialize_map(SyntaxVisitor)
}
-
-pub struct ThemePrinter(theme2::Theme);
-
-struct HslaPrinter(Hsla);
-
-impl Debug for HslaPrinter {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "{:?}", IntoPrinter(&Rgba::from(self.0)))
- }
-}
-
-struct IntoPrinter<'a, D: Debug>(&'a D);
-
-impl<'a, D: Debug> Debug for IntoPrinter<'a, D> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "{:?}.into()", self.0)
- }
-}
-
-impl Debug for ThemePrinter {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct("Theme")
- .field("metadata", &ThemeMetadataPrinter(self.0.metadata.clone()))
- .field("transparent", &HslaPrinter(self.0.transparent))
- .field(
- "mac_os_traffic_light_red",
- &HslaPrinter(self.0.mac_os_traffic_light_red),
- )
- .field(
- "mac_os_traffic_light_yellow",
- &HslaPrinter(self.0.mac_os_traffic_light_yellow),
- )
- .field(
- "mac_os_traffic_light_green",
- &HslaPrinter(self.0.mac_os_traffic_light_green),
- )
- .field("border", &HslaPrinter(self.0.border))
- .field("border_variant", &HslaPrinter(self.0.border_variant))
- .field("border_focused", &HslaPrinter(self.0.border_focused))
- .field(
- "border_transparent",
- &HslaPrinter(self.0.border_transparent),
- )
- .field("elevated_surface", &HslaPrinter(self.0.elevated_surface))
- .field("surface", &HslaPrinter(self.0.surface))
- .field("background", &HslaPrinter(self.0.background))
- .field("filled_element", &HslaPrinter(self.0.filled_element))
- .field(
- "filled_element_hover",
- &HslaPrinter(self.0.filled_element_hover),
- )
- .field(
- "filled_element_active",
- &HslaPrinter(self.0.filled_element_active),
- )
- .field(
- "filled_element_selected",
- &HslaPrinter(self.0.filled_element_selected),
- )
- .field(
- "filled_element_disabled",
- &HslaPrinter(self.0.filled_element_disabled),
- )
- .field("ghost_element", &HslaPrinter(self.0.ghost_element))
- .field(
- "ghost_element_hover",
- &HslaPrinter(self.0.ghost_element_hover),
- )
- .field(
- "ghost_element_active",
- &HslaPrinter(self.0.ghost_element_active),
- )
- .field(
- "ghost_element_selected",
- &HslaPrinter(self.0.ghost_element_selected),
- )
- .field(
- "ghost_element_disabled",
- &HslaPrinter(self.0.ghost_element_disabled),
- )
- .field("text", &HslaPrinter(self.0.text))
- .field("text_muted", &HslaPrinter(self.0.text_muted))
- .field("text_placeholder", &HslaPrinter(self.0.text_placeholder))
- .field("text_disabled", &HslaPrinter(self.0.text_disabled))
- .field("text_accent", &HslaPrinter(self.0.text_accent))
- .field("icon_muted", &HslaPrinter(self.0.icon_muted))
- .field("syntax", &SyntaxThemePrinter(self.0.syntax.clone()))
- .field("status_bar", &HslaPrinter(self.0.status_bar))
- .field("title_bar", &HslaPrinter(self.0.title_bar))
- .field("toolbar", &HslaPrinter(self.0.toolbar))
- .field("tab_bar", &HslaPrinter(self.0.tab_bar))
- .field("editor", &HslaPrinter(self.0.editor))
- .field("editor_subheader", &HslaPrinter(self.0.editor_subheader))
- .field(
- "editor_active_line",
- &HslaPrinter(self.0.editor_active_line),
- )
- .field("terminal", &HslaPrinter(self.0.terminal))
- .field(
- "image_fallback_background",
- &HslaPrinter(self.0.image_fallback_background),
- )
- .field("git_created", &HslaPrinter(self.0.git_created))
- .field("git_modified", &HslaPrinter(self.0.git_modified))
- .field("git_deleted", &HslaPrinter(self.0.git_deleted))
- .field("git_conflict", &HslaPrinter(self.0.git_conflict))
- .field("git_ignored", &HslaPrinter(self.0.git_ignored))
- .field("git_renamed", &HslaPrinter(self.0.git_renamed))
- .field("players", &self.0.players.map(PlayerThemePrinter))
- .finish()
- }
-}
-
-pub struct ThemeMetadataPrinter(ThemeMetadata);
-
-impl Debug for ThemeMetadataPrinter {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- f.debug_struct("ThemeMetadata")
- .field("name", &IntoPrinter(&self.0.name))
- .field("is_light", &self.0.is_light)
- .finish()
- }
-}
-
-pub struct SyntaxThemePrinter(SyntaxTheme);
-
-impl Debug for SyntaxThemePrinter {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- f.debug_struct("SyntaxTheme")
- .field(
- "highlights",
- &VecPrinter(
- &self
- .0
- .highlights
- .iter()
- .map(|(token, highlight)| {
- (IntoPrinter(token), HslaPrinter(highlight.color.unwrap()))
- })
- .collect(),
- ),
- )
- .finish()
- }
-}
-
-pub struct VecPrinter<'a, T>(&'a Vec<T>);
-
-impl<'a, T: Debug> Debug for VecPrinter<'a, T> {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- write!(f, "vec!{:?}", &self.0)
- }
-}
-
-pub struct PlayerThemePrinter(PlayerTheme);
-
-impl Debug for PlayerThemePrinter {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- f.debug_struct("PlayerTheme")
- .field("cursor", &HslaPrinter(self.0.cursor))
- .field("selection", &HslaPrinter(self.0.selection))
- .finish()
- }
-}
@@ -0,0 +1,174 @@
+use std::fmt::{self, Debug};
+
+use gpui2::{Hsla, Rgba};
+use theme2::{PlayerTheme, SyntaxTheme, Theme, ThemeMetadata};
+
+pub struct ThemePrinter(Theme);
+
+impl ThemePrinter {
+ pub fn new(theme: Theme) -> Self {
+ Self(theme)
+ }
+}
+
+struct HslaPrinter(Hsla);
+
+impl Debug for HslaPrinter {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "{:?}", IntoPrinter(&Rgba::from(self.0)))
+ }
+}
+
+struct IntoPrinter<'a, D: Debug>(&'a D);
+
+impl<'a, D: Debug> Debug for IntoPrinter<'a, D> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "{:?}.into()", self.0)
+ }
+}
+
+impl Debug for ThemePrinter {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("Theme")
+ .field("metadata", &ThemeMetadataPrinter(self.0.metadata.clone()))
+ .field("transparent", &HslaPrinter(self.0.transparent))
+ .field(
+ "mac_os_traffic_light_red",
+ &HslaPrinter(self.0.mac_os_traffic_light_red),
+ )
+ .field(
+ "mac_os_traffic_light_yellow",
+ &HslaPrinter(self.0.mac_os_traffic_light_yellow),
+ )
+ .field(
+ "mac_os_traffic_light_green",
+ &HslaPrinter(self.0.mac_os_traffic_light_green),
+ )
+ .field("border", &HslaPrinter(self.0.border))
+ .field("border_variant", &HslaPrinter(self.0.border_variant))
+ .field("border_focused", &HslaPrinter(self.0.border_focused))
+ .field(
+ "border_transparent",
+ &HslaPrinter(self.0.border_transparent),
+ )
+ .field("elevated_surface", &HslaPrinter(self.0.elevated_surface))
+ .field("surface", &HslaPrinter(self.0.surface))
+ .field("background", &HslaPrinter(self.0.background))
+ .field("filled_element", &HslaPrinter(self.0.filled_element))
+ .field(
+ "filled_element_hover",
+ &HslaPrinter(self.0.filled_element_hover),
+ )
+ .field(
+ "filled_element_active",
+ &HslaPrinter(self.0.filled_element_active),
+ )
+ .field(
+ "filled_element_selected",
+ &HslaPrinter(self.0.filled_element_selected),
+ )
+ .field(
+ "filled_element_disabled",
+ &HslaPrinter(self.0.filled_element_disabled),
+ )
+ .field("ghost_element", &HslaPrinter(self.0.ghost_element))
+ .field(
+ "ghost_element_hover",
+ &HslaPrinter(self.0.ghost_element_hover),
+ )
+ .field(
+ "ghost_element_active",
+ &HslaPrinter(self.0.ghost_element_active),
+ )
+ .field(
+ "ghost_element_selected",
+ &HslaPrinter(self.0.ghost_element_selected),
+ )
+ .field(
+ "ghost_element_disabled",
+ &HslaPrinter(self.0.ghost_element_disabled),
+ )
+ .field("text", &HslaPrinter(self.0.text))
+ .field("text_muted", &HslaPrinter(self.0.text_muted))
+ .field("text_placeholder", &HslaPrinter(self.0.text_placeholder))
+ .field("text_disabled", &HslaPrinter(self.0.text_disabled))
+ .field("text_accent", &HslaPrinter(self.0.text_accent))
+ .field("icon_muted", &HslaPrinter(self.0.icon_muted))
+ .field("syntax", &SyntaxThemePrinter(self.0.syntax.clone()))
+ .field("status_bar", &HslaPrinter(self.0.status_bar))
+ .field("title_bar", &HslaPrinter(self.0.title_bar))
+ .field("toolbar", &HslaPrinter(self.0.toolbar))
+ .field("tab_bar", &HslaPrinter(self.0.tab_bar))
+ .field("editor", &HslaPrinter(self.0.editor))
+ .field("editor_subheader", &HslaPrinter(self.0.editor_subheader))
+ .field(
+ "editor_active_line",
+ &HslaPrinter(self.0.editor_active_line),
+ )
+ .field("terminal", &HslaPrinter(self.0.terminal))
+ .field(
+ "image_fallback_background",
+ &HslaPrinter(self.0.image_fallback_background),
+ )
+ .field("git_created", &HslaPrinter(self.0.git_created))
+ .field("git_modified", &HslaPrinter(self.0.git_modified))
+ .field("git_deleted", &HslaPrinter(self.0.git_deleted))
+ .field("git_conflict", &HslaPrinter(self.0.git_conflict))
+ .field("git_ignored", &HslaPrinter(self.0.git_ignored))
+ .field("git_renamed", &HslaPrinter(self.0.git_renamed))
+ .field("players", &self.0.players.map(PlayerThemePrinter))
+ .finish()
+ }
+}
+
+pub struct ThemeMetadataPrinter(ThemeMetadata);
+
+impl Debug for ThemeMetadataPrinter {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ f.debug_struct("ThemeMetadata")
+ .field("name", &IntoPrinter(&self.0.name))
+ .field("is_light", &self.0.is_light)
+ .finish()
+ }
+}
+
+pub struct SyntaxThemePrinter(SyntaxTheme);
+
+impl Debug for SyntaxThemePrinter {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ f.debug_struct("SyntaxTheme")
+ .field(
+ "highlights",
+ &VecPrinter(
+ &self
+ .0
+ .highlights
+ .iter()
+ .map(|(token, highlight)| {
+ (IntoPrinter(token), HslaPrinter(highlight.color.unwrap()))
+ })
+ .collect(),
+ ),
+ )
+ .finish()
+ }
+}
+
+pub struct VecPrinter<'a, T>(&'a Vec<T>);
+
+impl<'a, T: Debug> Debug for VecPrinter<'a, T> {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ write!(f, "vec!{:?}", &self.0)
+ }
+}
+
+pub struct PlayerThemePrinter(PlayerTheme);
+
+impl Debug for PlayerThemePrinter {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ f.debug_struct("PlayerTheme")
+ .field("cursor", &HslaPrinter(self.0.cursor))
+ .field("selection", &HslaPrinter(self.0.selection))
+ .finish()
+ }
+}
@@ -1,7 +1,6 @@
-use gpui2::{rems, AbsoluteLength};
-
use crate::prelude::*;
use crate::{Icon, IconButton, Label, Panel, PanelSide};
+use gpui2::{rems, AbsoluteLength};
#[derive(Component)]
pub struct AssistantPanel {
@@ -76,15 +75,15 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
- use crate::Story;
-
use super::*;
-
- #[derive(Component)]
+ use crate::Story;
+ use gpui2::{Div, Render};
pub struct AssistantPanelStory;
- impl AssistantPanelStory {
- fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
+ impl Render for AssistantPanelStory {
+ type Element = Div<Self>;
+
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
Story::container(cx)
.child(Story::title_for::<_, AssistantPanel>(cx))
.child(Story::label(cx, "Default"))
@@ -73,21 +73,17 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
- use std::str::FromStr;
-
- use crate::Story;
-
use super::*;
+ use crate::Story;
+ use gpui2::Render;
+ use std::str::FromStr;
- #[derive(Component)]
pub struct BreadcrumbStory;
- impl BreadcrumbStory {
- fn render<V: 'static>(
- self,
- view_state: &mut V,
- cx: &mut ViewContext<V>,
- ) -> impl Component<V> {
+ impl Render for BreadcrumbStory {
+ type Element = Div<Self>;
+
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
let theme = theme(cx);
Story::container(cx)
@@ -233,20 +233,19 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
- use gpui2::rems;
-
+ use super::*;
use crate::{
empty_buffer_example, hello_world_rust_buffer_example,
hello_world_rust_buffer_with_status_example, Story,
};
+ use gpui2::{rems, Div, Render};
- use super::*;
-
- #[derive(Component)]
pub struct BufferStory;
- impl BufferStory {
- fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
+ impl Render for BufferStory {
+ type Element = Div<Self>;
+
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
let theme = theme(cx);
Story::container(cx)
@@ -1,4 +1,4 @@
-use gpui2::{AppContext, Context, View};
+use gpui2::{Div, Render, View, VisualContext};
use crate::prelude::*;
use crate::{h_stack, Icon, IconButton, IconColor, Input};
@@ -21,15 +21,15 @@ impl BufferSearch {
cx.notify();
}
- pub fn view(cx: &mut AppContext) -> View<Self> {
- {
- let state = cx.entity(|cx| Self::new());
- let render = Self::render;
- View::for_handle(state, render)
- }
+ pub fn view(cx: &mut WindowContext) -> View<Self> {
+ cx.build_view(|cx| Self::new())
}
+}
+
+impl Render for BufferSearch {
+ type Element = Div<Self>;
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Component<Self> {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Div<Self> {
let theme = theme(cx);
h_stack().bg(theme.toolbar).p_2().child(
@@ -108,16 +108,18 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
use chrono::DateTime;
+ use gpui2::{Div, Render};
use crate::{Panel, Story};
use super::*;
- #[derive(Component)]
pub struct ChatPanelStory;
- impl ChatPanelStory {
- fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
+ impl Render for ChatPanelStory {
+ type Element = Div<Self>;
+
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
Story::container(cx)
.child(Story::title_for::<_, ChatPanel>(cx))
.child(Story::label(cx, "Default"))
@@ -89,15 +89,16 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
- use crate::Story;
-
use super::*;
+ use crate::Story;
+ use gpui2::{Div, Render};
- #[derive(Component)]
pub struct CollabPanelStory;
- impl CollabPanelStory {
- fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
+ impl Render for CollabPanelStory {
+ type Element = Div<Self>;
+
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
Story::container(cx)
.child(Story::title_for::<_, CollabPanel>(cx))
.child(Story::label(cx, "Default"))
@@ -27,15 +27,18 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
+ use gpui2::{Div, Render};
+
use crate::Story;
use super::*;
- #[derive(Component)]
pub struct CommandPaletteStory;
- impl CommandPaletteStory {
- fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
+ impl Render for CommandPaletteStory {
+ type Element = Div<Self>;
+
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
Story::container(cx)
.child(Story::title_for::<_, CommandPalette>(cx))
.child(Story::label(cx, "Default"))
@@ -68,15 +68,16 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
- use crate::story::Story;
-
use super::*;
+ use crate::story::Story;
+ use gpui2::{Div, Render};
- #[derive(Component)]
pub struct ContextMenuStory;
- impl ContextMenuStory {
- fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
+ impl Render for ContextMenuStory {
+ type Element = Div<Self>;
+
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
Story::container(cx)
.child(Story::title_for::<_, ContextMenu>(cx))
.child(Story::label(cx, "Default"))
@@ -25,15 +25,18 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
+ use gpui2::{Div, Render};
+
use crate::Story;
use super::*;
- #[derive(Component)]
pub struct CopilotModalStory;
- impl CopilotModalStory {
- fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
+ impl Render for CopilotModalStory {
+ type Element = Div<Self>;
+
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
Story::container(cx)
.child(Story::title_for::<_, CopilotModal>(cx))
.child(Story::label(cx, "Default"))
@@ -1,6 +1,6 @@
use std::path::PathBuf;
-use gpui2::{AppContext, Context, View};
+use gpui2::{Div, Render, View, VisualContext};
use crate::prelude::*;
use crate::{
@@ -20,7 +20,7 @@ pub struct EditorPane {
impl EditorPane {
pub fn new(
- cx: &mut AppContext,
+ cx: &mut ViewContext<Self>,
tabs: Vec<Tab>,
path: PathBuf,
symbols: Vec<Symbol>,
@@ -42,15 +42,15 @@ impl EditorPane {
cx.notify();
}
- pub fn view(cx: &mut AppContext) -> View<Self> {
- {
- let state = cx.entity(|cx| hello_world_rust_editor_with_status_example(cx));
- let render = Self::render;
- View::for_handle(state, render)
- }
+ pub fn view(cx: &mut WindowContext) -> View<Self> {
+ cx.build_view(|cx| hello_world_rust_editor_with_status_example(cx))
}
+}
+
+impl Render for EditorPane {
+ type Element = Div<Self>;
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Component<Self> {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Div<Self> {
v_stack()
.w_full()
.h_full()
@@ -31,15 +31,16 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
- use crate::{static_players, Story};
-
use super::*;
+ use crate::{static_players, Story};
+ use gpui2::{Div, Render};
- #[derive(Component)]
pub struct FacepileStory;
- impl FacepileStory {
- fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
+ impl Render for FacepileStory {
+ type Element = Div<Self>;
+
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
let players = static_players();
Story::container(cx)
@@ -158,17 +158,17 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
- use itertools::Itertools;
-
- use crate::Story;
-
use super::*;
+ use crate::Story;
+ use gpui2::{Div, Render};
+ use itertools::Itertools;
- #[derive(Component)]
pub struct KeybindingStory;
- impl KeybindingStory {
- fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
+ impl Render for KeybindingStory {
+ type Element = Div<Self>;
+
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
let all_modifier_permutations = ModifierKey::iter().permutations(2);
Story::container(cx)
@@ -38,15 +38,16 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
- use crate::Story;
-
use super::*;
+ use crate::Story;
+ use gpui2::{Div, Render};
- #[derive(Component)]
pub struct LanguageSelectorStory;
- impl LanguageSelectorStory {
- fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
+ impl Render for LanguageSelectorStory {
+ type Element = Div<Self>;
+
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
Story::container(cx)
.child(Story::title_for::<_, LanguageSelector>(cx))
.child(Story::label(cx, "Default"))
@@ -40,15 +40,16 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
- use crate::{hello_world_rust_buffer_example, Story};
-
use super::*;
+ use crate::{hello_world_rust_buffer_example, Story};
+ use gpui2::{Div, Render};
- #[derive(Component)]
pub struct MultiBufferStory;
- impl MultiBufferStory {
- fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
+ impl Render for MultiBufferStory {
+ type Element = Div<Self>;
+
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
let theme = theme(cx);
Story::container(cx)
@@ -48,15 +48,16 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
- use crate::{Panel, Story};
-
use super::*;
+ use crate::{Panel, Story};
+ use gpui2::{Div, Render};
- #[derive(Component)]
pub struct NotificationsPanelStory;
- impl NotificationsPanelStory {
- fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
+ impl Render for NotificationsPanelStory {
+ type Element = Div<Self>;
+
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
Story::container(cx)
.child(Story::title_for::<_, NotificationsPanel>(cx))
.child(Story::label(cx, "Default"))
@@ -152,58 +152,71 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
+ use gpui2::{Div, Render};
+
use crate::{ModifierKeys, Story};
use super::*;
- #[derive(Component)]
pub struct PaletteStory;
- impl PaletteStory {
- fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
- Story::container(cx)
- .child(Story::title_for::<_, Palette>(cx))
- .child(Story::label(cx, "Default"))
- .child(Palette::new("palette-1"))
- .child(Story::label(cx, "With Items"))
- .child(
- Palette::new("palette-2")
- .placeholder("Execute a command...")
- .items(vec![
- PaletteItem::new("theme selector: toggle").keybinding(
- Keybinding::new_chord(
- ("k".to_string(), ModifierKeys::new().command(true)),
- ("t".to_string(), ModifierKeys::new().command(true)),
+ impl Render for PaletteStory {
+ type Element = Div<Self>;
+
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
+ {
+ Story::container(cx)
+ .child(Story::title_for::<_, Palette>(cx))
+ .child(Story::label(cx, "Default"))
+ .child(Palette::new("palette-1"))
+ .child(Story::label(cx, "With Items"))
+ .child(
+ Palette::new("palette-2")
+ .placeholder("Execute a command...")
+ .items(vec![
+ PaletteItem::new("theme selector: toggle").keybinding(
+ Keybinding::new_chord(
+ ("k".to_string(), ModifierKeys::new().command(true)),
+ ("t".to_string(), ModifierKeys::new().command(true)),
+ ),
+ ),
+ PaletteItem::new("assistant: inline assist").keybinding(
+ Keybinding::new(
+ "enter".to_string(),
+ ModifierKeys::new().command(true),
+ ),
+ ),
+ PaletteItem::new("assistant: quote selection").keybinding(
+ Keybinding::new(
+ ">".to_string(),
+ ModifierKeys::new().command(true),
+ ),
+ ),
+ PaletteItem::new("assistant: toggle focus").keybinding(
+ Keybinding::new(
+ "?".to_string(),
+ ModifierKeys::new().command(true),
+ ),
),
- ),
- PaletteItem::new("assistant: inline assist").keybinding(
- Keybinding::new(
- "enter".to_string(),
- ModifierKeys::new().command(true),
+ PaletteItem::new("auto update: check"),
+ PaletteItem::new("auto update: view release notes"),
+ PaletteItem::new("branches: open recent").keybinding(
+ Keybinding::new(
+ "b".to_string(),
+ ModifierKeys::new().command(true).alt(true),
+ ),
),
- ),
- PaletteItem::new("assistant: quote selection").keybinding(
- Keybinding::new(">".to_string(), ModifierKeys::new().command(true)),
- ),
- PaletteItem::new("assistant: toggle focus").keybinding(
- Keybinding::new("?".to_string(), ModifierKeys::new().command(true)),
- ),
- PaletteItem::new("auto update: check"),
- PaletteItem::new("auto update: view release notes"),
- PaletteItem::new("branches: open recent").keybinding(Keybinding::new(
- "b".to_string(),
- ModifierKeys::new().command(true).alt(true),
- )),
- PaletteItem::new("chat panel: toggle focus"),
- PaletteItem::new("cli: install"),
- PaletteItem::new("client: sign in"),
- PaletteItem::new("client: sign out"),
- PaletteItem::new("editor: cancel").keybinding(Keybinding::new(
- "escape".to_string(),
- ModifierKeys::new(),
- )),
- ]),
- )
+ PaletteItem::new("chat panel: toggle focus"),
+ PaletteItem::new("cli: install"),
+ PaletteItem::new("client: sign in"),
+ PaletteItem::new("client: sign out"),
+ PaletteItem::new("editor: cancel").keybinding(Keybinding::new(
+ "escape".to_string(),
+ ModifierKeys::new(),
+ )),
+ ]),
+ )
+ }
}
}
}
@@ -128,17 +128,18 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
- use crate::{Label, Story};
-
use super::*;
+ use crate::{Label, Story};
+ use gpui2::{Div, Render};
- #[derive(Component)]
pub struct PanelStory;
- impl PanelStory {
- fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
+ impl Render for PanelStory {
+ type Element = Div<Self>;
+
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
Story::container(cx)
- .child(Story::title_for::<_, Panel<V>>(cx))
+ .child(Story::title_for::<_, Panel<Self>>(cx))
.child(Story::label(cx, "Default"))
.child(
Panel::new("panel", cx).child(
@@ -1,4 +1,4 @@
-use gpui2::{hsla, red, AnyElement, ElementId, ExternalPaths, Hsla, Length, Size};
+use gpui2::{hsla, red, AnyElement, ElementId, ExternalPaths, Hsla, Length, Size, View};
use smallvec::SmallVec;
use crate::prelude::*;
@@ -18,13 +18,6 @@ pub struct Pane<V: 'static> {
children: SmallVec<[AnyElement<V>; 2]>,
}
-// impl<V: 'static> IntoAnyElement<V> for Pane<V> {
-// fn into_any(self) -> AnyElement<V> {
-// (move |view_state: &mut V, cx: &mut ViewContext<'_, '_, V>| self.render(view_state, cx))
-// .into_any()
-// }
-// }
-
impl<V: 'static> Pane<V> {
pub fn new(id: impl Into<ElementId>, size: Size<Length>) -> Self {
// Fill is only here for debugging purposes, remove before release
@@ -57,8 +50,8 @@ impl<V: 'static> Pane<V> {
.z_index(1)
.id("drag-target")
.drag_over::<ExternalPaths>(|d| d.bg(red()))
- .on_drop(|_, files: ExternalPaths, _| {
- dbg!("dropped files!", files);
+ .on_drop(|_, files: View<ExternalPaths>, cx| {
+ dbg!("dropped files!", files.read(cx));
})
.absolute()
.inset_0(),
@@ -57,15 +57,16 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
- use crate::{Panel, Story};
-
use super::*;
+ use crate::{Panel, Story};
+ use gpui2::{Div, Render};
- #[derive(Component)]
pub struct ProjectPanelStory;
- impl ProjectPanelStory {
- fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
+ impl Render for ProjectPanelStory {
+ type Element = Div<Self>;
+
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
Story::container(cx)
.child(Story::title_for::<_, ProjectPanel>(cx))
.child(Story::label(cx, "Default"))
@@ -34,15 +34,16 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
- use crate::Story;
-
use super::*;
+ use crate::Story;
+ use gpui2::{Div, Render};
- #[derive(Component)]
pub struct RecentProjectsStory;
- impl RecentProjectsStory {
- fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
+ impl Render for RecentProjectsStory {
+ type Element = Div<Self>;
+
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
Story::container(cx)
.child(Story::title_for::<_, RecentProjects>(cx))
.child(Story::label(cx, "Default"))
@@ -1,5 +1,6 @@
use crate::prelude::*;
use crate::{Icon, IconColor, IconElement, Label, LabelColor};
+use gpui2::{black, red, Div, ElementId, Render, View, VisualContext};
#[derive(Component, Clone)]
pub struct Tab {
@@ -19,6 +20,14 @@ struct TabDragState {
title: String,
}
+impl Render for TabDragState {
+ type Element = Div<Self>;
+
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
+ div().w_8().h_4().bg(red())
+ }
+}
+
impl Tab {
pub fn new(id: impl Into<ElementId>) -> Self {
Self {
@@ -118,12 +127,10 @@ impl Tab {
div()
.id(self.id.clone())
- .on_drag(move |_view, _cx| {
- Drag::new(drag_state.clone(), |view, cx| div().w_8().h_4().bg(red()))
- })
+ .on_drag(move |_view, cx| cx.build_view(|cx| drag_state.clone()))
.drag_over::<TabDragState>(|d| d.bg(black()))
- .on_drop(|_view, state: TabDragState, cx| {
- dbg!(state);
+ .on_drop(|_view, state: View<TabDragState>, cx| {
+ dbg!(state.read(cx));
})
.px_2()
.py_0p5()
@@ -160,23 +167,21 @@ impl Tab {
}
}
-use gpui2::{black, red, Drag, ElementId};
#[cfg(feature = "stories")]
pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
- use strum::IntoEnumIterator;
-
- use crate::{h_stack, v_stack, Icon, Story};
-
use super::*;
+ use crate::{h_stack, v_stack, Icon, Story};
+ use strum::IntoEnumIterator;
- #[derive(Component)]
pub struct TabStory;
- impl TabStory {
- fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
+ impl Render for TabStory {
+ type Element = Div<Self>;
+
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
let git_statuses = GitStatus::iter();
let fs_statuses = FileSystemStatus::iter();
@@ -92,15 +92,16 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
- use crate::Story;
-
use super::*;
+ use crate::Story;
+ use gpui2::{Div, Render};
- #[derive(Component)]
pub struct TabBarStory;
- impl TabBarStory {
- fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
+ impl Render for TabBarStory {
+ type Element = Div<Self>;
+
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
Story::container(cx)
.child(Story::title_for::<_, TabBar>(cx))
.child(Story::label(cx, "Default"))
@@ -83,15 +83,15 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
- use crate::Story;
-
use super::*;
-
- #[derive(Component)]
+ use crate::Story;
+ use gpui2::{Div, Render};
pub struct TerminalStory;
- impl TerminalStory {
- fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
+ impl Render for TerminalStory {
+ type Element = Div<Self>;
+
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
Story::container(cx)
.child(Story::title_for::<_, Terminal>(cx))
.child(Story::label(cx, "Default"))
@@ -39,15 +39,18 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
+ use gpui2::{Div, Render};
+
use crate::Story;
use super::*;
- #[derive(Component)]
pub struct ThemeSelectorStory;
- impl ThemeSelectorStory {
- fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
+ impl Render for ThemeSelectorStory {
+ type Element = Div<Self>;
+
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
Story::container(cx)
.child(Story::title_for::<_, ThemeSelector>(cx))
.child(Story::label(cx, "Default"))
@@ -1,7 +1,7 @@
use std::sync::atomic::AtomicBool;
use std::sync::Arc;
-use gpui2::{AppContext, Context, ModelContext, View};
+use gpui2::{Div, Render, View, VisualContext};
use crate::prelude::*;
use crate::settings::user_settings;
@@ -28,7 +28,7 @@ pub struct TitleBar {
}
impl TitleBar {
- pub fn new(cx: &mut ModelContext<Self>) -> Self {
+ pub fn new(cx: &mut ViewContext<Self>) -> Self {
let is_active = Arc::new(AtomicBool::new(true));
let active = is_active.clone();
@@ -80,15 +80,15 @@ impl TitleBar {
cx.notify();
}
- pub fn view(cx: &mut AppContext, livestream: Option<Livestream>) -> View<Self> {
- {
- let state = cx.entity(|cx| Self::new(cx).set_livestream(livestream));
- let render = Self::render;
- View::for_handle(state, render)
- }
+ pub fn view(cx: &mut WindowContext, livestream: Option<Livestream>) -> View<Self> {
+ cx.build_view(|cx| Self::new(cx).set_livestream(livestream))
}
+}
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Component<Self> {
+impl Render for TitleBar {
+ type Element = Div<Self>;
+
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Div<Self> {
let theme = theme(cx);
let settings = user_settings(cx);
@@ -187,26 +187,25 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
- use crate::Story;
-
use super::*;
+ use crate::Story;
pub struct TitleBarStory {
title_bar: View<TitleBar>,
}
impl TitleBarStory {
- pub fn view(cx: &mut AppContext) -> View<Self> {
- {
- let state = cx.entity(|cx| Self {
- title_bar: TitleBar::view(cx, None),
- });
- let render = Self::render;
- View::for_handle(state, render)
- }
+ pub fn view(cx: &mut WindowContext) -> View<Self> {
+ cx.build_view(|cx| Self {
+ title_bar: TitleBar::view(cx, None),
+ })
}
+ }
+
+ impl Render for TitleBarStory {
+ type Element = Div<Self>;
- fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Component<Self> {
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Div<Self> {
Story::container(cx)
.child(Story::title_for::<_, TitleBar>(cx))
.child(Story::label(cx, "Default"))
@@ -72,17 +72,20 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
+ use gpui2::{Div, Render};
+
use crate::{Label, Story};
use super::*;
- #[derive(Component)]
pub struct ToastStory;
- impl ToastStory {
- fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
+ impl Render for ToastStory {
+ type Element = Div<Self>;
+
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
Story::container(cx)
- .child(Story::title_for::<_, Toast<V>>(cx))
+ .child(Story::title_for::<_, Toast<Self>>(cx))
.child(Story::label(cx, "Default"))
.child(Toast::new(ToastOrigin::Bottom).child(Label::new("label")))
}
@@ -75,19 +75,22 @@ mod stories {
use std::path::PathBuf;
use std::str::FromStr;
+ use gpui2::{Div, Render};
+
use crate::{Breadcrumb, HighlightedText, Icon, IconButton, Story, Symbol};
use super::*;
- #[derive(Component)]
pub struct ToolbarStory;
- impl ToolbarStory {
- fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
+ impl Render for ToolbarStory {
+ type Element = Div<Self>;
+
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
let theme = theme(cx);
Story::container(cx)
- .child(Story::title_for::<_, Toolbar<V>>(cx))
+ .child(Story::title_for::<_, Toolbar<Self>>(cx))
.child(Story::label(cx, "Default"))
.child(
Toolbar::new()
@@ -77,15 +77,18 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
+ use gpui2::{Div, Render};
+
use crate::Story;
use super::*;
- #[derive(Component)]
pub struct TrafficLightsStory;
- impl TrafficLightsStory {
- fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
+ impl Render for TrafficLightsStory {
+ type Element = Div<Self>;
+
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
Story::container(cx)
.child(Story::title_for::<_, TrafficLights>(cx))
.child(Story::label(cx, "Default"))
@@ -1,15 +1,15 @@
use std::sync::Arc;
use chrono::DateTime;
-use gpui2::{px, relative, rems, AppContext, Context, Size, View};
+use gpui2::{px, relative, rems, Div, Render, Size, View, VisualContext};
+use crate::{prelude::*, NotificationsPanel};
use crate::{
- old_theme, static_livestream, user_settings_mut, v_stack, AssistantPanel, Button, ChatMessage,
- ChatPanel, CollabPanel, EditorPane, FakeSettings, Label, LanguageSelector, Pane, PaneGroup,
- Panel, PanelAllowedSides, PanelSide, ProjectPanel, SettingValue, SplitDirection, StatusBar,
- Terminal, TitleBar, Toast, ToastOrigin,
+ static_livestream, user_settings_mut, v_stack, AssistantPanel, Button, ChatMessage, ChatPanel,
+ CollabPanel, EditorPane, FakeSettings, Label, LanguageSelector, Pane, PaneGroup, Panel,
+ PanelAllowedSides, PanelSide, ProjectPanel, SettingValue, SplitDirection, StatusBar, Terminal,
+ TitleBar, Toast, ToastOrigin,
};
-use crate::{prelude::*, NotificationsPanel};
#[derive(Clone)]
pub struct Gpui2UiDebug {
@@ -44,7 +44,7 @@ pub struct Workspace {
}
impl Workspace {
- pub fn new(cx: &mut AppContext) -> Self {
+ pub fn new(cx: &mut ViewContext<Self>) -> Self {
Self {
title_bar: TitleBar::view(cx, None),
editor_1: EditorPane::view(cx),
@@ -170,16 +170,16 @@ impl Workspace {
cx.notify();
}
- pub fn view(cx: &mut AppContext) -> View<Self> {
- {
- let state = cx.entity(|cx| Self::new(cx));
- let render = Self::render;
- View::for_handle(state, render)
- }
+ pub fn view(cx: &mut WindowContext) -> View<Self> {
+ cx.build_view(|cx| Self::new(cx))
}
+}
+
+impl Render for Workspace {
+ type Element = Div<Self>;
- pub fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Component<Self> {
- let theme = old_theme(cx).clone();
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Div<Self> {
+ let theme = theme(cx);
// HACK: This should happen inside of `debug_toggle_user_settings`, but
// we don't have `cx.global::<FakeSettings>()` in event handlers at the moment.
@@ -216,8 +216,8 @@ impl Workspace {
.gap_0()
.justify_start()
.items_start()
- .text_color(theme.lowest.base.default.foreground)
- .bg(theme.lowest.base.default.background)
+ .text_color(theme.text)
+ .bg(theme.background)
.child(self.title_bar.clone())
.child(
div()
@@ -228,7 +228,7 @@ impl Workspace {
.overflow_hidden()
.border_t()
.border_b()
- .border_color(theme.lowest.base.default.border)
+ .border_color(theme.border)
.children(
Some(
Panel::new("project-panel-outer", cx)
@@ -355,9 +355,8 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
- use gpui2::VisualContext;
-
use super::*;
+ use gpui2::VisualContext;
pub struct WorkspaceStory {
workspace: View<Workspace>,
@@ -365,12 +364,17 @@ mod stories {
impl WorkspaceStory {
pub fn view(cx: &mut WindowContext) -> View<Self> {
- cx.build_view(
- |cx| Self {
- workspace: Workspace::view(cx),
- },
- |view, cx| view.workspace.clone(),
- )
+ cx.build_view(|cx| Self {
+ workspace: Workspace::view(cx),
+ })
+ }
+ }
+
+ impl Render for WorkspaceStory {
+ type Element = Div<Self>;
+
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
+ div().child(self.workspace.clone())
}
}
}
@@ -43,15 +43,16 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
- use crate::Story;
-
use super::*;
+ use crate::Story;
+ use gpui2::{Div, Render};
- #[derive(Component)]
pub struct AvatarStory;
- impl AvatarStory {
- fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
+ impl Render for AvatarStory {
+ type Element = Div<Self>;
+
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
Story::container(cx)
.child(Story::title_for::<_, Avatar>(cx))
.child(Story::label(cx, "Default"))
@@ -219,22 +219,21 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
- use gpui2::rems;
- use strum::IntoEnumIterator;
-
- use crate::{h_stack, v_stack, LabelColor, Story};
-
use super::*;
+ use crate::{h_stack, v_stack, LabelColor, Story};
+ use gpui2::{rems, Div, Render};
+ use strum::IntoEnumIterator;
- #[derive(Component)]
pub struct ButtonStory;
- impl ButtonStory {
- fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
+ impl Render for ButtonStory {
+ type Element = Div<Self>;
+
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
let states = InteractionState::iter();
Story::container(cx)
- .child(Story::title_for::<_, Button<V>>(cx))
+ .child(Story::title_for::<_, Button<Self>>(cx))
.child(
div()
.flex()
@@ -46,17 +46,18 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
- use crate::{Button, Story};
-
use super::*;
+ use crate::{Button, Story};
+ use gpui2::{Div, Render};
- #[derive(Component)]
pub struct DetailsStory;
- impl DetailsStory {
- fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
+ impl Render for DetailsStory {
+ type Element = Div<Self>;
+
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
Story::container(cx)
- .child(Story::title_for::<_, Details<V>>(cx))
+ .child(Story::title_for::<_, Details<Self>>(cx))
.child(Story::label(cx, "Default"))
.child(Details::new("The quick brown fox jumps over the lazy dog"))
.child(Story::label(cx, "With meta"))
@@ -2,7 +2,6 @@ use gpui2::{svg, Hsla};
use strum::EnumIter;
use crate::prelude::*;
-use crate::theme::old_theme;
#[derive(Default, PartialEq, Copy, Clone)]
pub enum IconSize {
@@ -27,17 +26,17 @@ pub enum IconColor {
impl IconColor {
pub fn color(self, cx: &WindowContext) -> Hsla {
- let theme = old_theme(cx);
+ let theme = theme(cx);
match self {
- IconColor::Default => theme.lowest.base.default.foreground,
- IconColor::Muted => theme.lowest.variant.default.foreground,
- IconColor::Disabled => theme.lowest.base.disabled.foreground,
- IconColor::Placeholder => theme.lowest.base.disabled.foreground,
- IconColor::Accent => theme.lowest.accent.default.foreground,
- IconColor::Error => theme.lowest.negative.default.foreground,
- IconColor::Warning => theme.lowest.warning.default.foreground,
- IconColor::Success => theme.lowest.positive.default.foreground,
- IconColor::Info => theme.lowest.accent.default.foreground,
+ IconColor::Default => gpui2::red(),
+ IconColor::Muted => gpui2::red(),
+ IconColor::Disabled => gpui2::red(),
+ IconColor::Placeholder => gpui2::red(),
+ IconColor::Accent => gpui2::red(),
+ IconColor::Error => gpui2::red(),
+ IconColor::Warning => gpui2::red(),
+ IconColor::Success => gpui2::red(),
+ IconColor::Info => gpui2::red(),
}
}
}
@@ -192,17 +191,19 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
+ use gpui2::{Div, Render};
use strum::IntoEnumIterator;
use crate::Story;
use super::*;
- #[derive(Component)]
pub struct IconStory;
- impl IconStory {
- fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
+ impl Render for IconStory {
+ type Element = Div<Self>;
+
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
let icons = Icon::iter();
Story::container(cx)
@@ -112,15 +112,16 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
- use crate::Story;
-
use super::*;
+ use crate::Story;
+ use gpui2::{Div, Render};
- #[derive(Component)]
pub struct InputStory;
- impl InputStory {
- fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
+ impl Render for InputStory {
+ type Element = Div<Self>;
+
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
Story::container(cx)
.child(Story::title_for::<_, Input>(cx))
.child(Story::label(cx, "Default"))
@@ -2,8 +2,6 @@ use gpui2::{relative, Hsla, WindowContext};
use smallvec::SmallVec;
use crate::prelude::*;
-use crate::theme::old_theme;
-
#[derive(Default, PartialEq, Copy, Clone)]
pub enum LabelColor {
#[default]
@@ -21,19 +19,17 @@ pub enum LabelColor {
impl LabelColor {
pub fn hsla(&self, cx: &WindowContext) -> Hsla {
let theme = theme(cx);
- // TODO: Remove
- let old_theme = old_theme(cx);
match self {
Self::Default => theme.text,
Self::Muted => theme.text_muted,
- Self::Created => old_theme.middle.positive.default.foreground,
- Self::Modified => old_theme.middle.warning.default.foreground,
- Self::Deleted => old_theme.middle.negative.default.foreground,
+ Self::Created => gpui2::red(),
+ Self::Modified => gpui2::red(),
+ Self::Deleted => gpui2::red(),
Self::Disabled => theme.text_disabled,
- Self::Hidden => old_theme.middle.variant.default.foreground,
+ Self::Hidden => gpui2::red(),
Self::Placeholder => theme.text_placeholder,
- Self::Accent => old_theme.middle.accent.default.foreground,
+ Self::Accent => gpui2::red(),
}
}
}
@@ -201,15 +197,16 @@ pub use stories::*;
#[cfg(feature = "stories")]
mod stories {
- use crate::Story;
-
use super::*;
+ use crate::Story;
+ use gpui2::{Div, Render};
- #[derive(Component)]
pub struct LabelStory;
- impl LabelStory {
- fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
+ impl Render for LabelStory {
+ type Element = Div<Self>;
+
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
Story::container(cx)
.child(Story::title_for::<_, Label>(cx))
.child(Story::label(cx, "Default"))
@@ -23,7 +23,6 @@ mod elevation;
pub mod prelude;
pub mod settings;
mod static_data;
-mod theme;
pub use components::*;
pub use elements::*;
@@ -38,7 +37,6 @@ pub use static_data::*;
// AFAICT this is something to do with conflicting names between crates and modules that
// interfaces with declaring the `ClassDecl`.
pub use crate::settings::*;
-pub use crate::theme::*;
#[cfg(feature = "stories")]
mod story;
@@ -5,7 +5,8 @@ pub use gpui2::{
pub use crate::elevation::*;
use crate::settings::user_settings;
-pub use crate::{old_theme, theme, ButtonVariant, Theme};
+pub use crate::ButtonVariant;
+pub use theme2::theme;
use gpui2::{rems, Hsla, Rems};
use strum::EnumIter;
@@ -1,7 +1,7 @@
use std::path::PathBuf;
use std::str::FromStr;
-use gpui2::{AppContext, WindowContext};
+use gpui2::ViewContext;
use rand::Rng;
use theme2::Theme;
@@ -628,7 +628,7 @@ pub fn example_editor_actions() -> Vec<PaletteItem> {
]
}
-pub fn empty_editor_example(cx: &mut WindowContext) -> EditorPane {
+pub fn empty_editor_example(cx: &mut ViewContext<EditorPane>) -> EditorPane {
EditorPane::new(
cx,
static_tabs_example(),
@@ -642,7 +642,7 @@ pub fn empty_buffer_example() -> Buffer {
Buffer::new("empty-buffer").set_rows(Some(BufferRows::default()))
}
-pub fn hello_world_rust_editor_example(cx: &mut WindowContext) -> EditorPane {
+pub fn hello_world_rust_editor_example(cx: &mut ViewContext<EditorPane>) -> EditorPane {
let theme = theme(cx);
EditorPane::new(
@@ -781,7 +781,7 @@ pub fn hello_world_rust_buffer_rows(theme: &Theme) -> Vec<BufferRow> {
]
}
-pub fn hello_world_rust_editor_with_status_example(cx: &mut AppContext) -> EditorPane {
+pub fn hello_world_rust_editor_with_status_example(cx: &mut ViewContext<EditorPane>) -> EditorPane {
let theme = theme(cx);
EditorPane::new(
@@ -1,225 +0,0 @@
-use gpui2::{
- AnyElement, AppContext, Bounds, Component, Element, Hsla, LayoutId, Pixels, Result,
- ViewContext, WindowContext,
-};
-use serde::{de::Visitor, Deserialize, Deserializer};
-use std::collections::HashMap;
-use std::fmt;
-use std::sync::Arc;
-
-#[derive(Deserialize, Clone, Default, Debug)]
-pub struct Theme {
- pub name: String,
- pub is_light: bool,
- pub lowest: Layer,
- pub middle: Layer,
- pub highest: Layer,
- pub popover_shadow: Shadow,
- pub modal_shadow: Shadow,
- #[serde(deserialize_with = "deserialize_player_colors")]
- pub players: Vec<PlayerColors>,
- #[serde(deserialize_with = "deserialize_syntax_colors")]
- pub syntax: HashMap<String, Hsla>,
-}
-
-#[derive(Deserialize, Clone, Default, Debug)]
-pub struct Layer {
- pub base: StyleSet,
- pub variant: StyleSet,
- pub on: StyleSet,
- pub accent: StyleSet,
- pub positive: StyleSet,
- pub warning: StyleSet,
- pub negative: StyleSet,
-}
-
-#[derive(Deserialize, Clone, Default, Debug)]
-pub struct StyleSet {
- #[serde(rename = "default")]
- pub default: ContainerColors,
- pub hovered: ContainerColors,
- pub pressed: ContainerColors,
- pub active: ContainerColors,
- pub disabled: ContainerColors,
- pub inverted: ContainerColors,
-}
-
-#[derive(Deserialize, Clone, Default, Debug)]
-pub struct ContainerColors {
- pub background: Hsla,
- pub foreground: Hsla,
- pub border: Hsla,
-}
-
-#[derive(Deserialize, Clone, Default, Debug)]
-pub struct PlayerColors {
- pub selection: Hsla,
- pub cursor: Hsla,
-}
-
-#[derive(Deserialize, Clone, Default, Debug)]
-pub struct Shadow {
- pub blur: u8,
- pub color: Hsla,
- pub offset: Vec<u8>,
-}
-
-fn deserialize_player_colors<'de, D>(deserializer: D) -> Result<Vec<PlayerColors>, D::Error>
-where
- D: Deserializer<'de>,
-{
- struct PlayerArrayVisitor;
-
- impl<'de> Visitor<'de> for PlayerArrayVisitor {
- type Value = Vec<PlayerColors>;
-
- fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
- formatter.write_str("an object with integer keys")
- }
-
- fn visit_map<A: serde::de::MapAccess<'de>>(
- self,
- mut map: A,
- ) -> Result<Self::Value, A::Error> {
- let mut players = Vec::with_capacity(8);
- while let Some((key, value)) = map.next_entry::<usize, PlayerColors>()? {
- if key < 8 {
- players.push(value);
- } else {
- return Err(serde::de::Error::invalid_value(
- serde::de::Unexpected::Unsigned(key as u64),
- &"a key in range 0..7",
- ));
- }
- }
- Ok(players)
- }
- }
-
- deserializer.deserialize_map(PlayerArrayVisitor)
-}
-
-fn deserialize_syntax_colors<'de, D>(deserializer: D) -> Result<HashMap<String, Hsla>, D::Error>
-where
- D: serde::Deserializer<'de>,
-{
- #[derive(Deserialize)]
- struct ColorWrapper {
- color: Hsla,
- }
-
- struct SyntaxVisitor;
-
- impl<'de> Visitor<'de> for SyntaxVisitor {
- type Value = HashMap<String, Hsla>;
-
- fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
- formatter.write_str("a map with keys and objects with a single color field as values")
- }
-
- fn visit_map<M>(self, mut map: M) -> Result<HashMap<String, Hsla>, M::Error>
- where
- M: serde::de::MapAccess<'de>,
- {
- let mut result = HashMap::new();
- while let Some(key) = map.next_key()? {
- let wrapper: ColorWrapper = map.next_value()?; // Deserialize values as Hsla
- result.insert(key, wrapper.color);
- }
- Ok(result)
- }
- }
- deserializer.deserialize_map(SyntaxVisitor)
-}
-
-pub fn themed<V, E, F>(theme: Theme, cx: &mut ViewContext<V>, build_child: F) -> Themed<E>
-where
- V: 'static,
- E: Element<V>,
- F: FnOnce(&mut ViewContext<V>) -> E,
-{
- cx.default_global::<ThemeStack>().0.push(theme.clone());
- let child = build_child(cx);
- cx.default_global::<ThemeStack>().0.pop();
- Themed { theme, child }
-}
-
-pub struct Themed<E> {
- pub(crate) theme: Theme,
- pub(crate) child: E,
-}
-
-impl<V, E> Component<V> for Themed<E>
-where
- V: 'static,
- E: 'static + Element<V> + Send,
- E::ElementState: Send,
-{
- fn render(self) -> AnyElement<V> {
- AnyElement::new(self)
- }
-}
-
-#[derive(Default)]
-struct ThemeStack(Vec<Theme>);
-
-impl<V, E: 'static + Element<V> + Send> Element<V> for Themed<E>
-where
- V: 'static,
- E::ElementState: Send,
-{
- type ElementState = E::ElementState;
-
- fn id(&self) -> Option<gpui2::ElementId> {
- None
- }
-
- fn initialize(
- &mut self,
- view_state: &mut V,
- element_state: Option<Self::ElementState>,
- cx: &mut ViewContext<V>,
- ) -> Self::ElementState {
- cx.default_global::<ThemeStack>().0.push(self.theme.clone());
- let element_state = self.child.initialize(view_state, element_state, cx);
- cx.default_global::<ThemeStack>().0.pop();
- element_state
- }
-
- fn layout(
- &mut self,
- view_state: &mut V,
- element_state: &mut Self::ElementState,
- cx: &mut ViewContext<V>,
- ) -> LayoutId
- where
- Self: Sized,
- {
- cx.default_global::<ThemeStack>().0.push(self.theme.clone());
- let layout_id = self.child.layout(view_state, element_state, cx);
- cx.default_global::<ThemeStack>().0.pop();
- layout_id
- }
-
- fn paint(
- &mut self,
- bounds: Bounds<Pixels>,
- view_state: &mut V,
- frame_state: &mut Self::ElementState,
- cx: &mut ViewContext<V>,
- ) where
- Self: Sized,
- {
- cx.default_global::<ThemeStack>().0.push(self.theme.clone());
- self.child.paint(bounds, view_state, frame_state, cx);
- cx.default_global::<ThemeStack>().0.pop();
- }
-}
-
-pub fn old_theme(cx: &WindowContext) -> Arc<Theme> {
- Arc::new(cx.global::<Theme>().clone())
-}
-
-pub fn theme(cx: &AppContext) -> Arc<theme2::Theme> {
- theme2::active_theme(cx).clone()
-}
@@ -17,7 +17,7 @@ use theme2::Theme;
// use gpui2::geometry::vector::Vector2F;
// use gpui2::AnyWindowHandle;
// use gpui2::{
-// fonts::HighlightStyle, AnyElement, AnyViewHandle, AppContext, Handle, Task, View,
+// fonts::HighlightStyle, AnyElement, AnyViewHandle, AppContext, Model, Task, View,
// ViewContext, View, WeakViewHandle, WindowContext,
// };
// use project2::{Project, ProjectEntryId, ProjectPath};
@@ -135,14 +135,14 @@ pub trait Item: EventEmitter + Sized {
// }
// fn save(
// &mut self,
- // _project: Handle<Project>,
+ // _project: Model<Project>,
// _cx: &mut ViewContext<Self>,
// ) -> Task<Result<()>> {
// unimplemented!("save() must be implemented if can_save() returns true")
// }
// fn save_as(
// &mut self,
- // _project: Handle<Project>,
+ // _project: Model<Project>,
// _abs_path: PathBuf,
// _cx: &mut ViewContext<Self>,
// ) -> Task<Result<()>> {
@@ -150,7 +150,7 @@ pub trait Item: EventEmitter + Sized {
// }
// fn reload(
// &mut self,
- // _project: Handle<Project>,
+ // _project: Model<Project>,
// _cx: &mut ViewContext<Self>,
// ) -> Task<Result<()>> {
// unimplemented!("reload() must be implemented if can_save() returns true")
@@ -197,7 +197,7 @@ pub trait Item: EventEmitter + Sized {
// }
// fn deserialize(
- // _project: Handle<Project>,
+ // _project: Model<Project>,
// _workspace: WeakViewHandle<Workspace>,
// _workspace_id: WorkspaceId,
// _item_id: ItemId,
@@ -229,8 +229,8 @@ use std::{
};
use gpui2::{
- AnyElement, AnyWindowHandle, AppContext, EventEmitter, Handle, HighlightStyle, Pixels, Point,
- SharedString, Task, View, ViewContext, VisualContext, WindowContext,
+ AnyElement, AnyWindowHandle, AppContext, EventEmitter, HighlightStyle, Model, Pixels, Point,
+ SharedString, Task, View, ViewContext, WindowContext,
};
use project2::{Project, ProjectEntryId, ProjectPath};
use smallvec::SmallVec;
@@ -279,14 +279,14 @@ pub trait ItemHandle: 'static + Send {
fn is_dirty(&self, cx: &AppContext) -> bool;
fn has_conflict(&self, cx: &AppContext) -> bool;
fn can_save(&self, cx: &AppContext) -> bool;
- fn save(&self, project: Handle<Project>, cx: &mut WindowContext) -> Task<Result<()>>;
+ fn save(&self, project: Model<Project>, cx: &mut WindowContext) -> Task<Result<()>>;
fn save_as(
&self,
- project: Handle<Project>,
+ project: Model<Project>,
abs_path: PathBuf,
cx: &mut WindowContext,
) -> Task<Result<()>>;
- fn reload(&self, project: Handle<Project>, cx: &mut WindowContext) -> Task<Result<()>>;
+ fn reload(&self, project: Model<Project>, cx: &mut WindowContext) -> Task<Result<()>>;
// fn act_as_type<'a>(&'a self, type_id: TypeId, cx: &'a AppContext) -> Option<&'a AnyViewHandle>; todo!()
fn to_followable_item_handle(&self, cx: &AppContext) -> Option<Box<dyn FollowableItemHandle>>;
fn on_release(
@@ -587,20 +587,20 @@ impl<T: Item> ItemHandle for View<T> {
self.read(cx).can_save(cx)
}
- fn save(&self, project: Handle<Project>, cx: &mut WindowContext) -> Task<Result<()>> {
+ fn save(&self, project: Model<Project>, cx: &mut WindowContext) -> Task<Result<()>> {
self.update(cx, |item, cx| item.save(project, cx))
}
fn save_as(
&self,
- project: Handle<Project>,
+ project: Model<Project>,
abs_path: PathBuf,
cx: &mut WindowContext,
) -> Task<anyhow::Result<()>> {
self.update(cx, |item, cx| item.save_as(project, abs_path, cx))
}
- fn reload(&self, project: Handle<Project>, cx: &mut WindowContext) -> Task<Result<()>> {
+ fn reload(&self, project: Model<Project>, cx: &mut WindowContext) -> Task<Result<()>> {
self.update(cx, |item, cx| item.reload(project, cx))
}
@@ -688,8 +688,8 @@ pub trait ProjectItem: Item {
type Item: project2::Item;
fn for_project_item(
- project: Handle<Project>,
- item: Handle<Self::Item>,
+ project: Model<Project>,
+ item: Model<Self::Item>,
cx: &mut ViewContext<Self>,
) -> Self
where
@@ -714,7 +714,7 @@ pub trait FollowableItem: Item {
) -> bool;
fn apply_update_proto(
&mut self,
- project: &Handle<Project>,
+ project: &Model<Project>,
message: proto::update_view::Variant,
cx: &mut ViewContext<Self>,
) -> Task<Result<()>>;
@@ -736,7 +736,7 @@ pub trait FollowableItemHandle: ItemHandle {
) -> bool;
fn apply_update_proto(
&self,
- project: &Handle<Project>,
+ project: &Model<Project>,
message: proto::update_view::Variant,
cx: &mut WindowContext,
) -> Task<Result<()>>;
@@ -777,7 +777,7 @@ pub trait FollowableItemHandle: ItemHandle {
// fn apply_update_proto(
// &self,
-// project: &Handle<Project>,
+// project: &Model<Project>,
// message: proto::update_view::Variant,
// cx: &mut WindowContext,
// ) -> Task<Result<()>> {
@@ -802,7 +802,7 @@ pub trait FollowableItemHandle: ItemHandle {
// use super::{Item, ItemEvent};
// use crate::{ItemId, ItemNavHistory, Pane, Workspace, WorkspaceId};
// use gpui2::{
-// elements::Empty, AnyElement, AppContext, Element, Entity, Handle, Task, View,
+// elements::Empty, AnyElement, AppContext, Element, Entity, Model, Task, View,
// ViewContext, View, WeakViewHandle,
// };
// use project2::{Project, ProjectEntryId, ProjectPath, WorktreeId};
@@ -824,7 +824,7 @@ pub trait FollowableItemHandle: ItemHandle {
// pub is_dirty: bool,
// pub is_singleton: bool,
// pub has_conflict: bool,
-// pub project_items: Vec<Handle<TestProjectItem>>,
+// pub project_items: Vec<Model<TestProjectItem>>,
// pub nav_history: Option<ItemNavHistory>,
// pub tab_descriptions: Option<Vec<&'static str>>,
// pub tab_detail: Cell<Option<usize>>,
@@ -869,7 +869,7 @@ pub trait FollowableItemHandle: ItemHandle {
// }
// impl TestProjectItem {
-// pub fn new(id: u64, path: &str, cx: &mut AppContext) -> Handle<Self> {
+// pub fn new(id: u64, path: &str, cx: &mut AppContext) -> Model<Self> {
// let entry_id = Some(ProjectEntryId::from_proto(id));
// let project_path = Some(ProjectPath {
// worktree_id: WorktreeId::from_usize(0),
@@ -881,7 +881,7 @@ pub trait FollowableItemHandle: ItemHandle {
// })
// }
-// pub fn new_untitled(cx: &mut AppContext) -> Handle<Self> {
+// pub fn new_untitled(cx: &mut AppContext) -> Model<Self> {
// cx.add_model(|_| Self {
// project_path: None,
// entry_id: None,
@@ -934,7 +934,7 @@ pub trait FollowableItemHandle: ItemHandle {
// self
// }
-// pub fn with_project_items(mut self, items: &[Handle<TestProjectItem>]) -> Self {
+// pub fn with_project_items(mut self, items: &[Model<TestProjectItem>]) -> Self {
// self.project_items.clear();
// self.project_items.extend(items.iter().cloned());
// self
@@ -1045,7 +1045,7 @@ pub trait FollowableItemHandle: ItemHandle {
// fn save(
// &mut self,
-// _: Handle<Project>,
+// _: Model<Project>,
// _: &mut ViewContext<Self>,
// ) -> Task<anyhow::Result<()>> {
// self.save_count += 1;
@@ -1055,7 +1055,7 @@ pub trait FollowableItemHandle: ItemHandle {
// fn save_as(
// &mut self,
-// _: Handle<Project>,
+// _: Model<Project>,
// _: std::path::PathBuf,
// _: &mut ViewContext<Self>,
// ) -> Task<anyhow::Result<()>> {
@@ -1066,7 +1066,7 @@ pub trait FollowableItemHandle: ItemHandle {
// fn reload(
// &mut self,
-// _: Handle<Project>,
+// _: Model<Project>,
// _: &mut ViewContext<Self>,
// ) -> Task<anyhow::Result<()>> {
// self.reload_count += 1;
@@ -1083,7 +1083,7 @@ pub trait FollowableItemHandle: ItemHandle {
// }
// fn deserialize(
-// _project: Handle<Project>,
+// _project: Model<Project>,
// _workspace: WeakViewHandle<Workspace>,
// workspace_id: WorkspaceId,
// _item_id: ItemId,
@@ -1,4 +1,4 @@
-use ai::embedding::OpenAIEmbeddings;
+use ai::providers::open_ai::OpenAIEmbeddingProvider;
use anyhow::{anyhow, Result};
use client::{self, UserStore};
use gpui::{AsyncAppContext, ModelHandle, Task};
@@ -475,7 +475,7 @@ fn main() {
let semantic_index = SemanticIndex::new(
fs.clone(),
db_file_path,
- Arc::new(OpenAIEmbeddings::new(http_client, cx.background())),
+ Arc::new(OpenAIEmbeddingProvider::new(http_client, cx.background())),
languages.clone(),
cx.clone(),
)
@@ -321,8 +321,8 @@ impl LspAdapter for NextLspAdapter {
latest_github_release("elixir-tools/next-ls", false, delegate.http_client()).await?;
let version = release.name.clone();
let platform = match consts::ARCH {
- "x86_64" => "darwin_arm64",
- "aarch64" => "darwin_amd64",
+ "x86_64" => "darwin_amd64",
+ "aarch64" => "darwin_arm64",
other => bail!("Running on unsupported platform: {other}"),
};
let asset_name = format!("next_ls_{}", platform);
@@ -15,6 +15,7 @@ name = "Zed"
path = "src/main.rs"
[dependencies]
+ai2 = { path = "../ai2"}
# audio = { path = "../audio" }
# activity_indicator = { path = "../activity_indicator" }
# auto_update = { path = "../auto_update" }
@@ -120,7 +120,7 @@ fn main() {
let node_runtime = RealNodeRuntime::new(http.clone());
language2::init(cx);
- let user_store = cx.entity(|cx| UserStore::new(client.clone(), http.clone(), cx));
+ let user_store = cx.build_model(|cx| UserStore::new(client.clone(), http.clone(), cx));
// let workspace_store = cx.add_model(|cx| WorkspaceStore::new(client.clone(), cx));
cx.set_global(client.clone());
@@ -5,7 +5,7 @@ mod open_listener;
pub use assets::*;
use client2::{Client, UserStore};
use collections::HashMap;
-use gpui2::{AsyncAppContext, Handle, Point};
+use gpui2::{AsyncAppContext, Model};
pub use only_instance::*;
pub use open_listener::*;
@@ -52,7 +52,7 @@ pub fn connect_to_cli(
pub struct AppState {
pub client: Arc<Client>,
- pub user_store: Handle<UserStore>,
+ pub user_store: Model<UserStore>,
}
pub async fn handle_cli_connection(
@@ -0,0 +1,27 @@
+import os
+from pathlib import Path
+
+THIS_SCRIPT_PATH: Path = Path(__file__)
+CRATES_DIR: Path = THIS_SCRIPT_PATH.parent.parent / "crates"
+
+zed_1_crate_count: int = 0
+zed_2_crate_count: int = 0
+
+for child in os.listdir(CRATES_DIR):
+ child_path: str = os.path.join(CRATES_DIR, child)
+
+ if not os.path.isdir(child_path):
+ continue
+
+ if child.endswith("2"):
+ zed_2_crate_count += 1
+ else:
+ zed_1_crate_count += 1
+
+print(f"crates ported: {zed_2_crate_count}")
+print(f"crates in total: {zed_1_crate_count}")
+
+percent_complete: float = (zed_2_crate_count / zed_1_crate_count) * 100
+percent_complete_rounded: float = round(percent_complete, 2)
+
+print(f"progress: {percent_complete_rounded}%")