Compare commits
4 Commits
derive-doc
...
kcl-test-s
Author | SHA1 | Date | |
---|---|---|---|
ac605c2434 | |||
f6ecdfcb02 | |||
28815eb2f1 | |||
166fa71f7e |
@ -18,7 +18,7 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"private": false,
|
"private": false,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/autocomplete": "^6.16.3",
|
"@codemirror/autocomplete": "6.17.0",
|
||||||
"@codemirror/language": "^6.10.2",
|
"@codemirror/language": "^6.10.2",
|
||||||
"@codemirror/state": "^6.4.1",
|
"@codemirror/state": "^6.4.1",
|
||||||
"@lezer/highlight": "^1.2.0",
|
"@lezer/highlight": "^1.2.0",
|
||||||
|
@ -2,10 +2,10 @@
|
|||||||
# yarn lockfile v1
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
"@codemirror/autocomplete@^6.16.3":
|
"@codemirror/autocomplete@6.17.0":
|
||||||
version "6.16.3"
|
version "6.17.0"
|
||||||
resolved "https://registry.yarnpkg.com/@codemirror/autocomplete/-/autocomplete-6.16.3.tgz#04d5a4e4e44ccae1ba525d47db53a5479bf46338"
|
resolved "https://registry.yarnpkg.com/@codemirror/autocomplete/-/autocomplete-6.17.0.tgz#24ff5fc37fd91f6439df6f4ff9c8e910cde1b053"
|
||||||
integrity sha512-Vl/tIeRVVUCRDuOG48lttBasNQu8usGgXQawBXI7WJAiUDSFOfzflmEsZFZo48mAvAaa4FZ/4/yLLxFtdJaKYA==
|
integrity sha512-fdfj6e6ZxZf8yrkMHUSJJir7OJkHkZKaOZGzLWIYp2PZ3jd+d+UjG8zVPqJF6d3bKxkhvXTPan/UZ1t7Bqm0gA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@codemirror/language" "^6.0.0"
|
"@codemirror/language" "^6.0.0"
|
||||||
"@codemirror/state" "^6.0.0"
|
"@codemirror/state" "^6.0.0"
|
||||||
|
@ -5,7 +5,8 @@ export COMMIT=$(git rev-parse --short HEAD)
|
|||||||
|
|
||||||
# package.json
|
# package.json
|
||||||
yarn files:set-version
|
yarn files:set-version
|
||||||
echo "$(jq --arg name 'Zoo Modeling App (Nightly)' '.productName=$name' package.json --indent 2)" > package.json
|
PACKAGE=$(jq '.productName="Zoo Modeling App (Nightly)" | .name="zoo-modeling-app-nightly"' package.json --indent 2)
|
||||||
|
echo "$PACKAGE" > package.json
|
||||||
|
|
||||||
# electron-builder.yml
|
# electron-builder.yml
|
||||||
yq -i '.publish[0].url = "https://dl.zoo.dev/releases/modeling-app/nightly"' electron-builder.yml
|
yq -i '.publish[0].url = "https://dl.zoo.dev/releases/modeling-app/nightly"' electron-builder.yml
|
||||||
|
@ -13,7 +13,7 @@ import { isDesktop } from 'lib/isDesktop'
|
|||||||
import { ActionButton } from 'components/ActionButton'
|
import { ActionButton } from 'components/ActionButton'
|
||||||
import { SettingsFieldInput } from './SettingsFieldInput'
|
import { SettingsFieldInput } from './SettingsFieldInput'
|
||||||
import toast from 'react-hot-toast'
|
import toast from 'react-hot-toast'
|
||||||
import { APP_VERSION } from 'routes/Settings'
|
import { APP_VERSION, PACKAGE_NAME } from 'routes/Settings'
|
||||||
import { PATHS } from 'lib/paths'
|
import { PATHS } from 'lib/paths'
|
||||||
import {
|
import {
|
||||||
createAndOpenNewTutorialProject,
|
createAndOpenNewTutorialProject,
|
||||||
@ -264,6 +264,22 @@ export const AllSettingsFields = forwardRef(
|
|||||||
, and start a discussion if you don't see it! Your feedback will
|
, and start a discussion if you don't see it! Your feedback will
|
||||||
help us prioritize what to build next.
|
help us prioritize what to build next.
|
||||||
</p>
|
</p>
|
||||||
|
{PACKAGE_NAME.indexOf('-nightly') === -1 && (
|
||||||
|
<p className="max-w-2xl mt-6">
|
||||||
|
Want to experience the latest and (hopefully) greatest from our
|
||||||
|
main development branch?{' '}
|
||||||
|
<a
|
||||||
|
href="https://zoo.dev/modeling-app/download/nightly"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
Click here to grab Zoo Modeling App (Nightly)
|
||||||
|
</a>
|
||||||
|
. It can be installed side-by-side with the stable version
|
||||||
|
you're running now. But careful there, a lot less testing is
|
||||||
|
involved in their release 🤖.
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -26,6 +26,10 @@ export const APP_VERSION =
|
|||||||
window.electron.packageJson.version
|
window.electron.packageJson.version
|
||||||
: 'main'
|
: 'main'
|
||||||
|
|
||||||
|
export const PACKAGE_NAME = isDesktop()
|
||||||
|
? window.electron.packageJson.name
|
||||||
|
: 'zoo-modeling-app'
|
||||||
|
|
||||||
export const Settings = () => {
|
export const Settings = () => {
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const [searchParams, setSearchParams] = useSearchParams()
|
const [searchParams, setSearchParams] = useSearchParams()
|
||||||
|
6
src/wasm-lib/Cargo.lock
generated
6
src/wasm-lib/Cargo.lock
generated
@ -1675,7 +1675,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kcl-lib"
|
name = "kcl-lib"
|
||||||
version = "0.2.25"
|
version = "0.2.26"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"approx 0.5.1",
|
"approx 0.5.1",
|
||||||
@ -1806,9 +1806,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kittycad-modeling-cmds"
|
name = "kittycad-modeling-cmds"
|
||||||
version = "0.2.76"
|
version = "0.2.77"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2394fe2b28a1c6bd524dec1dbcd7e839c2782a6ecc743085e122cde77ee19cfa"
|
checksum = "3b77259b37acafa360d98af27431ac394bc8899eeed7037513832ddbee856811"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"chrono",
|
"chrono",
|
||||||
|
@ -203,7 +203,7 @@ fn bad_gateway(msg: String) -> Response<Body> {
|
|||||||
resp
|
resp
|
||||||
}
|
}
|
||||||
|
|
||||||
fn kcl_err(err: anyhow::Error) -> Response<Body> {
|
fn kcl_err(err: impl std::fmt::Display) -> Response<Body> {
|
||||||
eprintln!("\tBad KCL");
|
eprintln!("\tBad KCL");
|
||||||
bad_gateway(format!("{err}"))
|
bad_gateway(format!("{err}"))
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "kcl-lib"
|
name = "kcl-lib"
|
||||||
description = "KittyCAD Language implementation and tools"
|
description = "KittyCAD Language implementation and tools"
|
||||||
version = "0.2.25"
|
version = "0.2.26"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
repository = "https://github.com/KittyCAD/modeling-app"
|
repository = "https://github.com/KittyCAD/modeling-app"
|
||||||
|
@ -4,6 +4,26 @@ use tower_lsp::lsp_types::{Diagnostic, DiagnosticSeverity};
|
|||||||
|
|
||||||
use crate::{ast::types::ModuleId, executor::SourceRange, lsp::IntoDiagnostic};
|
use crate::{ast::types::ModuleId, executor::SourceRange, lsp::IntoDiagnostic};
|
||||||
|
|
||||||
|
/// How did the KCL execution fail
|
||||||
|
#[derive(thiserror::Error, Debug)]
|
||||||
|
pub enum ExecError {
|
||||||
|
#[error("{0}")]
|
||||||
|
Kcl(#[from] crate::KclError),
|
||||||
|
#[error("Could not connect to engine: {0}")]
|
||||||
|
Connection(#[from] ConnectionError),
|
||||||
|
#[error("PNG snapshot could not be decoded: {0}")]
|
||||||
|
BadPng(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// How did KCL client fail to connect to the engine
|
||||||
|
#[derive(thiserror::Error, Debug)]
|
||||||
|
pub enum ConnectionError {
|
||||||
|
#[error("Could not create a Zoo client: {0}")]
|
||||||
|
CouldNotMakeClient(anyhow::Error),
|
||||||
|
#[error("Could not establish connection to engine: {0}")]
|
||||||
|
Establishing(anyhow::Error),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Error, Debug, Serialize, Deserialize, ts_rs::TS, Clone, PartialEq, Eq)]
|
#[derive(Error, Debug, Serialize, Deserialize, ts_rs::TS, Clone, PartialEq, Eq)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
#[serde(tag = "kind", rename_all = "snake_case")]
|
#[serde(tag = "kind", rename_all = "snake_case")]
|
||||||
|
@ -34,7 +34,7 @@ use crate::{
|
|||||||
fs::{FileManager, FileSystem},
|
fs::{FileManager, FileSystem},
|
||||||
settings::types::UnitLength,
|
settings::types::UnitLength,
|
||||||
std::{args::Arg, StdLib},
|
std::{args::Arg, StdLib},
|
||||||
Program,
|
ExecError, Program,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// State for executing a program.
|
/// State for executing a program.
|
||||||
@ -2179,12 +2179,16 @@ impl ExecutorContext {
|
|||||||
&self,
|
&self,
|
||||||
program: &Program,
|
program: &Program,
|
||||||
exec_state: &mut ExecState,
|
exec_state: &mut ExecState,
|
||||||
) -> Result<TakeSnapshot> {
|
) -> std::result::Result<TakeSnapshot, ExecError> {
|
||||||
self.execute_and_prepare(program, exec_state).await
|
self.execute_and_prepare(program, exec_state).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Execute the program, return the interpreter and outputs.
|
/// Execute the program, return the interpreter and outputs.
|
||||||
pub async fn execute_and_prepare(&self, program: &Program, exec_state: &mut ExecState) -> Result<TakeSnapshot> {
|
pub async fn execute_and_prepare(
|
||||||
|
&self,
|
||||||
|
program: &Program,
|
||||||
|
exec_state: &mut ExecState,
|
||||||
|
) -> std::result::Result<TakeSnapshot, ExecError> {
|
||||||
self.run(program, exec_state).await?;
|
self.run(program, exec_state).await?;
|
||||||
|
|
||||||
// Zoom to fit.
|
// Zoom to fit.
|
||||||
@ -2216,7 +2220,9 @@ impl ExecutorContext {
|
|||||||
modeling_response: OkModelingCmdResponse::TakeSnapshot(contents),
|
modeling_response: OkModelingCmdResponse::TakeSnapshot(contents),
|
||||||
} = resp
|
} = resp
|
||||||
else {
|
else {
|
||||||
anyhow::bail!("Unexpected response from engine: {:?}", resp);
|
return Err(ExecError::BadPng(format!(
|
||||||
|
"Instead of a TakeSnapshot response, the engine returned {resp:?}"
|
||||||
|
)));
|
||||||
};
|
};
|
||||||
Ok(contents)
|
Ok(contents)
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ pub use ast::modify::modify_ast_for_sketch;
|
|||||||
pub use ast::types::{FormatOptions, ModuleId};
|
pub use ast::types::{FormatOptions, ModuleId};
|
||||||
pub use coredump::CoreDump;
|
pub use coredump::CoreDump;
|
||||||
pub use engine::{EngineManager, ExecutionKind};
|
pub use engine::{EngineManager, ExecutionKind};
|
||||||
pub use errors::KclError;
|
pub use errors::{ConnectionError, ExecError, KclError};
|
||||||
pub use executor::{ExecState, ExecutorContext, ExecutorSettings, SourceRange};
|
pub use executor::{ExecState, ExecutorContext, ExecutorSettings, SourceRange};
|
||||||
pub use lsp::copilot::Backend as CopilotLspBackend;
|
pub use lsp::copilot::Backend as CopilotLspBackend;
|
||||||
pub use lsp::kcl::Backend as KclLspBackend;
|
pub use lsp::kcl::Backend as KclLspBackend;
|
||||||
|
@ -308,6 +308,10 @@ fn analyze_faces(exec_state: &mut ExecState, args: &Args, face_infos: Vec<Extrus
|
|||||||
match face_info.cap {
|
match face_info.cap {
|
||||||
ExtrusionFaceCapType::Bottom => faces.start_cap_id = face_info.face_id,
|
ExtrusionFaceCapType::Bottom => faces.start_cap_id = face_info.face_id,
|
||||||
ExtrusionFaceCapType::Top => faces.end_cap_id = face_info.face_id,
|
ExtrusionFaceCapType::Top => faces.end_cap_id = face_info.face_id,
|
||||||
|
ExtrusionFaceCapType::Both => {
|
||||||
|
faces.end_cap_id = face_info.face_id;
|
||||||
|
faces.start_cap_id = face_info.face_id;
|
||||||
|
}
|
||||||
ExtrusionFaceCapType::None => {
|
ExtrusionFaceCapType::None => {
|
||||||
if let Some(curve_id) = face_info.curve_id {
|
if let Some(curve_id) = face_info.curve_id {
|
||||||
faces.sides.insert(curve_id, face_info.face_id);
|
faces.sides.insert(curve_id, face_info.face_id);
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
executor::{new_zoo_client, ExecutorContext, ExecutorSettings, ProgramMemory},
|
executor::{new_zoo_client, ExecutorContext, ExecutorSettings, ProgramMemory},
|
||||||
settings::types::UnitLength,
|
settings::types::UnitLength,
|
||||||
ExecState, Program,
|
ConnectionError, ExecError, ExecState, Program,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(serde::Deserialize, serde::Serialize)]
|
#[derive(serde::Deserialize, serde::Serialize)]
|
||||||
@ -15,7 +15,7 @@ pub struct RequestBody {
|
|||||||
|
|
||||||
/// Executes a kcl program and takes a snapshot of the result.
|
/// Executes a kcl program and takes a snapshot of the result.
|
||||||
/// This returns the bytes of the snapshot.
|
/// This returns the bytes of the snapshot.
|
||||||
pub async fn execute_and_snapshot(code: &str, units: UnitLength) -> anyhow::Result<image::DynamicImage> {
|
pub async fn execute_and_snapshot(code: &str, units: UnitLength) -> Result<image::DynamicImage, ExecError> {
|
||||||
let ctx = new_context(units, true).await?;
|
let ctx = new_context(units, true).await?;
|
||||||
let program = Program::parse(code)?;
|
let program = Program::parse(code)?;
|
||||||
do_execute_and_snapshot(&ctx, program).await.map(|(_state, snap)| snap)
|
do_execute_and_snapshot(&ctx, program).await.map(|(_state, snap)| snap)
|
||||||
@ -26,14 +26,14 @@ pub async fn execute_and_snapshot(code: &str, units: UnitLength) -> anyhow::Resu
|
|||||||
pub async fn execute_and_snapshot_ast(
|
pub async fn execute_and_snapshot_ast(
|
||||||
ast: Program,
|
ast: Program,
|
||||||
units: UnitLength,
|
units: UnitLength,
|
||||||
) -> anyhow::Result<(ProgramMemory, image::DynamicImage)> {
|
) -> Result<(ProgramMemory, image::DynamicImage), ExecError> {
|
||||||
let ctx = new_context(units, true).await?;
|
let ctx = new_context(units, true).await?;
|
||||||
do_execute_and_snapshot(&ctx, ast)
|
do_execute_and_snapshot(&ctx, ast)
|
||||||
.await
|
.await
|
||||||
.map(|(state, snap)| (state.memory, snap))
|
.map(|(state, snap)| (state.memory, snap))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn execute_and_snapshot_no_auth(code: &str, units: UnitLength) -> anyhow::Result<image::DynamicImage> {
|
pub async fn execute_and_snapshot_no_auth(code: &str, units: UnitLength) -> Result<image::DynamicImage, ExecError> {
|
||||||
let ctx = new_context(units, false).await?;
|
let ctx = new_context(units, false).await?;
|
||||||
let program = Program::parse(code)?;
|
let program = Program::parse(code)?;
|
||||||
do_execute_and_snapshot(&ctx, program).await.map(|(_state, snap)| snap)
|
do_execute_and_snapshot(&ctx, program).await.map(|(_state, snap)| snap)
|
||||||
@ -42,21 +42,21 @@ pub async fn execute_and_snapshot_no_auth(code: &str, units: UnitLength) -> anyh
|
|||||||
async fn do_execute_and_snapshot(
|
async fn do_execute_and_snapshot(
|
||||||
ctx: &ExecutorContext,
|
ctx: &ExecutorContext,
|
||||||
program: Program,
|
program: Program,
|
||||||
) -> anyhow::Result<(crate::executor::ExecState, image::DynamicImage)> {
|
) -> Result<(crate::executor::ExecState, image::DynamicImage), ExecError> {
|
||||||
let mut exec_state = ExecState::default();
|
let mut exec_state = ExecState::default();
|
||||||
let snapshot = ctx.execute_and_prepare(&program, &mut exec_state).await?;
|
let snapshot_png_bytes = ctx.execute_and_prepare(&program, &mut exec_state).await?.contents.0;
|
||||||
|
|
||||||
// Create a temporary file to write the output to.
|
|
||||||
let output_file = std::env::temp_dir().join(format!("kcl_output_{}.png", uuid::Uuid::new_v4()));
|
|
||||||
// Save the snapshot locally, to that temporary file.
|
|
||||||
std::fs::write(&output_file, snapshot.contents.0)?;
|
|
||||||
// Decode the snapshot, return it.
|
// Decode the snapshot, return it.
|
||||||
let img = image::ImageReader::open(output_file).unwrap().decode()?;
|
let img = image::ImageReader::new(std::io::Cursor::new(snapshot_png_bytes))
|
||||||
|
.with_guessed_format()
|
||||||
|
.map_err(|e| ExecError::BadPng(e.to_string()))
|
||||||
|
.and_then(|x| x.decode().map_err(|e| ExecError::BadPng(e.to_string())))?;
|
||||||
Ok((exec_state, img))
|
Ok((exec_state, img))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn new_context(units: UnitLength, with_auth: bool) -> anyhow::Result<ExecutorContext> {
|
async fn new_context(units: UnitLength, with_auth: bool) -> Result<ExecutorContext, ConnectionError> {
|
||||||
let mut client = new_zoo_client(if with_auth { None } else { Some("bad_token".to_string()) }, None)?;
|
let mut client = new_zoo_client(if with_auth { None } else { Some("bad_token".to_string()) }, None)
|
||||||
|
.map_err(ConnectionError::CouldNotMakeClient)?;
|
||||||
if !with_auth {
|
if !with_auth {
|
||||||
// Use prod, don't override based on env vars.
|
// Use prod, don't override based on env vars.
|
||||||
// We do this so even in the engine repo, tests that need to run with
|
// We do this so even in the engine repo, tests that need to run with
|
||||||
@ -74,6 +74,7 @@ async fn new_context(units: UnitLength, with_auth: bool) -> anyhow::Result<Execu
|
|||||||
replay: None,
|
replay: None,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await?;
|
.await
|
||||||
|
.map_err(ConnectionError::Establishing)?;
|
||||||
Ok(ctx)
|
Ok(ctx)
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user