Compare commits

...

4 Commits

Author SHA1 Message Date
3464f93a30 fix: revert quick file write on refresh (#5943)
* fix: REVERT REVERT REVERT

* fix: one more unused remove

* A snapshot a day keeps the bugs away! 📷🐛

* A snapshot a day keeps the bugs away! 📷🐛

* A snapshot a day keeps the bugs away! 📷🐛

* Make sure connection is established before advancing settings theme test

* A snapshot a day keeps the bugs away! 📷🐛

* A snapshot a day keeps the bugs away! 📷🐛

* A snapshot a day keeps the bugs away! 📷🐛

* A snapshot a day keeps the bugs away! 📷🐛

* A snapshot a day keeps the bugs away! 📷🐛

* A snapshot a day keeps the bugs away! 📷🐛

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frankjohnson1993@gmail.com>
2025-03-21 17:33:43 -07:00
f6936f55d6 bump kcl friends (#5948)
Signed-off-by: Jess Frazelle <github@jessfraz.com>
2025-03-21 17:33:26 -07:00
eef1a28ebb Move helix revolutions into the main helix args (#5942)
* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* docs

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updaes

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fix

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2025-03-21 22:38:08 +00:00
5aed80e930 Switch to a variable that is set on pushes (#5940) 2025-03-21 20:00:07 +00:00
42 changed files with 789 additions and 2419 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -74,7 +74,6 @@ layout: manual
* [`getOppositeEdge`](kcl/getOppositeEdge)
* [`getPreviousAdjacentEdge`](kcl/getPreviousAdjacentEdge)
* [`helix`](kcl/helix)
* [`helixRevolutions`](kcl/helixRevolutions)
* [`hole`](kcl/hole)
* [`hollow`](kcl/hollow)
* [`inch`](kcl/inch)

File diff suppressed because it is too large Load Diff

View File

@ -21,6 +21,7 @@ A helix.
| `revolutions` |[`number`](/docs/kcl/types/number)| Number of revolutions. | No |
| `angleStart` |[`number`](/docs/kcl/types/number)| Start angle (in degrees). | No |
| `ccw` |`boolean`| Is the helix rotation counter clockwise? | No |
| `cylinderId` |[`string`](/docs/kcl/types/string)| The cylinder the helix was created on. | No |
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A unit of length. | No |

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 69 KiB

View File

@ -56,7 +56,7 @@ export const editorSelector = '[role="textbox"][data-language="kcl"]'
type PaneId = 'variables' | 'code' | 'files' | 'logs'
export function orRunWhenFullSuiteEnabled() {
return process.env.GITHUB_HEAD_REF !== 'all-e2e'
return process.env.GITHUB_REF !== 'all-e2e'
}
async function waitForPageLoadWithRetry(page: Page) {

View File

@ -746,6 +746,7 @@ test.describe('Testing settings', () => {
})
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await expect(toolbar.startSketchBtn).toBeEnabled({ timeout: 15_000 })
await scene.settled(cmdBar)
await page.waitForTimeout(1000)

20
rust/Cargo.lock generated
View File

@ -1780,7 +1780,7 @@ dependencies = [
[[package]]
name = "kcl-bumper"
version = "0.1.52"
version = "0.1.53"
dependencies = [
"anyhow",
"clap",
@ -1791,7 +1791,7 @@ dependencies = [
[[package]]
name = "kcl-derive-docs"
version = "0.1.52"
version = "0.1.53"
dependencies = [
"Inflector",
"anyhow",
@ -1810,7 +1810,7 @@ dependencies = [
[[package]]
name = "kcl-directory-test-macro"
version = "0.1.52"
version = "0.1.53"
dependencies = [
"proc-macro2",
"quote",
@ -1819,7 +1819,7 @@ dependencies = [
[[package]]
name = "kcl-language-server"
version = "0.2.52"
version = "0.2.53"
dependencies = [
"anyhow",
"clap",
@ -1840,7 +1840,7 @@ dependencies = [
[[package]]
name = "kcl-language-server-release"
version = "0.1.52"
version = "0.1.53"
dependencies = [
"anyhow",
"clap",
@ -1860,7 +1860,7 @@ dependencies = [
[[package]]
name = "kcl-lib"
version = "0.2.52"
version = "0.2.53"
dependencies = [
"anyhow",
"approx 0.5.1",
@ -1928,7 +1928,7 @@ dependencies = [
[[package]]
name = "kcl-python-bindings"
version = "0.3.52"
version = "0.3.53"
dependencies = [
"anyhow",
"kcl-lib",
@ -1943,7 +1943,7 @@ dependencies = [
[[package]]
name = "kcl-test-server"
version = "0.1.52"
version = "0.1.53"
dependencies = [
"anyhow",
"hyper 0.14.32",
@ -1956,7 +1956,7 @@ dependencies = [
[[package]]
name = "kcl-to-core"
version = "0.1.52"
version = "0.1.53"
dependencies = [
"anyhow",
"async-trait",
@ -1970,7 +1970,7 @@ dependencies = [
[[package]]
name = "kcl-wasm-lib"
version = "0.1.52"
version = "0.1.53"
dependencies = [
"bson",
"console_error_panic_hook",

View File

@ -1,7 +1,7 @@
[package]
name = "kcl-bumper"
version = "0.1.52"
version = "0.1.53"
edition = "2021"
repository = "https://github.com/KittyCAD/modeling-api"
rust-version = "1.76"

View File

@ -1,7 +1,7 @@
[package]
name = "kcl-derive-docs"
description = "A tool for generating documentation from Rust derive macros"
version = "0.1.52"
version = "0.1.53"
edition = "2021"
license = "MIT"
repository = "https://github.com/KittyCAD/modeling-app"

View File

@ -1,7 +1,7 @@
[package]
name = "kcl-directory-test-macro"
description = "A tool for generating tests from a directory of kcl files"
version = "0.1.52"
version = "0.1.53"
edition = "2021"
license = "MIT"
repository = "https://github.com/KittyCAD/modeling-app"

View File

@ -1,6 +1,6 @@
[package]
name = "kcl-language-server-release"
version = "0.1.52"
version = "0.1.53"
edition = "2021"
authors = ["KittyCAD Inc <kcl@kittycad.io>"]
publish = false

View File

@ -2,7 +2,7 @@
name = "kcl-language-server"
description = "A language server for KCL."
authors = ["KittyCAD Inc <kcl@kittycad.io>"]
version = "0.2.52"
version = "0.2.53"
edition = "2021"
license = "MIT"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View File

@ -1,7 +1,7 @@
[package]
name = "kcl-lib"
description = "KittyCAD Language implementation and tools"
version = "0.2.52"
version = "0.2.53"
edition = "2021"
license = "MIT"
repository = "https://github.com/KittyCAD/modeling-app"

View File

@ -1,4 +1,4 @@
const part001 = startSketchOn(XY)
|> circle(center= [5, 5], radius= 10)
|> extrude(length = 10)
|> helixRevolutions({revolutions = 16, angleStart = 0}, %)
|> helix(revolutions = 16, angleStart = 0, cylinder = %)

View File

@ -1,4 +1,4 @@
const part001 = startSketchOn(XY)
|> circle(center = [5, 5], radius = 10)
|> extrude(length = -10)
|> helixRevolutions({revolutions = 16, angleStart = 0}, %)
|> helix(revolutions = 16, angleStart = 0, cylinder = %)

View File

@ -1,4 +1,4 @@
const part001 = startSketchOn(XY)
|> circle(center= [5, 5], radius= 10)
|> extrude(length = 10)
|> helixRevolutions({revolutions = 16, angleStart = 0, length = 3}, %)
|> helix(revolutions = 16, angleStart = 0, length = 3, cylinder = %)

View File

@ -127,13 +127,14 @@ impl StdLibFnArg {
} else {
""
};
if self.type_ == "Sketch"
if (self.type_ == "Sketch"
|| self.type_ == "[Sketch]"
|| self.type_ == "Solid"
|| self.type_ == "[Solid]"
|| self.type_ == "SketchSurface"
|| self.type_ == "SketchOrSurface"
|| self.type_ == "SolidOrSketchOrImportedGeometry"
|| self.type_ == "SolidOrSketchOrImportedGeometry")
&& (self.required || self.include_in_snippet)
{
return Ok(Some((index, format!("{label}${{{}:{}}}", index, "%"))));
} else if (self.type_ == "TagDeclarator" || self.type_ == "TagNode") && self.required {
@ -1094,16 +1095,38 @@ mod tests {
#[test]
#[allow(clippy::literal_string_with_formatting_args)]
fn get_autocomplete_snippet_helix_revolutions() {
let helix_fn: Box<dyn StdLibFn> = Box::new(crate::std::helix::HelixRevolutions);
let snippet = helix_fn.to_autocomplete_snippet().unwrap();
fn get_autocomplete_snippet_union() {
let union_fn: Box<dyn StdLibFn> = Box::new(crate::std::csg::Union);
let snippet = union_fn.to_autocomplete_snippet().unwrap();
assert_eq!(snippet, r#"union(${0:%})${}"#);
}
#[test]
#[allow(clippy::literal_string_with_formatting_args)]
fn get_autocomplete_snippet_subtract() {
let subtract_fn: Box<dyn StdLibFn> = Box::new(crate::std::csg::Subtract);
let snippet = subtract_fn.to_autocomplete_snippet().unwrap();
assert_eq!(snippet, r#"subtract(${0:%}, tools = ${1:%})${}"#);
}
#[test]
#[allow(clippy::literal_string_with_formatting_args)]
fn get_autocomplete_snippet_intersect() {
let intersect_fn: Box<dyn StdLibFn> = Box::new(crate::std::csg::Intersect);
let snippet = intersect_fn.to_autocomplete_snippet().unwrap();
assert_eq!(snippet, r#"intersect(${0:%})${}"#);
}
#[test]
#[allow(clippy::literal_string_with_formatting_args)]
fn get_autocomplete_snippet_get_common_edge() {
let get_common_edge_fn: Box<dyn StdLibFn> = Box::new(crate::std::edge::GetCommonEdge);
let snippet = get_common_edge_fn.to_autocomplete_snippet().unwrap();
assert_eq!(
snippet,
r#"helixRevolutions({
revolutions = ${0:3.14},
angleStart = ${1:3.14},
ccw = ${2:false},
}, ${3:%})${}"#
r#"getCommonEdge(faces = [{
value = ${0:"string"},
}])${}"#
);
}

View File

@ -152,6 +152,8 @@ pub struct Helix {
pub angle_start: f64,
/// Is the helix rotation counter clockwise?
pub ccw: bool,
/// The cylinder the helix was created on.
pub cylinder_id: Option<uuid::Uuid>,
pub units: UnitLen,
#[serde(skip)]
pub meta: Vec<Metadata>,

View File

@ -1258,23 +1258,6 @@ impl<'a> FromKclValue<'a> for super::sketch::BezierData {
}
}
impl<'a> FromKclValue<'a> for super::helix::HelixRevolutionsData {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
let obj = arg.as_object()?;
let_field_of!(obj, revolutions);
let_field_of!(obj, length?);
let_field_of!(obj, ccw?);
let ccw = ccw.unwrap_or_default();
let angle_start = obj.get("angleStart")?.as_f64()?;
Some(Self {
revolutions,
angle_start,
ccw,
length,
})
}
}
impl<'a> FromKclValue<'a> for FaceTag {
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
let case1 = || match arg.as_str() {

View File

@ -4,8 +4,6 @@ use anyhow::Result;
use kcl_derive_docs::stdlib;
use kcmc::{each_cmd as mcmd, length_unit::LengthUnit, shared::Angle, ModelingCmd};
use kittycad_modeling_cmds as kcmc;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use crate::{
errors::KclError,
@ -18,11 +16,71 @@ pub async fn helix(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
let angle_start = args.get_kw_arg("angleStart")?;
let revolutions = args.get_kw_arg("revolutions")?;
let ccw = args.get_kw_arg_opt("ccw")?;
let radius = args.get_kw_arg("radius")?;
let axis = args.get_kw_arg("axis")?;
let radius = args.get_kw_arg_opt("radius")?;
let axis = args.get_kw_arg_opt("axis")?;
let length = args.get_kw_arg_opt("length")?;
let cylinder = args.get_kw_arg_opt("cylinder")?;
let value = inner_helix(revolutions, angle_start, ccw, radius, axis, length, exec_state, args).await?;
// Make sure we have a radius if we don't have a cylinder.
if radius.is_none() && cylinder.is_none() {
return Err(KclError::Semantic(crate::errors::KclErrorDetails {
message: "Radius is required when creating a helix without a cylinder.".to_string(),
source_ranges: vec![args.source_range],
}));
}
// Make sure we don't have a radius if we have a cylinder.
if radius.is_some() && cylinder.is_some() {
return Err(KclError::Semantic(crate::errors::KclErrorDetails {
message: "Radius is not allowed when creating a helix with a cylinder.".to_string(),
source_ranges: vec![args.source_range],
}));
}
// Make sure we have an axis if we don't have a cylinder.
if axis.is_none() && cylinder.is_none() {
return Err(KclError::Semantic(crate::errors::KclErrorDetails {
message: "Axis is required when creating a helix without a cylinder.".to_string(),
source_ranges: vec![args.source_range],
}));
}
// Make sure we don't have an axis if we have a cylinder.
if axis.is_some() && cylinder.is_some() {
return Err(KclError::Semantic(crate::errors::KclErrorDetails {
message: "Axis is not allowed when creating a helix with a cylinder.".to_string(),
source_ranges: vec![args.source_range],
}));
}
// Make sure we have a radius if we have an axis.
if radius.is_none() && axis.is_some() {
return Err(KclError::Semantic(crate::errors::KclErrorDetails {
message: "Radius is required when creating a helix around an axis.".to_string(),
source_ranges: vec![args.source_range],
}));
}
// Make sure we have an axis if we have a radius.
if axis.is_none() && radius.is_some() {
return Err(KclError::Semantic(crate::errors::KclErrorDetails {
message: "Axis is required when creating a helix around an axis.".to_string(),
source_ranges: vec![args.source_range],
}));
}
let value = inner_helix(
revolutions,
angle_start,
ccw,
radius,
axis,
length,
cylinder,
exec_state,
args,
)
.await?;
Ok(KclValue::Helix { value })
}
@ -88,6 +146,23 @@ pub async fn helix(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
/// |> circle( center = [0, 0], radius = 1 )
/// |> sweep(path = helixPath)
/// ```
///
///
///
/// ```no_run
/// // Create a helix on a cylinder.
///
/// part001 = startSketchOn('XY')
/// |> circle( center= [5, 5], radius= 10 )
/// |> extrude(length = 10)
///
/// helix(
/// angleStart = 0,
/// ccw = true,
/// revolutions = 16,
/// cylinder = part001,
/// )
/// ```
#[stdlib {
name = "helix",
keywords = true,
@ -96,9 +171,10 @@ pub async fn helix(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
revolutions = { docs = "Number of revolutions."},
angle_start = { docs = "Start angle (in degrees)."},
ccw = { docs = "Is the helix rotation counter clockwise? The default is `false`.", include_in_snippet = false},
radius = { docs = "Radius of the helix."},
axis = { docs = "Axis to use for the helix."},
radius = { docs = "Radius of the helix.", include_in_snippet = true},
axis = { docs = "Axis to use for the helix.", include_in_snippet = true},
length = { docs = "Length of the helix. This is not necessary if the helix is created around an edge. If not given the length of the edge is used.", include_in_snippet = true},
cylinder = { docs = "Cylinder to create the helix on.", include_in_snippet = false},
},
feature_tree_operation = true,
}]
@ -107,9 +183,10 @@ async fn inner_helix(
revolutions: f64,
angle_start: f64,
ccw: Option<bool>,
radius: f64,
axis: Axis3dOrEdgeReference,
radius: Option<f64>,
axis: Option<Axis3dOrEdgeReference>,
length: Option<f64>,
cylinder: Option<Solid>,
exec_state: &mut ExecState,
args: Args,
) -> Result<Box<HelixValue>, KclError> {
@ -120,6 +197,7 @@ async fn inner_helix(
artifact_id: id.into(),
revolutions,
angle_start,
cylinder_id: cylinder.as_ref().map(|c| c.id),
ccw: ccw.unwrap_or(false),
units: exec_state.length_unit(),
meta: vec![args.source_range.into()],
@ -129,113 +207,63 @@ async fn inner_helix(
return Ok(helix_result);
}
match axis {
Axis3dOrEdgeReference::Axis(axis) => {
let (axis, origin) = axis.axis_and_origin()?;
if let Some(cylinder) = cylinder {
args.batch_modeling_cmd(
id,
ModelingCmd::from(mcmd::EntityMakeHelix {
cylinder_id: cylinder.id,
is_clockwise: !helix_result.ccw,
length: LengthUnit(length.unwrap_or(cylinder.height)),
revolutions,
start_angle: Angle::from_degrees(angle_start),
}),
)
.await?;
} else if let (Some(axis), Some(radius)) = (axis, radius) {
match axis {
Axis3dOrEdgeReference::Axis(axis) => {
let (axis, origin) = axis.axis_and_origin()?;
// Make sure they gave us a length.
let Some(length) = length else {
return Err(KclError::Semantic(crate::errors::KclErrorDetails {
message: "Length is required when creating a helix around an axis.".to_string(),
source_ranges: vec![args.source_range],
}));
};
// Make sure they gave us a length.
let Some(length) = length else {
return Err(KclError::Semantic(crate::errors::KclErrorDetails {
message: "Length is required when creating a helix around an axis.".to_string(),
source_ranges: vec![args.source_range],
}));
};
args.batch_modeling_cmd(
id,
ModelingCmd::from(mcmd::EntityMakeHelixFromParams {
radius: LengthUnit(radius),
is_clockwise: !helix_result.ccw,
length: LengthUnit(length),
revolutions,
start_angle: Angle::from_degrees(angle_start),
axis,
center: origin,
}),
)
.await?;
}
Axis3dOrEdgeReference::Edge(edge) => {
let edge_id = edge.get_engine_id(exec_state, &args)?;
args.batch_modeling_cmd(
id,
ModelingCmd::from(mcmd::EntityMakeHelixFromParams {
radius: LengthUnit(radius),
is_clockwise: !helix_result.ccw,
length: LengthUnit(length),
revolutions,
start_angle: Angle::from_degrees(angle_start),
axis,
center: origin,
}),
)
.await?;
}
Axis3dOrEdgeReference::Edge(edge) => {
let edge_id = edge.get_engine_id(exec_state, &args)?;
args.batch_modeling_cmd(
id,
ModelingCmd::from(mcmd::EntityMakeHelixFromEdge {
radius: LengthUnit(radius),
is_clockwise: !helix_result.ccw,
length: length.map(LengthUnit),
revolutions,
start_angle: Angle::from_degrees(angle_start),
edge_id,
}),
)
.await?;
}
};
args.batch_modeling_cmd(
id,
ModelingCmd::from(mcmd::EntityMakeHelixFromEdge {
radius: LengthUnit(radius),
is_clockwise: !helix_result.ccw,
length: length.map(LengthUnit),
revolutions,
start_angle: Angle::from_degrees(angle_start),
edge_id,
}),
)
.await?;
}
};
}
Ok(helix_result)
}
/// Data for helix revolutions.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]
pub struct HelixRevolutionsData {
/// Number of revolutions.
pub revolutions: f64,
/// Start angle (in degrees).
#[serde(rename = "angleStart")]
pub angle_start: f64,
/// Is the helix rotation counter clockwise?
/// The default is `false`.
#[serde(default)]
pub ccw: bool,
/// Length of the helix. If this argument is not provided, the height of
/// the solid is used.
pub length: Option<f64>,
}
/// Create a helix on a cylinder.
pub async fn helix_revolutions(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let (data, solid): (HelixRevolutionsData, Box<Solid>) = args.get_data_and_solid(exec_state)?;
let value = inner_helix_revolutions(data, solid, exec_state, args).await?;
Ok(KclValue::Solid { value })
}
/// Create a helix on a cylinder.
///
/// ```no_run
/// part001 = startSketchOn('XY')
/// |> circle( center= [5, 5], radius= 10 )
/// |> extrude(length = 10)
/// |> helixRevolutions({
/// angleStart = 0,
/// ccw = true,
/// revolutions = 16,
/// }, %)
/// ```
#[stdlib {
name = "helixRevolutions",
feature_tree_operation = true,
}]
async fn inner_helix_revolutions(
data: HelixRevolutionsData,
solid: Box<Solid>,
exec_state: &mut ExecState,
args: Args,
) -> Result<Box<Solid>, KclError> {
let id = exec_state.next_uuid();
args.batch_modeling_cmd(
id,
ModelingCmd::from(mcmd::EntityMakeHelix {
cylinder_id: solid.id,
is_clockwise: !data.ccw,
length: LengthUnit(data.length.unwrap_or(solid.height)),
revolutions: data.revolutions,
start_angle: Angle::from_degrees(data.angle_start),
}),
)
.await?;
Ok(solid)
}

View File

@ -114,7 +114,6 @@ lazy_static! {
Box::new(crate::std::edge::GetPreviousAdjacentEdge),
Box::new(crate::std::edge::GetCommonEdge),
Box::new(crate::std::helix::Helix),
Box::new(crate::std::helix::HelixRevolutions),
Box::new(crate::std::shell::Shell),
Box::new(crate::std::shell::Hollow),
Box::new(crate::std::revolve::Revolve),

View File

@ -168,106 +168,99 @@ description: Result of parsing helix_ccw.kcl
{
"arguments": [
{
"commentStart": 120,
"end": 0,
"properties": [
{
"commentStart": 129,
"end": 0,
"key": {
"commentStart": 129,
"end": 0,
"name": "revolutions",
"start": 0,
"type": "Identifier"
},
"start": 0,
"type": "ObjectProperty",
"value": {
"commentStart": 143,
"end": 0,
"raw": "16",
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 16.0,
"suffix": "None"
}
}
},
{
"commentStart": 154,
"end": 0,
"key": {
"commentStart": 154,
"end": 0,
"name": "angleStart",
"start": 0,
"type": "Identifier"
},
"start": 0,
"type": "ObjectProperty",
"value": {
"commentStart": 167,
"end": 0,
"raw": "0",
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 0.0,
"suffix": "None"
}
}
},
{
"commentStart": 177,
"end": 0,
"key": {
"commentStart": 177,
"end": 0,
"name": "ccw",
"start": 0,
"type": "Identifier"
},
"start": 0,
"type": "ObjectProperty",
"value": {
"commentStart": 183,
"end": 0,
"raw": "true",
"start": 0,
"type": "Literal",
"type": "Literal",
"value": true
}
"type": "LabeledArg",
"label": {
"commentStart": 117,
"end": 0,
"name": "revolutions",
"start": 0,
"type": "Identifier"
},
"arg": {
"commentStart": 131,
"end": 0,
"raw": "16",
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 16.0,
"suffix": "None"
}
],
"start": 0,
"type": "ObjectExpression",
"type": "ObjectExpression"
}
},
{
"commentStart": 196,
"end": 0,
"start": 0,
"type": "PipeSubstitution",
"type": "PipeSubstitution"
"type": "LabeledArg",
"label": {
"commentStart": 142,
"end": 0,
"name": "angleStart",
"start": 0,
"type": "Identifier"
},
"arg": {
"commentStart": 155,
"end": 0,
"raw": "0",
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 0.0,
"suffix": "None"
}
}
},
{
"type": "LabeledArg",
"label": {
"commentStart": 165,
"end": 0,
"name": "ccw",
"start": 0,
"type": "Identifier"
},
"arg": {
"commentStart": 171,
"end": 0,
"raw": "true",
"start": 0,
"type": "Literal",
"type": "Literal",
"value": true
}
},
{
"type": "LabeledArg",
"label": {
"commentStart": 184,
"end": 0,
"name": "cylinder",
"start": 0,
"type": "Identifier"
},
"arg": {
"commentStart": 195,
"end": 0,
"start": 0,
"type": "PipeSubstitution",
"type": "PipeSubstitution"
}
}
],
"callee": {
"commentStart": 103,
"end": 0,
"name": "helixRevolutions",
"name": "helix",
"start": 0,
"type": "Identifier"
},
"commentStart": 103,
"end": 0,
"start": 0,
"type": "CallExpression",
"type": "CallExpression"
"type": "CallExpressionKw",
"type": "CallExpressionKw",
"unlabeled": null
}
],
"commentStart": 10,

View File

@ -1,8 +1,8 @@
part001 = startSketchOn('XY')
|> circle(center = [5, 5], radius = 10)
|> extrude(length = 10)
|> helixRevolutions({
|> helix(
revolutions = 16,
angleStart = 0,
ccw = true
}, %)
ccw = true,
cylinder = %)

View File

@ -52,45 +52,30 @@ description: Operations executed helix_ccw.kcl
},
{
"labeledArgs": {
"data": {
"angleStart": {
"value": {
"type": "Object",
"value": {
"angleStart": {
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"ccw": {
"type": "Bool",
"value": true
},
"revolutions": {
"type": "Number",
"value": 16.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
"angle": {
"type": "Degrees"
}
}
},
"sourceRange": []
},
"solid": {
"ccw": {
"value": {
"type": "Bool",
"value": true
},
"sourceRange": []
},
"cylinder": {
"value": {
"type": "Solid",
"value": {
@ -98,11 +83,35 @@ description: Operations executed helix_ccw.kcl
}
},
"sourceRange": []
},
"revolutions": {
"value": {
"type": "Number",
"value": 16.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"sourceRange": []
}
},
"name": "helixRevolutions",
"name": "helix",
"sourceRange": [],
"type": "StdLibCall",
"unlabeledArg": null
"unlabeledArg": {
"value": {
"type": "Solid",
"value": {
"artifactId": "[uuid]"
}
},
"sourceRange": []
}
}
]

View File

@ -4,106 +4,14 @@ description: Variables in memory after executing helix_ccw.kcl
---
{
"part001": {
"type": "Solid",
"type": "Helix",
"value": {
"type": "Solid",
"id": "[uuid]",
"value": "[uuid]",
"artifactId": "[uuid]",
"value": [
{
"faceId": "[uuid]",
"id": "[uuid]",
"sourceRange": [],
"tag": null,
"type": "extrudeArc"
}
],
"sketch": {
"type": "Sketch",
"id": "[uuid]",
"paths": [
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"ccw": true,
"center": [
5.0,
5.0
],
"from": [
15.0,
5.0
],
"radius": 10.0,
"tag": null,
"to": [
15.0,
5.0
],
"type": "Circle",
"units": {
"type": "Mm"
}
}
],
"on": {
"type": "plane",
"id": "[uuid]",
"artifactId": "[uuid]",
"value": "XY",
"origin": {
"x": 0.0,
"y": 0.0,
"z": 0.0
},
"xAxis": {
"x": 1.0,
"y": 0.0,
"z": 0.0
},
"yAxis": {
"x": 0.0,
"y": 1.0,
"z": 0.0
},
"zAxis": {
"x": 0.0,
"y": 0.0,
"z": 1.0
},
"units": {
"type": "Mm"
}
},
"start": {
"from": [
15.0,
5.0
],
"to": [
15.0,
5.0
],
"units": {
"type": "Mm"
},
"tag": null,
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
}
},
"artifactId": "[uuid]",
"originalId": "[uuid]",
"units": {
"type": "Mm"
}
},
"height": 10.0,
"startCapId": "[uuid]",
"endCapId": "[uuid]",
"revolutions": 16.0,
"angleStart": 0.0,
"ccw": true,
"cylinderId": "[uuid]",
"units": {
"type": "Mm"
}

View File

@ -5,8 +5,9 @@ description: Result of unparsing helix_ccw.kcl
part001 = startSketchOn(XY)
|> circle(center = [5, 5], radius = 10)
|> extrude(length = 10)
|> helixRevolutions({
|> helix(
revolutions = 16,
angleStart = 0,
ccw = true
}, %)
ccw = true,
cylinder = %,
)

View File

@ -16,6 +16,7 @@ description: Variables in memory after executing helix_simple.kcl
"revolutions": 5.0,
"angleStart": 0.0,
"ccw": true,
"cylinderId": null,
"units": {
"type": "Mm"
}

View File

Before

Width:  |  Height:  |  Size: 138 KiB

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

View File

@ -1,6 +1,6 @@
[package]
name = "kcl-python-bindings"
version = "0.3.52"
version = "0.3.53"
edition = "2021"
repository = "https://github.com/kittycad/modeling-app"

View File

@ -1,7 +1,7 @@
[package]
name = "kcl-test-server"
description = "A test server for KCL"
version = "0.1.52"
version = "0.1.53"
edition = "2021"
license = "MIT"

View File

@ -1,7 +1,7 @@
[package]
name = "kcl-to-core"
description = "Utility methods to convert kcl to engine core executable tests"
version = "0.1.52"
version = "0.1.53"
edition = "2021"
license = "MIT"
repository = "https://github.com/KittyCAD/modeling-app"

View File

@ -1,6 +1,6 @@
[package]
name = "kcl-wasm-lib"
version = "0.1.52"
version = "0.1.53"
edition = "2021"
repository = "https://github.com/KittyCAD/modeling-app"
rust-version = "1.83"

View File

@ -34,7 +34,6 @@ import { settingsActor, useSettings } from 'machines/appMachine'
import { createRouteCommands } from 'lib/commandBarConfigs/routeCommandConfig'
import { useToken } from 'machines/appMachine'
import { createNamedViewsCommand } from 'lib/commandBarConfigs/namedViewsConfig'
import { reportRejection } from 'lib/trap'
type MachineContext<T extends AnyStateMachine> = {
state: StateFrom<T>
@ -61,20 +60,6 @@ export const FileMachineProvider = ({
[]
)
// Write code mirror content to disk when the page is trying to reroute
// Our logic for codeManager.writeToFile has an artificial 1000ms timeout which
// won't run quickly enough so users can make an edit, exit the page and lose their
// progress within that 1000ms window.
useEffect(() => {
const preventUnload = (event: BeforeUnloadEvent) => {
codeManager.writeToFileNoTimeout().catch(reportRejection)
}
window.addEventListener('beforeunload', preventUnload)
return () => {
window.removeEventListener('beforeunload', preventUnload)
}
}, [])
useEffect(() => {
// TODO: Engine feature is not deployed
if (DEV) {

View File

@ -164,32 +164,6 @@ export default class CodeManager {
}
}
// When we unload the page via changing routes we want to instantly write to disk to save their progress
// There is a race condition in the system. writeToFile takes 1000ms to run, if they make an edit and leave within the 1000ms
// window they won't get their content saved. Use this to always save their file before rerouting
async writeToFileNoTimeout() {
if (isDesktop()) {
return new Promise((resolve, reject) => {
if (!this._currentFilePath)
return reject(new Error('currentFilePath not set'))
// Wait one event loop to give a chance for params to be set
// Save the file to disk
window.electron
.writeFile(this._currentFilePath, this.code ?? '')
.then(resolve)
.catch((err: Error) => {
// TODO: add tracing per GH issue #254 (https://github.com/KittyCAD/modeling-app/issues/254)
console.error('error saving file', err)
toast.error('Error saving file, please check file permissions')
reject(err)
})
})
} else {
safeLSSetItem(PERSIST_CODE_KEY, this.code)
}
}
async updateEditorWithAstAndWriteToFile(ast: Program) {
// We clear the AST when there it cannot be parsed, so if we are trying to write an empty AST, its
// probably because of an earlier error. That's a bad state to be in and it's not going to be