Merge branch 'main' into lsp-log-messages
This commit is contained in:
commit
afaff7f9a9
67 changed files with 1002 additions and 730 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -2440,6 +2440,7 @@ dependencies = [
|
||||||
"parking_lot 0.11.2",
|
"parking_lot 0.11.2",
|
||||||
"regex",
|
"regex",
|
||||||
"rope",
|
"rope",
|
||||||
|
"rpc",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
|
|
@ -66,6 +66,7 @@ impl<'a> AddAssign<&'a Local> for Local {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A vector clock
|
||||||
#[derive(Clone, Default, Hash, Eq, PartialEq)]
|
#[derive(Clone, Default, Hash, Eq, PartialEq)]
|
||||||
pub struct Global(SmallVec<[u32; 8]>);
|
pub struct Global(SmallVec<[u32; 8]>);
|
||||||
|
|
||||||
|
|
|
@ -76,6 +76,7 @@ CREATE TABLE "worktree_entries" (
|
||||||
"is_symlink" BOOL NOT NULL,
|
"is_symlink" BOOL NOT NULL,
|
||||||
"is_ignored" BOOL NOT NULL,
|
"is_ignored" BOOL NOT NULL,
|
||||||
"is_deleted" BOOL NOT NULL,
|
"is_deleted" BOOL NOT NULL,
|
||||||
|
"git_status" INTEGER,
|
||||||
PRIMARY KEY(project_id, worktree_id, id),
|
PRIMARY KEY(project_id, worktree_id, id),
|
||||||
FOREIGN KEY(project_id, worktree_id) REFERENCES worktrees (project_id, id) ON DELETE CASCADE
|
FOREIGN KEY(project_id, worktree_id) REFERENCES worktrees (project_id, id) ON DELETE CASCADE
|
||||||
);
|
);
|
||||||
|
@ -96,22 +97,6 @@ CREATE TABLE "worktree_repositories" (
|
||||||
CREATE INDEX "index_worktree_repositories_on_project_id" ON "worktree_repositories" ("project_id");
|
CREATE INDEX "index_worktree_repositories_on_project_id" ON "worktree_repositories" ("project_id");
|
||||||
CREATE INDEX "index_worktree_repositories_on_project_id_and_worktree_id" ON "worktree_repositories" ("project_id", "worktree_id");
|
CREATE INDEX "index_worktree_repositories_on_project_id_and_worktree_id" ON "worktree_repositories" ("project_id", "worktree_id");
|
||||||
|
|
||||||
CREATE TABLE "worktree_repository_statuses" (
|
|
||||||
"project_id" INTEGER NOT NULL,
|
|
||||||
"worktree_id" INTEGER NOT NULL,
|
|
||||||
"work_directory_id" INTEGER NOT NULL,
|
|
||||||
"repo_path" VARCHAR NOT NULL,
|
|
||||||
"status" INTEGER NOT NULL,
|
|
||||||
"scan_id" INTEGER NOT NULL,
|
|
||||||
"is_deleted" BOOL NOT NULL,
|
|
||||||
PRIMARY KEY(project_id, worktree_id, work_directory_id, repo_path),
|
|
||||||
FOREIGN KEY(project_id, worktree_id) REFERENCES worktrees (project_id, id) ON DELETE CASCADE,
|
|
||||||
FOREIGN KEY(project_id, worktree_id, work_directory_id) REFERENCES worktree_entries (project_id, worktree_id, id) ON DELETE CASCADE
|
|
||||||
);
|
|
||||||
CREATE INDEX "index_worktree_repository_statuses_on_project_id" ON "worktree_repository_statuses" ("project_id");
|
|
||||||
CREATE INDEX "index_worktree_repository_statuses_on_project_id_and_worktree_id" ON "worktree_repository_statuses" ("project_id", "worktree_id");
|
|
||||||
CREATE INDEX "index_worktree_repository_statuses_on_project_id_and_worktree_id_and_work_directory_id" ON "worktree_repository_statuses" ("project_id", "worktree_id", "work_directory_id");
|
|
||||||
|
|
||||||
CREATE TABLE "worktree_settings_files" (
|
CREATE TABLE "worktree_settings_files" (
|
||||||
"project_id" INTEGER NOT NULL,
|
"project_id" INTEGER NOT NULL,
|
||||||
"worktree_id" INTEGER NOT NULL,
|
"worktree_id" INTEGER NOT NULL,
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
DROP TABLE "worktree_repository_statuses";
|
||||||
|
|
||||||
|
ALTER TABLE "worktree_entries"
|
||||||
|
ADD "git_status" INT8;
|
|
@ -1539,6 +1539,7 @@ impl Database {
|
||||||
}),
|
}),
|
||||||
is_symlink: db_entry.is_symlink,
|
is_symlink: db_entry.is_symlink,
|
||||||
is_ignored: db_entry.is_ignored,
|
is_ignored: db_entry.is_ignored,
|
||||||
|
git_status: db_entry.git_status.map(|status| status as i32),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1573,54 +1574,6 @@ impl Database {
|
||||||
worktree.updated_repositories.push(proto::RepositoryEntry {
|
worktree.updated_repositories.push(proto::RepositoryEntry {
|
||||||
work_directory_id: db_repository.work_directory_id as u64,
|
work_directory_id: db_repository.work_directory_id as u64,
|
||||||
branch: db_repository.branch,
|
branch: db_repository.branch,
|
||||||
removed_repo_paths: Default::default(),
|
|
||||||
updated_statuses: Default::default(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Repository Status Entries
|
|
||||||
for repository in worktree.updated_repositories.iter_mut() {
|
|
||||||
let repository_status_entry_filter =
|
|
||||||
if let Some(rejoined_worktree) = rejoined_worktree {
|
|
||||||
worktree_repository_statuses::Column::ScanId
|
|
||||||
.gt(rejoined_worktree.scan_id)
|
|
||||||
} else {
|
|
||||||
worktree_repository_statuses::Column::IsDeleted.eq(false)
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut db_repository_statuses =
|
|
||||||
worktree_repository_statuses::Entity::find()
|
|
||||||
.filter(
|
|
||||||
Condition::all()
|
|
||||||
.add(
|
|
||||||
worktree_repository_statuses::Column::ProjectId
|
|
||||||
.eq(project.id),
|
|
||||||
)
|
|
||||||
.add(
|
|
||||||
worktree_repository_statuses::Column::WorktreeId
|
|
||||||
.eq(worktree.id),
|
|
||||||
)
|
|
||||||
.add(
|
|
||||||
worktree_repository_statuses::Column::WorkDirectoryId
|
|
||||||
.eq(repository.work_directory_id),
|
|
||||||
)
|
|
||||||
.add(repository_status_entry_filter),
|
|
||||||
)
|
|
||||||
.stream(&*tx)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
while let Some(db_status_entry) = db_repository_statuses.next().await {
|
|
||||||
let db_status_entry = db_status_entry?;
|
|
||||||
if db_status_entry.is_deleted {
|
|
||||||
repository
|
|
||||||
.removed_repo_paths
|
|
||||||
.push(db_status_entry.repo_path);
|
|
||||||
} else {
|
|
||||||
repository.updated_statuses.push(proto::StatusEntry {
|
|
||||||
repo_path: db_status_entry.repo_path,
|
|
||||||
status: db_status_entry.status as i32,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2396,6 +2349,7 @@ impl Database {
|
||||||
mtime_nanos: ActiveValue::set(mtime.nanos as i32),
|
mtime_nanos: ActiveValue::set(mtime.nanos as i32),
|
||||||
is_symlink: ActiveValue::set(entry.is_symlink),
|
is_symlink: ActiveValue::set(entry.is_symlink),
|
||||||
is_ignored: ActiveValue::set(entry.is_ignored),
|
is_ignored: ActiveValue::set(entry.is_ignored),
|
||||||
|
git_status: ActiveValue::set(entry.git_status.map(|status| status as i64)),
|
||||||
is_deleted: ActiveValue::set(false),
|
is_deleted: ActiveValue::set(false),
|
||||||
scan_id: ActiveValue::set(update.scan_id as i64),
|
scan_id: ActiveValue::set(update.scan_id as i64),
|
||||||
}
|
}
|
||||||
|
@ -2414,6 +2368,7 @@ impl Database {
|
||||||
worktree_entry::Column::MtimeNanos,
|
worktree_entry::Column::MtimeNanos,
|
||||||
worktree_entry::Column::IsSymlink,
|
worktree_entry::Column::IsSymlink,
|
||||||
worktree_entry::Column::IsIgnored,
|
worktree_entry::Column::IsIgnored,
|
||||||
|
worktree_entry::Column::GitStatus,
|
||||||
worktree_entry::Column::ScanId,
|
worktree_entry::Column::ScanId,
|
||||||
])
|
])
|
||||||
.to_owned(),
|
.to_owned(),
|
||||||
|
@ -2467,68 +2422,6 @@ impl Database {
|
||||||
)
|
)
|
||||||
.exec(&*tx)
|
.exec(&*tx)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
for repository in update.updated_repositories.iter() {
|
|
||||||
if !repository.updated_statuses.is_empty() {
|
|
||||||
worktree_repository_statuses::Entity::insert_many(
|
|
||||||
repository.updated_statuses.iter().map(|status_entry| {
|
|
||||||
worktree_repository_statuses::ActiveModel {
|
|
||||||
project_id: ActiveValue::set(project_id),
|
|
||||||
worktree_id: ActiveValue::set(worktree_id),
|
|
||||||
work_directory_id: ActiveValue::set(
|
|
||||||
repository.work_directory_id as i64,
|
|
||||||
),
|
|
||||||
repo_path: ActiveValue::set(status_entry.repo_path.clone()),
|
|
||||||
status: ActiveValue::set(status_entry.status as i64),
|
|
||||||
scan_id: ActiveValue::set(update.scan_id as i64),
|
|
||||||
is_deleted: ActiveValue::set(false),
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
.on_conflict(
|
|
||||||
OnConflict::columns([
|
|
||||||
worktree_repository_statuses::Column::ProjectId,
|
|
||||||
worktree_repository_statuses::Column::WorktreeId,
|
|
||||||
worktree_repository_statuses::Column::WorkDirectoryId,
|
|
||||||
worktree_repository_statuses::Column::RepoPath,
|
|
||||||
])
|
|
||||||
.update_columns([
|
|
||||||
worktree_repository_statuses::Column::ScanId,
|
|
||||||
worktree_repository_statuses::Column::Status,
|
|
||||||
worktree_repository_statuses::Column::IsDeleted,
|
|
||||||
])
|
|
||||||
.to_owned(),
|
|
||||||
)
|
|
||||||
.exec(&*tx)
|
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
|
|
||||||
if !repository.removed_repo_paths.is_empty() {
|
|
||||||
worktree_repository_statuses::Entity::update_many()
|
|
||||||
.filter(
|
|
||||||
worktree_repository_statuses::Column::ProjectId
|
|
||||||
.eq(project_id)
|
|
||||||
.and(
|
|
||||||
worktree_repository_statuses::Column::WorktreeId
|
|
||||||
.eq(worktree_id),
|
|
||||||
)
|
|
||||||
.and(
|
|
||||||
worktree_repository_statuses::Column::WorkDirectoryId
|
|
||||||
.eq(repository.work_directory_id as i64),
|
|
||||||
)
|
|
||||||
.and(worktree_repository_statuses::Column::RepoPath.is_in(
|
|
||||||
repository.removed_repo_paths.iter().map(String::as_str),
|
|
||||||
)),
|
|
||||||
)
|
|
||||||
.set(worktree_repository_statuses::ActiveModel {
|
|
||||||
is_deleted: ActiveValue::Set(true),
|
|
||||||
scan_id: ActiveValue::Set(update.scan_id as i64),
|
|
||||||
..Default::default()
|
|
||||||
})
|
|
||||||
.exec(&*tx)
|
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !update.removed_repositories.is_empty() {
|
if !update.removed_repositories.is_empty() {
|
||||||
|
@ -2812,6 +2705,7 @@ impl Database {
|
||||||
}),
|
}),
|
||||||
is_symlink: db_entry.is_symlink,
|
is_symlink: db_entry.is_symlink,
|
||||||
is_ignored: db_entry.is_ignored,
|
is_ignored: db_entry.is_ignored,
|
||||||
|
git_status: db_entry.git_status.map(|status| status as i32),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2837,41 +2731,12 @@ impl Database {
|
||||||
proto::RepositoryEntry {
|
proto::RepositoryEntry {
|
||||||
work_directory_id: db_repository_entry.work_directory_id as u64,
|
work_directory_id: db_repository_entry.work_directory_id as u64,
|
||||||
branch: db_repository_entry.branch,
|
branch: db_repository_entry.branch,
|
||||||
removed_repo_paths: Default::default(),
|
|
||||||
updated_statuses: Default::default(),
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
let mut db_status_entries = worktree_repository_statuses::Entity::find()
|
|
||||||
.filter(
|
|
||||||
Condition::all()
|
|
||||||
.add(worktree_repository_statuses::Column::ProjectId.eq(project_id))
|
|
||||||
.add(worktree_repository_statuses::Column::IsDeleted.eq(false)),
|
|
||||||
)
|
|
||||||
.stream(&*tx)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
while let Some(db_status_entry) = db_status_entries.next().await {
|
|
||||||
let db_status_entry = db_status_entry?;
|
|
||||||
if let Some(worktree) = worktrees.get_mut(&(db_status_entry.worktree_id as u64))
|
|
||||||
{
|
|
||||||
if let Some(repository_entry) = worktree
|
|
||||||
.repository_entries
|
|
||||||
.get_mut(&(db_status_entry.work_directory_id as u64))
|
|
||||||
{
|
|
||||||
repository_entry.updated_statuses.push(proto::StatusEntry {
|
|
||||||
repo_path: db_status_entry.repo_path,
|
|
||||||
status: db_status_entry.status as i32,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Populate worktree diagnostic summaries.
|
// Populate worktree diagnostic summaries.
|
||||||
{
|
{
|
||||||
let mut db_summaries = worktree_diagnostic_summary::Entity::find()
|
let mut db_summaries = worktree_diagnostic_summary::Entity::find()
|
||||||
|
|
|
@ -15,6 +15,7 @@ pub struct Model {
|
||||||
pub inode: i64,
|
pub inode: i64,
|
||||||
pub mtime_seconds: i64,
|
pub mtime_seconds: i64,
|
||||||
pub mtime_nanos: i32,
|
pub mtime_nanos: i32,
|
||||||
|
pub git_status: Option<i64>,
|
||||||
pub is_symlink: bool,
|
pub is_symlink: bool,
|
||||||
pub is_ignored: bool,
|
pub is_ignored: bool,
|
||||||
pub is_deleted: bool,
|
pub is_deleted: bool,
|
||||||
|
|
|
@ -2415,14 +2415,10 @@ async fn test_git_diff_base_change(
|
||||||
"
|
"
|
||||||
.unindent();
|
.unindent();
|
||||||
|
|
||||||
client_a
|
client_a.fs.as_fake().set_index_for_repo(
|
||||||
.fs
|
|
||||||
.as_fake()
|
|
||||||
.set_index_for_repo(
|
|
||||||
Path::new("/dir/.git"),
|
Path::new("/dir/.git"),
|
||||||
&[(Path::new("a.txt"), diff_base.clone())],
|
&[(Path::new("a.txt"), diff_base.clone())],
|
||||||
)
|
);
|
||||||
.await;
|
|
||||||
|
|
||||||
// Create the buffer
|
// Create the buffer
|
||||||
let buffer_local_a = project_local
|
let buffer_local_a = project_local
|
||||||
|
@ -2464,14 +2460,10 @@ async fn test_git_diff_base_change(
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
client_a
|
client_a.fs.as_fake().set_index_for_repo(
|
||||||
.fs
|
|
||||||
.as_fake()
|
|
||||||
.set_index_for_repo(
|
|
||||||
Path::new("/dir/.git"),
|
Path::new("/dir/.git"),
|
||||||
&[(Path::new("a.txt"), new_diff_base.clone())],
|
&[(Path::new("a.txt"), new_diff_base.clone())],
|
||||||
)
|
);
|
||||||
.await;
|
|
||||||
|
|
||||||
// Wait for buffer_local_a to receive it
|
// Wait for buffer_local_a to receive it
|
||||||
deterministic.run_until_parked();
|
deterministic.run_until_parked();
|
||||||
|
@ -2513,14 +2505,10 @@ async fn test_git_diff_base_change(
|
||||||
"
|
"
|
||||||
.unindent();
|
.unindent();
|
||||||
|
|
||||||
client_a
|
client_a.fs.as_fake().set_index_for_repo(
|
||||||
.fs
|
|
||||||
.as_fake()
|
|
||||||
.set_index_for_repo(
|
|
||||||
Path::new("/dir/sub/.git"),
|
Path::new("/dir/sub/.git"),
|
||||||
&[(Path::new("b.txt"), diff_base.clone())],
|
&[(Path::new("b.txt"), diff_base.clone())],
|
||||||
)
|
);
|
||||||
.await;
|
|
||||||
|
|
||||||
// Create the buffer
|
// Create the buffer
|
||||||
let buffer_local_b = project_local
|
let buffer_local_b = project_local
|
||||||
|
@ -2562,14 +2550,10 @@ async fn test_git_diff_base_change(
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
client_a
|
client_a.fs.as_fake().set_index_for_repo(
|
||||||
.fs
|
|
||||||
.as_fake()
|
|
||||||
.set_index_for_repo(
|
|
||||||
Path::new("/dir/sub/.git"),
|
Path::new("/dir/sub/.git"),
|
||||||
&[(Path::new("b.txt"), new_diff_base.clone())],
|
&[(Path::new("b.txt"), new_diff_base.clone())],
|
||||||
)
|
);
|
||||||
.await;
|
|
||||||
|
|
||||||
// Wait for buffer_local_b to receive it
|
// Wait for buffer_local_b to receive it
|
||||||
deterministic.run_until_parked();
|
deterministic.run_until_parked();
|
||||||
|
@ -2646,8 +2630,7 @@ async fn test_git_branch_name(
|
||||||
client_a
|
client_a
|
||||||
.fs
|
.fs
|
||||||
.as_fake()
|
.as_fake()
|
||||||
.set_branch_name(Path::new("/dir/.git"), Some("branch-1"))
|
.set_branch_name(Path::new("/dir/.git"), Some("branch-1"));
|
||||||
.await;
|
|
||||||
|
|
||||||
// Wait for it to catch up to the new branch
|
// Wait for it to catch up to the new branch
|
||||||
deterministic.run_until_parked();
|
deterministic.run_until_parked();
|
||||||
|
@ -2673,8 +2656,7 @@ async fn test_git_branch_name(
|
||||||
client_a
|
client_a
|
||||||
.fs
|
.fs
|
||||||
.as_fake()
|
.as_fake()
|
||||||
.set_branch_name(Path::new("/dir/.git"), Some("branch-2"))
|
.set_branch_name(Path::new("/dir/.git"), Some("branch-2"));
|
||||||
.await;
|
|
||||||
|
|
||||||
// Wait for buffer_local_a to receive it
|
// Wait for buffer_local_a to receive it
|
||||||
deterministic.run_until_parked();
|
deterministic.run_until_parked();
|
||||||
|
@ -2726,17 +2708,13 @@ async fn test_git_status_sync(
|
||||||
const A_TXT: &'static str = "a.txt";
|
const A_TXT: &'static str = "a.txt";
|
||||||
const B_TXT: &'static str = "b.txt";
|
const B_TXT: &'static str = "b.txt";
|
||||||
|
|
||||||
client_a
|
client_a.fs.as_fake().set_status_for_repo_via_git_operation(
|
||||||
.fs
|
|
||||||
.as_fake()
|
|
||||||
.set_status_for_repo(
|
|
||||||
Path::new("/dir/.git"),
|
Path::new("/dir/.git"),
|
||||||
&[
|
&[
|
||||||
(&Path::new(A_TXT), GitFileStatus::Added),
|
(&Path::new(A_TXT), GitFileStatus::Added),
|
||||||
(&Path::new(B_TXT), GitFileStatus::Added),
|
(&Path::new(B_TXT), GitFileStatus::Added),
|
||||||
],
|
],
|
||||||
)
|
);
|
||||||
.await;
|
|
||||||
|
|
||||||
let (project_local, _worktree_id) = client_a.build_local_project("/dir", cx_a).await;
|
let (project_local, _worktree_id) = client_a.build_local_project("/dir", cx_a).await;
|
||||||
let project_id = active_call_a
|
let project_id = active_call_a
|
||||||
|
@ -2763,8 +2741,7 @@ async fn test_git_status_sync(
|
||||||
assert_eq!(worktrees.len(), 1);
|
assert_eq!(worktrees.len(), 1);
|
||||||
let worktree = worktrees[0].clone();
|
let worktree = worktrees[0].clone();
|
||||||
let snapshot = worktree.read(cx).snapshot();
|
let snapshot = worktree.read(cx).snapshot();
|
||||||
let root_entry = snapshot.root_git_entry().unwrap();
|
assert_eq!(snapshot.status_for_file(file), status);
|
||||||
assert_eq!(root_entry.status_for_file(&snapshot, file), status);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Smoke test status reading
|
// Smoke test status reading
|
||||||
|
@ -2780,14 +2757,13 @@ async fn test_git_status_sync(
|
||||||
client_a
|
client_a
|
||||||
.fs
|
.fs
|
||||||
.as_fake()
|
.as_fake()
|
||||||
.set_status_for_repo(
|
.set_status_for_repo_via_working_copy_change(
|
||||||
Path::new("/dir/.git"),
|
Path::new("/dir/.git"),
|
||||||
&[
|
&[
|
||||||
(&Path::new(A_TXT), GitFileStatus::Modified),
|
(&Path::new(A_TXT), GitFileStatus::Modified),
|
||||||
(&Path::new(B_TXT), GitFileStatus::Modified),
|
(&Path::new(B_TXT), GitFileStatus::Modified),
|
||||||
],
|
],
|
||||||
)
|
);
|
||||||
.await;
|
|
||||||
|
|
||||||
// Wait for buffer_local_a to receive it
|
// Wait for buffer_local_a to receive it
|
||||||
deterministic.run_until_parked();
|
deterministic.run_until_parked();
|
||||||
|
|
|
@ -422,7 +422,7 @@ async fn apply_client_operation(
|
||||||
);
|
);
|
||||||
|
|
||||||
ensure_project_shared(&project, client, cx).await;
|
ensure_project_shared(&project, client, cx).await;
|
||||||
if !client.fs.paths().contains(&new_root_path) {
|
if !client.fs.paths(false).contains(&new_root_path) {
|
||||||
client.fs.create_dir(&new_root_path).await.unwrap();
|
client.fs.create_dir(&new_root_path).await.unwrap();
|
||||||
}
|
}
|
||||||
project
|
project
|
||||||
|
@ -628,12 +628,13 @@ async fn apply_client_operation(
|
||||||
|
|
||||||
ensure_project_shared(&project, client, cx).await;
|
ensure_project_shared(&project, client, cx).await;
|
||||||
let requested_version = buffer.read_with(cx, |buffer, _| buffer.version());
|
let requested_version = buffer.read_with(cx, |buffer, _| buffer.version());
|
||||||
let save = project.update(cx, |project, cx| project.save_buffer(buffer, cx));
|
let save = project.update(cx, |project, cx| project.save_buffer(buffer.clone(), cx));
|
||||||
let save = cx.background().spawn(async move {
|
let save = cx.spawn(|cx| async move {
|
||||||
let (saved_version, _, _) = save
|
save.await
|
||||||
.await
|
|
||||||
.map_err(|err| anyhow!("save request failed: {:?}", err))?;
|
.map_err(|err| anyhow!("save request failed: {:?}", err))?;
|
||||||
assert!(saved_version.observed_all(&requested_version));
|
assert!(buffer
|
||||||
|
.read_with(&cx, |buffer, _| { buffer.saved_version().to_owned() })
|
||||||
|
.observed_all(&requested_version));
|
||||||
anyhow::Ok(())
|
anyhow::Ok(())
|
||||||
});
|
});
|
||||||
if detach {
|
if detach {
|
||||||
|
@ -743,7 +744,7 @@ async fn apply_client_operation(
|
||||||
} => {
|
} => {
|
||||||
if !client
|
if !client
|
||||||
.fs
|
.fs
|
||||||
.directories()
|
.directories(false)
|
||||||
.contains(&path.parent().unwrap().to_owned())
|
.contains(&path.parent().unwrap().to_owned())
|
||||||
{
|
{
|
||||||
return Err(TestError::Inapplicable);
|
return Err(TestError::Inapplicable);
|
||||||
|
@ -770,10 +771,16 @@ async fn apply_client_operation(
|
||||||
repo_path,
|
repo_path,
|
||||||
contents,
|
contents,
|
||||||
} => {
|
} => {
|
||||||
if !client.fs.directories().contains(&repo_path) {
|
if !client.fs.directories(false).contains(&repo_path) {
|
||||||
return Err(TestError::Inapplicable);
|
return Err(TestError::Inapplicable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (path, _) in contents.iter() {
|
||||||
|
if !client.fs.files().contains(&repo_path.join(path)) {
|
||||||
|
return Err(TestError::Inapplicable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
log::info!(
|
log::info!(
|
||||||
"{}: writing git index for repo {:?}: {:?}",
|
"{}: writing git index for repo {:?}: {:?}",
|
||||||
client.username,
|
client.username,
|
||||||
|
@ -789,13 +796,13 @@ async fn apply_client_operation(
|
||||||
if client.fs.metadata(&dot_git_dir).await?.is_none() {
|
if client.fs.metadata(&dot_git_dir).await?.is_none() {
|
||||||
client.fs.create_dir(&dot_git_dir).await?;
|
client.fs.create_dir(&dot_git_dir).await?;
|
||||||
}
|
}
|
||||||
client.fs.set_index_for_repo(&dot_git_dir, &contents).await;
|
client.fs.set_index_for_repo(&dot_git_dir, &contents);
|
||||||
}
|
}
|
||||||
GitOperation::WriteGitBranch {
|
GitOperation::WriteGitBranch {
|
||||||
repo_path,
|
repo_path,
|
||||||
new_branch,
|
new_branch,
|
||||||
} => {
|
} => {
|
||||||
if !client.fs.directories().contains(&repo_path) {
|
if !client.fs.directories(false).contains(&repo_path) {
|
||||||
return Err(TestError::Inapplicable);
|
return Err(TestError::Inapplicable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -810,15 +817,21 @@ async fn apply_client_operation(
|
||||||
if client.fs.metadata(&dot_git_dir).await?.is_none() {
|
if client.fs.metadata(&dot_git_dir).await?.is_none() {
|
||||||
client.fs.create_dir(&dot_git_dir).await?;
|
client.fs.create_dir(&dot_git_dir).await?;
|
||||||
}
|
}
|
||||||
client.fs.set_branch_name(&dot_git_dir, new_branch).await;
|
client.fs.set_branch_name(&dot_git_dir, new_branch);
|
||||||
}
|
}
|
||||||
GitOperation::WriteGitStatuses {
|
GitOperation::WriteGitStatuses {
|
||||||
repo_path,
|
repo_path,
|
||||||
statuses,
|
statuses,
|
||||||
|
git_operation,
|
||||||
} => {
|
} => {
|
||||||
if !client.fs.directories().contains(&repo_path) {
|
if !client.fs.directories(false).contains(&repo_path) {
|
||||||
return Err(TestError::Inapplicable);
|
return Err(TestError::Inapplicable);
|
||||||
}
|
}
|
||||||
|
for (path, _) in statuses.iter() {
|
||||||
|
if !client.fs.files().contains(&repo_path.join(path)) {
|
||||||
|
return Err(TestError::Inapplicable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
log::info!(
|
log::info!(
|
||||||
"{}: writing git statuses for repo {:?}: {:?}",
|
"{}: writing git statuses for repo {:?}: {:?}",
|
||||||
|
@ -838,10 +851,16 @@ async fn apply_client_operation(
|
||||||
client.fs.create_dir(&dot_git_dir).await?;
|
client.fs.create_dir(&dot_git_dir).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if git_operation {
|
||||||
client
|
client
|
||||||
.fs
|
.fs
|
||||||
.set_status_for_repo(&dot_git_dir, statuses.as_slice())
|
.set_status_for_repo_via_git_operation(&dot_git_dir, statuses.as_slice());
|
||||||
.await;
|
} else {
|
||||||
|
client.fs.set_status_for_repo_via_working_copy_change(
|
||||||
|
&dot_git_dir,
|
||||||
|
statuses.as_slice(),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -913,9 +932,10 @@ fn check_consistency_between_clients(clients: &[(Rc<TestClient>, TestAppContext)
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
guest_snapshot.entries(false).collect::<Vec<_>>(),
|
guest_snapshot.entries(false).collect::<Vec<_>>(),
|
||||||
host_snapshot.entries(false).collect::<Vec<_>>(),
|
host_snapshot.entries(false).collect::<Vec<_>>(),
|
||||||
"{} has different snapshot than the host for worktree {:?} and project {:?}",
|
"{} has different snapshot than the host for worktree {:?} ({:?}) and project {:?}",
|
||||||
client.username,
|
client.username,
|
||||||
host_snapshot.abs_path(),
|
host_snapshot.abs_path(),
|
||||||
|
id,
|
||||||
guest_project.remote_id(),
|
guest_project.remote_id(),
|
||||||
);
|
);
|
||||||
assert_eq!(guest_snapshot.repositories().collect::<Vec<_>>(), host_snapshot.repositories().collect::<Vec<_>>(),
|
assert_eq!(guest_snapshot.repositories().collect::<Vec<_>>(), host_snapshot.repositories().collect::<Vec<_>>(),
|
||||||
|
@ -1230,6 +1250,7 @@ enum GitOperation {
|
||||||
WriteGitStatuses {
|
WriteGitStatuses {
|
||||||
repo_path: PathBuf,
|
repo_path: PathBuf,
|
||||||
statuses: Vec<(PathBuf, GitFileStatus)>,
|
statuses: Vec<(PathBuf, GitFileStatus)>,
|
||||||
|
git_operation: bool,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1575,7 +1596,7 @@ impl TestPlan {
|
||||||
.choose(&mut self.rng)
|
.choose(&mut self.rng)
|
||||||
.cloned() else { continue };
|
.cloned() else { continue };
|
||||||
let project_root_name = root_name_for_project(&project, cx);
|
let project_root_name = root_name_for_project(&project, cx);
|
||||||
let mut paths = client.fs.paths();
|
let mut paths = client.fs.paths(false);
|
||||||
paths.remove(0);
|
paths.remove(0);
|
||||||
let new_root_path = if paths.is_empty() || self.rng.gen() {
|
let new_root_path = if paths.is_empty() || self.rng.gen() {
|
||||||
Path::new("/").join(&self.next_root_dir_name(user_id))
|
Path::new("/").join(&self.next_root_dir_name(user_id))
|
||||||
|
@ -1755,7 +1776,7 @@ impl TestPlan {
|
||||||
let is_dir = self.rng.gen::<bool>();
|
let is_dir = self.rng.gen::<bool>();
|
||||||
let content;
|
let content;
|
||||||
let mut path;
|
let mut path;
|
||||||
let dir_paths = client.fs.directories();
|
let dir_paths = client.fs.directories(false);
|
||||||
|
|
||||||
if is_dir {
|
if is_dir {
|
||||||
content = String::new();
|
content = String::new();
|
||||||
|
@ -1809,7 +1830,7 @@ impl TestPlan {
|
||||||
|
|
||||||
let repo_path = client
|
let repo_path = client
|
||||||
.fs
|
.fs
|
||||||
.directories()
|
.directories(false)
|
||||||
.choose(&mut self.rng)
|
.choose(&mut self.rng)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.clone();
|
.clone();
|
||||||
|
@ -1855,9 +1876,12 @@ impl TestPlan {
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let git_operation = self.rng.gen::<bool>();
|
||||||
|
|
||||||
GitOperation::WriteGitStatuses {
|
GitOperation::WriteGitStatuses {
|
||||||
repo_path,
|
repo_path,
|
||||||
statuses,
|
statuses,
|
||||||
|
git_operation,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
|
|
|
@ -14,6 +14,8 @@ lsp = { path = "../lsp" }
|
||||||
rope = { path = "../rope" }
|
rope = { path = "../rope" }
|
||||||
util = { path = "../util" }
|
util = { path = "../util" }
|
||||||
sum_tree = { path = "../sum_tree" }
|
sum_tree = { path = "../sum_tree" }
|
||||||
|
rpc = { path = "../rpc" }
|
||||||
|
|
||||||
anyhow.workspace = true
|
anyhow.workspace = true
|
||||||
async-trait.workspace = true
|
async-trait.workspace = true
|
||||||
futures.workspace = true
|
futures.workspace = true
|
||||||
|
|
|
@ -29,6 +29,8 @@ use collections::{btree_map, BTreeMap};
|
||||||
#[cfg(any(test, feature = "test-support"))]
|
#[cfg(any(test, feature = "test-support"))]
|
||||||
use repository::{FakeGitRepositoryState, GitFileStatus};
|
use repository::{FakeGitRepositoryState, GitFileStatus};
|
||||||
#[cfg(any(test, feature = "test-support"))]
|
#[cfg(any(test, feature = "test-support"))]
|
||||||
|
use std::ffi::OsStr;
|
||||||
|
#[cfg(any(test, feature = "test-support"))]
|
||||||
use std::sync::Weak;
|
use std::sync::Weak;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
|
@ -501,6 +503,11 @@ impl FakeFsState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(test, feature = "test-support"))]
|
||||||
|
lazy_static! {
|
||||||
|
pub static ref FS_DOT_GIT: &'static OsStr = OsStr::new(".git");
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(any(test, feature = "test-support"))]
|
#[cfg(any(test, feature = "test-support"))]
|
||||||
impl FakeFs {
|
impl FakeFs {
|
||||||
pub fn new(executor: Arc<gpui::executor::Background>) -> Arc<Self> {
|
pub fn new(executor: Arc<gpui::executor::Background>) -> Arc<Self> {
|
||||||
|
@ -619,7 +626,7 @@ impl FakeFs {
|
||||||
.boxed()
|
.boxed()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_git_state<F>(&self, dot_git: &Path, f: F)
|
pub fn with_git_state<F>(&self, dot_git: &Path, emit_git_event: bool, f: F)
|
||||||
where
|
where
|
||||||
F: FnOnce(&mut FakeGitRepositoryState),
|
F: FnOnce(&mut FakeGitRepositoryState),
|
||||||
{
|
{
|
||||||
|
@ -633,18 +640,22 @@ impl FakeFs {
|
||||||
|
|
||||||
f(&mut repo_state);
|
f(&mut repo_state);
|
||||||
|
|
||||||
|
if emit_git_event {
|
||||||
state.emit_event([dot_git]);
|
state.emit_event([dot_git]);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
panic!("not a directory");
|
panic!("not a directory");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn set_branch_name(&self, dot_git: &Path, branch: Option<impl Into<String>>) {
|
pub fn set_branch_name(&self, dot_git: &Path, branch: Option<impl Into<String>>) {
|
||||||
self.with_git_state(dot_git, |state| state.branch_name = branch.map(Into::into))
|
self.with_git_state(dot_git, true, |state| {
|
||||||
|
state.branch_name = branch.map(Into::into)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn set_index_for_repo(&self, dot_git: &Path, head_state: &[(&Path, String)]) {
|
pub fn set_index_for_repo(&self, dot_git: &Path, head_state: &[(&Path, String)]) {
|
||||||
self.with_git_state(dot_git, |state| {
|
self.with_git_state(dot_git, true, |state| {
|
||||||
state.index_contents.clear();
|
state.index_contents.clear();
|
||||||
state.index_contents.extend(
|
state.index_contents.extend(
|
||||||
head_state
|
head_state
|
||||||
|
@ -654,8 +665,32 @@ impl FakeFs {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn set_status_for_repo(&self, dot_git: &Path, statuses: &[(&Path, GitFileStatus)]) {
|
pub fn set_status_for_repo_via_working_copy_change(
|
||||||
self.with_git_state(dot_git, |state| {
|
&self,
|
||||||
|
dot_git: &Path,
|
||||||
|
statuses: &[(&Path, GitFileStatus)],
|
||||||
|
) {
|
||||||
|
self.with_git_state(dot_git, false, |state| {
|
||||||
|
state.worktree_statuses.clear();
|
||||||
|
state.worktree_statuses.extend(
|
||||||
|
statuses
|
||||||
|
.iter()
|
||||||
|
.map(|(path, content)| ((**path).into(), content.clone())),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
self.state.lock().emit_event(
|
||||||
|
statuses
|
||||||
|
.iter()
|
||||||
|
.map(|(path, _)| dot_git.parent().unwrap().join(path)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_status_for_repo_via_git_operation(
|
||||||
|
&self,
|
||||||
|
dot_git: &Path,
|
||||||
|
statuses: &[(&Path, GitFileStatus)],
|
||||||
|
) {
|
||||||
|
self.with_git_state(dot_git, true, |state| {
|
||||||
state.worktree_statuses.clear();
|
state.worktree_statuses.clear();
|
||||||
state.worktree_statuses.extend(
|
state.worktree_statuses.extend(
|
||||||
statuses
|
statuses
|
||||||
|
@ -665,7 +700,7 @@ impl FakeFs {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn paths(&self) -> Vec<PathBuf> {
|
pub fn paths(&self, include_dot_git: bool) -> Vec<PathBuf> {
|
||||||
let mut result = Vec::new();
|
let mut result = Vec::new();
|
||||||
let mut queue = collections::VecDeque::new();
|
let mut queue = collections::VecDeque::new();
|
||||||
queue.push_back((PathBuf::from("/"), self.state.lock().root.clone()));
|
queue.push_back((PathBuf::from("/"), self.state.lock().root.clone()));
|
||||||
|
@ -675,12 +710,18 @@ impl FakeFs {
|
||||||
queue.push_back((path.join(name), entry.clone()));
|
queue.push_back((path.join(name), entry.clone()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if include_dot_git
|
||||||
|
|| !path
|
||||||
|
.components()
|
||||||
|
.any(|component| component.as_os_str() == *FS_DOT_GIT)
|
||||||
|
{
|
||||||
result.push(path);
|
result.push(path);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn directories(&self) -> Vec<PathBuf> {
|
pub fn directories(&self, include_dot_git: bool) -> Vec<PathBuf> {
|
||||||
let mut result = Vec::new();
|
let mut result = Vec::new();
|
||||||
let mut queue = collections::VecDeque::new();
|
let mut queue = collections::VecDeque::new();
|
||||||
queue.push_back((PathBuf::from("/"), self.state.lock().root.clone()));
|
queue.push_back((PathBuf::from("/"), self.state.lock().root.clone()));
|
||||||
|
@ -689,9 +730,15 @@ impl FakeFs {
|
||||||
for (name, entry) in entries {
|
for (name, entry) in entries {
|
||||||
queue.push_back((path.join(name), entry.clone()));
|
queue.push_back((path.join(name), entry.clone()));
|
||||||
}
|
}
|
||||||
|
if include_dot_git
|
||||||
|
|| !path
|
||||||
|
.components()
|
||||||
|
.any(|component| component.as_os_str() == *FS_DOT_GIT)
|
||||||
|
{
|
||||||
result.push(path);
|
result.push(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use collections::HashMap;
|
use collections::HashMap;
|
||||||
|
use git2::ErrorCode;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
use rpc::proto;
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use std::{
|
use std::{
|
||||||
cmp::Ordering,
|
cmp::Ordering,
|
||||||
|
@ -24,7 +26,7 @@ pub trait GitRepository: Send {
|
||||||
|
|
||||||
fn statuses(&self) -> Option<TreeMap<RepoPath, GitFileStatus>>;
|
fn statuses(&self) -> Option<TreeMap<RepoPath, GitFileStatus>>;
|
||||||
|
|
||||||
fn status(&self, path: &RepoPath) -> Option<GitFileStatus>;
|
fn status(&self, path: &RepoPath) -> Result<Option<GitFileStatus>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Debug for dyn GitRepository {
|
impl std::fmt::Debug for dyn GitRepository {
|
||||||
|
@ -91,9 +93,18 @@ impl GitRepository for LibGitRepository {
|
||||||
Some(map)
|
Some(map)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn status(&self, path: &RepoPath) -> Option<GitFileStatus> {
|
fn status(&self, path: &RepoPath) -> Result<Option<GitFileStatus>> {
|
||||||
let status = self.status_file(path).log_err()?;
|
let status = self.status_file(path);
|
||||||
read_status(status)
|
match status {
|
||||||
|
Ok(status) => Ok(read_status(status)),
|
||||||
|
Err(e) => {
|
||||||
|
if e.code() == ErrorCode::NotFound {
|
||||||
|
Ok(None)
|
||||||
|
} else {
|
||||||
|
Err(e.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,9 +166,9 @@ impl GitRepository for FakeGitRepository {
|
||||||
Some(map)
|
Some(map)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn status(&self, path: &RepoPath) -> Option<GitFileStatus> {
|
fn status(&self, path: &RepoPath) -> Result<Option<GitFileStatus>> {
|
||||||
let state = self.state.lock();
|
let state = self.state.lock();
|
||||||
state.worktree_statuses.get(path).cloned()
|
Ok(state.worktree_statuses.get(path).cloned())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,8 +208,51 @@ pub enum GitFileStatus {
|
||||||
Conflict,
|
Conflict,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl GitFileStatus {
|
||||||
|
pub fn merge(
|
||||||
|
this: Option<GitFileStatus>,
|
||||||
|
other: Option<GitFileStatus>,
|
||||||
|
prefer_other: bool,
|
||||||
|
) -> Option<GitFileStatus> {
|
||||||
|
if prefer_other {
|
||||||
|
return other;
|
||||||
|
} else {
|
||||||
|
match (this, other) {
|
||||||
|
(Some(GitFileStatus::Conflict), _) | (_, Some(GitFileStatus::Conflict)) => {
|
||||||
|
Some(GitFileStatus::Conflict)
|
||||||
|
}
|
||||||
|
(Some(GitFileStatus::Modified), _) | (_, Some(GitFileStatus::Modified)) => {
|
||||||
|
Some(GitFileStatus::Modified)
|
||||||
|
}
|
||||||
|
(Some(GitFileStatus::Added), _) | (_, Some(GitFileStatus::Added)) => {
|
||||||
|
Some(GitFileStatus::Added)
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_proto(git_status: Option<i32>) -> Option<GitFileStatus> {
|
||||||
|
git_status.and_then(|status| {
|
||||||
|
proto::GitStatus::from_i32(status).map(|status| match status {
|
||||||
|
proto::GitStatus::Added => GitFileStatus::Added,
|
||||||
|
proto::GitStatus::Modified => GitFileStatus::Modified,
|
||||||
|
proto::GitStatus::Conflict => GitFileStatus::Conflict,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_proto(self) -> i32 {
|
||||||
|
match self {
|
||||||
|
GitFileStatus::Added => proto::GitStatus::Added as i32,
|
||||||
|
GitFileStatus::Modified => proto::GitStatus::Modified as i32,
|
||||||
|
GitFileStatus::Conflict => proto::GitStatus::Conflict as i32,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Ord, Hash, PartialOrd, Eq, PartialEq)]
|
#[derive(Clone, Debug, Ord, Hash, PartialOrd, Eq, PartialEq)]
|
||||||
pub struct RepoPath(PathBuf);
|
pub struct RepoPath(pub PathBuf);
|
||||||
|
|
||||||
impl RepoPath {
|
impl RepoPath {
|
||||||
pub fn new(path: PathBuf) -> Self {
|
pub fn new(path: PathBuf) -> Self {
|
||||||
|
|
|
@ -37,8 +37,8 @@ use language::{
|
||||||
range_from_lsp, range_to_lsp, Anchor, Bias, Buffer, CachedLspAdapter, CodeAction, CodeLabel,
|
range_from_lsp, range_to_lsp, Anchor, Bias, Buffer, CachedLspAdapter, CodeAction, CodeLabel,
|
||||||
Completion, Diagnostic, DiagnosticEntry, DiagnosticSet, Diff, Event as BufferEvent, File as _,
|
Completion, Diagnostic, DiagnosticEntry, DiagnosticSet, Diff, Event as BufferEvent, File as _,
|
||||||
Language, LanguageRegistry, LanguageServerName, LocalFile, OffsetRangeExt, Operation, Patch,
|
Language, LanguageRegistry, LanguageServerName, LocalFile, OffsetRangeExt, Operation, Patch,
|
||||||
PendingLanguageServer, PointUtf16, RopeFingerprint, TextBufferSnapshot, ToOffset, ToPointUtf16,
|
PendingLanguageServer, PointUtf16, TextBufferSnapshot, ToOffset, ToPointUtf16, Transaction,
|
||||||
Transaction, Unclipped,
|
Unclipped,
|
||||||
};
|
};
|
||||||
use log::error;
|
use log::error;
|
||||||
use lsp::{
|
use lsp::{
|
||||||
|
@ -69,7 +69,7 @@ use std::{
|
||||||
atomic::{AtomicUsize, Ordering::SeqCst},
|
atomic::{AtomicUsize, Ordering::SeqCst},
|
||||||
Arc,
|
Arc,
|
||||||
},
|
},
|
||||||
time::{Duration, Instant, SystemTime},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
use terminals::Terminals;
|
use terminals::Terminals;
|
||||||
use util::{
|
use util::{
|
||||||
|
@ -1618,7 +1618,7 @@ impl Project {
|
||||||
&self,
|
&self,
|
||||||
buffer: ModelHandle<Buffer>,
|
buffer: ModelHandle<Buffer>,
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) -> Task<Result<(clock::Global, RopeFingerprint, SystemTime)>> {
|
) -> Task<Result<()>> {
|
||||||
let Some(file) = File::from_dyn(buffer.read(cx).file()) else {
|
let Some(file) = File::from_dyn(buffer.read(cx).file()) else {
|
||||||
return Task::ready(Err(anyhow!("buffer doesn't have a file")));
|
return Task::ready(Err(anyhow!("buffer doesn't have a file")));
|
||||||
};
|
};
|
||||||
|
@ -5161,9 +5161,9 @@ impl Project {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let path = &project_path.path;
|
let path = &project_path.path;
|
||||||
changed_repos.iter().find(|(work_dir, change)| {
|
changed_repos
|
||||||
path.starts_with(work_dir) && change.git_dir_changed
|
.iter()
|
||||||
})?;
|
.find(|(work_dir, _)| path.starts_with(work_dir))?;
|
||||||
let receiver = receiver.clone();
|
let receiver = receiver.clone();
|
||||||
let path = path.clone();
|
let path = path.clone();
|
||||||
Some(async move {
|
Some(async move {
|
||||||
|
@ -5186,9 +5186,9 @@ impl Project {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let path = file.path();
|
let path = file.path();
|
||||||
changed_repos.iter().find(|(work_dir, change)| {
|
changed_repos
|
||||||
path.starts_with(work_dir) && change.git_dir_changed
|
.iter()
|
||||||
})?;
|
.find(|(work_dir, _)| path.starts_with(work_dir))?;
|
||||||
Some((buffer, path.clone()))
|
Some((buffer, path.clone()))
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
@ -5989,16 +5989,15 @@ impl Project {
|
||||||
.await?;
|
.await?;
|
||||||
let buffer_id = buffer.read_with(&cx, |buffer, _| buffer.remote_id());
|
let buffer_id = buffer.read_with(&cx, |buffer, _| buffer.remote_id());
|
||||||
|
|
||||||
let (saved_version, fingerprint, mtime) = this
|
this.update(&mut cx, |this, cx| this.save_buffer(buffer.clone(), cx))
|
||||||
.update(&mut cx, |this, cx| this.save_buffer(buffer, cx))
|
|
||||||
.await?;
|
.await?;
|
||||||
Ok(proto::BufferSaved {
|
Ok(buffer.read_with(&cx, |buffer, _| proto::BufferSaved {
|
||||||
project_id,
|
project_id,
|
||||||
buffer_id,
|
buffer_id,
|
||||||
version: serialize_version(&saved_version),
|
version: serialize_version(buffer.saved_version()),
|
||||||
mtime: Some(mtime.into()),
|
mtime: Some(buffer.saved_mtime().into()),
|
||||||
fingerprint: language::proto::serialize_fingerprint(fingerprint),
|
fingerprint: language::proto::serialize_fingerprint(buffer.saved_version_fingerprint()),
|
||||||
})
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle_reload_buffers(
|
async fn handle_reload_buffers(
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1002,6 +1002,7 @@ impl ProjectPanel {
|
||||||
mtime: entry.mtime,
|
mtime: entry.mtime,
|
||||||
is_symlink: false,
|
is_symlink: false,
|
||||||
is_ignored: false,
|
is_ignored: false,
|
||||||
|
git_status: entry.git_status,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if expanded_dir_ids.binary_search(&entry.id).is_err()
|
if expanded_dir_ids.binary_search(&entry.id).is_err()
|
||||||
|
@ -1011,6 +1012,9 @@ impl ProjectPanel {
|
||||||
}
|
}
|
||||||
entry_iter.advance();
|
entry_iter.advance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
snapshot.propagate_git_statuses(&mut visible_worktree_entries);
|
||||||
|
|
||||||
visible_worktree_entries.sort_by(|entry_a, entry_b| {
|
visible_worktree_entries.sort_by(|entry_a, entry_b| {
|
||||||
let mut components_a = entry_a.path.components().peekable();
|
let mut components_a = entry_a.path.components().peekable();
|
||||||
let mut components_b = entry_b.path.components().peekable();
|
let mut components_b = entry_b.path.components().peekable();
|
||||||
|
@ -1108,14 +1112,8 @@ impl ProjectPanel {
|
||||||
.unwrap_or(&[]);
|
.unwrap_or(&[]);
|
||||||
|
|
||||||
let entry_range = range.start.saturating_sub(ix)..end_ix - ix;
|
let entry_range = range.start.saturating_sub(ix)..end_ix - ix;
|
||||||
for (entry, repo) in
|
for entry in visible_worktree_entries[entry_range].iter() {
|
||||||
snapshot.entries_with_repositories(visible_worktree_entries[entry_range].iter())
|
let status = git_status_setting.then(|| entry.git_status).flatten();
|
||||||
{
|
|
||||||
let status = (git_status_setting
|
|
||||||
&& entry.path.parent().is_some()
|
|
||||||
&& !entry.is_ignored)
|
|
||||||
.then(|| repo.and_then(|repo| repo.status_for_path(&snapshot, &entry.path)))
|
|
||||||
.flatten();
|
|
||||||
|
|
||||||
let mut details = EntryDetails {
|
let mut details = EntryDetails {
|
||||||
filename: entry
|
filename: entry
|
||||||
|
|
|
@ -1005,13 +1005,12 @@ message Entry {
|
||||||
Timestamp mtime = 5;
|
Timestamp mtime = 5;
|
||||||
bool is_symlink = 6;
|
bool is_symlink = 6;
|
||||||
bool is_ignored = 7;
|
bool is_ignored = 7;
|
||||||
|
optional GitStatus git_status = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
message RepositoryEntry {
|
message RepositoryEntry {
|
||||||
uint64 work_directory_id = 1;
|
uint64 work_directory_id = 1;
|
||||||
optional string branch = 2;
|
optional string branch = 2;
|
||||||
repeated string removed_repo_paths = 3;
|
|
||||||
repeated StatusEntry updated_statuses = 4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message StatusEntry {
|
message StatusEntry {
|
||||||
|
|
|
@ -480,6 +480,11 @@ impl<T: Item> SumTree<T> {
|
||||||
} => child_trees.last().unwrap().rightmost_leaf(),
|
} => child_trees.last().unwrap().rightmost_leaf(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
pub fn _debug_entries(&self) -> Vec<&T> {
|
||||||
|
self.iter().collect::<Vec<_>>()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Item + PartialEq> PartialEq for SumTree<T> {
|
impl<T: Item + PartialEq> PartialEq for SumTree<T> {
|
||||||
|
|
|
@ -57,7 +57,7 @@ pub fn post_inc<T: From<u8> + AddAssign<T> + Copy>(value: &mut T) -> T {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extend a sorted vector with a sorted sequence of items, maintaining the vector's sort order and
|
/// Extend a sorted vector with a sorted sequence of items, maintaining the vector's sort order and
|
||||||
/// enforcing a maximum length. Sort the items according to the given callback. Before calling this,
|
/// enforcing a maximum length. This also de-duplicates items. Sort the items according to the given callback. Before calling this,
|
||||||
/// both `vec` and `new_items` should already be sorted according to the `cmp` comparator.
|
/// both `vec` and `new_items` should already be sorted according to the `cmp` comparator.
|
||||||
pub fn extend_sorted<T, I, F>(vec: &mut Vec<T>, new_items: I, limit: usize, mut cmp: F)
|
pub fn extend_sorted<T, I, F>(vec: &mut Vec<T>, new_items: I, limit: usize, mut cmp: F)
|
||||||
where
|
where
|
||||||
|
|
11
styles/package-lock.json
generated
11
styles/package-lock.json
generated
|
@ -9,6 +9,7 @@
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@tokens-studio/types": "^0.2.3",
|
||||||
"@types/chroma-js": "^2.4.0",
|
"@types/chroma-js": "^2.4.0",
|
||||||
"@types/node": "^18.14.1",
|
"@types/node": "^18.14.1",
|
||||||
"ayu": "^8.0.1",
|
"ayu": "^8.0.1",
|
||||||
|
@ -53,6 +54,11 @@
|
||||||
"@jridgewell/sourcemap-codec": "^1.4.10"
|
"@jridgewell/sourcemap-codec": "^1.4.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@tokens-studio/types": {
|
||||||
|
"version": "0.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tokens-studio/types/-/types-0.2.3.tgz",
|
||||||
|
"integrity": "sha512-2KN3V0JPf+Zh8aoVMwykJq29Lsi7vYgKGYBQ/zQ+FbDEmrH6T/Vwn8kG7cvbTmW1JAAvgxVxMIivgC9PmFelNA=="
|
||||||
|
},
|
||||||
"node_modules/@tsconfig/node10": {
|
"node_modules/@tsconfig/node10": {
|
||||||
"version": "1.0.9",
|
"version": "1.0.9",
|
||||||
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz",
|
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz",
|
||||||
|
@ -271,6 +277,11 @@
|
||||||
"@jridgewell/sourcemap-codec": "^1.4.10"
|
"@jridgewell/sourcemap-codec": "^1.4.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@tokens-studio/types": {
|
||||||
|
"version": "0.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tokens-studio/types/-/types-0.2.3.tgz",
|
||||||
|
"integrity": "sha512-2KN3V0JPf+Zh8aoVMwykJq29Lsi7vYgKGYBQ/zQ+FbDEmrH6T/Vwn8kG7cvbTmW1JAAvgxVxMIivgC9PmFelNA=="
|
||||||
|
},
|
||||||
"@tsconfig/node10": {
|
"@tsconfig/node10": {
|
||||||
"version": "1.0.9",
|
"version": "1.0.9",
|
||||||
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz",
|
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz",
|
||||||
|
|
|
@ -5,11 +5,13 @@
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "ts-node ./src/buildThemes.ts",
|
"build": "ts-node ./src/buildThemes.ts",
|
||||||
"build-licenses": "ts-node ./src/buildLicenses.ts"
|
"build-licenses": "ts-node ./src/buildLicenses.ts",
|
||||||
|
"build-tokens": "ts-node ./src/buildTokens.ts"
|
||||||
},
|
},
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@tokens-studio/types": "^0.2.3",
|
||||||
"@types/chroma-js": "^2.4.0",
|
"@types/chroma-js": "^2.4.0",
|
||||||
"@types/node": "^18.14.1",
|
"@types/node": "^18.14.1",
|
||||||
"ayu": "^8.0.1",
|
"ayu": "^8.0.1",
|
||||||
|
|
|
@ -30,17 +30,19 @@ function generateLicenseFile(themes: ThemeConfig[]) {
|
||||||
checkLicenses(themes)
|
checkLicenses(themes)
|
||||||
for (const theme of themes) {
|
for (const theme of themes) {
|
||||||
const licenseText = fs.readFileSync(theme.licenseFile).toString()
|
const licenseText = fs.readFileSync(theme.licenseFile).toString()
|
||||||
writeLicense(theme.name, theme.licenseUrl, licenseText)
|
writeLicense(theme.name, licenseText, theme.licenseUrl)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function writeLicense(
|
function writeLicense(
|
||||||
themeName: string,
|
themeName: string,
|
||||||
licenseUrl: string,
|
licenseText: string,
|
||||||
licenseText: String
|
licenseUrl?: string
|
||||||
) {
|
) {
|
||||||
process.stdout.write(
|
process.stdout.write(
|
||||||
`## [${themeName}](${licenseUrl})\n\n${licenseText}\n********************************************************************************\n\n`
|
licenseUrl
|
||||||
|
? `## [${themeName}](${licenseUrl})\n\n${licenseText}\n********************************************************************************\n\n`
|
||||||
|
: `## ${themeName}\n\n${licenseText}\n********************************************************************************\n\n`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ import * as fs from "fs"
|
||||||
import { tmpdir } from "os"
|
import { tmpdir } from "os"
|
||||||
import * as path from "path"
|
import * as path from "path"
|
||||||
import app from "./styleTree/app"
|
import app from "./styleTree/app"
|
||||||
import { ColorScheme, createColorScheme } from "./themes/common/colorScheme"
|
import { ColorScheme, createColorScheme } from "./theme/colorScheme"
|
||||||
import snakeCase from "./utils/snakeCase"
|
import snakeCase from "./utils/snakeCase"
|
||||||
import { themes } from "./themes"
|
import { themes } from "./themes"
|
||||||
|
|
||||||
|
@ -35,7 +35,9 @@ function writeThemes(colorSchemes: ColorScheme[], outputDirectory: string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const colorSchemes: ColorScheme[] = themes.map((theme) => createColorScheme(theme))
|
const colorSchemes: ColorScheme[] = themes.map((theme) =>
|
||||||
|
createColorScheme(theme)
|
||||||
|
)
|
||||||
|
|
||||||
// Write new themes to theme directory
|
// Write new themes to theme directory
|
||||||
writeThemes(colorSchemes, `${assetsDirectory}/themes`)
|
writeThemes(colorSchemes, `${assetsDirectory}/themes`)
|
||||||
|
|
39
styles/src/buildTokens.ts
Normal file
39
styles/src/buildTokens.ts
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
import * as fs from "fs"
|
||||||
|
import * as path from "path"
|
||||||
|
import { ColorScheme, createColorScheme } from "./common"
|
||||||
|
import { themes } from "./themes"
|
||||||
|
import { slugify } from "./utils/slugify"
|
||||||
|
import { colorSchemeTokens } from "./theme/tokens/colorScheme"
|
||||||
|
|
||||||
|
const TOKENS_DIRECTORY = path.join(__dirname, "..", "target", "tokens")
|
||||||
|
|
||||||
|
function clearTokens(tokensDirectory: string) {
|
||||||
|
if (!fs.existsSync(tokensDirectory)) {
|
||||||
|
fs.mkdirSync(tokensDirectory, { recursive: true })
|
||||||
|
} else {
|
||||||
|
for (const file of fs.readdirSync(tokensDirectory)) {
|
||||||
|
if (file.endsWith(".json")) {
|
||||||
|
fs.unlinkSync(path.join(tokensDirectory, file))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeTokens(colorSchemes: ColorScheme[], tokensDirectory: string) {
|
||||||
|
clearTokens(tokensDirectory)
|
||||||
|
|
||||||
|
for (const colorScheme of colorSchemes) {
|
||||||
|
const fileName = slugify(colorScheme.name)
|
||||||
|
const tokens = colorSchemeTokens(colorScheme)
|
||||||
|
const tokensJSON = JSON.stringify(tokens, null, 2)
|
||||||
|
const outPath = path.join(tokensDirectory, `${fileName}.json`)
|
||||||
|
fs.writeFileSync(outPath, tokensJSON)
|
||||||
|
console.log(`- ${outPath} created`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const colorSchemes: ColorScheme[] = themes.map((theme) =>
|
||||||
|
createColorScheme(theme)
|
||||||
|
)
|
||||||
|
|
||||||
|
writeTokens(colorSchemes, TOKENS_DIRECTORY)
|
|
@ -1,5 +1,5 @@
|
||||||
import chroma from "chroma-js"
|
import chroma from "chroma-js"
|
||||||
export * from "./themes/common"
|
export * from "./theme"
|
||||||
export { chroma }
|
export { chroma }
|
||||||
|
|
||||||
export const fontFamilies = {
|
export const fontFamilies = {
|
||||||
|
|
|
@ -19,7 +19,7 @@ import terminal from "./terminal"
|
||||||
import contactList from "./contactList"
|
import contactList from "./contactList"
|
||||||
import lspLogMenu from "./lspLogMenu"
|
import lspLogMenu from "./lspLogMenu"
|
||||||
import incomingCallNotification from "./incomingCallNotification"
|
import incomingCallNotification from "./incomingCallNotification"
|
||||||
import { ColorScheme } from "../themes/common/colorScheme"
|
import { ColorScheme } from "../theme/colorScheme"
|
||||||
import feedback from "./feedback"
|
import feedback from "./feedback"
|
||||||
import welcome from "./welcome"
|
import welcome from "./welcome"
|
||||||
import copilot from "./copilot"
|
import copilot from "./copilot"
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
import { ColorScheme } from "../themes/common/colorScheme"
|
import { ColorScheme } from "../theme/colorScheme"
|
||||||
import { text, border, background, foreground } from "./components"
|
import { text, border, background, foreground } from "./components"
|
||||||
import editor from "./editor"
|
import editor from "./editor"
|
||||||
|
|
||||||
export default function assistant(colorScheme: ColorScheme) {
|
export default function assistant(colorScheme: ColorScheme) {
|
||||||
const layer = colorScheme.highest;
|
const layer = colorScheme.highest
|
||||||
return {
|
return {
|
||||||
container: {
|
container: {
|
||||||
background: editor(colorScheme).background,
|
background: editor(colorScheme).background,
|
||||||
padding: { left: 12 }
|
padding: { left: 12 },
|
||||||
},
|
},
|
||||||
header: {
|
header: {
|
||||||
border: border(layer, "default", { bottom: true, top: true }),
|
border: border(layer, "default", { bottom: true, top: true }),
|
||||||
margin: { bottom: 6, top: 6 },
|
margin: { bottom: 6, top: 6 },
|
||||||
background: editor(colorScheme).background
|
background: editor(colorScheme).background,
|
||||||
},
|
},
|
||||||
userSender: {
|
userSender: {
|
||||||
...text(layer, "sans", "default", { size: "sm", weight: "bold" }),
|
...text(layer, "sans", "default", { size: "sm", weight: "bold" }),
|
||||||
|
@ -38,7 +38,7 @@ export default function assistant(colorScheme: ColorScheme) {
|
||||||
...text(layer, "sans", "default", { size: "xs" }),
|
...text(layer, "sans", "default", { size: "xs" }),
|
||||||
hover: {
|
hover: {
|
||||||
background: background(layer, "on", "hovered"),
|
background: background(layer, "on", "hovered"),
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
remainingTokens: {
|
remainingTokens: {
|
||||||
background: background(layer, "on"),
|
background: background(layer, "on"),
|
||||||
|
@ -80,6 +80,6 @@ export default function assistant(colorScheme: ColorScheme) {
|
||||||
apiKeyPrompt: {
|
apiKeyPrompt: {
|
||||||
padding: 10,
|
padding: 10,
|
||||||
...text(layer, "sans", "default", { size: "xs" }),
|
...text(layer, "sans", "default", { size: "xs" }),
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { ColorScheme } from "../themes/common/colorScheme"
|
import { ColorScheme } from "../theme/colorScheme"
|
||||||
import { withOpacity } from "../utils/color"
|
import { withOpacity } from "../theme/color"
|
||||||
import { text, background } from "./components"
|
import { text, background } from "./components"
|
||||||
|
|
||||||
export default function commandPalette(colorScheme: ColorScheme) {
|
export default function commandPalette(colorScheme: ColorScheme) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { fontFamilies, fontSizes, FontWeight } from "../common"
|
import { fontFamilies, fontSizes, FontWeight } from "../common"
|
||||||
import { Layer, Styles, StyleSets, Style } from "../themes/common/colorScheme"
|
import { Layer, Styles, StyleSets, Style } from "../theme/colorScheme"
|
||||||
|
|
||||||
function isStyleSet(key: any): key is StyleSets {
|
function isStyleSet(key: any): key is StyleSets {
|
||||||
return [
|
return [
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import picker from "./picker"
|
import picker from "./picker"
|
||||||
import { ColorScheme } from "../themes/common/colorScheme"
|
import { ColorScheme } from "../theme/colorScheme"
|
||||||
import { background, border, foreground, text } from "./components"
|
import { background, border, foreground, text } from "./components"
|
||||||
|
|
||||||
export default function contactFinder(colorScheme: ColorScheme): any {
|
export default function contactFinder(colorScheme: ColorScheme): any {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { ColorScheme } from "../themes/common/colorScheme"
|
import { ColorScheme } from "../theme/colorScheme"
|
||||||
import { background, border, borderColor, foreground, text } from "./components"
|
import { background, border, borderColor, foreground, text } from "./components"
|
||||||
|
|
||||||
export default function contactsPanel(colorScheme: ColorScheme) {
|
export default function contactsPanel(colorScheme: ColorScheme) {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { ColorScheme } from "../themes/common/colorScheme"
|
import { ColorScheme } from "../theme/colorScheme"
|
||||||
import { background, foreground, text } from "./components"
|
import { background, foreground, text } from "./components"
|
||||||
|
|
||||||
const avatarSize = 12
|
const avatarSize = 12
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { ColorScheme } from "../themes/common/colorScheme"
|
import { ColorScheme } from "../theme/colorScheme"
|
||||||
import { background, border, text } from "./components"
|
import { background, border, text } from "./components"
|
||||||
|
|
||||||
export default function contactsPopover(colorScheme: ColorScheme) {
|
export default function contactsPopover(colorScheme: ColorScheme) {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { ColorScheme } from "../themes/common/colorScheme"
|
import { ColorScheme } from "../theme/colorScheme"
|
||||||
import { background, border, borderColor, text } from "./components"
|
import { background, border, borderColor, text } from "./components"
|
||||||
|
|
||||||
export default function contextMenu(colorScheme: ColorScheme) {
|
export default function contextMenu(colorScheme: ColorScheme) {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { ColorScheme } from "../themes/common/colorScheme"
|
import { ColorScheme } from "../theme/colorScheme"
|
||||||
import { background, border, foreground, svg, text } from "./components"
|
import { background, border, foreground, svg, text } from "./components"
|
||||||
|
|
||||||
export default function copilot(colorScheme: ColorScheme) {
|
export default function copilot(colorScheme: ColorScheme) {
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { withOpacity } from "../utils/color"
|
import { withOpacity } from "../theme/color"
|
||||||
import { ColorScheme, Layer, StyleSets } from "../themes/common/colorScheme"
|
import { ColorScheme, Layer, StyleSets } from "../theme/colorScheme"
|
||||||
import { background, border, borderColor, foreground, text } from "./components"
|
import { background, border, borderColor, foreground, text } from "./components"
|
||||||
import hoverPopover from "./hoverPopover"
|
import hoverPopover from "./hoverPopover"
|
||||||
|
|
||||||
import { buildSyntax } from "../themes/common/syntax"
|
import { buildSyntax } from "../theme/syntax"
|
||||||
|
|
||||||
export default function editor(colorScheme: ColorScheme) {
|
export default function editor(colorScheme: ColorScheme) {
|
||||||
const { isLight } = colorScheme
|
const { isLight } = colorScheme
|
||||||
|
@ -186,7 +186,10 @@ export default function editor(colorScheme: ColorScheme) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
source: {
|
source: {
|
||||||
text: text(colorScheme.middle, "sans", { size: "sm", weight: "bold", }),
|
text: text(colorScheme.middle, "sans", {
|
||||||
|
size: "sm",
|
||||||
|
weight: "bold",
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
message: {
|
message: {
|
||||||
highlightText: text(colorScheme.middle, "sans", {
|
highlightText: text(colorScheme.middle, "sans", {
|
||||||
|
@ -250,7 +253,7 @@ export default function editor(colorScheme: ColorScheme) {
|
||||||
right: true,
|
right: true,
|
||||||
left: true,
|
left: true,
|
||||||
bottom: false,
|
bottom: false,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
git: {
|
git: {
|
||||||
deleted: isLight
|
deleted: isLight
|
||||||
|
@ -262,7 +265,7 @@ export default function editor(colorScheme: ColorScheme) {
|
||||||
inserted: isLight
|
inserted: isLight
|
||||||
? withOpacity(colorScheme.ramps.green(0.5).hex(), 0.8)
|
? withOpacity(colorScheme.ramps.green(0.5).hex(), 0.8)
|
||||||
: withOpacity(colorScheme.ramps.green(0.4).hex(), 0.8),
|
: withOpacity(colorScheme.ramps.green(0.4).hex(), 0.8),
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
compositionMark: {
|
compositionMark: {
|
||||||
underline: {
|
underline: {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { ColorScheme } from "../themes/common/colorScheme"
|
import { ColorScheme } from "../theme/colorScheme"
|
||||||
import { background, border, text } from "./components"
|
import { background, border, text } from "./components"
|
||||||
|
|
||||||
export default function feedback(colorScheme: ColorScheme) {
|
export default function feedback(colorScheme: ColorScheme) {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { ColorScheme } from "../themes/common/colorScheme"
|
import { ColorScheme } from "../theme/colorScheme"
|
||||||
import { background, border, foreground, text } from "./components"
|
import { background, border, foreground, text } from "./components"
|
||||||
|
|
||||||
export default function HoverPopover(colorScheme: ColorScheme) {
|
export default function HoverPopover(colorScheme: ColorScheme) {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { ColorScheme } from "../themes/common/colorScheme"
|
import { ColorScheme } from "../theme/colorScheme"
|
||||||
import { background, border, text } from "./components"
|
import { background, border, text } from "./components"
|
||||||
|
|
||||||
export default function incomingCallNotification(
|
export default function incomingCallNotification(
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { ColorScheme } from "../themes/common/colorScheme"
|
import { ColorScheme } from "../theme/colorScheme"
|
||||||
import { background, border, text } from "./components"
|
import { background, border, text } from "./components"
|
||||||
|
|
||||||
export default function contactsPanel(colorScheme: ColorScheme) {
|
export default function contactsPanel(colorScheme: ColorScheme) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { ColorScheme } from "../themes/common/colorScheme"
|
import { ColorScheme } from "../theme/colorScheme"
|
||||||
import { withOpacity } from "../utils/color"
|
import { withOpacity } from "../theme/color"
|
||||||
import { background, border, text } from "./components"
|
import { background, border, text } from "./components"
|
||||||
|
|
||||||
export default function picker(colorScheme: ColorScheme): any {
|
export default function picker(colorScheme: ColorScheme): any {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { ColorScheme } from "../themes/common/colorScheme"
|
import { ColorScheme } from "../theme/colorScheme"
|
||||||
import { background, text } from "./components"
|
import { background, text } from "./components"
|
||||||
|
|
||||||
export default function projectDiagnostics(colorScheme: ColorScheme) {
|
export default function projectDiagnostics(colorScheme: ColorScheme) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { ColorScheme } from "../themes/common/colorScheme"
|
import { ColorScheme } from "../theme/colorScheme"
|
||||||
import { withOpacity } from "../utils/color"
|
import { withOpacity } from "../theme/color"
|
||||||
import { background, border, foreground, text } from "./components"
|
import { background, border, foreground, text } from "./components"
|
||||||
|
|
||||||
export default function projectPanel(colorScheme: ColorScheme) {
|
export default function projectPanel(colorScheme: ColorScheme) {
|
||||||
|
@ -24,8 +24,8 @@ export default function projectPanel(colorScheme: ColorScheme) {
|
||||||
: colorScheme.ramps.green(0.5).hex(),
|
: colorScheme.ramps.green(0.5).hex(),
|
||||||
conflict: isLight
|
conflict: isLight
|
||||||
? colorScheme.ramps.red(0.6).hex()
|
? colorScheme.ramps.red(0.6).hex()
|
||||||
: colorScheme.ramps.red(0.5).hex()
|
: colorScheme.ramps.red(0.5).hex(),
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
let entry = {
|
let entry = {
|
||||||
|
@ -44,7 +44,7 @@ export default function projectPanel(colorScheme: ColorScheme) {
|
||||||
background: background(layer, "active"),
|
background: background(layer, "active"),
|
||||||
text: text(layer, "mono", "active", { size: "sm" }),
|
text: text(layer, "mono", "active", { size: "sm" }),
|
||||||
},
|
},
|
||||||
status
|
status,
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -79,7 +79,7 @@ export default function projectPanel(colorScheme: ColorScheme) {
|
||||||
text: text(layer, "mono", "on", { size: "sm" }),
|
text: text(layer, "mono", "on", { size: "sm" }),
|
||||||
background: withOpacity(background(layer, "on"), 0.9),
|
background: withOpacity(background(layer, "on"), 0.9),
|
||||||
border: border(layer),
|
border: border(layer),
|
||||||
status
|
status,
|
||||||
},
|
},
|
||||||
ignoredEntry: {
|
ignoredEntry: {
|
||||||
...entry,
|
...entry,
|
||||||
|
@ -88,7 +88,7 @@ export default function projectPanel(colorScheme: ColorScheme) {
|
||||||
active: {
|
active: {
|
||||||
...entry.active,
|
...entry.active,
|
||||||
iconColor: foreground(layer, "variant"),
|
iconColor: foreground(layer, "variant"),
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
cutEntry: {
|
cutEntry: {
|
||||||
...entry,
|
...entry,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { ColorScheme } from "../themes/common/colorScheme"
|
import { ColorScheme } from "../theme/colorScheme"
|
||||||
import { background, border, text } from "./components"
|
import { background, border, text } from "./components"
|
||||||
|
|
||||||
export default function projectSharedNotification(
|
export default function projectSharedNotification(
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { ColorScheme } from "../themes/common/colorScheme"
|
import { ColorScheme } from "../theme/colorScheme"
|
||||||
import { withOpacity } from "../utils/color"
|
import { withOpacity } from "../theme/color"
|
||||||
import { background, border, foreground, text } from "./components"
|
import { background, border, foreground, text } from "./components"
|
||||||
|
|
||||||
export default function search(colorScheme: ColorScheme) {
|
export default function search(colorScheme: ColorScheme) {
|
||||||
|
@ -30,7 +30,7 @@ export default function search(colorScheme: ColorScheme) {
|
||||||
...editor,
|
...editor,
|
||||||
minWidth: 100,
|
minWidth: 100,
|
||||||
maxWidth: 250,
|
maxWidth: 250,
|
||||||
};
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
// TODO: Add an activeMatchBackground on the rust side to differentiate between active and inactive
|
// TODO: Add an activeMatchBackground on the rust side to differentiate between active and inactive
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { ColorScheme } from "../themes/common/colorScheme"
|
import { ColorScheme } from "../theme/colorScheme"
|
||||||
import { background } from "./components"
|
import { background } from "./components"
|
||||||
|
|
||||||
export default function sharedScreen(colorScheme: ColorScheme) {
|
export default function sharedScreen(colorScheme: ColorScheme) {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { ColorScheme } from "../themes/common/colorScheme"
|
import { ColorScheme } from "../theme/colorScheme"
|
||||||
import { background, border, foreground, text } from "./components"
|
import { background, border, foreground, text } from "./components"
|
||||||
|
|
||||||
const headerPadding = 8
|
const headerPadding = 8
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { ColorScheme } from "../themes/common/colorScheme"
|
import { ColorScheme } from "../theme/colorScheme"
|
||||||
import { background, border, foreground, text } from "./components"
|
import { background, border, foreground, text } from "./components"
|
||||||
|
|
||||||
export default function statusBar(colorScheme: ColorScheme) {
|
export default function statusBar(colorScheme: ColorScheme) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { ColorScheme } from "../themes/common/colorScheme"
|
import { ColorScheme } from "../theme/colorScheme"
|
||||||
import { withOpacity } from "../utils/color"
|
import { withOpacity } from "../theme/color"
|
||||||
import { text, border, background, foreground } from "./components"
|
import { text, border, background, foreground } from "./components"
|
||||||
|
|
||||||
export default function tabBar(colorScheme: ColorScheme) {
|
export default function tabBar(colorScheme: ColorScheme) {
|
||||||
|
@ -96,7 +96,7 @@ export default function tabBar(colorScheme: ColorScheme) {
|
||||||
},
|
},
|
||||||
active: {
|
active: {
|
||||||
color: foreground(layer, "accent"),
|
color: foreground(layer, "accent"),
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
paneButtonContainer: {
|
paneButtonContainer: {
|
||||||
background: tab.background,
|
background: tab.background,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { ColorScheme } from "../themes/common/colorScheme"
|
import { ColorScheme } from "../theme/colorScheme"
|
||||||
|
|
||||||
export default function terminal(colorScheme: ColorScheme) {
|
export default function terminal(colorScheme: ColorScheme) {
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { ColorScheme } from "../themes/common/colorScheme"
|
import { ColorScheme } from "../theme/colorScheme"
|
||||||
import { background, border, text } from "./components"
|
import { background, border, text } from "./components"
|
||||||
|
|
||||||
export default function tooltip(colorScheme: ColorScheme) {
|
export default function tooltip(colorScheme: ColorScheme) {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { ColorScheme } from "../themes/common/colorScheme"
|
import { ColorScheme } from "../theme/colorScheme"
|
||||||
import { foreground, text } from "./components"
|
import { foreground, text } from "./components"
|
||||||
|
|
||||||
const headerPadding = 8
|
const headerPadding = 8
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { ColorScheme } from "../themes/common/colorScheme"
|
import { ColorScheme } from "../theme/colorScheme"
|
||||||
import { withOpacity } from "../utils/color"
|
import { withOpacity } from "../theme/color"
|
||||||
import {
|
import {
|
||||||
border,
|
border,
|
||||||
background,
|
background,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { ColorScheme } from "../themes/common/colorScheme"
|
import { ColorScheme } from "../theme/colorScheme"
|
||||||
import { withOpacity } from "../utils/color"
|
import { withOpacity } from "../theme/color"
|
||||||
import {
|
import {
|
||||||
background,
|
background,
|
||||||
border,
|
border,
|
||||||
|
@ -123,7 +123,7 @@ export default function workspace(colorScheme: ColorScheme) {
|
||||||
cursor: "Arrow",
|
cursor: "Arrow",
|
||||||
background: isLight
|
background: isLight
|
||||||
? withOpacity(background(colorScheme.lowest), 0.8)
|
? withOpacity(background(colorScheme.lowest), 0.8)
|
||||||
: withOpacity(background(colorScheme.highest), 0.6)
|
: withOpacity(background(colorScheme.highest), 0.6),
|
||||||
},
|
},
|
||||||
zoomedPaneForeground: {
|
zoomedPaneForeground: {
|
||||||
margin: 16,
|
margin: 16,
|
||||||
|
@ -143,7 +143,7 @@ export default function workspace(colorScheme: ColorScheme) {
|
||||||
},
|
},
|
||||||
right: {
|
right: {
|
||||||
border: border(layer, { left: true }),
|
border: border(layer, { left: true }),
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
paneDivider: {
|
paneDivider: {
|
||||||
color: borderColor(layer),
|
color: borderColor(layer),
|
||||||
|
|
|
@ -5,7 +5,7 @@ import {
|
||||||
ThemeConfig,
|
ThemeConfig,
|
||||||
ThemeAppearance,
|
ThemeAppearance,
|
||||||
ThemeConfigInputColors,
|
ThemeConfigInputColors,
|
||||||
} from "../../themeConfig"
|
} from "./themeConfig"
|
||||||
import { getRamps } from "./ramps"
|
import { getRamps } from "./ramps"
|
||||||
|
|
||||||
export interface ColorScheme {
|
export interface ColorScheme {
|
|
@ -1,4 +1,4 @@
|
||||||
export * from "./colorScheme"
|
export * from "./colorScheme"
|
||||||
export * from "./ramps"
|
export * from "./ramps"
|
||||||
export * from "./syntax"
|
export * from "./syntax"
|
||||||
export * from "../../themeConfig"
|
export * from "./themeConfig"
|
|
@ -3,7 +3,7 @@ import { RampSet } from "./colorScheme"
|
||||||
import {
|
import {
|
||||||
ThemeConfigInputColors,
|
ThemeConfigInputColors,
|
||||||
ThemeConfigInputColorsKeys,
|
ThemeConfigInputColorsKeys,
|
||||||
} from "../../themeConfig"
|
} from "./themeConfig"
|
||||||
|
|
||||||
export function colorRamp(color: Color): Scale {
|
export function colorRamp(color: Color): Scale {
|
||||||
let endColor = color.desaturate(1).brighten(5)
|
let endColor = color.desaturate(1).brighten(5)
|
|
@ -1,5 +1,5 @@
|
||||||
import deepmerge from "deepmerge"
|
import deepmerge from "deepmerge"
|
||||||
import { FontWeight, fontWeights } from "../../common"
|
import { FontWeight, fontWeights } from "../common"
|
||||||
import { ColorScheme } from "./colorScheme"
|
import { ColorScheme } from "./colorScheme"
|
||||||
import chroma from "chroma-js"
|
import chroma from "chroma-js"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Scale, Color } from "chroma-js"
|
import { Scale, Color } from "chroma-js"
|
||||||
import { Syntax } from "./themes/common/syntax"
|
import { Syntax } from "./syntax"
|
||||||
|
|
||||||
interface ThemeMeta {
|
interface ThemeMeta {
|
||||||
/** The name of the theme */
|
/** The name of the theme */
|
||||||
|
@ -23,6 +23,11 @@ interface ThemeMeta {
|
||||||
themeUrl?: string
|
themeUrl?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type ThemeFamilyMeta = Pick<
|
||||||
|
ThemeMeta,
|
||||||
|
"name" | "author" | "licenseType" | "licenseUrl"
|
||||||
|
>
|
||||||
|
|
||||||
export interface ThemeConfigInputColors {
|
export interface ThemeConfigInputColors {
|
||||||
neutral: Scale<Color>
|
neutral: Scale<Color>
|
||||||
red: Scale<Color>
|
red: Scale<Color>
|
12
styles/src/theme/tokens/colorScheme.ts
Normal file
12
styles/src/theme/tokens/colorScheme.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import { ColorScheme } from "../colorScheme"
|
||||||
|
import { PlayerTokens, players } from "./players"
|
||||||
|
|
||||||
|
interface ColorSchemeTokens {
|
||||||
|
players: PlayerTokens
|
||||||
|
}
|
||||||
|
|
||||||
|
export function colorSchemeTokens(colorScheme: ColorScheme): ColorSchemeTokens {
|
||||||
|
return {
|
||||||
|
players: players(colorScheme),
|
||||||
|
}
|
||||||
|
}
|
28
styles/src/theme/tokens/players.ts
Normal file
28
styles/src/theme/tokens/players.ts
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
import { SingleColorToken } from "@tokens-studio/types"
|
||||||
|
import { ColorScheme, Players } from "../../common"
|
||||||
|
import { colorToken } from "./token"
|
||||||
|
|
||||||
|
export type PlayerToken = Record<"selection" | "cursor", SingleColorToken>
|
||||||
|
|
||||||
|
export type PlayerTokens = Record<keyof Players, PlayerToken>
|
||||||
|
|
||||||
|
function buildPlayerToken(colorScheme: ColorScheme, index: number): PlayerToken {
|
||||||
|
|
||||||
|
const playerNumber = index.toString() as keyof Players
|
||||||
|
|
||||||
|
return {
|
||||||
|
selection: colorToken(`player${index}Selection`, colorScheme.players[playerNumber].selection),
|
||||||
|
cursor: colorToken(`player${index}Cursor`, colorScheme.players[playerNumber].cursor),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const players = (colorScheme: ColorScheme): PlayerTokens => ({
|
||||||
|
"0": buildPlayerToken(colorScheme, 0),
|
||||||
|
"1": buildPlayerToken(colorScheme, 1),
|
||||||
|
"2": buildPlayerToken(colorScheme, 2),
|
||||||
|
"3": buildPlayerToken(colorScheme, 3),
|
||||||
|
"4": buildPlayerToken(colorScheme, 4),
|
||||||
|
"5": buildPlayerToken(colorScheme, 5),
|
||||||
|
"6": buildPlayerToken(colorScheme, 6),
|
||||||
|
"7": buildPlayerToken(colorScheme, 7)
|
||||||
|
})
|
14
styles/src/theme/tokens/token.ts
Normal file
14
styles/src/theme/tokens/token.ts
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
import { SingleColorToken, TokenTypes } from "@tokens-studio/types"
|
||||||
|
|
||||||
|
export function colorToken(name: string, value: string, description?: string): SingleColorToken {
|
||||||
|
const token: SingleColorToken = {
|
||||||
|
name,
|
||||||
|
type: TokenTypes.COLOR,
|
||||||
|
value,
|
||||||
|
description,
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!token.value || token.value === '') throw new Error("Color token must have a value")
|
||||||
|
|
||||||
|
return token
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
import { ThemeLicenseType, ThemeConfig, ThemeSyntax } from "../../common"
|
import { ThemeLicenseType, ThemeSyntax, ThemeFamilyMeta } from "../../common"
|
||||||
|
|
||||||
export interface Variant {
|
export interface Variant {
|
||||||
colors: {
|
colors: {
|
||||||
|
@ -21,7 +21,7 @@ export interface Variant {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const meta: Partial<ThemeConfig> = {
|
export const meta: ThemeFamilyMeta = {
|
||||||
name: "Atelier",
|
name: "Atelier",
|
||||||
author: "Bram de Haan (http://atelierbramdehaan.nl)",
|
author: "Bram de Haan (http://atelierbramdehaan.nl)",
|
||||||
licenseType: ThemeLicenseType.MIT,
|
licenseType: ThemeLicenseType.MIT,
|
||||||
|
|
|
@ -3,8 +3,8 @@ import {
|
||||||
chroma,
|
chroma,
|
||||||
colorRamp,
|
colorRamp,
|
||||||
ThemeLicenseType,
|
ThemeLicenseType,
|
||||||
ThemeConfig,
|
|
||||||
ThemeSyntax,
|
ThemeSyntax,
|
||||||
|
ThemeFamilyMeta,
|
||||||
} from "../../common"
|
} from "../../common"
|
||||||
|
|
||||||
export const ayu = {
|
export const ayu = {
|
||||||
|
@ -77,7 +77,7 @@ export const buildSyntax = (t: typeof dark): ThemeSyntax => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const meta: Partial<ThemeConfig> = {
|
export const meta: ThemeFamilyMeta = {
|
||||||
name: "Ayu",
|
name: "Ayu",
|
||||||
author: "dempfi",
|
author: "dempfi",
|
||||||
licenseType: ThemeLicenseType.MIT,
|
licenseType: ThemeLicenseType.MIT,
|
||||||
|
|
|
@ -5,9 +5,10 @@ import {
|
||||||
ThemeLicenseType,
|
ThemeLicenseType,
|
||||||
ThemeConfig,
|
ThemeConfig,
|
||||||
ThemeSyntax,
|
ThemeSyntax,
|
||||||
|
ThemeFamilyMeta,
|
||||||
} from "../../common"
|
} from "../../common"
|
||||||
|
|
||||||
const meta: Partial<ThemeConfig> = {
|
const meta: ThemeFamilyMeta = {
|
||||||
name: "Gruvbox",
|
name: "Gruvbox",
|
||||||
author: "morhetz <morhetz@gmail.com>",
|
author: "morhetz <morhetz@gmail.com>",
|
||||||
licenseType: ThemeLicenseType.MIT,
|
licenseType: ThemeLicenseType.MIT,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { ThemeConfig } from "./common"
|
import { ThemeConfig } from "../theme"
|
||||||
import { darkDefault as gruvboxDark } from "./gruvbox/gruvbox-dark"
|
import { darkDefault as gruvboxDark } from "./gruvbox/gruvbox-dark"
|
||||||
import { darkHard as gruvboxDarkHard } from "./gruvbox/gruvbox-dark-hard"
|
import { darkHard as gruvboxDarkHard } from "./gruvbox/gruvbox-dark-hard"
|
||||||
import { darkSoft as gruvboxDarkSoft } from "./gruvbox/gruvbox-dark-soft"
|
import { darkSoft as gruvboxDarkSoft } from "./gruvbox/gruvbox-dark-soft"
|
||||||
|
|
1
styles/src/utils/slugify.ts
Normal file
1
styles/src/utils/slugify.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export function slugify(t: string): string { return t.toString().toLowerCase().replace(/\s+/g, '-').replace(/[^\w\-]+/g, '').replace(/\-\-+/g, '-').replace(/^-+/, '').replace(/-+$/, '') }
|
|
@ -6,7 +6,21 @@
|
||||||
"noImplicitAny": true,
|
"noImplicitAny": true,
|
||||||
"removeComments": true,
|
"removeComments": true,
|
||||||
"preserveConstEnums": true,
|
"preserveConstEnums": true,
|
||||||
"sourceMap": true
|
"sourceMap": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"declaration": true,
|
||||||
|
"strict": true,
|
||||||
|
"strictNullChecks": true,
|
||||||
|
"noImplicitThis": true,
|
||||||
|
"alwaysStrict": true,
|
||||||
|
"noUnusedLocals": false,
|
||||||
|
"noUnusedParameters": false,
|
||||||
|
"noImplicitReturns": true,
|
||||||
|
"noFallthroughCasesInSwitch": false,
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"strictPropertyInitialization": false,
|
||||||
|
"skipLibCheck": true
|
||||||
},
|
},
|
||||||
"exclude": ["node_modules"]
|
"exclude": ["node_modules"]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue