Declare parts of std in KCL rather than Rust (#5147)

Declare std in KCL
This commit is contained in:
Nick Cameron
2025-02-20 19:33:21 +13:00
committed by GitHub
parent 099c48cd63
commit 7500ef0065
205 changed files with 17053 additions and 1503 deletions

15
docs/kcl/HALF_TURN.md Normal file
View File

@ -0,0 +1,15 @@
---
title: "HALF_TURN"
excerpt: ""
layout: manual
---
```js
HALF_TURN: number(deg) = 180deg
```

15
docs/kcl/QUARTER_TURN.md Normal file
View File

@ -0,0 +1,15 @@
---
title: "QUARTER_TURN"
excerpt: ""
layout: manual
---
```js
QUARTER_TURN: number(deg) = 90deg
```

View File

@ -0,0 +1,15 @@
---
title: "THREE_QUARTER_TURN"
excerpt: ""
layout: manual
---
```js
THREE_QUARTER_TURN: number(deg) = 270deg
```

15
docs/kcl/ZERO.md Normal file
View File

@ -0,0 +1,15 @@
---
title: "ZERO"
excerpt: ""
layout: manual
---
```js
ZERO: number = 0
```

View File

@ -25,7 +25,7 @@ abs(num: number) -> number
### Returns ### Returns
`number` `number`
### Examples ### Examples

View File

@ -25,7 +25,7 @@ acos(num: number) -> number
### Returns ### Returns
`number` `number`
### Examples ### Examples

View File

@ -23,7 +23,7 @@ angleToMatchLengthX(tag: TagIdentifier, to: number, sketch: Sketch) -> number
### Returns ### Returns
`number` `number`
### Examples ### Examples

View File

@ -23,7 +23,7 @@ angleToMatchLengthY(tag: TagIdentifier, to: number, sketch: Sketch) -> number
### Returns ### Returns
`number` `number`
### Examples ### Examples

View File

@ -25,7 +25,7 @@ asin(num: number) -> number
### Returns ### Returns
`number` `number`
### Examples ### Examples

View File

@ -22,7 +22,7 @@ assert(data: bool, message: string) -> ()
### Returns ### Returns
`()` `()`
### Examples ### Examples

View File

@ -24,7 +24,7 @@ assertEqual(left: number, right: number, epsilon: number, message: string) -> ()
### Returns ### Returns
`()` `()`
### Examples ### Examples

View File

@ -23,7 +23,7 @@ assertGreaterThan(left: number, right: number, message: string) -> ()
### Returns ### Returns
`()` `()`
### Examples ### Examples

View File

@ -23,7 +23,7 @@ assertGreaterThanOrEq(left: number, right: number, message: string) -> ()
### Returns ### Returns
`()` `()`
### Examples ### Examples

View File

@ -23,7 +23,7 @@ assertLessThan(left: number, right: number, message: string) -> ()
### Returns ### Returns
`()` `()`
### Examples ### Examples

View File

@ -23,7 +23,7 @@ assertLessThanOrEq(left: number, right: number, message: string) -> ()
### Returns ### Returns
`()` `()`
### Examples ### Examples

View File

@ -25,7 +25,7 @@ atan(num: number) -> number
### Returns ### Returns
`number` `number`
### Examples ### Examples

View File

@ -26,7 +26,7 @@ atan2(y: number, x: number) -> number
### Returns ### Returns
`number` `number`
### Examples ### Examples

View File

@ -25,7 +25,7 @@ ceil(num: number) -> number
### Returns ### Returns
`number` `number`
### Examples ### Examples

View File

@ -26,7 +26,7 @@ cm() -> number
### Returns ### Returns
`number` `number`
### Examples ### Examples

32
docs/kcl/const_E.md Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,15 @@
---
title: "HALF_TURN"
excerpt: ""
layout: manual
---
```js
HALF_TURN: number(deg) = 180deg
```

28
docs/kcl/const_PI.md Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,15 @@
---
title: "QUARTER_TURN"
excerpt: ""
layout: manual
---
```js
QUARTER_TURN: number(deg) = 90deg
```

32
docs/kcl/const_TAU.md Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,15 @@
---
title: "THREE_QUARTER_TURN"
excerpt: ""
layout: manual
---
```js
THREE_QUARTER_TURN: number(deg) = 270deg
```

15
docs/kcl/const_ZERO.md Normal file
View File

@ -0,0 +1,15 @@
---
title: "ZERO"
excerpt: ""
layout: manual
---
```js
ZERO: number = 0
```

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,15 @@
---
title: "std::prelude::HALF_TURN"
excerpt: ""
layout: manual
---
```js
std::prelude::HALF_TURN: number(deg) = 180deg
```

View File

@ -0,0 +1,15 @@
---
title: "std::prelude::QUARTER_TURN"
excerpt: ""
layout: manual
---
```js
std::prelude::QUARTER_TURN: number(deg) = 90deg
```

View File

@ -0,0 +1,15 @@
---
title: "std::prelude::THREE_QUARTER_TURN"
excerpt: ""
layout: manual
---
```js
std::prelude::THREE_QUARTER_TURN: number(deg) = 270deg
```

View File

@ -0,0 +1,15 @@
---
title: "std::prelude::ZERO"
excerpt: ""
layout: manual
---
```js
std::prelude::ZERO: number = 0
```

File diff suppressed because one or more lines are too long

View File

@ -4,9 +4,11 @@ excerpt: "Return the value of Eulers number `e`."
layout: manual layout: manual
--- ---
**WARNING:** This function is deprecated.
Return the value of Eulers number `e`. Return the value of Eulers number `e`.
**DEPRECATED** use the constant E
```js ```js
e() -> number e() -> number
@ -20,7 +22,7 @@ e() -> number
### Returns ### Returns
`number` `number`
### Examples ### Examples

View File

@ -25,7 +25,7 @@ floor(num: number) -> number
### Returns ### Returns
`number` `number`
### Examples ### Examples

View File

@ -26,7 +26,7 @@ ft() -> number
### Returns ### Returns
`number` `number`
### Examples ### Examples

View File

@ -21,7 +21,7 @@ getNextAdjacentEdge(tag: TagIdentifier) -> Uuid
### Returns ### Returns
`Uuid` `Uuid`
### Examples ### Examples

View File

@ -21,7 +21,7 @@ getOppositeEdge(tag: TagIdentifier) -> Uuid
### Returns ### Returns
`Uuid` `Uuid`
### Examples ### Examples

View File

@ -21,7 +21,7 @@ getPreviousAdjacentEdge(tag: TagIdentifier) -> Uuid
### Returns ### Returns
`Uuid` `Uuid`
### Examples ### Examples

View File

@ -26,7 +26,7 @@ inch() -> number
### Returns ### Returns
`number` `number`
### Examples ### Examples

View File

@ -9,110 +9,117 @@ layout: manual
* [Types](kcl/types) * [Types](kcl/types)
* [Modules](kcl/modules) * [Modules](kcl/modules)
* [Known Issues](kcl/KNOWN-ISSUES) * [Known Issues](kcl/KNOWN-ISSUES)
* [`abs`](kcl/abs) * **`std`**
* [`acos`](kcl/acos) * [`abs`](kcl/abs)
* [`angleToMatchLengthX`](kcl/angleToMatchLengthX) * [`acos`](kcl/acos)
* [`angleToMatchLengthY`](kcl/angleToMatchLengthY) * [`angleToMatchLengthX`](kcl/angleToMatchLengthX)
* [`angledLine`](kcl/angledLine) * [`angleToMatchLengthY`](kcl/angleToMatchLengthY)
* [`angledLineOfXLength`](kcl/angledLineOfXLength) * [`angledLine`](kcl/angledLine)
* [`angledLineOfYLength`](kcl/angledLineOfYLength) * [`angledLineOfXLength`](kcl/angledLineOfXLength)
* [`angledLineThatIntersects`](kcl/angledLineThatIntersects) * [`angledLineOfYLength`](kcl/angledLineOfYLength)
* [`angledLineToX`](kcl/angledLineToX) * [`angledLineThatIntersects`](kcl/angledLineThatIntersects)
* [`angledLineToY`](kcl/angledLineToY) * [`angledLineToX`](kcl/angledLineToX)
* [`appearance`](kcl/appearance) * [`angledLineToY`](kcl/angledLineToY)
* [`arc`](kcl/arc) * [`appearance`](kcl/appearance)
* [`arcTo`](kcl/arcTo) * [`arc`](kcl/arc)
* [`asin`](kcl/asin) * [`arcTo`](kcl/arcTo)
* [`assert`](kcl/assert) * [`asin`](kcl/asin)
* [`assertEqual`](kcl/assertEqual) * [`assert`](kcl/assert)
* [`assertGreaterThan`](kcl/assertGreaterThan) * [`assertEqual`](kcl/assertEqual)
* [`assertGreaterThanOrEq`](kcl/assertGreaterThanOrEq) * [`assertGreaterThan`](kcl/assertGreaterThan)
* [`assertLessThan`](kcl/assertLessThan) * [`assertGreaterThanOrEq`](kcl/assertGreaterThanOrEq)
* [`assertLessThanOrEq`](kcl/assertLessThanOrEq) * [`assertLessThan`](kcl/assertLessThan)
* [`atan`](kcl/atan) * [`assertLessThanOrEq`](kcl/assertLessThanOrEq)
* [`atan2`](kcl/atan2) * [`atan`](kcl/atan)
* [`bezierCurve`](kcl/bezierCurve) * [`atan2`](kcl/atan2)
* [`ceil`](kcl/ceil) * [`bezierCurve`](kcl/bezierCurve)
* [`chamfer`](kcl/chamfer) * [`ceil`](kcl/ceil)
* [`circle`](kcl/circle) * [`chamfer`](kcl/chamfer)
* [`circleThreePoint`](kcl/circleThreePoint) * [`circle`](kcl/circle)
* [`close`](kcl/close) * [`circleThreePoint`](kcl/circleThreePoint)
* [`cm`](kcl/cm) * [`close`](kcl/close)
* [`cos`](kcl/cos) * [`cm`](kcl/cm)
* [`e`](kcl/e) * [`extrude`](kcl/extrude)
* [`extrude`](kcl/extrude) * [`fillet`](kcl/fillet)
* [`fillet`](kcl/fillet) * [`floor`](kcl/floor)
* [`floor`](kcl/floor) * [`ft`](kcl/ft)
* [`ft`](kcl/ft) * [`getNextAdjacentEdge`](kcl/getNextAdjacentEdge)
* [`getNextAdjacentEdge`](kcl/getNextAdjacentEdge) * [`getOppositeEdge`](kcl/getOppositeEdge)
* [`getOppositeEdge`](kcl/getOppositeEdge) * [`getPreviousAdjacentEdge`](kcl/getPreviousAdjacentEdge)
* [`getPreviousAdjacentEdge`](kcl/getPreviousAdjacentEdge) * [`helix`](kcl/helix)
* [`helix`](kcl/helix) * [`helixRevolutions`](kcl/helixRevolutions)
* [`helixRevolutions`](kcl/helixRevolutions) * [`hole`](kcl/hole)
* [`hole`](kcl/hole) * [`hollow`](kcl/hollow)
* [`hollow`](kcl/hollow) * [`inch`](kcl/inch)
* [`inch`](kcl/inch) * [`lastSegX`](kcl/lastSegX)
* [`lastSegX`](kcl/lastSegX) * [`lastSegY`](kcl/lastSegY)
* [`lastSegY`](kcl/lastSegY) * [`legAngX`](kcl/legAngX)
* [`legAngX`](kcl/legAngX) * [`legAngY`](kcl/legAngY)
* [`legAngY`](kcl/legAngY) * [`legLen`](kcl/legLen)
* [`legLen`](kcl/legLen) * [`line`](kcl/line)
* [`line`](kcl/line) * [`ln`](kcl/ln)
* [`ln`](kcl/ln) * [`loft`](kcl/loft)
* [`loft`](kcl/loft) * [`log`](kcl/log)
* [`log`](kcl/log) * [`log10`](kcl/log10)
* [`log10`](kcl/log10) * [`log2`](kcl/log2)
* [`log2`](kcl/log2) * [`m`](kcl/m)
* [`m`](kcl/m) * [`map`](kcl/map)
* [`map`](kcl/map) * [`max`](kcl/max)
* [`max`](kcl/max) * [`min`](kcl/min)
* [`min`](kcl/min) * [`mirror2d`](kcl/mirror2d)
* [`mirror2d`](kcl/mirror2d) * [`mm`](kcl/mm)
* [`mm`](kcl/mm) * [`offsetPlane`](kcl/offsetPlane)
* [`offsetPlane`](kcl/offsetPlane) * [`patternCircular2d`](kcl/patternCircular2d)
* [`patternCircular2d`](kcl/patternCircular2d) * [`patternCircular3d`](kcl/patternCircular3d)
* [`patternCircular3d`](kcl/patternCircular3d) * [`patternLinear2d`](kcl/patternLinear2d)
* [`patternLinear2d`](kcl/patternLinear2d) * [`patternLinear3d`](kcl/patternLinear3d)
* [`patternLinear3d`](kcl/patternLinear3d) * [`patternTransform`](kcl/patternTransform)
* [`patternTransform`](kcl/patternTransform) * [`patternTransform2d`](kcl/patternTransform2d)
* [`patternTransform2d`](kcl/patternTransform2d) * [`polar`](kcl/polar)
* [`pi`](kcl/pi) * [`polygon`](kcl/polygon)
* [`polar`](kcl/polar) * [`pop`](kcl/pop)
* [`polygon`](kcl/polygon) * [`pow`](kcl/pow)
* [`pop`](kcl/pop) * [`profileStart`](kcl/profileStart)
* [`pow`](kcl/pow) * [`profileStartX`](kcl/profileStartX)
* [`profileStart`](kcl/profileStart) * [`profileStartY`](kcl/profileStartY)
* [`profileStartX`](kcl/profileStartX) * [`push`](kcl/push)
* [`profileStartY`](kcl/profileStartY) * [`reduce`](kcl/reduce)
* [`push`](kcl/push) * [`rem`](kcl/rem)
* [`reduce`](kcl/reduce) * [`revolve`](kcl/revolve)
* [`rem`](kcl/rem) * [`round`](kcl/round)
* [`revolve`](kcl/revolve) * [`segAng`](kcl/segAng)
* [`round`](kcl/round) * [`segEnd`](kcl/segEnd)
* [`segAng`](kcl/segAng) * [`segEndX`](kcl/segEndX)
* [`segEnd`](kcl/segEnd) * [`segEndY`](kcl/segEndY)
* [`segEndX`](kcl/segEndX) * [`segLen`](kcl/segLen)
* [`segEndY`](kcl/segEndY) * [`segStart`](kcl/segStart)
* [`segLen`](kcl/segLen) * [`segStartX`](kcl/segStartX)
* [`segStart`](kcl/segStart) * [`segStartY`](kcl/segStartY)
* [`segStartX`](kcl/segStartX) * [`shell`](kcl/shell)
* [`segStartY`](kcl/segStartY) * [`sqrt`](kcl/sqrt)
* [`shell`](kcl/shell) * [`startProfileAt`](kcl/startProfileAt)
* [`sin`](kcl/sin) * [`startSketchOn`](kcl/startSketchOn)
* [`sqrt`](kcl/sqrt) * [`sweep`](kcl/sweep)
* [`startProfileAt`](kcl/startProfileAt) * [`tangentToEnd`](kcl/tangentToEnd)
* [`startSketchOn`](kcl/startSketchOn) * [`tangentialArc`](kcl/tangentialArc)
* [`sweep`](kcl/sweep) * [`tangentialArcTo`](kcl/tangentialArcTo)
* [`tan`](kcl/tan) * [`tangentialArcToRelative`](kcl/tangentialArcToRelative)
* [`tangentToEnd`](kcl/tangentToEnd) * [`toDegrees`](kcl/toDegrees)
* [`tangentialArc`](kcl/tangentialArc) * [`toRadians`](kcl/toRadians)
* [`tangentialArcTo`](kcl/tangentialArcTo) * [`xLine`](kcl/xLine)
* [`tangentialArcToRelative`](kcl/tangentialArcToRelative) * [`xLineTo`](kcl/xLineTo)
* [`tau`](kcl/tau) * [`yLine`](kcl/yLine)
* [`toDegrees`](kcl/toDegrees) * [`yLineTo`](kcl/yLineTo)
* [`toRadians`](kcl/toRadians) * [`yd`](kcl/yd)
* [`xLine`](kcl/xLine) * **`std::math`**
* [`xLineTo`](kcl/xLineTo) * [`E`](kcl/const_std-math-E)
* [`yLine`](kcl/yLine) * [`PI`](kcl/const_std-math-PI)
* [`yLineTo`](kcl/yLineTo) * [`TAU`](kcl/const_std-math-TAU)
* [`yd`](kcl/yd) * [`cos`](kcl/std-math-cos)
* [`sin`](kcl/std-math-sin)
* [`tan`](kcl/std-math-tan)
* **`std::prelude`**
* [`HALF_TURN`](kcl/const_std-prelude-HALF_TURN)
* [`QUARTER_TURN`](kcl/const_std-prelude-QUARTER_TURN)
* [`THREE_QUARTER_TURN`](kcl/const_std-prelude-THREE_QUARTER_TURN)
* [`ZERO`](kcl/const_std-prelude-ZERO)

View File

@ -27,7 +27,7 @@ int(num: number) -> number
### Returns ### Returns
`number` `number`
### Examples ### Examples

View File

@ -21,7 +21,7 @@ lastSegX(sketch: Sketch) -> number
### Returns ### Returns
`number` `number`
### Examples ### Examples

View File

@ -21,7 +21,7 @@ lastSegY(sketch: Sketch) -> number
### Returns ### Returns
`number` `number`
### Examples ### Examples

View File

@ -26,7 +26,7 @@ legAngX(hypotenuse: number, leg: number) -> number
### Returns ### Returns
`number` `number`
### Examples ### Examples

View File

@ -26,7 +26,7 @@ legAngY(hypotenuse: number, leg: number) -> number
### Returns ### Returns
`number` `number`
### Examples ### Examples

View File

@ -26,7 +26,7 @@ legLen(hypotenuse: number, leg: number) -> number
### Returns ### Returns
`number` `number`
### Examples ### Examples

View File

@ -25,7 +25,7 @@ ln(num: number) -> number
### Returns ### Returns
`number` `number`
### Examples ### Examples

View File

@ -26,7 +26,7 @@ log(num: number, base: number) -> number
### Returns ### Returns
`number` `number`
### Examples ### Examples

View File

@ -25,7 +25,7 @@ log10(num: number) -> number
### Returns ### Returns
`number` `number`
### Examples ### Examples

View File

@ -25,7 +25,7 @@ log2(num: number) -> number
### Returns ### Returns
`number` `number`
### Examples ### Examples

View File

@ -26,7 +26,7 @@ m() -> number
### Returns ### Returns
`number` `number`
### Examples ### Examples

View File

@ -22,7 +22,7 @@ map(array: [KclValue], map_fn: FunctionParam) -> [KclValue]
### Returns ### Returns
[`[KclValue]`](/docs/kcl/types/KclValue) [`[KclValue]`](/docs/kcl/types/KclValue)
### Examples ### Examples

View File

@ -25,7 +25,7 @@ max(args: [number]) -> number
### Returns ### Returns
`number` `number`
### Examples ### Examples

View File

@ -25,7 +25,7 @@ min(args: [number]) -> number
### Returns ### Returns
`number` `number`
### Examples ### Examples

View File

@ -24,7 +24,7 @@ mirror2d(data: Mirror2dData, sketch_set: SketchSet) -> [Sketch]
### Returns ### Returns
[`[Sketch]`](/docs/kcl/types/Sketch) [`[Sketch]`](/docs/kcl/types/Sketch)
### Examples ### Examples

View File

@ -26,7 +26,7 @@ mm() -> number
### Returns ### Returns
`number` `number`
### Examples ### Examples

View File

@ -26,7 +26,7 @@ patternCircular2d(sketch_set: SketchSet, instances: integer, center: [number], a
### Returns ### Returns
[`[Sketch]`](/docs/kcl/types/Sketch) [`[Sketch]`](/docs/kcl/types/Sketch)
### Examples ### Examples

View File

@ -27,7 +27,7 @@ patternCircular3d(solid_set: SolidSet, instances: integer, axis: [number], cente
### Returns ### Returns
[`[Solid]`](/docs/kcl/types/Solid) [`[Solid]`](/docs/kcl/types/Solid)
### Examples ### Examples

View File

@ -25,7 +25,7 @@ patternLinear2d(sketch_set: SketchSet, instances: integer, distance: number, axi
### Returns ### Returns
[`[Sketch]`](/docs/kcl/types/Sketch) [`[Sketch]`](/docs/kcl/types/Sketch)
### Examples ### Examples

View File

@ -25,7 +25,7 @@ patternLinear3d(solid_set: SolidSet, instances: integer, distance: number, axis:
### Returns ### Returns
[`[Solid]`](/docs/kcl/types/Solid) [`[Solid]`](/docs/kcl/types/Solid)
### Examples ### Examples

View File

@ -50,7 +50,7 @@ patternTransform(solid_set: SolidSet, instances: integer, transform: FunctionPar
### Returns ### Returns
[`[Solid]`](/docs/kcl/types/Solid) [`[Solid]`](/docs/kcl/types/Solid)
### Examples ### Examples

View File

@ -24,7 +24,7 @@ patternTransform2d(sketch_set: SketchSet, instances: integer, transform: Functio
### Returns ### Returns
[`[Sketch]`](/docs/kcl/types/Sketch) [`[Sketch]`](/docs/kcl/types/Sketch)
### Examples ### Examples

View File

@ -4,9 +4,11 @@ excerpt: "Return the value of `pi`. Archimedes constant (π)."
layout: manual layout: manual
--- ---
**WARNING:** This function is deprecated.
Return the value of `pi`. Archimedes constant (π). Return the value of `pi`. Archimedes constant (π).
**DEPRECATED** use the constant PI
```js ```js
pi() -> number pi() -> number
@ -20,7 +22,7 @@ pi() -> number
### Returns ### Returns
`number` `number`
### Examples ### Examples

View File

@ -21,7 +21,7 @@ polar(data: PolarCoordsData) -> [number]
### Returns ### Returns
`[number]` `[number]`
### Examples ### Examples

View File

@ -26,7 +26,7 @@ pow(num: number, pow: number) -> number
### Returns ### Returns
`number` `number`
### Examples ### Examples

View File

@ -21,7 +21,7 @@ profileStart(sketch: Sketch) -> [number]
### Returns ### Returns
`[number]` `[number]`
### Examples ### Examples

View File

@ -21,7 +21,7 @@ profileStartX(sketch: Sketch) -> number
### Returns ### Returns
`number` `number`
### Examples ### Examples

View File

@ -21,7 +21,7 @@ profileStartY(sketch: Sketch) -> number
### Returns ### Returns
`number` `number`
### Examples ### Examples

View File

@ -76,7 +76,7 @@ assertEqual(sum, 6, 0.00001, "1 + 2 + 3 summed is 6")
// Declare a function that sketches a decagon. // Declare a function that sketches a decagon.
fn decagon(radius) { fn decagon(radius) {
// Each side of the decagon is turned this many degrees from the previous angle. // Each side of the decagon is turned this many degrees from the previous angle.
stepAngle = 1 / 10 * tau() stepAngle = 1 / 10 * TAU
// Start the decagon sketch at this point. // Start the decagon sketch at this point.
startOfDecagonSketch = startSketchOn('XY') startOfDecagonSketch = startSketchOn('XY')
@ -97,7 +97,7 @@ fn decagon(radius) {
/* The `decagon` above is basically like this pseudo-code: /* The `decagon` above is basically like this pseudo-code:
fn decagon(radius): fn decagon(radius):
stepAngle = (1/10) * tau() stepAngle = (1/10) * TAU
plane = startSketchOn('XY') plane = startSketchOn('XY')
startOfDecagonSketch = startProfileAt([(cos(0)*radius), (sin(0) * radius)], plane) startOfDecagonSketch = startProfileAt([(cos(0)*radius), (sin(0) * radius)], plane)

View File

@ -26,7 +26,7 @@ rem(num: number, divisor: number) -> number
### Returns ### Returns
`number` `number`
### Examples ### Examples

View File

@ -25,7 +25,7 @@ round(num: number) -> number
### Returns ### Returns
`number` `number`
### Examples ### Examples

View File

@ -21,7 +21,7 @@ segAng(tag: TagIdentifier) -> number
### Returns ### Returns
`number` `number`
### Examples ### Examples

View File

@ -21,7 +21,7 @@ segEnd(tag: TagIdentifier) -> [number]
### Returns ### Returns
`[number]` `[number]`
### Examples ### Examples

View File

@ -21,7 +21,7 @@ segEndX(tag: TagIdentifier) -> number
### Returns ### Returns
`number` `number`
### Examples ### Examples

View File

@ -21,7 +21,7 @@ segEndY(tag: TagIdentifier) -> number
### Returns ### Returns
`number` `number`
### Examples ### Examples

View File

@ -21,7 +21,7 @@ segLen(tag: TagIdentifier) -> number
### Returns ### Returns
`number` `number`
### Examples ### Examples

View File

@ -21,7 +21,7 @@ segStart(tag: TagIdentifier) -> [number]
### Returns ### Returns
`[number]` `[number]`
### Examples ### Examples

View File

@ -21,7 +21,7 @@ segStartX(tag: TagIdentifier) -> number
### Returns ### Returns
`number` `number`
### Examples ### Examples

View File

@ -21,7 +21,7 @@ segStartY(tag: TagIdentifier) -> number
### Returns ### Returns
`number` `number`
### Examples ### Examples

File diff suppressed because one or more lines are too long

View File

@ -25,7 +25,7 @@ sqrt(num: number) -> number
### Returns ### Returns
`number` `number`
### Examples ### Examples

44
docs/kcl/std-math-cos.md Normal file

File diff suppressed because one or more lines are too long

44
docs/kcl/std-math-sin.md Normal file

File diff suppressed because one or more lines are too long

44
docs/kcl/std-math-tan.md Normal file

File diff suppressed because one or more lines are too long

View File

@ -83689,52 +83689,10 @@
"totalWidth = 10 * cm()" "totalWidth = 10 * cm()"
] ]
}, },
{
"name": "cos",
"summary": "Compute the cosine of a number (in radians).",
"description": "",
"tags": [
"math"
],
"keywordArguments": false,
"args": [
{
"name": "num",
"type": "number",
"schema": {
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
"title": "double",
"type": "number",
"format": "double"
},
"required": true,
"includeInSnippet": true,
"labelRequired": true
}
],
"returnValue": {
"name": "",
"type": "number",
"schema": {
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
"title": "double",
"type": "number",
"format": "double"
},
"required": true,
"includeInSnippet": true,
"labelRequired": true
},
"unpublished": false,
"deprecated": false,
"examples": [
"exampleSketch = startSketchOn(\"XZ\")\n |> startProfileAt([0, 0], %)\n |> angledLine({\n angle = 30,\n length = 3 / cos(toRadians(30))\n }, %)\n |> yLineTo(0, %)\n |> close()\n\nexample = extrude(exampleSketch, length = 5)"
]
},
{ {
"name": "e", "name": "e",
"summary": "Return the value of Eulers number `e`.", "summary": "Return the value of Eulers number `e`.",
"description": "", "description": "**DEPRECATED** use the constant E",
"tags": [ "tags": [
"math" "math"
], ],
@ -83754,7 +83712,7 @@
"labelRequired": true "labelRequired": true
}, },
"unpublished": false, "unpublished": false,
"deprecated": false, "deprecated": true,
"examples": [ "examples": [
"exampleSketch = startSketchOn(\"XZ\")\n |> startProfileAt([0, 0], %)\n |> angledLine({ angle = 30, length = 2 * e() ^ 2 }, %)\n |> yLineTo(0, %)\n |> close()\n\nexample = extrude(exampleSketch, length = 10)" "exampleSketch = startSketchOn(\"XZ\")\n |> startProfileAt([0, 0], %)\n |> angledLine({ angle = 30, length = 2 * e() ^ 2 }, %)\n |> yLineTo(0, %)\n |> close()\n\nexample = extrude(exampleSketch, length = 10)"
] ]
@ -135417,7 +135375,6 @@
"type": "object", "type": "object",
"required": [ "required": [
"__meta", "__meta",
"memory",
"type" "type"
], ],
"properties": { "properties": {
@ -135428,7 +135385,12 @@
] ]
}, },
"memory": { "memory": {
"$ref": "#/components/schemas/EnvironmentRef" "allOf": [
{
"$ref": "#/components/schemas/EnvironmentRef"
}
],
"nullable": true
}, },
"__meta": { "__meta": {
"type": "array", "type": "array",
@ -138031,7 +137993,6 @@
"type": "object", "type": "object",
"required": [ "required": [
"__meta", "__meta",
"memory",
"type" "type"
], ],
"properties": { "properties": {
@ -138042,7 +138003,12 @@
] ]
}, },
"memory": { "memory": {
"$ref": "#/components/schemas/EnvironmentRef" "allOf": [
{
"$ref": "#/components/schemas/EnvironmentRef"
}
],
"nullable": true
}, },
"__meta": { "__meta": {
"type": "array", "type": "array",
@ -140649,7 +140615,6 @@
"type": "object", "type": "object",
"required": [ "required": [
"__meta", "__meta",
"memory",
"type" "type"
], ],
"properties": { "properties": {
@ -140660,7 +140625,12 @@
] ]
}, },
"memory": { "memory": {
"$ref": "#/components/schemas/EnvironmentRef" "allOf": [
{
"$ref": "#/components/schemas/EnvironmentRef"
}
],
"nullable": true
}, },
"__meta": { "__meta": {
"type": "array", "type": "array",
@ -208035,7 +208005,7 @@
{ {
"name": "pi", "name": "pi",
"summary": "Return the value of `pi`. Archimedes constant (π).", "summary": "Return the value of `pi`. Archimedes constant (π).",
"description": "", "description": "**DEPRECATED** use the constant PI",
"tags": [ "tags": [
"math" "math"
], ],
@ -208055,7 +208025,7 @@
"labelRequired": true "labelRequired": true
}, },
"unpublished": false, "unpublished": false,
"deprecated": false, "deprecated": true,
"examples": [ "examples": [
"circumference = 70\n\nexampleSketch = startSketchOn(\"XZ\")\n |> circle({\n center = [0, 0],\n radius = circumference / (2 * pi())\n }, %)\n\nexample = extrude(exampleSketch, length = 5)" "circumference = 70\n\nexampleSketch = startSketchOn(\"XZ\")\n |> circle({\n center = [0, 0],\n radius = circumference / (2 * pi())\n }, %)\n\nexample = extrude(exampleSketch, length = 5)"
] ]
@ -213842,7 +213812,6 @@
"type": "object", "type": "object",
"required": [ "required": [
"__meta", "__meta",
"memory",
"type" "type"
], ],
"properties": { "properties": {
@ -213853,7 +213822,12 @@
] ]
}, },
"memory": { "memory": {
"$ref": "#/components/schemas/EnvironmentRef" "allOf": [
{
"$ref": "#/components/schemas/EnvironmentRef"
}
],
"nullable": true
}, },
"__meta": { "__meta": {
"type": "array", "type": "array",
@ -216455,7 +216429,6 @@
"type": "object", "type": "object",
"required": [ "required": [
"__meta", "__meta",
"memory",
"type" "type"
], ],
"properties": { "properties": {
@ -216466,7 +216439,12 @@
] ]
}, },
"memory": { "memory": {
"$ref": "#/components/schemas/EnvironmentRef" "allOf": [
{
"$ref": "#/components/schemas/EnvironmentRef"
}
],
"nullable": true
}, },
"__meta": { "__meta": {
"type": "array", "type": "array",
@ -217342,7 +217320,6 @@
"type": "object", "type": "object",
"required": [ "required": [
"__meta", "__meta",
"memory",
"type" "type"
], ],
"properties": { "properties": {
@ -217353,7 +217330,12 @@
] ]
}, },
"memory": { "memory": {
"$ref": "#/components/schemas/EnvironmentRef" "allOf": [
{
"$ref": "#/components/schemas/EnvironmentRef"
}
],
"nullable": true
}, },
"__meta": { "__meta": {
"type": "array", "type": "array",
@ -224740,7 +224722,6 @@
"type": "object", "type": "object",
"required": [ "required": [
"__meta", "__meta",
"memory",
"type" "type"
], ],
"properties": { "properties": {
@ -224751,7 +224732,12 @@
] ]
}, },
"memory": { "memory": {
"$ref": "#/components/schemas/EnvironmentRef" "allOf": [
{
"$ref": "#/components/schemas/EnvironmentRef"
}
],
"nullable": true
}, },
"__meta": { "__meta": {
"type": "array", "type": "array",
@ -227351,7 +227337,6 @@
"type": "object", "type": "object",
"required": [ "required": [
"__meta", "__meta",
"memory",
"type" "type"
], ],
"properties": { "properties": {
@ -227362,7 +227347,12 @@
] ]
}, },
"memory": { "memory": {
"$ref": "#/components/schemas/EnvironmentRef" "allOf": [
{
"$ref": "#/components/schemas/EnvironmentRef"
}
],
"nullable": true
}, },
"__meta": { "__meta": {
"type": "array", "type": "array",
@ -227858,7 +227848,6 @@
"type": "object", "type": "object",
"required": [ "required": [
"__meta", "__meta",
"memory",
"type" "type"
], ],
"properties": { "properties": {
@ -227869,7 +227858,12 @@
] ]
}, },
"memory": { "memory": {
"$ref": "#/components/schemas/EnvironmentRef" "allOf": [
{
"$ref": "#/components/schemas/EnvironmentRef"
}
],
"nullable": true
}, },
"__meta": { "__meta": {
"type": "array", "type": "array",
@ -230470,7 +230464,6 @@
"type": "object", "type": "object",
"required": [ "required": [
"__meta", "__meta",
"memory",
"type" "type"
], ],
"properties": { "properties": {
@ -230481,7 +230474,12 @@
] ]
}, },
"memory": { "memory": {
"$ref": "#/components/schemas/EnvironmentRef" "allOf": [
{
"$ref": "#/components/schemas/EnvironmentRef"
}
],
"nullable": true
}, },
"__meta": { "__meta": {
"type": "array", "type": "array",
@ -231357,7 +231355,6 @@
"type": "object", "type": "object",
"required": [ "required": [
"__meta", "__meta",
"memory",
"type" "type"
], ],
"properties": { "properties": {
@ -231368,7 +231365,12 @@
] ]
}, },
"memory": { "memory": {
"$ref": "#/components/schemas/EnvironmentRef" "allOf": [
{
"$ref": "#/components/schemas/EnvironmentRef"
}
],
"nullable": true
}, },
"__meta": { "__meta": {
"type": "array", "type": "array",
@ -233607,7 +233609,6 @@
"type": "object", "type": "object",
"required": [ "required": [
"__meta", "__meta",
"memory",
"type" "type"
], ],
"properties": { "properties": {
@ -233618,7 +233619,12 @@
] ]
}, },
"memory": { "memory": {
"$ref": "#/components/schemas/EnvironmentRef" "allOf": [
{
"$ref": "#/components/schemas/EnvironmentRef"
}
],
"nullable": true
}, },
"__meta": { "__meta": {
"type": "array", "type": "array",
@ -236218,7 +236224,6 @@
"type": "object", "type": "object",
"required": [ "required": [
"__meta", "__meta",
"memory",
"type" "type"
], ],
"properties": { "properties": {
@ -236229,7 +236234,12 @@
] ]
}, },
"memory": { "memory": {
"$ref": "#/components/schemas/EnvironmentRef" "allOf": [
{
"$ref": "#/components/schemas/EnvironmentRef"
}
],
"nullable": true
}, },
"__meta": { "__meta": {
"type": "array", "type": "array",
@ -236725,7 +236735,6 @@
"type": "object", "type": "object",
"required": [ "required": [
"__meta", "__meta",
"memory",
"type" "type"
], ],
"properties": { "properties": {
@ -236736,7 +236745,12 @@
] ]
}, },
"memory": { "memory": {
"$ref": "#/components/schemas/EnvironmentRef" "allOf": [
{
"$ref": "#/components/schemas/EnvironmentRef"
}
],
"nullable": true
}, },
"__meta": { "__meta": {
"type": "array", "type": "array",
@ -239339,7 +239353,6 @@
"type": "object", "type": "object",
"required": [ "required": [
"__meta", "__meta",
"memory",
"type" "type"
], ],
"properties": { "properties": {
@ -239350,7 +239363,12 @@
] ]
}, },
"memory": { "memory": {
"$ref": "#/components/schemas/EnvironmentRef" "allOf": [
{
"$ref": "#/components/schemas/EnvironmentRef"
}
],
"nullable": true
}, },
"__meta": { "__meta": {
"type": "array", "type": "array",
@ -241951,7 +241969,6 @@
"type": "object", "type": "object",
"required": [ "required": [
"__meta", "__meta",
"memory",
"type" "type"
], ],
"properties": { "properties": {
@ -241962,7 +241979,12 @@
] ]
}, },
"memory": { "memory": {
"$ref": "#/components/schemas/EnvironmentRef" "allOf": [
{
"$ref": "#/components/schemas/EnvironmentRef"
}
],
"nullable": true
}, },
"__meta": { "__meta": {
"type": "array", "type": "array",
@ -242838,7 +242860,6 @@
"type": "object", "type": "object",
"required": [ "required": [
"__meta", "__meta",
"memory",
"type" "type"
], ],
"properties": { "properties": {
@ -242849,7 +242870,12 @@
] ]
}, },
"memory": { "memory": {
"$ref": "#/components/schemas/EnvironmentRef" "allOf": [
{
"$ref": "#/components/schemas/EnvironmentRef"
}
],
"nullable": true
}, },
"__meta": { "__meta": {
"type": "array", "type": "array",
@ -244660,7 +244686,7 @@
"examples": [ "examples": [
"// This function adds two numbers.\nfn add(a, b) {\n return a + b\n}\n\n// This function adds an array of numbers.\n// It uses the `reduce` function, to call the `add` function on every\n// element of the `arr` parameter. The starting value is 0.\nfn sum(arr) {\n return reduce(arr, 0, add)\n}\n\n/* The above is basically like this pseudo-code:\nfn sum(arr):\n sumSoFar = 0\n for i in arr:\n sumSoFar = add(sumSoFar, i)\n return sumSoFar */\n\n\n// We use `assertEqual` to check that our `sum` function gives the\n// expected result. It's good to check your work!\nassertEqual(sum([1, 2, 3]), 6, 0.00001, \"1 + 2 + 3 summed is 6\")", "// This function adds two numbers.\nfn add(a, b) {\n return a + b\n}\n\n// This function adds an array of numbers.\n// It uses the `reduce` function, to call the `add` function on every\n// element of the `arr` parameter. The starting value is 0.\nfn sum(arr) {\n return reduce(arr, 0, add)\n}\n\n/* The above is basically like this pseudo-code:\nfn sum(arr):\n sumSoFar = 0\n for i in arr:\n sumSoFar = add(sumSoFar, i)\n return sumSoFar */\n\n\n// We use `assertEqual` to check that our `sum` function gives the\n// expected result. It's good to check your work!\nassertEqual(sum([1, 2, 3]), 6, 0.00001, \"1 + 2 + 3 summed is 6\")",
"// This example works just like the previous example above, but it uses\n// an anonymous `add` function as its parameter, instead of declaring a\n// named function outside.\narr = [1, 2, 3]\nsum = reduce(arr, 0, fn(i, result_so_far) {\n return i + result_so_far\n})\n\n// We use `assertEqual` to check that our `sum` function gives the\n// expected result. It's good to check your work!\nassertEqual(sum, 6, 0.00001, \"1 + 2 + 3 summed is 6\")", "// This example works just like the previous example above, but it uses\n// an anonymous `add` function as its parameter, instead of declaring a\n// named function outside.\narr = [1, 2, 3]\nsum = reduce(arr, 0, fn(i, result_so_far) {\n return i + result_so_far\n})\n\n// We use `assertEqual` to check that our `sum` function gives the\n// expected result. It's good to check your work!\nassertEqual(sum, 6, 0.00001, \"1 + 2 + 3 summed is 6\")",
"// Declare a function that sketches a decagon.\nfn decagon(radius) {\n // Each side of the decagon is turned this many degrees from the previous angle.\n stepAngle = 1 / 10 * tau()\n\n // Start the decagon sketch at this point.\n startOfDecagonSketch = startSketchOn('XY')\n |> startProfileAt([cos(0) * radius, sin(0) * radius], %)\n\n // Use a `reduce` to draw the remaining decagon sides.\n // For each number in the array 1..10, run the given function,\n // which takes a partially-sketched decagon and adds one more edge to it.\n fullDecagon = reduce([1..10], startOfDecagonSketch, fn(i, partialDecagon) {\n // Draw one edge of the decagon.\n x = cos(stepAngle * i) * radius\n y = sin(stepAngle * i) * radius\n return line(partialDecagon, end = [x, y])\n })\n\n return fullDecagon\n}\n\n/* The `decagon` above is basically like this pseudo-code:\nfn decagon(radius):\n stepAngle = (1/10) * tau()\n plane = startSketchOn('XY')\n startOfDecagonSketch = startProfileAt([(cos(0)*radius), (sin(0) * radius)], plane)\n\n // Here's the reduce part.\n partialDecagon = startOfDecagonSketch\n for i in [1..10]:\n x = cos(stepAngle * i) * radius\n y = sin(stepAngle * i) * radius\n partialDecagon = line(partialDecagon, end = [x, y])\n fullDecagon = partialDecagon // it's now full\n return fullDecagon */\n\n\n// Use the `decagon` function declared above, to sketch a decagon with radius 5.\ndecagon(5.0)\n |> close()" "// Declare a function that sketches a decagon.\nfn decagon(radius) {\n // Each side of the decagon is turned this many degrees from the previous angle.\n stepAngle = 1 / 10 * TAU\n\n // Start the decagon sketch at this point.\n startOfDecagonSketch = startSketchOn('XY')\n |> startProfileAt([cos(0) * radius, sin(0) * radius], %)\n\n // Use a `reduce` to draw the remaining decagon sides.\n // For each number in the array 1..10, run the given function,\n // which takes a partially-sketched decagon and adds one more edge to it.\n fullDecagon = reduce([1..10], startOfDecagonSketch, fn(i, partialDecagon) {\n // Draw one edge of the decagon.\n x = cos(stepAngle * i) * radius\n y = sin(stepAngle * i) * radius\n return line(partialDecagon, end = [x, y])\n })\n\n return fullDecagon\n}\n\n/* The `decagon` above is basically like this pseudo-code:\nfn decagon(radius):\n stepAngle = (1/10) * TAU\n plane = startSketchOn('XY')\n startOfDecagonSketch = startProfileAt([(cos(0)*radius), (sin(0) * radius)], plane)\n\n // Here's the reduce part.\n partialDecagon = startOfDecagonSketch\n for i in [1..10]:\n x = cos(stepAngle * i) * radius\n y = sin(stepAngle * i) * radius\n partialDecagon = line(partialDecagon, end = [x, y])\n fullDecagon = partialDecagon // it's now full\n return fullDecagon */\n\n\n// Use the `decagon` function declared above, to sketch a decagon with radius 5.\ndecagon(5.0)\n |> close()"
] ]
}, },
{ {
@ -265136,48 +265162,6 @@
"// Shell sketched on face objects on the end face, include all sketches to shell\n// the entire object.\n\n\nsize = 100\ncase = startSketchOn('XY')\n |> startProfileAt([-size, -size], %)\n |> line(end = [2 * size, 0])\n |> line(end = [0, 2 * size])\n |> tangentialArcTo([-size, size], %)\n |> close()\n |> extrude(length = 65)\n\nthing1 = startSketchOn(case, 'end')\n |> circle({\n center = [-size / 2, -size / 2],\n radius = 25\n }, %)\n |> extrude(length = 50)\n\nthing2 = startSketchOn(case, 'end')\n |> circle({\n center = [size / 2, -size / 2],\n radius = 25\n }, %)\n |> extrude(length = 50)\n\n// We put \"thing1\" and \"thing2\" in the shell function to shell the end face of the object.\nshell([thing1, thing2], faces = ['end'], thickness = 5)" "// Shell sketched on face objects on the end face, include all sketches to shell\n// the entire object.\n\n\nsize = 100\ncase = startSketchOn('XY')\n |> startProfileAt([-size, -size], %)\n |> line(end = [2 * size, 0])\n |> line(end = [0, 2 * size])\n |> tangentialArcTo([-size, size], %)\n |> close()\n |> extrude(length = 65)\n\nthing1 = startSketchOn(case, 'end')\n |> circle({\n center = [-size / 2, -size / 2],\n radius = 25\n }, %)\n |> extrude(length = 50)\n\nthing2 = startSketchOn(case, 'end')\n |> circle({\n center = [size / 2, -size / 2],\n radius = 25\n }, %)\n |> extrude(length = 50)\n\n// We put \"thing1\" and \"thing2\" in the shell function to shell the end face of the object.\nshell([thing1, thing2], faces = ['end'], thickness = 5)"
] ]
}, },
{
"name": "sin",
"summary": "Compute the sine of a number (in radians).",
"description": "",
"tags": [
"math"
],
"keywordArguments": false,
"args": [
{
"name": "num",
"type": "number",
"schema": {
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
"title": "double",
"type": "number",
"format": "double"
},
"required": true,
"includeInSnippet": true,
"labelRequired": true
}
],
"returnValue": {
"name": "",
"type": "number",
"schema": {
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
"title": "double",
"type": "number",
"format": "double"
},
"required": true,
"includeInSnippet": true,
"labelRequired": true
},
"unpublished": false,
"deprecated": false,
"examples": [
"exampleSketch = startSketchOn(\"XZ\")\n |> startProfileAt([0, 0], %)\n |> angledLine({\n angle = 50,\n length = 15 / sin(toDegrees(135))\n }, %)\n |> yLineTo(0, %)\n |> close()\n\nexample = extrude(exampleSketch, length = 5)"
]
},
{ {
"name": "sqrt", "name": "sqrt",
"summary": "Compute the square root of a number.", "summary": "Compute the square root of a number.",
@ -285689,48 +285673,6 @@
"// Create a spring by sweeping around a helix path.\n\n\n// Create a helix around the Z axis.\nhelixPath = helix(\n angleStart = 0,\n ccw = true,\n revolutions = 4,\n length = 10,\n radius = 5,\n axis = 'Z',\n)\n\n// Create a spring by sweeping around the helix path.\nspringSketch = startSketchOn('YZ')\n |> circle({ center = [0, 0], radius = 1 }, %)\n |> sweep(path = helixPath)" "// Create a spring by sweeping around a helix path.\n\n\n// Create a helix around the Z axis.\nhelixPath = helix(\n angleStart = 0,\n ccw = true,\n revolutions = 4,\n length = 10,\n radius = 5,\n axis = 'Z',\n)\n\n// Create a spring by sweeping around the helix path.\nspringSketch = startSketchOn('YZ')\n |> circle({ center = [0, 0], radius = 1 }, %)\n |> sweep(path = helixPath)"
] ]
}, },
{
"name": "tan",
"summary": "Compute the tangent of a number (in radians).",
"description": "",
"tags": [
"math"
],
"keywordArguments": false,
"args": [
{
"name": "num",
"type": "number",
"schema": {
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
"title": "double",
"type": "number",
"format": "double"
},
"required": true,
"includeInSnippet": true,
"labelRequired": true
}
],
"returnValue": {
"name": "",
"type": "number",
"schema": {
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
"title": "double",
"type": "number",
"format": "double"
},
"required": true,
"includeInSnippet": true,
"labelRequired": true
},
"unpublished": false,
"deprecated": false,
"examples": [
"exampleSketch = startSketchOn(\"XZ\")\n |> startProfileAt([0, 0], %)\n |> angledLine({ angle = 50, length = 50 * tan(1 / 2) }, %)\n |> yLineTo(0, %)\n |> close()\n\nexample = extrude(exampleSketch, length = 5)"
]
},
{ {
"name": "tangentToEnd", "name": "tangentToEnd",
"summary": "Returns the angle coming out of the end of the segment in degrees.", "summary": "Returns the angle coming out of the end of the segment in degrees.",
@ -301795,7 +301737,7 @@
{ {
"name": "tau", "name": "tau",
"summary": "Return the value of `tau`. The full circle constant (τ). Equal to 2π.", "summary": "Return the value of `tau`. The full circle constant (τ). Equal to 2π.",
"description": "", "description": "**DEPRECATED** use the constant TAU",
"tags": [ "tags": [
"math" "math"
], ],
@ -301815,7 +301757,7 @@
"labelRequired": true "labelRequired": true
}, },
"unpublished": false, "unpublished": false,
"deprecated": false, "deprecated": true,
"examples": [ "examples": [
"exampleSketch = startSketchOn(\"XZ\")\n |> startProfileAt([0, 0], %)\n |> angledLine({ angle = 50, length = 10 * tau() }, %)\n |> yLineTo(0, %)\n |> close()\n\nexample = extrude(exampleSketch, length = 5)" "exampleSketch = startSketchOn(\"XZ\")\n |> startProfileAt([0, 0], %)\n |> angledLine({ angle = 50, length = 10 * tau() }, %)\n |> yLineTo(0, %)\n |> close()\n\nexample = extrude(exampleSketch, length = 5)"
] ]

File diff suppressed because one or more lines are too long

View File

@ -21,7 +21,7 @@ tangentToEnd(tag: TagIdentifier) -> number
### Returns ### Returns
`number` `number`
### Examples ### Examples

View File

@ -4,9 +4,11 @@ excerpt: "Return the value of `tau`. The full circle constant (τ). Equal to 2π
layout: manual layout: manual
--- ---
**WARNING:** This function is deprecated.
Return the value of `tau`. The full circle constant (τ). Equal to 2π. Return the value of `tau`. The full circle constant (τ). Equal to 2π.
**DEPRECATED** use the constant TAU
```js ```js
tau() -> number tau() -> number
@ -20,7 +22,7 @@ tau() -> number
### Returns ### Returns
`number` `number`
### Examples ### Examples

View File

@ -25,7 +25,7 @@ toDegrees(num: number) -> number
### Returns ### Returns
`number` `number`
### Examples ### Examples

View File

@ -25,7 +25,7 @@ toRadians(num: number) -> number
### Returns ### Returns
`number` `number`
### Examples ### Examples

View File

@ -295,7 +295,7 @@ Data for an imported geometry.
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `type` |enum: `Function`| | No | | `type` |enum: `Function`| | No |
| `memory` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| Any KCL value. | No | | `memory` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No | | `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |

View File

@ -26,7 +26,7 @@ yd() -> number
### Returns ### Returns
`number` `number`
### Examples ### Examples

View File

@ -33,49 +33,45 @@ describe('processMemory', () => {
const output = processMemory(execState.variables) const output = processMemory(execState.variables)
expect(output.myVar).toEqual(5) expect(output.myVar).toEqual(5)
expect(output.otherVar).toEqual(3) expect(output.otherVar).toEqual(3)
expect(output).toEqual({ expect(output.myFn).toEqual('__function(a)__')
myVar: 5, expect(output.theExtrude).toEqual([
myFn: '__function(a)__', {
otherVar: 3, type: 'extrudePlane',
theExtrude: [ tag: null,
{ id: expect.any(String),
type: 'extrudePlane', faceId: expect.any(String),
tag: null, sourceRange: [expect.any(Number), expect.any(Number), 0],
id: expect.any(String), },
faceId: expect.any(String), {
sourceRange: [expect.any(Number), expect.any(Number), 0], type: 'extrudePlane',
}, tag: null,
{ id: expect.any(String),
type: 'extrudePlane', faceId: expect.any(String),
tag: null, sourceRange: [expect.any(Number), expect.any(Number), 0],
id: expect.any(String), },
faceId: expect.any(String), ])
sourceRange: [expect.any(Number), expect.any(Number), 0], expect(output.theSketch).toEqual([
}, {
], type: 'ToPoint',
theSketch: [ to: [-3.35, 0.17],
{ from: [0, 0],
type: 'ToPoint', units: { type: 'Mm' },
to: [-3.35, 0.17], tag: null,
from: [0, 0], },
units: { type: 'Mm' }, {
tag: null, type: 'ToPoint',
}, to: [0.98, 5.16],
{ from: [-3.35, 0.17],
type: 'ToPoint', units: { type: 'Mm' },
to: [0.98, 5.16], tag: null,
from: [-3.35, 0.17], },
units: { type: 'Mm' }, {
tag: null, type: 'ToPoint',
}, to: [2.15, 4.32],
{ from: [0.98, 5.16],
type: 'ToPoint', units: { type: 'Mm' },
to: [2.15, 4.32], tag: null,
from: [0.98, 5.16], },
units: { type: 'Mm' }, ])
tag: null,
},
],
})
}) })
}) })

View File

@ -57,6 +57,7 @@ export function UnitsMenu() {
const newCode = changeKclSettings(codeManager.code, { const newCode = changeKclSettings(codeManager.code, {
defaultLengthUnits: unitLengthToUnitLen(unit), defaultLengthUnits: unitLengthToUnitLen(unit),
defaultAngleUnits: { type: 'Degrees' }, defaultAngleUnits: { type: 'Degrees' },
stdPath: null,
}) })
if (err(newCode)) { if (err(newCode)) {
toast.error( toast.error(

View File

@ -1,4 +1,4 @@
use std::collections::BTreeMap; use std::collections::{BTreeMap, HashMap};
use anyhow::Result; use anyhow::Result;
use base64::Engine; use base64::Engine;
@ -13,6 +13,8 @@ use crate::{
std::StdLib, std::StdLib,
}; };
use super::kcl_doc::{ConstData, DocData, FnData};
const TYPES_DIR: &str = "../../../docs/kcl/types"; const TYPES_DIR: &str = "../../../docs/kcl/types";
fn init_handlebars() -> Result<handlebars::Handlebars<'static>> { fn init_handlebars() -> Result<handlebars::Handlebars<'static>> {
@ -289,17 +291,19 @@ fn init_handlebars() -> Result<handlebars::Handlebars<'static>> {
hbs.register_template_string("schema", include_str!("templates/schema.hbs"))?; hbs.register_template_string("schema", include_str!("templates/schema.hbs"))?;
hbs.register_template_string("index", include_str!("templates/index.hbs"))?; hbs.register_template_string("index", include_str!("templates/index.hbs"))?;
hbs.register_template_string("function", include_str!("templates/function.hbs"))?; hbs.register_template_string("function", include_str!("templates/function.hbs"))?;
hbs.register_template_string("const", include_str!("templates/const.hbs"))?;
hbs.register_template_string("type", include_str!("templates/type.hbs"))?; hbs.register_template_string("type", include_str!("templates/type.hbs"))?;
Ok(hbs) Ok(hbs)
} }
fn generate_index(combined: &IndexMap<String, Box<dyn StdLibFn>>) -> Result<()> { fn generate_index(combined: &IndexMap<String, Box<dyn StdLibFn>>, kcl_lib: &[DocData]) -> Result<()> {
let hbs = init_handlebars()?; let hbs = init_handlebars()?;
let mut functions = Vec::new(); let mut functions = HashMap::new();
functions.insert("std".to_owned(), Vec::new());
for key in combined.keys().sorted() { for key in combined.keys() {
let internal_fn = combined let internal_fn = combined
.get(key) .get(key)
.ok_or_else(|| anyhow::anyhow!("Failed to get internal function: {}", key))?; .ok_or_else(|| anyhow::anyhow!("Failed to get internal function: {}", key))?;
@ -308,13 +312,41 @@ fn generate_index(combined: &IndexMap<String, Box<dyn StdLibFn>>) -> Result<()>
continue; continue;
} }
functions.push(json!({ functions
"name": internal_fn.name(), .get_mut("std")
})); .unwrap()
.push((internal_fn.name(), internal_fn.name()));
} }
for d in kcl_lib {
if d.hide() {
continue;
}
functions.entry(d.mod_name()).or_default().push(match d {
DocData::Fn(f) => (f.name.clone(), d.file_name()),
DocData::Const(c) => (c.name.clone(), d.file_name()),
});
}
let mut sorted: Vec<_> = functions
.into_iter()
.map(|(m, mut fns)| {
fns.sort();
let val = json!({
"name": m,
"functions": fns.into_iter().map(|(n, f)| json!({
"name": n,
"file_name": f,
})).collect::<Vec<_>>(),
});
(m, val)
})
.collect();
sorted.sort_by(|t1, t2| t1.0.cmp(&t2.0));
let data: Vec<_> = sorted.into_iter().map(|(_, val)| val).collect();
let data = json!({ let data = json!({
"functions": functions, "modules": data,
}); });
let output = hbs.render("index", &data)?; let output = hbs.render("index", &data)?;
@ -324,6 +356,112 @@ fn generate_index(combined: &IndexMap<String, Box<dyn StdLibFn>>) -> Result<()>
Ok(()) Ok(())
} }
fn generate_function_from_kcl(function: &FnData, file_name: String) -> Result<()> {
if function.properties.doc_hidden {
return Ok(());
}
let hbs = init_handlebars()?;
let name = function.name.clone();
let examples: Vec<serde_json::Value> = function
.examples
.iter()
.enumerate()
.map(|(index, example)| {
let image_path = format!(
"{}/tests/outputs/serial_test_example_{}{}.png",
env!("CARGO_MANIFEST_DIR"),
file_name,
index
);
let image_data =
std::fs::read(&image_path).unwrap_or_else(|_| panic!("Failed to read image file: {}", image_path));
let image_base64 = base64::engine::general_purpose::STANDARD.encode(&image_data);
json!({
"content": example,
"image_base64": image_base64,
})
})
.collect();
let data = json!({
"name": function.qual_name,
"summary": function.summary,
"description": function.description,
"deprecated": function.properties.deprecated,
"fn_signature": name.clone() + &function.fn_signature(),
"tags": [],
"examples": examples,
"is_utilities": false,
"args": function.args.iter().map(|arg| {
json!({
"name": arg.name,
"type_": arg.ty,
"description": arg.docs.as_deref().unwrap_or(""),
"required": arg.kind.required(),
})
}).collect::<Vec<_>>(),
"return_value": function.return_type.as_ref().map(|t| {
json!({
"type_": t,
"description": "",
})
}),
});
let output = hbs.render("function", &data)?;
expectorate::assert_contents(format!("../../../docs/kcl/{}.md", file_name), &output);
Ok(())
}
fn generate_const_from_kcl(cnst: &ConstData, file_name: String) -> Result<()> {
if cnst.properties.doc_hidden {
return Ok(());
}
let hbs = init_handlebars()?;
let examples: Vec<serde_json::Value> = cnst
.examples
.iter()
.enumerate()
.map(|(index, example)| {
let image_path = format!(
"{}/tests/outputs/serial_test_example_{}{}.png",
env!("CARGO_MANIFEST_DIR"),
file_name,
index
);
let image_data =
std::fs::read(&image_path).unwrap_or_else(|_| panic!("Failed to read image file: {}", image_path));
let image_base64 = base64::engine::general_purpose::STANDARD.encode(&image_data);
json!({
"content": example,
"image_base64": image_base64,
})
})
.collect();
let data = json!({
"name": cnst.qual_name,
"summary": cnst.summary,
"description": cnst.description,
"deprecated": cnst.properties.deprecated,
"type_": cnst.ty,
"examples": examples,
"value": cnst.value.as_deref().unwrap_or(""),
});
let output = hbs.render("const", &data)?;
expectorate::assert_contents(format!("../../../docs/kcl/const_{}.md", file_name), &output);
Ok(())
}
fn generate_function(internal_fn: Box<dyn StdLibFn>) -> Result<BTreeMap<String, schemars::schema::Schema>> { fn generate_function(internal_fn: Box<dyn StdLibFn>) -> Result<BTreeMap<String, schemars::schema::Schema>> {
let hbs = init_handlebars()?; let hbs = init_handlebars()?;
@ -802,9 +940,10 @@ fn recurse_and_create_references(
fn test_generate_stdlib_markdown_docs() { fn test_generate_stdlib_markdown_docs() {
let stdlib = StdLib::new(); let stdlib = StdLib::new();
let combined = stdlib.combined(); let combined = stdlib.combined();
let kcl_std = crate::docs::kcl_doc::walk_prelude();
// Generate the index which is the table of contents. // Generate the index which is the table of contents.
generate_index(&combined).unwrap(); generate_index(&combined, &kcl_std).unwrap();
let mut types = BTreeMap::new(); let mut types = BTreeMap::new();
for key in combined.keys().sorted() { for key in combined.keys().sorted() {
@ -817,6 +956,13 @@ fn test_generate_stdlib_markdown_docs() {
for (name, schema) in &types { for (name, schema) in &types {
generate_type(name, schema, &types).unwrap(); generate_type(name, schema, &types).unwrap();
} }
for d in &kcl_std {
match d {
DocData::Fn(f) => generate_function_from_kcl(f, d.file_name()).unwrap(),
DocData::Const(c) => generate_const_from_kcl(c, d.file_name()).unwrap(),
}
}
} }
#[test] #[test]

View File

@ -0,0 +1,704 @@
use tower_lsp::lsp_types::{
CompletionItem, CompletionItemKind, CompletionItemLabelDetails, Documentation, InsertTextFormat, MarkupContent,
MarkupKind, ParameterInformation, ParameterLabel, SignatureHelp, SignatureInformation,
};
use crate::{
parsing::{
ast::types::{Annotation, Node, NonCodeNode, NonCodeValue, VariableKind},
token::NumericSuffix,
},
ModuleId,
};
pub fn walk_prelude() -> Vec<DocData> {
let mut visitor = CollectionVisitor::default();
visitor.visit_module("prelude").unwrap();
visitor.result
}
#[derive(Debug, Clone, Default)]
struct CollectionVisitor {
name: String,
result: Vec<DocData>,
id: usize,
}
impl CollectionVisitor {
fn visit_module(&mut self, name: &str) -> Result<(), String> {
let old_name = std::mem::replace(&mut self.name, name.to_owned());
let source = crate::modules::read_std(name).unwrap();
let parsed = crate::parsing::parse_str(source, ModuleId::from_usize(self.id))
.parse_errs_as_err()
.unwrap();
self.id += 1;
for (i, n) in parsed.body.iter().enumerate() {
match n {
crate::parsing::ast::types::BodyItem::ImportStatement(import) if !import.visibility.is_default() => {
// Only supports glob imports for now.
assert!(matches!(
import.selector,
crate::parsing::ast::types::ImportSelector::Glob(..)
));
match &import.path {
crate::parsing::ast::types::ImportPath::Std { path } => {
self.visit_module(&path[1])?;
}
p => return Err(format!("Unexpected import: `{p}`")),
}
}
crate::parsing::ast::types::BodyItem::VariableDeclaration(var) if !var.visibility.is_default() => {
let mut dd = match var.kind {
// TODO metadata for args
VariableKind::Fn => DocData::Fn(FnData::from_ast(var, format!("std::{}::", self.name))),
VariableKind::Const => {
DocData::Const(ConstData::from_ast(var, format!("std::{}::", self.name)))
}
};
// FIXME this association of metadata with items is pretty flaky.
if i == 0 {
dd.with_meta(&parsed.non_code_meta.start_nodes, &var.outer_attrs);
} else if let Some(meta) = parsed.non_code_meta.non_code_nodes.get(&(i - 1)) {
dd.with_meta(meta, &var.outer_attrs);
}
self.result.push(dd);
}
_ => {}
}
}
self.name = old_name;
Ok(())
}
}
#[derive(Debug, Clone)]
pub enum DocData {
Fn(FnData),
Const(ConstData),
}
impl DocData {
pub fn name(&self) -> &str {
match self {
DocData::Fn(f) => &f.name,
DocData::Const(c) => &c.name,
}
}
#[allow(dead_code)]
pub fn file_name(&self) -> String {
match self {
DocData::Fn(f) => f.qual_name.replace("::", "-"),
DocData::Const(c) => format!("const_{}", c.qual_name.replace("::", "-")),
}
}
#[allow(dead_code)]
pub fn mod_name(&self) -> String {
let q = match self {
DocData::Fn(f) => &f.qual_name,
DocData::Const(c) => &c.qual_name,
};
q[0..q.rfind("::").unwrap()].to_owned()
}
#[allow(dead_code)]
pub fn hide(&self) -> bool {
match self {
DocData::Fn(f) => f.properties.doc_hidden || f.properties.deprecated,
DocData::Const(c) => c.properties.doc_hidden || c.properties.deprecated,
}
}
pub fn to_completion_item(&self) -> CompletionItem {
match self {
DocData::Fn(f) => f.to_completion_item(),
DocData::Const(c) => c.to_completion_item(),
}
}
pub fn to_signature_help(&self) -> Option<SignatureHelp> {
match self {
DocData::Fn(f) => Some(f.to_signature_help()),
DocData::Const(_) => None,
}
}
fn with_meta(&mut self, meta: &[Node<NonCodeNode>], attrs: &[Node<Annotation>]) {
match self {
DocData::Fn(f) => f.with_meta(meta, attrs),
DocData::Const(c) => c.with_meta(meta, attrs),
}
}
#[cfg(test)]
fn examples(&self) -> &[String] {
match self {
DocData::Fn(f) => &f.examples,
DocData::Const(c) => &c.examples,
}
}
}
#[derive(Debug, Clone)]
pub struct ConstData {
pub name: String,
/// The fully qualified name.
pub qual_name: String,
pub value: Option<String>,
pub ty: Option<String>,
pub properties: Properties,
/// The summary of the function.
pub summary: Option<String>,
/// The description of the function.
pub description: Option<String>,
/// Code examples.
/// These are tested and we know they compile and execute.
pub examples: Vec<String>,
}
impl ConstData {
fn from_ast(var: &crate::parsing::ast::types::VariableDeclaration, mut qual_name: String) -> Self {
assert_eq!(var.kind, crate::parsing::ast::types::VariableKind::Const);
let (value, ty) = match &var.declaration.init {
crate::parsing::ast::types::Expr::Literal(lit) => (
Some(lit.raw.clone()),
Some(match &lit.value {
crate::parsing::ast::types::LiteralValue::Number { suffix, .. } => {
if *suffix == NumericSuffix::None || *suffix == NumericSuffix::Count {
"number".to_owned()
} else {
format!("number({suffix})")
}
}
crate::parsing::ast::types::LiteralValue::String { .. } => "string".to_owned(),
crate::parsing::ast::types::LiteralValue::Bool { .. } => "boolean".to_owned(),
}),
),
_ => (None, None),
};
let name = var.declaration.id.name.clone();
qual_name.push_str(&name);
ConstData {
name,
qual_name,
value,
// TODO use type decl when we have them.
ty,
properties: Properties {
exported: !var.visibility.is_default(),
deprecated: false,
doc_hidden: false,
impl_kind: ImplKind::Kcl,
},
summary: None,
description: None,
examples: Vec::new(),
}
}
fn short_docs(&self) -> Option<String> {
match (&self.summary, &self.description) {
(None, None) => None,
(None, Some(d)) | (Some(d), None) => Some(d.clone()),
(Some(s), Some(d)) => Some(format!("{s}\n\n{d}")),
}
}
fn to_completion_item(&self) -> CompletionItem {
let mut detail = self.qual_name.clone();
if let Some(ty) = &self.ty {
detail.push_str(": ");
detail.push_str(ty);
}
CompletionItem {
label: self.name.clone(),
label_details: Some(CompletionItemLabelDetails {
detail: self.value.clone(),
description: None,
}),
kind: Some(CompletionItemKind::CONSTANT),
detail: Some(detail),
documentation: self.short_docs().map(|s| {
Documentation::MarkupContent(MarkupContent {
kind: MarkupKind::Markdown,
value: s,
})
}),
deprecated: Some(self.properties.deprecated),
preselect: None,
sort_text: None,
filter_text: None,
insert_text: None,
insert_text_format: None,
insert_text_mode: None,
text_edit: None,
additional_text_edits: None,
command: None,
commit_characters: None,
data: None,
tags: None,
}
}
}
#[derive(Debug, Clone)]
pub struct FnData {
/// The name of the function.
pub name: String,
/// The fully qualified name.
pub qual_name: String,
/// The args of the function.
pub args: Vec<ArgData>,
/// The return value of the function.
pub return_type: Option<String>,
pub properties: Properties,
/// The summary of the function.
pub summary: Option<String>,
/// The description of the function.
pub description: Option<String>,
/// Code examples.
/// These are tested and we know they compile and execute.
pub examples: Vec<String>,
}
impl FnData {
fn from_ast(var: &crate::parsing::ast::types::VariableDeclaration, mut qual_name: String) -> Self {
assert_eq!(var.kind, crate::parsing::ast::types::VariableKind::Fn);
let crate::parsing::ast::types::Expr::FunctionExpression(expr) = &var.declaration.init else {
unreachable!();
};
let name = var.declaration.id.name.clone();
qual_name.push_str(&name);
FnData {
name,
qual_name,
args: expr.params.iter().map(ArgData::from_ast).collect(),
return_type: expr.return_type.as_ref().map(|t| t.recast(&Default::default(), 0)),
properties: Properties {
exported: !var.visibility.is_default(),
deprecated: false,
doc_hidden: false,
impl_kind: ImplKind::Kcl,
},
summary: None,
description: None,
examples: Vec::new(),
}
}
fn short_docs(&self) -> Option<String> {
match (&self.summary, &self.description) {
(None, None) => None,
(None, Some(d)) | (Some(d), None) => Some(d.clone()),
(Some(s), Some(d)) => Some(format!("{s}\n\n{d}")),
}
}
pub fn fn_signature(&self) -> String {
let mut signature = String::new();
signature.push('(');
for (i, arg) in self.args.iter().enumerate() {
if i > 0 {
signature.push_str(", ");
}
match &arg.kind {
ArgKind::Special => signature.push_str(&format!("@{}", arg.name)),
ArgKind::Labelled(false) => signature.push_str(&arg.name),
ArgKind::Labelled(true) => signature.push_str(&format!("{}?", arg.name)),
}
if let Some(ty) = &arg.ty {
signature.push_str(&format!(": {ty}"));
}
}
signature.push(')');
if let Some(ty) = &self.return_type {
signature.push_str(&format!(": {ty}"));
}
signature
}
fn to_completion_item(&self) -> CompletionItem {
CompletionItem {
label: self.name.clone(),
label_details: Some(CompletionItemLabelDetails {
detail: Some(self.fn_signature()),
description: None,
}),
kind: Some(CompletionItemKind::FUNCTION),
detail: Some(self.qual_name.clone()),
documentation: self.short_docs().map(|s| {
Documentation::MarkupContent(MarkupContent {
kind: MarkupKind::Markdown,
value: s,
})
}),
deprecated: Some(self.properties.deprecated),
preselect: None,
sort_text: None,
filter_text: None,
insert_text: Some(self.to_autocomplete_snippet()),
insert_text_format: Some(InsertTextFormat::SNIPPET),
insert_text_mode: None,
text_edit: None,
additional_text_edits: None,
command: None,
commit_characters: None,
data: None,
tags: None,
}
}
fn to_autocomplete_snippet(&self) -> String {
if self.name == "loft" {
return "loft([${0:sketch000}, ${1:sketch001}])${}".to_owned();
} else if self.name == "hole" {
return "hole(${0:holeSketch}, ${1:%})${}".to_owned();
}
let mut args = Vec::new();
let mut index = 0;
for arg in self.args.iter() {
if let Some((i, arg_str)) = arg.get_autocomplete_snippet(index) {
index = i + 1;
args.push(arg_str);
}
}
// We end with ${} so you can jump to the end of the snippet.
// After the last argument.
format!("{}({})${{}}", self.name, args.join(", "))
}
fn to_signature_help(&self) -> SignatureHelp {
// TODO Fill this in based on the current position of the cursor.
let active_parameter = None;
SignatureHelp {
signatures: vec![SignatureInformation {
label: self.name.clone(),
documentation: self.short_docs().map(|s| {
Documentation::MarkupContent(MarkupContent {
kind: MarkupKind::Markdown,
value: s,
})
}),
parameters: Some(self.args.iter().map(|arg| arg.to_param_info()).collect()),
active_parameter,
}],
active_signature: Some(0),
active_parameter,
}
}
}
#[derive(Debug, Clone)]
pub struct Properties {
pub deprecated: bool,
pub doc_hidden: bool,
#[allow(dead_code)]
pub exported: bool,
pub impl_kind: ImplKind,
}
#[derive(Debug, Clone)]
pub enum ImplKind {
Kcl,
Rust,
}
#[derive(Debug, Clone)]
pub struct ArgData {
/// The name of the argument.
pub name: String,
/// The type of the argument.
pub ty: Option<String>,
/// If the argument is required.
pub kind: ArgKind,
/// Additional information that could be used instead of the type's description.
/// This is helpful if the type is really basic, like "u32" -- that won't tell the user much about
/// how this argument is meant to be used.
pub docs: Option<String>,
}
#[derive(Debug, Clone, Copy)]
pub enum ArgKind {
Special,
// Parameter is whether the arg is optional.
// TODO should store default value if present
Labelled(bool),
}
impl ArgData {
fn from_ast(arg: &crate::parsing::ast::types::Parameter) -> Self {
ArgData {
name: arg.identifier.name.clone(),
ty: arg.type_.as_ref().map(|t| t.recast(&Default::default(), 0)),
// Doc comments are not yet supported on parameters.
docs: None,
kind: if arg.labeled {
ArgKind::Labelled(arg.optional())
} else {
ArgKind::Special
},
}
}
fn _with_meta(&mut self, _meta: &[Node<NonCodeNode>]) {
// TODO use comments for docs (we can't currently get the comments for an argument)
}
pub fn get_autocomplete_snippet(&self, index: usize) -> Option<(usize, String)> {
match &self.ty {
Some(s)
if [
"Sketch",
"SketchSet",
"Solid",
"SolidSet",
"SketchSurface",
"SketchOrSurface",
]
.contains(&&**s) =>
{
Some((index, format!("${{{}:{}}}", index, "%")))
}
_ => None,
}
}
fn to_param_info(&self) -> ParameterInformation {
ParameterInformation {
label: ParameterLabel::Simple(self.name.clone()),
documentation: self.docs.as_ref().map(|docs| {
Documentation::MarkupContent(MarkupContent {
kind: MarkupKind::Markdown,
value: docs.clone(),
})
}),
}
}
}
impl ArgKind {
#[allow(dead_code)]
pub fn required(self) -> bool {
match self {
ArgKind::Special => true,
ArgKind::Labelled(opt) => !opt,
}
}
}
trait ApplyMeta {
fn apply_docs(&mut self, summary: Option<String>, description: Option<String>, examples: Vec<String>);
fn deprecated(&mut self, deprecated: bool);
fn doc_hidden(&mut self, doc_hidden: bool);
fn impl_kind(&mut self, impl_kind: ImplKind);
fn with_meta(&mut self, meta: &[Node<NonCodeNode>], attrs: &[Node<Annotation>]) {
for attr in attrs {
if let Annotation {
name: None,
properties: Some(props),
..
} = &attr.inner
{
for p in props {
match &*p.key.name {
"impl" => {
if let Some(s) = p.value.ident_name() {
self.impl_kind(match s {
"kcl" => ImplKind::Kcl,
"std_rust" => ImplKind::Rust,
_ => unreachable!(),
});
}
}
"deprecated" => {
if let Some(b) = p.value.literal_bool() {
self.deprecated(b);
}
}
"doc_hidden" => {
if let Some(b) = p.value.literal_bool() {
self.doc_hidden(b);
}
}
_ => {}
}
}
}
}
let mut comments = Vec::new();
for m in meta {
match &m.value {
NonCodeValue::BlockComment { value, .. } | NonCodeValue::NewLineBlockComment { value, .. } => {
comments.push(value)
}
_ => {}
}
}
let mut summary = None;
let mut description = None;
let mut example: Option<String> = None;
let mut examples = Vec::new();
for l in comments.into_iter().filter(|l| l.starts_with('/')).map(|l| {
if let Some(ll) = l.strip_prefix("/ ") {
ll
} else {
&l[1..]
}
}) {
if description.is_none() && summary.is_none() {
summary = Some(l.to_owned());
continue;
}
if description.is_none() {
if l.is_empty() {
description = Some(String::new());
} else {
description = summary;
summary = None;
let d = description.as_mut().unwrap();
d.push_str(l);
d.push('\n');
}
continue;
}
if l.starts_with("```") {
if let Some(e) = example {
examples.push(e.trim().to_owned());
example = None;
} else {
example = Some(String::new());
}
continue;
}
if let Some(e) = &mut example {
e.push_str(l);
e.push('\n');
continue;
}
match &mut description {
Some(d) => {
d.push_str(l);
d.push('\n');
}
None => unreachable!(),
}
}
assert!(example.is_none());
if let Some(d) = &mut description {
if d.is_empty() {
description = None;
}
}
self.apply_docs(
summary.map(|s| s.trim().to_owned()),
description.map(|s| s.trim().to_owned()),
examples,
);
}
}
impl ApplyMeta for ConstData {
fn apply_docs(&mut self, summary: Option<String>, description: Option<String>, examples: Vec<String>) {
self.summary = summary;
self.description = description;
self.examples = examples;
}
fn deprecated(&mut self, deprecated: bool) {
self.properties.deprecated = deprecated;
}
fn doc_hidden(&mut self, doc_hidden: bool) {
self.properties.doc_hidden = doc_hidden;
}
fn impl_kind(&mut self, _impl_kind: ImplKind) {}
}
impl ApplyMeta for FnData {
fn apply_docs(&mut self, summary: Option<String>, description: Option<String>, examples: Vec<String>) {
self.summary = summary;
self.description = description;
self.examples = examples;
}
fn deprecated(&mut self, deprecated: bool) {
self.properties.deprecated = deprecated;
}
fn doc_hidden(&mut self, doc_hidden: bool) {
self.properties.doc_hidden = doc_hidden;
}
fn impl_kind(&mut self, impl_kind: ImplKind) {
self.properties.impl_kind = impl_kind;
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn smoke() {
let result = walk_prelude();
for d in result {
if let DocData::Const(d) = d {
if d.name == "PI" {
assert!(d.value.unwrap().starts_with('3'));
assert_eq!(d.ty, Some("number".to_owned()));
assert_eq!(d.qual_name, "std::math::PI");
assert!(d.summary.is_some());
assert!(!d.examples.is_empty());
return;
}
}
}
panic!("didn't find PI");
}
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
async fn test_examples() -> miette::Result<()> {
let std = walk_prelude();
for d in std {
for (i, eg) in d.examples().iter().enumerate() {
let result =
match crate::test_server::execute_and_snapshot(eg, crate::settings::types::UnitLength::Mm, None)
.await
{
Err(crate::errors::ExecError::Kcl(e)) => {
return Err(miette::Report::new(crate::errors::Report {
error: e.error,
filename: format!("{}{i}", d.name()),
kcl_source: eg.to_string(),
}));
}
Err(other_err) => panic!("{}", other_err),
Ok(img) => img,
};
twenty_twenty::assert_image(
format!("tests/outputs/serial_test_example_{}{i}.png", d.file_name()),
&result,
0.99,
);
}
}
Ok(())
}
}

View File

@ -2,6 +2,7 @@
#[cfg(test)] #[cfg(test)]
mod gen_std_tests; mod gen_std_tests;
pub mod kcl_doc;
use std::path::Path; use std::path::Path;
@ -896,60 +897,6 @@ fn get_autocomplete_string_from_schema(schema: &schemars::schema::Schema) -> Res
} }
} }
pub fn completion_item_from_enum_schema(
schema: &schemars::schema::Schema,
kind: CompletionItemKind,
) -> Result<CompletionItem> {
// Get the docs for the schema.
let schemars::schema::Schema::Object(o) = schema else {
anyhow::bail!("expected object schema: {:#?}", schema);
};
let description = get_description_string_from_schema(&schemars::schema::RootSchema {
schema: o.clone(),
..Default::default()
})
.unwrap_or_default();
let Some(enum_values) = o.enum_values.as_ref() else {
anyhow::bail!("expected enum values: {:#?}", o);
};
if enum_values.len() > 1 {
anyhow::bail!("expected only one enum value: {:#?}", o);
}
if enum_values.is_empty() {
anyhow::bail!("expected at least one enum value: {:#?}", o);
}
let serde_json::Value::String(ref enum_value) = enum_values[0] else {
anyhow::bail!("expected string enum value: {:#?}", enum_values[0]);
};
Ok(CompletionItem {
label: enum_value.to_string(),
label_details: None,
kind: Some(kind),
detail: Some(description.to_string()),
documentation: Some(Documentation::MarkupContent(MarkupContent {
kind: MarkupKind::Markdown,
value: description.to_string(),
})),
deprecated: Some(false),
preselect: None,
sort_text: None,
filter_text: None,
insert_text: None,
insert_text_format: None,
insert_text_mode: None,
text_edit: None,
additional_text_edits: None,
command: None,
commit_characters: None,
data: None,
tags: None,
})
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use pretty_assertions::assert_eq; use pretty_assertions::assert_eq;
@ -1138,13 +1085,15 @@ mod tests {
#[test] #[test]
fn get_all_stdlib_autocomplete_snippets() { fn get_all_stdlib_autocomplete_snippets() {
let stdlib = crate::std::StdLib::new(); let stdlib = crate::std::StdLib::new();
crate::lsp::kcl::get_completions_from_stdlib(&stdlib).unwrap(); let kcl_std = crate::docs::kcl_doc::walk_prelude();
crate::lsp::kcl::get_completions_from_stdlib(&stdlib, &kcl_std).unwrap();
} }
// We want to test the signatures we compile at lsp start. // We want to test the signatures we compile at lsp start.
#[test] #[test]
fn get_all_stdlib_signatures() { fn get_all_stdlib_signatures() {
let stdlib = crate::std::StdLib::new(); let stdlib = crate::std::StdLib::new();
crate::lsp::kcl::get_signatures_from_stdlib(&stdlib); let kcl_std = crate::docs::kcl_doc::walk_prelude();
crate::lsp::kcl::get_signatures_from_stdlib(&stdlib, &kcl_std);
} }
} }

View File

@ -0,0 +1,33 @@
---
title: "{{name}}"
excerpt: "{{safe_yaml summary}}"
layout: manual
---
{{#if deprecated}}
**WARNING:** This function is deprecated.
{{/if}}
{{{summary}}}
{{{description}}}
```js
{{{name}}}{{#if type_}}: {{{type_}}}{{/if}}{{#if value}} = {{{value}}}{{/if}}
```
{{#if examples}}
### Examples
{{#each examples}}
```js
{{{this.content}}}
```
{{#unless @root.is_utilities}}
![Rendered example of {{@root.name}} {{@index}}](data:image/png;base64,{{{this.image_base64}}})
{{/unless}}
{{/each}}
{{/if}}

Some files were not shown because too many files have changed in this diff Show More