Compare commits
10 Commits
github-tok
...
configurat
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
52afd4720c | ||
|
|
773c1f16e3 | ||
|
|
42ab97f6a8 | ||
|
|
2d74297317 | ||
|
|
ff027f1570 | ||
|
|
aeff2c633c | ||
|
|
788a6ae14a | ||
|
|
8cef8da0e7 | ||
|
|
6602f7b2b6 | ||
|
|
39d08e1577 |
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -13735,6 +13735,8 @@ dependencies = [
|
|||||||
"cargo_metadata",
|
"cargo_metadata",
|
||||||
"cargo_toml",
|
"cargo_toml",
|
||||||
"clap",
|
"clap",
|
||||||
|
"schemars",
|
||||||
|
"serde_json",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ mod zed;
|
|||||||
|
|
||||||
use anyhow::{anyhow, Context as _, Result};
|
use anyhow::{anyhow, Context as _, Result};
|
||||||
use assistant::PromptBuilder;
|
use assistant::PromptBuilder;
|
||||||
use clap::{command, Parser};
|
use clap::{command, Parser, ValueEnum};
|
||||||
use cli::FORCE_CLI_MODE_ENV_VAR_NAME;
|
use cli::FORCE_CLI_MODE_ENV_VAR_NAME;
|
||||||
use client::{parse_zed_link, Client, DevServerToken, UserStore};
|
use client::{parse_zed_link, Client, DevServerToken, UserStore};
|
||||||
use collab_ui::channel_view::ChannelView;
|
use collab_ui::channel_view::ChannelView;
|
||||||
@@ -19,7 +19,7 @@ use fs::{Fs, RealFs};
|
|||||||
use futures::{future, StreamExt};
|
use futures::{future, StreamExt};
|
||||||
use git::GitHostingProviderRegistry;
|
use git::GitHostingProviderRegistry;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
Action, App, AppContext, AsyncAppContext, Context, DismissEvent, Global, Task,
|
Action, App, AppContext, AsyncAppContext, Context, DismissEvent, Global, ReadGlobal as _, Task,
|
||||||
UpdateGlobal as _, VisualContext,
|
UpdateGlobal as _, VisualContext,
|
||||||
};
|
};
|
||||||
use image_viewer;
|
use image_viewer;
|
||||||
@@ -536,19 +536,45 @@ fn main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let app_state = app_state.clone();
|
let state = app_state.clone();
|
||||||
let prompt_builder = prompt_builder.clone();
|
let prompt_builder = prompt_builder.clone();
|
||||||
cx.spawn(move |cx| async move {
|
cx.spawn(move |cx| async move {
|
||||||
while let Some(urls) = open_rx.next().await {
|
while let Some(urls) = open_rx.next().await {
|
||||||
cx.update(|cx| {
|
cx.update(|cx| {
|
||||||
if let Some(request) = OpenRequest::parse(urls, cx).log_err() {
|
if let Some(request) = OpenRequest::parse(urls, cx).log_err() {
|
||||||
handle_open_request(request, app_state.clone(), prompt_builder.clone(), cx);
|
handle_open_request(request, state.clone(), prompt_builder.clone(), cx);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.detach();
|
.detach();
|
||||||
|
if let Some(schema) = args.schema {
|
||||||
|
let app_state = app_state.clone();
|
||||||
|
cx.spawn(|cx| async move {
|
||||||
|
match schema {
|
||||||
|
SchemaKind::Settings => {
|
||||||
|
let language_names = app_state.languages.language_names();
|
||||||
|
let schema = cx.update(|cx| {
|
||||||
|
SettingsStore::global(cx).json_schema(
|
||||||
|
&settings::SettingsJsonSchemaParams {
|
||||||
|
staff_mode: false,
|
||||||
|
language_names: &language_names,
|
||||||
|
font_names: &[],
|
||||||
|
},
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
});
|
||||||
|
if let Ok(schema) = schema {
|
||||||
|
if let Ok(schema) = serde_json::to_string(&schema) {
|
||||||
|
let _ = std::fs::write("settings-schema.json", &(schema));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.detach();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1039,6 +1065,11 @@ fn stdout_is_a_pty() -> bool {
|
|||||||
std::env::var(FORCE_CLI_MODE_ENV_VAR_NAME).ok().is_none() && std::io::stdout().is_terminal()
|
std::env::var(FORCE_CLI_MODE_ENV_VAR_NAME).ok().is_none() && std::io::stdout().is_terminal()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, ValueEnum)]
|
||||||
|
enum SchemaKind {
|
||||||
|
Settings,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
#[command(name = "zed", disable_version_flag = true)]
|
#[command(name = "zed", disable_version_flag = true)]
|
||||||
struct Args {
|
struct Args {
|
||||||
@@ -1053,6 +1084,10 @@ struct Args {
|
|||||||
/// Instructs zed to run as a dev server on this machine. (not implemented)
|
/// Instructs zed to run as a dev server on this machine. (not implemented)
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
dev_server_token: Option<String>,
|
dev_server_token: Option<String>,
|
||||||
|
|
||||||
|
/// Instructs zed to dump a JSON schema to a file.
|
||||||
|
#[arg(long)]
|
||||||
|
schema: Option<SchemaKind>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_url_arg(arg: &str, cx: &AppContext) -> Result<String> {
|
fn parse_url_arg(arg: &str, cx: &AppContext) -> Result<String> {
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ site-url = "/docs/"
|
|||||||
[output.html]
|
[output.html]
|
||||||
no-section-label = true
|
no-section-label = true
|
||||||
preferred-dark-theme = "light"
|
preferred-dark-theme = "light"
|
||||||
additional-css = ["theme/page-toc.css", "theme/plugins.css"]
|
additional-css = ["theme/page-toc.css", "theme/settings-table.css", "theme/plugins.css"]
|
||||||
additional-js = ["theme/page-toc.js", "theme/plugins.js"]
|
additional-js = ["theme/page-toc.js", "theme/settings-table.js", "theme/plugins.js"]
|
||||||
|
|
||||||
[output.html.print]
|
[output.html.print]
|
||||||
enable = false
|
enable = false
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ Extensions that provide language servers may also provide default settings for t
|
|||||||
|
|
||||||
# Settings
|
# Settings
|
||||||
|
|
||||||
|
<div id="settings-container"></div>
|
||||||
|
|
||||||
## Active Pane Magnification
|
## Active Pane Magnification
|
||||||
|
|
||||||
- Description: Scale by which to zoom the active pane. When set to `1.0`, the active pane has the same size as others, but when set to a larger value, the active pane takes up more space.
|
- Description: Scale by which to zoom the active pane. When set to `1.0`, the active pane has the same size as others, but when set to a larger value, the active pane takes up more space.
|
||||||
|
|||||||
4
docs/theme/css/variables.css
vendored
4
docs/theme/css/variables.css
vendored
@@ -44,8 +44,8 @@
|
|||||||
--warning-bg: hsl(42, 100%, 60%, 0.1);
|
--warning-bg: hsl(42, 100%, 60%, 0.1);
|
||||||
--warning-icon: hsl(42, 100%, 30%);
|
--warning-icon: hsl(42, 100%, 30%);
|
||||||
|
|
||||||
--table-border-color: hsl(219, 93%, 42%, 0.15);
|
--table-border-color: hsl(219, 10%, 42%, 0.15);
|
||||||
--table-header-bg: hsl(0, 0%, 80%);
|
--table-header-bg: hsl(219, 18%, 68%, 0.15);
|
||||||
--table-alternate-bg: hsl(0, 0%, 97%);
|
--table-alternate-bg: hsl(0, 0%, 97%);
|
||||||
|
|
||||||
--searchbar-border-color: #aaa;
|
--searchbar-border-color: #aaa;
|
||||||
|
|||||||
95
docs/theme/settings-table.css
vendored
Normal file
95
docs/theme/settings-table.css
vendored
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
.settings-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
font-family: var(--font);
|
||||||
|
color: var(--fg);
|
||||||
|
background-color: var(--bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting-container {
|
||||||
|
padding: 12px 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
border-bottom: 1px solid var(--table-border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting-header {
|
||||||
|
grid-column: span 2 / span 2;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
gap: 0.8rem;
|
||||||
|
padding: 0.5em 1em 0.5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting-line {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
gap: 2rem;
|
||||||
|
/* padding: 0.5em 1em; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting-name {
|
||||||
|
font-family: monospace;
|
||||||
|
font-size: 1.3rem;
|
||||||
|
font-weight: bold;
|
||||||
|
color: var(--sidebar-fg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting-type {
|
||||||
|
font-family: monospace;
|
||||||
|
font-size: 1.3rem;
|
||||||
|
color: var(--fg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting-description {
|
||||||
|
font-size: 1.3rem;
|
||||||
|
color: var(--fg);
|
||||||
|
padding: 0.5em 0 0.5em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting-default {
|
||||||
|
font-family: monospace;
|
||||||
|
font-size: 1.3rem;
|
||||||
|
color: var(--fg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting-status {
|
||||||
|
width: fit-content;
|
||||||
|
padding: 0.2em 0.5em;
|
||||||
|
background-color: var(--sidebar-active-bg);
|
||||||
|
font-size: 1.2rem;
|
||||||
|
font-family: monospace;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting-details {
|
||||||
|
grid-column: span 4 / span 4;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting-details tr:nth-child(even) {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting-details td {
|
||||||
|
padding: 0.5em 0 0.5em 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting-label {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting-value {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-list code {
|
||||||
|
font-family: var(--mono-font);
|
||||||
|
font-size: 1.4rem;
|
||||||
|
background-color: var(--quote-bg);
|
||||||
|
padding: 2px 4px;
|
||||||
|
border-radius: 3px;
|
||||||
|
color: var(--inline-code-color);
|
||||||
|
}
|
||||||
1448
docs/theme/settings-table.js
vendored
Normal file
1448
docs/theme/settings-table.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@@ -13,3 +13,5 @@ anyhow.workspace = true
|
|||||||
cargo_metadata.workspace = true
|
cargo_metadata.workspace = true
|
||||||
cargo_toml.workspace = true
|
cargo_toml.workspace = true
|
||||||
clap = { workspace = true, features = ["derive"] }
|
clap = { workspace = true, features = ["derive"] }
|
||||||
|
schemars.workspace = true
|
||||||
|
serde_json.workspace = true
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ enum CliCommand {
|
|||||||
Licenses(tasks::licenses::LicensesArgs),
|
Licenses(tasks::licenses::LicensesArgs),
|
||||||
/// Checks that packages conform to a set of standards.
|
/// Checks that packages conform to a set of standards.
|
||||||
PackageConformity(tasks::package_conformity::PackageConformityArgs),
|
PackageConformity(tasks::package_conformity::PackageConformityArgs),
|
||||||
|
/// Checks that settings schema conforms to a set of standards.
|
||||||
|
ValidateSchema(tasks::validate_schema::SchemaValidationArgs),
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
@@ -29,5 +31,6 @@ fn main() -> Result<()> {
|
|||||||
CliCommand::PackageConformity(args) => {
|
CliCommand::PackageConformity(args) => {
|
||||||
tasks::package_conformity::run_package_conformity(args)
|
tasks::package_conformity::run_package_conformity(args)
|
||||||
}
|
}
|
||||||
|
CliCommand::ValidateSchema(args) => tasks::validate_schema::run_validate_schema(args),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
pub mod clippy;
|
pub mod clippy;
|
||||||
pub mod licenses;
|
pub mod licenses;
|
||||||
pub mod package_conformity;
|
pub mod package_conformity;
|
||||||
|
pub mod validate_schema;
|
||||||
|
|||||||
128
tooling/xtask/src/tasks/validate_schema.rs
Normal file
128
tooling/xtask/src/tasks/validate_schema.rs
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
use std::{collections::HashMap, path::PathBuf};
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use clap::Parser;
|
||||||
|
use schemars::{
|
||||||
|
schema::{RootSchema, SchemaObject},
|
||||||
|
visit::Visitor,
|
||||||
|
};
|
||||||
|
use serde_json::Value;
|
||||||
|
|
||||||
|
#[derive(Parser)]
|
||||||
|
pub struct SchemaValidationArgs {
|
||||||
|
path: PathBuf,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum Violation {
|
||||||
|
MissingDefault,
|
||||||
|
MissingExample,
|
||||||
|
MissingMetadata,
|
||||||
|
MissingDescription,
|
||||||
|
}
|
||||||
|
struct Violations {
|
||||||
|
schema: SchemaObject,
|
||||||
|
violations: Vec<(Vec<String>, Violation)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
struct SettingsSchemaValidator {
|
||||||
|
objects: Vec<Violations>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SettingsSchemaValidator {
|
||||||
|
fn validate_schema_object(&mut self, builder: &mut ViolationsBuilder, schema: &SchemaObject) {
|
||||||
|
if schema.metadata.is_none() {
|
||||||
|
builder.add(Violation::MissingMetadata);
|
||||||
|
} else if let Some(metadata) = &schema.metadata {
|
||||||
|
if metadata.description.is_none() {
|
||||||
|
builder.add(Violation::MissingDescription);
|
||||||
|
}
|
||||||
|
if metadata.default.is_none() {
|
||||||
|
builder.add(Violation::MissingDefault);
|
||||||
|
}
|
||||||
|
if metadata.examples.is_empty() && !Self::is_boolean_schema(schema) {
|
||||||
|
builder.add(Violation::MissingExample);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(object) = &schema.object {
|
||||||
|
for (property, property_schema) in &object.properties {
|
||||||
|
builder.push(property.clone());
|
||||||
|
self.validate_schema_object(builder, &property_schema.clone().into_object());
|
||||||
|
builder.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_boolean_schema(schema: &SchemaObject) -> bool {
|
||||||
|
schema.instance_type == Some(schemars::schema::InstanceType::Boolean.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ViolationsBuilder<'a> {
|
||||||
|
violations: &'a mut Violations,
|
||||||
|
current_path: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> ViolationsBuilder<'a> {
|
||||||
|
fn new(violations: &'a mut Violations) -> Self {
|
||||||
|
Self {
|
||||||
|
violations,
|
||||||
|
current_path: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add(&mut self, violation: Violation) {
|
||||||
|
self.violations
|
||||||
|
.violations
|
||||||
|
.push((self.current_path.clone(), violation));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push(&mut self, segment: String) {
|
||||||
|
self.current_path.push(segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pop(&mut self) {
|
||||||
|
self.current_path.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Visitor for SettingsSchemaValidator {
|
||||||
|
fn visit_schema_object(&mut self, schema: &mut SchemaObject) {
|
||||||
|
let mut violations = Violations {
|
||||||
|
schema: schema.clone(),
|
||||||
|
violations: Vec::new(),
|
||||||
|
};
|
||||||
|
let mut builder = ViolationsBuilder::new(&mut violations);
|
||||||
|
|
||||||
|
self.validate_schema_object(&mut builder, schema);
|
||||||
|
|
||||||
|
if !violations.violations.is_empty() {
|
||||||
|
self.objects.push(violations);
|
||||||
|
}
|
||||||
|
|
||||||
|
schemars::visit::visit_schema_object(self, schema)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run_validate_schema(args: SchemaValidationArgs) -> Result<()> {
|
||||||
|
let contents = std::fs::read_to_string(args.path)?;
|
||||||
|
let mut schema: RootSchema = serde_json::from_str(&contents)?;
|
||||||
|
let mut validator = SettingsSchemaValidator::default();
|
||||||
|
validator.visit_root_schema(&mut schema);
|
||||||
|
|
||||||
|
let total_violations: usize = validator.objects.iter().map(|v| v.violations.len()).sum();
|
||||||
|
println!("Total violations found: {}", total_violations);
|
||||||
|
|
||||||
|
for violation in validator.objects.iter().flat_map(|v| &v.violations) {
|
||||||
|
let path_str = if violation.0.is_empty() {
|
||||||
|
"<root>".to_string()
|
||||||
|
} else {
|
||||||
|
violation.0.join(".")
|
||||||
|
};
|
||||||
|
println!("{}: {:?}", path_str, violation.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user