Eliminate assets crate

This commit is contained in:
Max Brunsfeld 2023-06-06 11:46:46 -07:00
parent 53906fd3da
commit dbbd0558c3
24 changed files with 142 additions and 160 deletions

18
Cargo.lock generated
View File

@ -100,12 +100,12 @@ name = "ai"
version = "0.1.0"
dependencies = [
"anyhow",
"assets",
"collections",
"editor",
"futures 0.3.28",
"gpui",
"isahc",
"rust-embed",
"serde",
"serde_json",
"util",
@ -210,15 +210,6 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16"
[[package]]
name = "assets"
version = "0.1.0"
dependencies = [
"anyhow",
"gpui",
"rust-embed",
]
[[package]]
name = "async-broadcast"
version = "0.4.1"
@ -1402,7 +1393,6 @@ name = "copilot_button"
version = "0.1.0"
dependencies = [
"anyhow",
"assets",
"context_menu",
"copilot",
"editor",
@ -6114,7 +6104,6 @@ name = "settings"
version = "0.1.0"
dependencies = [
"anyhow",
"assets",
"collections",
"fs",
"futures 0.3.28",
@ -6123,6 +6112,7 @@ dependencies = [
"lazy_static",
"postage",
"pretty_assertions",
"rust-embed",
"schemars",
"serde",
"serde_derive",
@ -7749,6 +7739,7 @@ dependencies = [
"lazy_static",
"log",
"rand 0.8.5",
"rust-embed",
"serde",
"serde_json",
"smol",
@ -7819,7 +7810,6 @@ name = "vim"
version = "0.1.0"
dependencies = [
"anyhow",
"assets",
"async-compat",
"async-trait",
"collections",
@ -8647,7 +8637,6 @@ name = "workspace"
version = "0.1.0"
dependencies = [
"anyhow",
"assets",
"async-recursion 1.0.4",
"bincode",
"call",
@ -8747,7 +8736,6 @@ dependencies = [
"activity_indicator",
"ai",
"anyhow",
"assets",
"async-compression",
"async-recursion 0.3.2",
"async-tar",

View File

@ -2,7 +2,6 @@
members = [
"crates/activity_indicator",
"crates/ai",
"crates/assets",
"crates/auto_update",
"crates/breadcrumbs",
"crates/call",
@ -88,6 +87,7 @@ parking_lot = { version = "0.11.1" }
postage = { version = "0.5", features = ["futures-traits"] }
rand = { version = "0.8.5" }
regex = { version = "1.5" }
rust-embed = { version = "6.3", features = ["include-exclude"] }
schemars = { version = "0.8" }
serde = { version = "1.0", features = ["derive", "rc"] }
serde_derive = { version = "1.0", features = ["deserialize_in_place"] }

View File

@ -9,12 +9,12 @@ path = "src/ai.rs"
doctest = false
[dependencies]
assets = { path = "../assets"}
collections = { path = "../collections"}
editor = { path = "../editor" }
gpui = { path = "../gpui" }
util = { path = "../util" }
rust-embed.workspace = true
serde.workspace = true
serde_json.workspace = true
anyhow.workspace = true

View File

@ -1,5 +1,4 @@
use anyhow::{anyhow, Result};
use assets::Assets;
use collections::HashMap;
use editor::Editor;
use futures::AsyncBufReadExt;
@ -16,6 +15,14 @@ use std::{io, sync::Arc};
use util::channel::{ReleaseChannel, RELEASE_CHANNEL};
use util::{ResultExt, TryFutureExt};
use rust_embed::RustEmbed;
use std::str;
#[derive(RustEmbed)]
#[folder = "../../assets/contexts"]
#[exclude = "*.DS_Store"]
pub struct ContextAssets;
actions!(ai, [Assist]);
// Data types for chat completion requests
@ -173,7 +180,7 @@ impl Assistant {
let assist_task = cx.spawn(|_, mut cx| {
async move {
// TODO: We should have a get_string method on assets. This is repateated elsewhere.
let content = Assets::get("contexts/system.zmd").unwrap();
let content = ContextAssets::get("system.zmd").unwrap();
let mut system_message = std::str::from_utf8(content.data.as_ref())
.unwrap()
.to_string();

View File

@ -1,14 +0,0 @@
[package]
name = "assets"
version = "0.1.0"
edition = "2021"
publish = false
[lib]
path = "src/assets.rs"
doctest = false
[dependencies]
gpui = { path = "../gpui" }
anyhow.workspace = true
rust-embed = { version = "6.3", features = ["include-exclude"] }

View File

@ -1,29 +0,0 @@
use std::process::Command;
fn main() {
let output = Command::new("npm")
.current_dir("../../styles")
.args(["install", "--no-save"])
.output()
.expect("failed to run npm");
if !output.status.success() {
panic!(
"failed to install theme dependencies {}",
String::from_utf8_lossy(&output.stderr)
);
}
let output = Command::new("npm")
.current_dir("../../styles")
.args(["run", "build"])
.output()
.expect("failed to run npm");
if !output.status.success() {
panic!(
"build script failed {}",
String::from_utf8_lossy(&output.stderr)
);
}
println!("cargo:rerun-if-changed=../../styles/src");
}

View File

@ -9,7 +9,6 @@ path = "src/copilot_button.rs"
doctest = false
[dependencies]
assets = { path = "../assets" }
copilot = { path = "../copilot" }
editor = { path = "../editor" }
fs = { path = "../fs" }

View File

@ -315,9 +315,7 @@ async fn configure_disabled_globs(
let settings_editor = workspace
.update(&mut cx, |_, cx| {
create_and_open_local_file(&paths::SETTINGS, cx, || {
settings::initial_user_settings_content(&assets::Assets)
.as_ref()
.into()
settings::initial_user_settings_content().as_ref().into()
})
})?
.await?

View File

@ -12,7 +12,6 @@ doctest = false
test-support = ["gpui/test-support", "fs/test-support"]
[dependencies]
assets = { path = "../assets" }
collections = { path = "../collections" }
gpui = { path = "../gpui" }
sqlez = { path = "../sqlez" }
@ -25,6 +24,7 @@ futures.workspace = true
json_comments = "0.2"
lazy_static.workspace = true
postage.workspace = true
rust-embed.workspace = true
schemars.workspace = true
serde.workspace = true
serde_derive.workspace = true

View File

@ -1,6 +1,5 @@
use crate::settings_store::parse_json_with_comments;
use crate::{settings_store::parse_json_with_comments, SettingsAssets};
use anyhow::{Context, Result};
use assets::Assets;
use collections::BTreeMap;
use gpui::{keymap_matcher::Binding, AppContext};
use schemars::{
@ -10,11 +9,11 @@ use schemars::{
};
use serde::Deserialize;
use serde_json::{value::RawValue, Value};
use util::ResultExt;
use util::{asset_str, ResultExt};
#[derive(Deserialize, Default, Clone, JsonSchema)]
#[serde(transparent)]
pub struct KeymapFileContent(Vec<KeymapBlock>);
pub struct KeymapFile(Vec<KeymapBlock>);
#[derive(Deserialize, Default, Clone, JsonSchema)]
pub struct KeymapBlock {
@ -40,11 +39,10 @@ impl JsonSchema for KeymapAction {
#[derive(Deserialize)]
struct ActionWithData(Box<str>, Box<RawValue>);
impl KeymapFileContent {
impl KeymapFile {
pub fn load_asset(asset_path: &str, cx: &mut AppContext) -> Result<()> {
let content = Assets::get(asset_path).unwrap().data;
let content_str = std::str::from_utf8(content.as_ref()).unwrap();
Self::parse(content_str)?.add_to_cx(cx)
let content = asset_str::<SettingsAssets>(asset_path);
Self::parse(content.as_ref())?.add_to_cx(cx)
}
pub fn parse(content: &str) -> Result<Self> {
@ -83,40 +81,40 @@ impl KeymapFileContent {
}
Ok(())
}
}
pub fn keymap_file_json_schema(action_names: &[&'static str]) -> serde_json::Value {
let mut root_schema = SchemaSettings::draft07()
.with(|settings| settings.option_add_null_type = false)
.into_generator()
.into_root_schema_for::<KeymapFileContent>();
pub fn generate_json_schema(action_names: &[&'static str]) -> serde_json::Value {
let mut root_schema = SchemaSettings::draft07()
.with(|settings| settings.option_add_null_type = false)
.into_generator()
.into_root_schema_for::<KeymapFile>();
let action_schema = Schema::Object(SchemaObject {
subschemas: Some(Box::new(SubschemaValidation {
one_of: Some(vec![
Schema::Object(SchemaObject {
instance_type: Some(SingleOrVec::Single(Box::new(InstanceType::String))),
enum_values: Some(
action_names
.iter()
.map(|name| Value::String(name.to_string()))
.collect(),
),
..Default::default()
}),
Schema::Object(SchemaObject {
instance_type: Some(SingleOrVec::Single(Box::new(InstanceType::Array))),
..Default::default()
}),
]),
let action_schema = Schema::Object(SchemaObject {
subschemas: Some(Box::new(SubschemaValidation {
one_of: Some(vec![
Schema::Object(SchemaObject {
instance_type: Some(SingleOrVec::Single(Box::new(InstanceType::String))),
enum_values: Some(
action_names
.iter()
.map(|name| Value::String(name.to_string()))
.collect(),
),
..Default::default()
}),
Schema::Object(SchemaObject {
instance_type: Some(SingleOrVec::Single(Box::new(InstanceType::Array))),
..Default::default()
}),
]),
..Default::default()
})),
..Default::default()
})),
..Default::default()
});
});
root_schema
.definitions
.insert("KeymapAction".to_owned(), action_schema);
root_schema
.definitions
.insert("KeymapAction".to_owned(), action_schema);
serde_json::to_value(root_schema).unwrap()
serde_json::to_value(root_schema).unwrap()
}
}

View File

@ -2,31 +2,37 @@ mod keymap_file;
mod settings_file;
mod settings_store;
use gpui::AssetSource;
pub use keymap_file::{keymap_file_json_schema, KeymapFileContent};
use rust_embed::RustEmbed;
use std::{borrow::Cow, str};
use util::asset_str;
pub use keymap_file::KeymapFile;
pub use settings_file::*;
pub use settings_store::{Setting, SettingsJsonSchemaParams, SettingsStore};
use std::{borrow::Cow, str};
pub const DEFAULT_SETTINGS_ASSET_PATH: &str = "settings/default.json";
const INITIAL_USER_SETTINGS_ASSET_PATH: &str = "settings/initial_user_settings.json";
const INITIAL_LOCAL_SETTINGS_ASSET_PATH: &str = "settings/initial_local_settings.json";
#[derive(RustEmbed)]
#[folder = "../../assets"]
#[include = "settings/*"]
#[include = "keymaps/*"]
#[exclude = "*.DS_Store"]
pub struct SettingsAssets;
pub fn default_settings() -> Cow<'static, str> {
asset_str(&assets::Assets, DEFAULT_SETTINGS_ASSET_PATH)
asset_str::<SettingsAssets>("settings/default.json")
}
pub fn initial_user_settings_content(assets: &dyn AssetSource) -> Cow<'_, str> {
asset_str(assets, INITIAL_USER_SETTINGS_ASSET_PATH)
pub fn default_keymap() -> Cow<'static, str> {
asset_str::<SettingsAssets>("keymaps/default.json")
}
pub fn initial_local_settings_content(assets: &dyn AssetSource) -> Cow<'_, str> {
asset_str(assets, INITIAL_LOCAL_SETTINGS_ASSET_PATH)
pub fn vim_keymap() -> Cow<'static, str> {
asset_str::<SettingsAssets>("keymaps/vim.json")
}
fn asset_str<'a>(assets: &'a dyn AssetSource, path: &str) -> Cow<'a, str> {
match assets.load(path).unwrap() {
Cow::Borrowed(s) => Cow::Borrowed(str::from_utf8(s).unwrap()),
Cow::Owned(s) => Cow::Owned(String::from_utf8(s).unwrap()),
}
pub fn initial_user_settings_content() -> Cow<'static, str> {
asset_str::<SettingsAssets>("settings/initial_user_settings.json")
}
pub fn initial_local_settings_content() -> Cow<'static, str> {
asset_str::<SettingsAssets>("settings/initial_local_settings.json")
}

View File

@ -1,6 +1,5 @@
use crate::{settings_store::SettingsStore, Setting};
use anyhow::Result;
use assets::Assets;
use fs::Fs;
use futures::{channel::mpsc, StreamExt};
use gpui::{executor::Background, AppContext};
@ -111,7 +110,7 @@ async fn load_settings(fs: &Arc<dyn Fs>) -> Result<String> {
Err(err) => {
if let Some(e) = err.downcast_ref::<std::io::Error>() {
if e.kind() == ErrorKind::NotFound {
return Ok(crate::initial_user_settings_content(&Assets).to_string());
return Ok(crate::initial_user_settings_content().to_string());
}
}
return Err(err);

View File

@ -21,6 +21,7 @@ isahc.workspace = true
smol.workspace = true
url = "2.2"
rand.workspace = true
rust-embed.workspace = true
tempdir = { workspace = true, optional = true }
serde.workspace = true
serde_json.workspace = true

View File

@ -7,6 +7,7 @@ pub mod paths;
pub mod test;
use std::{
borrow::Cow,
cmp::{self, Ordering},
ops::{AddAssign, Range, RangeInclusive},
panic::Location,
@ -284,6 +285,14 @@ impl<T: Rng> Iterator for RandomCharIter<T> {
}
}
/// Get an embedded file as a string.
pub fn asset_str<A: rust_embed::RustEmbed>(path: &str) -> Cow<'static, str> {
match A::get(path).unwrap().data {
Cow::Borrowed(bytes) => Cow::Borrowed(std::str::from_utf8(bytes).unwrap()),
Cow::Owned(bytes) => Cow::Owned(String::from_utf8(bytes).unwrap()),
}
}
// copy unstable standard feature option unzip
// https://github.com/rust-lang/rust/issues/87800
// Remove when this ship in Rust 1.66 or 1.67

View File

@ -24,7 +24,6 @@ nvim-rs = { git = "https://github.com/KillTheMule/nvim-rs", branch = "master", f
tokio = { version = "1.15", "optional" = true }
serde_json.workspace = true
assets = { path = "../assets" }
collections = { path = "../collections" }
command_palette = { path = "../command_palette" }
editor = { path = "../editor" }

View File

@ -27,7 +27,7 @@ impl<'a> VimTestContext<'a> {
cx.update_global(|store: &mut SettingsStore, cx| {
store.update_user_settings::<VimModeSetting>(cx, |s| *s = Some(enabled));
});
settings::KeymapFileContent::load_asset("keymaps/vim.json", cx).unwrap();
settings::KeymapFile::load_asset("keymaps/vim.json", cx).unwrap();
});
// Setup search toolbars and keypress hook

View File

@ -19,7 +19,6 @@ test-support = [
]
[dependencies]
assets = { path = "../assets" }
db = { path = "../db" }
call = { path = "../call" }
client = { path = "../client" }

View File

@ -17,7 +17,6 @@ path = "src/main.rs"
[dependencies]
activity_indicator = { path = "../activity_indicator" }
assets = { path = "../assets" }
auto_update = { path = "../auto_update" }
breadcrumbs = { path = "../breadcrumbs" }
call = { path = "../call" }

View File

@ -1,3 +1,5 @@
use std::process::Command;
fn main() {
println!("cargo:rustc-env=MACOSX_DEPLOYMENT_TARGET=10.15.7");
@ -21,4 +23,32 @@ fn main() {
// Register exported Objective-C selectors, protocols, etc
println!("cargo:rustc-link-arg=-Wl,-ObjC");
// Install dependencies for theme-generation
let output = Command::new("npm")
.current_dir("../../styles")
.args(["install", "--no-save"])
.output()
.expect("failed to run npm");
if !output.status.success() {
panic!(
"failed to install theme dependencies {}",
String::from_utf8_lossy(&output.stderr)
);
}
// Regenerate themes
let output = Command::new("npm")
.current_dir("../../styles")
.args(["run", "build"])
.output()
.expect("failed to run npm");
if !output.status.success() {
panic!(
"build script failed {}",
String::from_utf8_lossy(&output.stderr)
);
}
println!("cargo:rerun-if-changed=../../styles/src");
}

View File

@ -4,6 +4,10 @@ use rust_embed::RustEmbed;
#[derive(RustEmbed)]
#[folder = "../../assets"]
#[include = "fonts/**/*"]
#[include = "icons/**/*"]
#[include = "themes/**/*"]
#[include = "*.md"]
#[exclude = "*.DS_Store"]
pub struct Assets;

View File

@ -3,6 +3,7 @@ pub use language::*;
use node_runtime::NodeRuntime;
use rust_embed::RustEmbed;
use std::{borrow::Cow, str, sync::Arc};
use util::asset_str;
mod c;
mod elixir;
@ -179,10 +180,7 @@ fn load_query(name: &str, filename_prefix: &str) -> Option<Cow<'static, str>> {
for path in LanguageDir::iter() {
if let Some(remainder) = path.strip_prefix(name) {
if remainder.starts_with(filename_prefix) {
let contents = match LanguageDir::get(path.as_ref()).unwrap().data {
Cow::Borrowed(s) => Cow::Borrowed(str::from_utf8(s).unwrap()),
Cow::Owned(s) => Cow::Owned(String::from_utf8(s).unwrap()),
};
let contents = asset_str::<LanguageDir>(path.as_ref());
match &mut result {
None => result = Some(contents),
Some(r) => r.to_mut().push_str(contents.as_ref()),

View File

@ -6,7 +6,7 @@ use gpui::AppContext;
use language::{LanguageRegistry, LanguageServerBinary, LanguageServerName, LspAdapter};
use node_runtime::NodeRuntime;
use serde_json::json;
use settings::{keymap_file_json_schema, SettingsJsonSchemaParams, SettingsStore};
use settings::{KeymapFile, SettingsJsonSchemaParams, SettingsStore};
use smol::fs;
use staff_mode::StaffMode;
use std::{
@ -143,7 +143,7 @@ impl LspAdapter for JsonLspAdapter {
},
{
"fileMatch": [schema_file_match(&paths::KEYMAP)],
"schema": keymap_file_json_schema(&action_names),
"schema": KeymapFile::generate_json_schema(&action_names),
}
]
}

View File

@ -2,7 +2,6 @@
#![allow(non_snake_case)]
use anyhow::{anyhow, Context, Result};
use assets::Assets;
use backtrace::Backtrace;
use cli::{
ipc::{self, IpcSender},
@ -58,7 +57,8 @@ use staff_mode::StaffMode;
use util::{channel::RELEASE_CHANNEL, paths, ResultExt, TryFutureExt};
use workspace::{item::ItemHandle, notifications::NotifyResultExt, AppState, Workspace};
use zed::{
self, build_window_options, handle_keymap_file_changes, initialize_workspace, languages, menus,
assets::Assets, build_window_options, handle_keymap_file_changes, initialize_workspace,
languages, menus,
};
fn main() {

View File

@ -1,7 +1,9 @@
pub mod assets;
pub mod languages;
pub mod menus;
#[cfg(any(test, feature = "test-support"))]
pub mod test;
use anyhow::Context;
use assets::Assets;
use breadcrumbs::Breadcrumbs;
@ -30,12 +32,11 @@ use project_panel::ProjectPanel;
use search::{BufferSearchBar, ProjectSearchBar};
use serde::Deserialize;
use serde_json::to_string_pretty;
use settings::{
initial_local_settings_content, KeymapFileContent, SettingsStore, DEFAULT_SETTINGS_ASSET_PATH,
};
use settings::{initial_local_settings_content, KeymapFile, SettingsStore};
use std::{borrow::Cow, str, sync::Arc};
use terminal_view::terminal_panel::{self, TerminalPanel};
use util::{
asset_str,
channel::ReleaseChannel,
paths::{self, LOCAL_SETTINGS_RELATIVE_PATH},
ResultExt,
@ -149,7 +150,7 @@ pub fn init(app_state: &Arc<AppState>, cx: &mut gpui::AppContext) {
move |workspace: &mut Workspace, _: &OpenLicenses, cx: &mut ViewContext<Workspace>| {
open_bundled_file(
workspace,
"licenses.md",
asset_str::<Assets>("licenses.md"),
"Open Source License Attribution",
"Markdown",
cx,
@ -169,9 +170,7 @@ pub fn init(app_state: &Arc<AppState>, cx: &mut gpui::AppContext) {
cx.add_action(
move |_: &mut Workspace, _: &OpenSettings, cx: &mut ViewContext<Workspace>| {
create_and_open_local_file(&paths::SETTINGS, cx, || {
settings::initial_user_settings_content(&Assets)
.as_ref()
.into()
settings::initial_user_settings_content().as_ref().into()
})
.detach_and_log_err(cx);
},
@ -181,7 +180,7 @@ pub fn init(app_state: &Arc<AppState>, cx: &mut gpui::AppContext) {
move |workspace: &mut Workspace, _: &OpenDefaultKeymap, cx: &mut ViewContext<Workspace>| {
open_bundled_file(
workspace,
"keymaps/default.json",
settings::default_keymap(),
"Default Key Bindings",
"JSON",
cx,
@ -194,7 +193,7 @@ pub fn init(app_state: &Arc<AppState>, cx: &mut gpui::AppContext) {
cx: &mut ViewContext<Workspace>| {
open_bundled_file(
workspace,
DEFAULT_SETTINGS_ASSET_PATH,
settings::default_settings(),
"Default Settings",
"JSON",
cx,
@ -521,11 +520,11 @@ fn open_log_file(workspace: &mut Workspace, cx: &mut ViewContext<Workspace>) {
pub fn load_default_keymap(cx: &mut AppContext) {
for path in ["keymaps/default.json", "keymaps/vim.json"] {
KeymapFileContent::load_asset(path, cx).unwrap();
KeymapFile::load_asset(path, cx).unwrap();
}
if let Some(asset_path) = settings::get::<BaseKeymap>(cx).asset_path() {
KeymapFileContent::load_asset(asset_path, cx).unwrap();
KeymapFile::load_asset(asset_path, cx).unwrap();
}
}
@ -536,7 +535,7 @@ pub fn handle_keymap_file_changes(
cx.spawn(move |mut cx| async move {
let mut settings_subscription = None;
while let Some(user_keymap_content) = user_keymap_file_rx.next().await {
if let Ok(keymap_content) = KeymapFileContent::parse(&user_keymap_content) {
if let Ok(keymap_content) = KeymapFile::parse(&user_keymap_content) {
cx.update(|cx| {
cx.clear_bindings();
load_default_keymap(cx);
@ -613,11 +612,7 @@ fn open_local_settings_file(
if let Some(buffer) = editor.buffer().read(cx).as_singleton() {
if buffer.read(cx).is_empty() {
buffer.update(cx, |buffer, cx| {
buffer.edit(
[(0..0, initial_local_settings_content(&Assets))],
None,
cx,
)
buffer.edit([(0..0, initial_local_settings_content())], None, cx)
});
}
}
@ -693,7 +688,7 @@ fn open_telemetry_log_file(workspace: &mut Workspace, cx: &mut ViewContext<Works
fn open_bundled_file(
workspace: &mut Workspace,
asset_path: &'static str,
text: Cow<'static, str>,
title: &'static str,
language: &'static str,
cx: &mut ViewContext<Workspace>,
@ -705,13 +700,9 @@ fn open_bundled_file(
.update(&mut cx, |workspace, cx| {
workspace.with_local_workspace(cx, |workspace, cx| {
let project = workspace.project();
let buffer = project.update(cx, |project, cx| {
let text = Assets::get(asset_path)
.map(|f| f.data)
.unwrap_or_else(|| Cow::Borrowed(b"File not found"));
let text = str::from_utf8(text.as_ref()).unwrap();
let buffer = project.update(cx, move |project, cx| {
project
.create_buffer(text, language, cx)
.create_buffer(text.as_ref(), language, cx)
.expect("creating buffers on a local workspace always succeeds")
});
let buffer = cx.add_model(|cx| {