generate kcl examples in docs from macro (#1710)
* rearrange Signed-off-by: Jess Frazelle <github@jessfraz.com> * examples Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix tests Signed-off-by: Jess Frazelle <github@jessfraz.com> * recast Signed-off-by: Jess Frazelle <github@jessfraz.com> * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * add more tests Signed-off-by: Jess Frazelle <github@jessfraz.com> * fixups Signed-off-by: Jess Frazelle <github@jessfraz.com> * add more samples Signed-off-by: Jess Frazelle <github@jessfraz.com> * more docs Signed-off-by: Jess Frazelle <github@jessfraz.com> * more Signed-off-by: Jess Frazelle <github@jessfraz.com> * more samples Signed-off-by: Jess Frazelle <github@jessfraz.com> * more Signed-off-by: Jess Frazelle <github@jessfraz.com> * fixups Signed-off-by: Jess Frazelle <github@jessfraz.com> * fixups Signed-off-by: Jess Frazelle <github@jessfraz.com> * fixes Signed-off-by: Jess Frazelle <github@jessfraz.com> * make serial Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix hang Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix import Signed-off-by: Jess Frazelle <github@jessfraz.com> * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * fixes Signed-off-by: Jess Frazelle <github@jessfraz.com> * atan Signed-off-by: Jess Frazelle <github@jessfraz.com> * atan Signed-off-by: Jess Frazelle <github@jessfraz.com> * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * fixes Signed-off-by: Jess Frazelle <github@jessfraz.com> * fixes Signed-off-by: Jess Frazelle <github@jessfraz.com> * make all tests pass Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix docs Signed-off-by: Jess Frazelle <github@jessfraz.com> * fixes Signed-off-by: Jess Frazelle <github@jessfraz.com> * must have code balock Signed-off-by: Jess Frazelle <github@jessfraz.com> * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * new docs Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix docs Signed-off-by: Jess Frazelle <github@jessfraz.com> * new docs Signed-off-by: Jess Frazelle <github@jessfraz.com> --------- Signed-off-by: Jess Frazelle <github@jessfraz.com>
This commit is contained in:
@ -25,7 +25,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"const myVar = abs(-4)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "acos",
|
||||
@ -53,7 +56,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"const myVar = acos(0.5)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "angleToMatchLengthX",
|
||||
@ -1050,7 +1056,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"const part001 = startSketchOn('XY')\n |> startProfileAt([0, 0], %)\n |> line({ to: [1, 3.82], tag: 'seg01' }, %)\n |> angledLineToX([\n -angleToMatchLengthX('seg01', 10, %),\n 5\n ], %)\n |> close(%)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "angleToMatchLengthY",
|
||||
@ -2047,7 +2056,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"const part001 = startSketchOn('XY')\n |> startProfileAt([0, 0], %)\n |> line({ to: [1, 3.82], tag: 'seg01' }, %)\n |> angledLineToX([\n -angleToMatchLengthY('seg01', 10, %),\n 5\n ], %)\n |> close(%)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "angledLine",
|
||||
@ -4024,7 +4036,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"startSketchOn('XY')\n |> startProfileAt([0, 0], %)\n |> angledLine({ angle: 45, length: 10, tag: \"edge1\" }, %)\n |> line([10, 10], %)\n |> line([0, 10], %)\n |> close(%, \"edge2\")\n |> extrude(10, %)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "angledLineOfXLength",
|
||||
@ -6001,7 +6016,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"startSketchOn('XZ')\n |> startProfileAt([0, 0], %)\n |> angledLineOfXLength({ angle: 45, length: 10, tag: \"edge1\" }, %)\n |> line([10, 10], %)\n |> line([0, 10], %)\n |> close(%, \"edge2\")\n |> extrude(10, %)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "angledLineOfYLength",
|
||||
@ -7978,7 +7996,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"startSketchOn('YZ')\n |> startProfileAt([0, 0], %)\n |> angledLineOfYLength({ angle: 45, length: 10, tag: \"edge1\" }, %)\n |> line([10, 10], %)\n |> line([0, 10], %)\n |> close(%, \"edge2\")\n |> extrude(10, %)\n |> fillet({ radius: 2, tags: [\"edge1\"] }, %)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "angledLineThatIntersects",
|
||||
@ -9945,7 +9966,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"const part001 = startSketchOn('XY')\n |> startProfileAt([0, 0], %)\n |> lineTo({ to: [2, 2], tag: \"yo\" }, %)\n |> lineTo([3, 1], %)\n |> angledLineThatIntersects({\n angle: 180,\n intersectTag: 'yo',\n offset: 12,\n tag: \"yo2\"\n }, %)\n |> line([4, 0], %)\n |> close(%, \"yo3\")\n |> extrude(10, %)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "angledLineToX",
|
||||
@ -11922,7 +11946,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"startSketchOn('XY')\n |> startProfileAt([0, 0], %)\n |> angledLineToX({ angle: 45, to: 10, tag: \"edge1\" }, %)\n |> line([10, 10], %)\n |> line([0, 10], %)\n |> close(%, \"edge2\")\n |> extrude(10, %)\n |> fillet({ radius: 2, tags: [\"edge1\"] }, %)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "angledLineToY",
|
||||
@ -13899,7 +13926,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"startSketchOn('XY')\n |> startProfileAt([0, 0], %)\n |> angledLineToY({ angle: 45, to: 10, tag: \"edge1\" }, %)\n |> line([10, 10], %)\n |> line([0, 10], %)\n |> close(%, \"edge2\")\n |> extrude(10, %)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "arc",
|
||||
@ -15915,7 +15945,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"startSketchOn('-YZ')\n |> startProfileAt([0, 0], %)\n |> arc({\n angle_start: 0,\n angle_end: 360,\n radius: 10,\n tag: \"edge1\"\n }, %)\n |> extrude(10, %)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "asin",
|
||||
@ -15943,7 +15976,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"const myVar = asin(0.5)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "atan",
|
||||
@ -15971,7 +16007,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"const myVar = atan(1.0)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "bezierCurve",
|
||||
@ -17954,7 +17993,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"startSketchOn('XY')\n |> startProfileAt([0, 0], %)\n |> bezierCurve({\n to: [10, 10],\n control1: [5, 0],\n control2: [5, 10],\n tag: \"edge1\"\n }, %)\n |> close(%)\n |> extrude(10, %)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ceil",
|
||||
@ -17982,7 +18024,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"const myVar = ceil(4.5)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "circle",
|
||||
@ -19284,7 +19329,8 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": []
|
||||
},
|
||||
{
|
||||
"name": "close",
|
||||
@ -21225,7 +21271,11 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"startSketchOn('XZ')\n |> startProfileAt([0, 0], %)\n |> line([10, 10], %)\n |> line([10, 0], %)\n |> close(%)",
|
||||
"startSketchOn('YZ')\n |> startProfileAt([0, 0], %)\n |> line([10, 10], %)\n |> line([10, 0], %)\n |> close(%, \"edge1\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "cos",
|
||||
@ -21253,7 +21303,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"const anotherVar = cos(2 * pi())"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "e",
|
||||
@ -21271,7 +21324,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"const myVar = e()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "extrude",
|
||||
@ -23007,7 +23063,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"startSketchOn('XY')\n |> startProfileAt([0, 0], %)\n |> line([0, 10], %)\n |> line([10, 0], %)\n |> line([0, -10], %)\n |> close(%)\n |> extrude(5, %)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "fillet",
|
||||
@ -24567,7 +24626,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"const part001 = startSketchOn('XY')\n |> startProfileAt([0, 0], %)\n |> line({ to: [0, 10], tag: \"thing\" }, %)\n |> line([10, 0], %)\n |> line({ to: [0, -10], tag: \"thing2\" }, %)\n |> close(%)\n |> extrude(10, %)\n |> fillet({ radius: 2, tags: [\"thing\", \"thing2\"] }, %)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "floor",
|
||||
@ -24595,7 +24657,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"const myVar = floor(4.5)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "getExtrudeWallTransform",
|
||||
@ -25425,7 +25490,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"const box = startSketchOn('XY')\n |> startProfileAt([0, 0], %)\n |> line([0, 10], %)\n |> line([10, 0], %)\n |> line({ to: [0, -10], tag: \"surface\" }, %)\n |> close(%)\n |> extrude(5, %)\n\nconst transform = getExtrudeWallTransform('surface', box)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "getNextAdjacentEdge",
|
||||
@ -26208,7 +26276,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"const part001 = startSketchOn('XY')\n |> startProfileAt([0, 0], %)\n |> line({ to: [0, 10], tag: \"thing\" }, %)\n |> line({ to: [10, 0], tag: \"thing1\" }, %)\n |> line({ to: [0, -10], tag: \"thing2\" }, %)\n |> close(%)\n |> extrude(10, %)\n |> fillet({\n radius: 2,\n tags: [getNextAdjacentEdge(\"thing\", %)]\n }, %)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "getOppositeEdge",
|
||||
@ -26991,7 +27062,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"const part001 = startSketchOn('XY')\n |> startProfileAt([0, 0], %)\n |> line({ to: [0, 10], tag: \"thing\" }, %)\n |> line([10, 0], %)\n |> line({ to: [0, -10], tag: \"thing2\" }, %)\n |> close(%)\n |> extrude(10, %)\n |> fillet({\n radius: 2,\n tags: [\"thing\", getOppositeEdge(\"thing\", %)]\n }, %)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "getPreviousAdjacentEdge",
|
||||
@ -27774,7 +27848,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"const part001 = startSketchOn('XY')\n |> startProfileAt([0, 0], %)\n |> line({ to: [0, 10], tag: \"thing\" }, %)\n |> line({ to: [10, 0], tag: \"thing1\" }, %)\n |> line({ to: [0, -10], tag: \"thing2\" }, %)\n |> close(%)\n |> extrude(10, %)\n |> fillet({\n radius: 2,\n tags: [getPreviousAdjacentEdge(\"thing2\", %)]\n }, %)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "hole",
|
||||
@ -31652,7 +31729,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"const square = startSketchOn('XY')\n |> startProfileAt([0, 0], %)\n |> line([0, 10], %)\n |> line([10, 0], %)\n |> line([0, -10], %)\n |> close(%)\n |> hole(circle([2, 2], .5, startSketchOn('XY')), %)\n |> hole(circle([2, 8], .5, startSketchOn('XY')), %)\n |> extrude(2, %)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "import",
|
||||
@ -32302,7 +32382,14 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"const model = import(\"thing.obj\")",
|
||||
"const model = import(\"cube.obj\", { type: \"obj\", units: \"m\" })",
|
||||
"const model = import(\"my_model.gltf\")",
|
||||
"const model = import(\"my_model.sldprt\")",
|
||||
"const model = import(\"my_model.step\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "lastSegX",
|
||||
@ -33282,7 +33369,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"startSketchOn(\"YZ\")\n |> startProfileAt([0, 0], %)\n |> line({ to: [5, 0], tag: \"thing\" }, %)\n |> line([5, 5], %)\n |> line([0, lastSegX(%)], %)\n |> close(%)\n |> extrude(5, %)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "lastSegY",
|
||||
@ -34262,7 +34352,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"startSketchOn(\"YZ\")\n |> startProfileAt([0, 0], %)\n |> line({ to: [5, 0], tag: \"thing\" }, %)\n |> line([5, 5], %)\n |> line([0, lastSegY(%)], %)\n |> close(%)\n |> extrude(5, %)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "legAngX",
|
||||
@ -34299,7 +34392,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"legAngX(5, 3)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "legAngY",
|
||||
@ -34336,7 +34432,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"legAngY(5, 3)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "legLen",
|
||||
@ -34373,7 +34472,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"legLen(5, 3)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "line",
|
||||
@ -36349,7 +36451,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"startSketchOn('-XY')\n |> startProfileAt([0, 0], %)\n |> line([10, 10], %)\n |> line({ to: [20, 10], tag: \"edge1\" }, %)\n |> close(%, \"edge2\")\n |> extrude(10, %)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "lineTo",
|
||||
@ -38325,7 +38430,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"fn rectShape = (pos, w, l) => {\n const rr = startSketchOn('YZ')\n |> startProfileAt([pos[0] - (w / 2), pos[1] - (l / 2)], %)\n |> lineTo({\n to: [pos[0] + w / 2, pos[1] - (l / 2)],\n tag: \"edge1\"\n }, %)\n |> lineTo({\n to: [pos[0] + w / 2, pos[1] + l / 2],\n tag: \"edge2\"\n }, %)\n |> lineTo({\n to: [pos[0] - (w / 2), pos[1] + l / 2],\n tag: \"edge3\"\n }, %)\n |> close(%, \"edge4\")\n return rr\n}\n\n// Create the mounting plate extrusion, holes, and fillets\nconst part = rectShape([0, 0], 20, 20)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ln",
|
||||
@ -38353,7 +38461,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"const myVar = ln(4)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "log",
|
||||
@ -38390,7 +38501,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"const myVar = log(4, 2)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "log10",
|
||||
@ -38418,7 +38532,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"const myVar = log10(4)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "log2",
|
||||
@ -38446,7 +38563,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"const myVar = log2(4)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "max",
|
||||
@ -38477,7 +38597,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"const myVar = max(4, 5, 6)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "min",
|
||||
@ -38508,7 +38631,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"const myVar = min(4, 5, 6)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "patternCircular2d",
|
||||
@ -40485,7 +40611,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"const part = startSketchOn('XY')\n |> circle([0, 0], 2, %)\n |> patternCircular2d({\n center: [20, 20],\n repetitions: 12,\n arcDegrees: 210,\n rotateDuplicates: true\n }, %)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "patternCircular3d",
|
||||
@ -42063,7 +42192,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"const part = startSketchOn('XY')\n |> startProfileAt([0, 0], %)\n |> line([0, 1], %)\n |> line([1, 0], %)\n |> line([0, -1], %)\n |> close(%)\n |> extrude(1, %)\n |> patternCircular3d({\n axis: [1, 1, 0],\n center: [10, 0, 10],\n repetitions: 10,\n arcDegrees: 360,\n rotateDuplicates: true\n }, %)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "patternLinear2d",
|
||||
@ -44035,7 +44167,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"const part = startSketchOn('XY')\n |> circle([0, 0], 2, %)\n |> patternLinear2d({\n axis: [0, 1],\n repetitions: 12,\n distance: 2\n }, %)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "patternLinear3d",
|
||||
@ -45597,7 +45732,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"const part = startSketchOn('XY')\n |> startProfileAt([0, 0], %)\n |> line([0, 1], %)\n |> line([1, 0], %)\n |> line([0, -1], %)\n |> close(%)\n |> extrude(1, %)\n |> patternLinear3d({\n axis: [1, 0, 1],\n repetitions: 3,\n distance: 6\n }, %)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "pi",
|
||||
@ -45615,7 +45753,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"const myVar = pi() * 3.0"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "pow",
|
||||
@ -45652,7 +45793,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"const myVar = pow(4, 2)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "segAng",
|
||||
@ -46640,7 +46784,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"const part001 = startSketchOn('XY')\n |> startProfileAt([4.83, 12.56], %)\n |> line([15.1, 2.48], %)\n |> line({ to: [3.15, -9.85], tag: 'seg01' }, %)\n |> line([-15.17, -4.1], %)\n |> angledLine([segAng('seg01', %), 12.35], %)\n |> line([-13.02, 10.03], %)\n |> close(%)\n |> extrude(4, %)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "segEndX",
|
||||
@ -47628,7 +47775,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"startSketchOn(\"YZ\")\n |> startProfileAt([0, 0], %)\n |> line({ to: [5, 0], tag: \"thing\" }, %)\n |> line([5, 5], %)\n |> line([segEndX(\"thing\", %), 5], %)\n |> close(%)\n |> extrude(5, %)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "segEndY",
|
||||
@ -48616,7 +48766,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"startSketchOn(\"YZ\")\n |> startProfileAt([0, 0], %)\n |> line({ to: [5, 0], tag: \"thing\" }, %)\n |> line([5, 5], %)\n |> line([segEndY(\"thing\", %), 5], %)\n |> close(%)\n |> extrude(5, %)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "segLen",
|
||||
@ -49604,7 +49757,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"startSketchOn(\"YZ\")\n |> startProfileAt([0, 0], %)\n |> line({ to: [5, 0], tag: \"thing\" }, %)\n |> line([5, 5], %)\n |> line([0, segLen(\"thing\", %)], %)\n |> close(%)\n |> extrude(5, %)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "sin",
|
||||
@ -49632,7 +49788,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"const myVar = sin(2 * pi())"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "sqrt",
|
||||
@ -49660,7 +49819,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"const myVar = sqrt(4)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "startProfileAt",
|
||||
@ -50975,7 +51137,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"startSketchOn('XY')\n |> startProfileAt([0, 0], %)\n |> line([10, 10], %)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "startSketchAt",
|
||||
@ -51990,7 +52155,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"startSketchAt([0, 0])\n |> line([10, 10], %)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "startSketchOn",
|
||||
@ -53254,7 +53422,11 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"startSketchOn('XY')\n |> startProfileAt([0, 0], %)\n |> line([10, 10], %)\n |> line({ to: [20, 10], tag: \"edge1\" }, %)\n |> close(%, \"edge2\")",
|
||||
"fn cube = (pos, scale) => {\n const sg = startSketchOn('XY')\n |> startProfileAt(pos, %)\n |> line([0, scale], %)\n |> line([scale, 0], %)\n |> line([0, -scale], %)\n |> close(%)\n |> extrude(scale, %)\n\n return sg\n}\n\nconst box = cube([0, 0], 20)\n\nconst part001 = startSketchOn(box, \"start\")\n |> startProfileAt([0, 0], %)\n |> line([10, 10], %)\n |> line({ to: [20, 10], tag: \"edge1\" }, %)\n |> close(%)\n |> extrude(20, %)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "tan",
|
||||
@ -53282,7 +53454,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"const myVar = tan(2 * pi())"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "tangentialArc",
|
||||
@ -55277,7 +55452,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"startSketchOn('-YZ')\n |> startProfileAt([0, 0], %)\n |> line({ to: [10, 10], tag: \"edge0\" }, %)\n |> tangentialArc({ radius: 10, offset: 90, tag: \"edge1\" }, %)\n |> close(%)\n |> extrude(10, %)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "tangentialArcTo",
|
||||
@ -57232,7 +57410,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"startSketchOn('-YZ')\n |> startProfileAt([0, 0], %)\n |> line({ to: [10, 10], tag: \"edge0\" }, %)\n |> tangentialArcTo([10, 0], %)\n |> close(%)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "tau",
|
||||
@ -57250,10 +57431,13 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"const myVar = tau()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "to_degrees",
|
||||
"name": "toDegrees",
|
||||
"summary": "Converts a number from radians to degrees.",
|
||||
"description": "",
|
||||
"tags": [],
|
||||
@ -57278,10 +57462,13 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"const myVar = toDegrees(2 * pi())"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "to_radians",
|
||||
"name": "toRadians",
|
||||
"summary": "Converts a number from degrees to radians.",
|
||||
"description": "",
|
||||
"tags": [],
|
||||
@ -57306,7 +57493,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"const myVar = toRadians(180)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "xLine",
|
||||
@ -59272,7 +59462,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"startSketchOn('YZ')\n |> startProfileAt([0, 0], %)\n |> xLine(10, %)\n |> line([10, 10], %)\n |> close(%, \"edge1\")\n |> extrude(10, %)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "xLineTo",
|
||||
@ -61238,7 +61431,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"startSketchOn('XY')\n |> startProfileAt([0, 0], %)\n |> xLineTo({ to: 10, tag: \"edge1\" }, %)\n |> line([10, 10], %)\n |> close(%, \"edge2\")\n |> extrude(10, %)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "yLine",
|
||||
@ -63204,7 +63400,10 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"startSketchOn('XY')\n |> startProfileAt([0, 0], %)\n |> yLine(10, %)\n |> line([10, 10], %)\n |> close(%, \"edge1\")\n |> extrude(10, %)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "yLineTo",
|
||||
@ -65170,6 +65369,9 @@
|
||||
"required": true
|
||||
},
|
||||
"unpublished": false,
|
||||
"deprecated": false
|
||||
"deprecated": false,
|
||||
"examples": [
|
||||
"startSketchOn('XZ')\n |> startProfileAt([0, 0], %)\n |> yLineTo({ to: 10, tag: \"edge1\" }, %)\n |> line([10, 10], %)\n |> close(%, \"edge2\")\n |> extrude(10, %)\n |> fillet({ radius: 2, tags: [\"edge2\"] }, %)"
|
||||
]
|
||||
}
|
||||
]
|
724
docs/kcl/std.md
724
docs/kcl/std.md
File diff suppressed because it is too large
Load Diff
21
src/wasm-lib/Cargo.lock
generated
21
src/wasm-lib/Cargo.lock
generated
@ -947,8 +947,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "derive-docs"
|
||||
version = "0.1.10"
|
||||
version = "0.1.11"
|
||||
dependencies = [
|
||||
"Inflector",
|
||||
"convert_case",
|
||||
"expectorate",
|
||||
"once_cell",
|
||||
@ -962,22 +963,6 @@ dependencies = [
|
||||
"syn 2.0.52",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive-docs"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fc85a0d10f808387cd56147b520be7efd94b8b198b1453f987b133cd2a90b7e"
|
||||
dependencies = [
|
||||
"convert_case",
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_tokenstream",
|
||||
"syn 2.0.52",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "diesel_derives"
|
||||
version = "2.1.2"
|
||||
@ -1919,7 +1904,7 @@ dependencies = [
|
||||
"criterion",
|
||||
"dashmap",
|
||||
"databake",
|
||||
"derive-docs 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"derive-docs",
|
||||
"expectorate",
|
||||
"futures",
|
||||
"gltf-json",
|
||||
|
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "derive-docs"
|
||||
description = "A tool for generating documentation from Rust derive macros"
|
||||
version = "0.1.10"
|
||||
version = "0.1.11"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
repository = "https://github.com/KittyCAD/modeling-app"
|
||||
@ -12,6 +12,7 @@ rust-version = "1.73"
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
Inflector = "0.11.4"
|
||||
convert_case = "0.6.0"
|
||||
once_cell = "1.19.0"
|
||||
proc-macro2 = "1"
|
||||
|
@ -2,7 +2,12 @@
|
||||
// automated enforcement.
|
||||
#![allow(clippy::style)]
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
mod unbox;
|
||||
|
||||
use convert_case::Casing;
|
||||
use inflector::Inflector;
|
||||
use once_cell::sync::Lazy;
|
||||
use quote::{format_ident, quote, quote_spanned, ToTokens};
|
||||
use regex::Regex;
|
||||
@ -12,6 +17,7 @@ use syn::{
|
||||
parse::{Parse, ParseStream},
|
||||
Attribute, Signature, Visibility,
|
||||
};
|
||||
use unbox::unbox;
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct StdlibMetadata {
|
||||
@ -101,6 +107,21 @@ fn do_stdlib_inner(
|
||||
}
|
||||
|
||||
let name = metadata.name;
|
||||
|
||||
// Fail if the name is not camel case.
|
||||
let whitelist = [
|
||||
"patternLinear3d",
|
||||
"patternLinear2d",
|
||||
"patternCircular3d",
|
||||
"patternCircular2d",
|
||||
];
|
||||
if !name.is_camel_case() && !whitelist.contains(&name.as_str()) {
|
||||
errors.push(Error::new_spanned(
|
||||
&ast.sig.ident,
|
||||
format!("stdlib function names must be in camel case: `{}`", name),
|
||||
));
|
||||
}
|
||||
|
||||
let name_ident = format_ident!("{}", name.to_case(convert_case::Case::UpperCamel));
|
||||
let name_str = name.to_string();
|
||||
|
||||
@ -110,16 +131,16 @@ fn do_stdlib_inner(
|
||||
let boxed_fn_name_ident = format_ident!("boxed_{}", fn_name_str);
|
||||
let _visibility = &ast.vis;
|
||||
|
||||
let (summary_text, description_text) = extract_doc_from_attrs(&ast.attrs);
|
||||
let doc_info = extract_doc_from_attrs(&ast.attrs);
|
||||
let comment_text = {
|
||||
let mut buf = String::new();
|
||||
buf.push_str("Std lib function: ");
|
||||
buf.push_str(&name_str);
|
||||
if let Some(s) = &summary_text {
|
||||
if let Some(s) = &doc_info.summary {
|
||||
buf.push_str("\n");
|
||||
buf.push_str(&s);
|
||||
}
|
||||
if let Some(s) = &description_text {
|
||||
if let Some(s) = &doc_info.description {
|
||||
buf.push_str("\n");
|
||||
buf.push_str(&s);
|
||||
}
|
||||
@ -129,17 +150,60 @@ fn do_stdlib_inner(
|
||||
#[doc = #comment_text]
|
||||
};
|
||||
|
||||
let summary = if let Some(summary) = summary_text {
|
||||
let summary = if let Some(summary) = doc_info.summary {
|
||||
quote! { #summary }
|
||||
} else {
|
||||
quote! { "" }
|
||||
};
|
||||
let description = if let Some(description) = description_text {
|
||||
let description = if let Some(description) = doc_info.description {
|
||||
quote! { #description }
|
||||
} else {
|
||||
quote! { "" }
|
||||
};
|
||||
|
||||
let cb = doc_info.code_blocks.clone();
|
||||
let code_blocks = if !cb.is_empty() {
|
||||
quote! {
|
||||
let code_blocks = vec![#(#cb),*];
|
||||
code_blocks.iter().map(|cb| {
|
||||
let tokens = crate::token::lexer(cb);
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
|
||||
let mut options: crate::ast::types::FormatOptions = Default::default();
|
||||
options.insert_final_newline = false;
|
||||
program.recast(&options, 0)
|
||||
}).collect::<Vec<String>>()
|
||||
}
|
||||
} else {
|
||||
errors.push(Error::new_spanned(
|
||||
&ast.sig,
|
||||
"stdlib functions must have at least one code block",
|
||||
));
|
||||
|
||||
quote! { vec![] }
|
||||
};
|
||||
|
||||
// Make sure the function name is in all the code blocks.
|
||||
for code_block in doc_info.code_blocks.iter() {
|
||||
if !code_block.contains(&name) {
|
||||
errors.push(Error::new_spanned(
|
||||
&ast.sig,
|
||||
format!(
|
||||
"stdlib functions must have the function name `{}` in the code block",
|
||||
name
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
let test_code_blocks = doc_info
|
||||
.code_blocks
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(index, code_block)| generate_code_block_test(&fn_name_str, code_block, index))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let tags = metadata
|
||||
.tags
|
||||
.iter()
|
||||
@ -242,7 +306,7 @@ fn do_stdlib_inner(
|
||||
let mut args = args.iter();
|
||||
let ok = args.next().unwrap();
|
||||
if let syn::GenericArgument::Type(ty) = ok {
|
||||
let ty = unbox(unbox_vec(ty.clone()));
|
||||
let ty = unbox(ty.clone());
|
||||
quote! { #ty }
|
||||
} else {
|
||||
quote! { () }
|
||||
@ -254,7 +318,7 @@ fn do_stdlib_inner(
|
||||
quote! { () }
|
||||
}
|
||||
} else {
|
||||
let ty = unbox(unbox_vec(*ty.clone()));
|
||||
let ty = unbox(*ty.clone());
|
||||
quote! { #ty }
|
||||
}
|
||||
} else {
|
||||
@ -295,9 +359,16 @@ fn do_stdlib_inner(
|
||||
pub(crate) const #name_ident: #name_ident = #name_ident {};
|
||||
};
|
||||
|
||||
let test_mod_name = format_ident!("test_examples_{}", fn_name_str);
|
||||
|
||||
// The final TokenStream returned will have a few components that reference
|
||||
// `#name_ident`, the name of the function to which this macro was applied...
|
||||
let stream = quote! {
|
||||
#[cfg(test)]
|
||||
mod #test_mod_name {
|
||||
#(#test_code_blocks)*
|
||||
}
|
||||
|
||||
// ... a struct type called `#name_ident` that has no members
|
||||
#[allow(non_camel_case_types, missing_docs)]
|
||||
#description_doc_comment
|
||||
@ -359,6 +430,10 @@ fn do_stdlib_inner(
|
||||
#deprecated
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<String> {
|
||||
#code_blocks
|
||||
}
|
||||
|
||||
fn std_lib_fn(&self) -> crate::std::StdFn {
|
||||
#boxed_fn_name_ident
|
||||
}
|
||||
@ -394,10 +469,18 @@ fn get_crate(var: Option<String>) -> proc_macro2::TokenStream {
|
||||
quote!(crate::docs)
|
||||
}
|
||||
|
||||
fn extract_doc_from_attrs(attrs: &[syn::Attribute]) -> (Option<String>, Option<String>) {
|
||||
let doc = syn::Ident::new("doc", proc_macro2::Span::call_site());
|
||||
#[derive(Debug)]
|
||||
struct DocInfo {
|
||||
pub summary: Option<String>,
|
||||
pub description: Option<String>,
|
||||
pub code_blocks: Vec<String>,
|
||||
}
|
||||
|
||||
let mut lines = attrs.iter().flat_map(|attr| {
|
||||
fn extract_doc_from_attrs(attrs: &[syn::Attribute]) -> DocInfo {
|
||||
let doc = syn::Ident::new("doc", proc_macro2::Span::call_site());
|
||||
let mut code_blocks: Vec<String> = Vec::new();
|
||||
|
||||
let raw_lines = attrs.iter().flat_map(|attr| {
|
||||
if let syn::Meta::NameValue(nv) = &attr.meta {
|
||||
if nv.path.is_ident(&doc) {
|
||||
if let syn::Expr::Lit(syn::ExprLit {
|
||||
@ -411,6 +494,53 @@ fn extract_doc_from_attrs(attrs: &[syn::Attribute]) -> (Option<String>, Option<S
|
||||
Vec::new()
|
||||
});
|
||||
|
||||
// Parse any code blocks from the doc string.
|
||||
let mut code_block: Option<String> = None;
|
||||
let mut parsed_lines = Vec::new();
|
||||
for line in raw_lines {
|
||||
if line.starts_with("```") {
|
||||
if let Some(ref inner_code_block) = code_block {
|
||||
code_blocks.push(inner_code_block.trim().to_string());
|
||||
code_block = None;
|
||||
} else {
|
||||
code_block = Some(String::new());
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
if let Some(ref mut code_block) = code_block {
|
||||
code_block.push_str(&line);
|
||||
code_block.push('\n');
|
||||
} else {
|
||||
parsed_lines.push(line);
|
||||
}
|
||||
}
|
||||
|
||||
// Parse code blocks that start with a tab or a space.
|
||||
let mut lines = Vec::new();
|
||||
for line in parsed_lines {
|
||||
if line.starts_with(" ") || line.starts_with('\t') {
|
||||
if let Some(ref mut code_block) = code_block {
|
||||
code_block.push_str(&line.trim_start_matches(" ").trim_start_matches('\t'));
|
||||
code_block.push('\n');
|
||||
} else {
|
||||
code_block = Some(format!("{}\n", line));
|
||||
}
|
||||
} else {
|
||||
if let Some(ref inner_code_block) = code_block {
|
||||
code_blocks.push(inner_code_block.trim().to_string());
|
||||
code_block = None;
|
||||
}
|
||||
lines.push(line);
|
||||
}
|
||||
}
|
||||
|
||||
let mut lines = lines.into_iter();
|
||||
|
||||
if let Some(code_block) = code_block {
|
||||
code_blocks.push(code_block.trim().to_string());
|
||||
}
|
||||
|
||||
// Skip initial blank lines; they make for excessively terse summaries.
|
||||
let summary = loop {
|
||||
match lines.next() {
|
||||
@ -426,7 +556,7 @@ fn extract_doc_from_attrs(attrs: &[syn::Attribute]) -> (Option<String>, Option<S
|
||||
}
|
||||
};
|
||||
|
||||
match (summary, first) {
|
||||
let (summary, description) = match (summary, first) {
|
||||
(None, _) => (None, None),
|
||||
(summary, None) => (summary, None),
|
||||
(Some(summary), Some(first)) => (
|
||||
@ -449,6 +579,12 @@ fn extract_doc_from_attrs(attrs: &[syn::Attribute]) -> (Option<String>, Option<S
|
||||
.to_string(),
|
||||
),
|
||||
),
|
||||
};
|
||||
|
||||
DocInfo {
|
||||
summary,
|
||||
description,
|
||||
code_blocks,
|
||||
}
|
||||
}
|
||||
|
||||
@ -458,16 +594,34 @@ fn normalize_comment_string(s: String) -> Vec<String> {
|
||||
.map(|(idx, s)| {
|
||||
// Rust-style comments are intrinsically single-line. We don't want
|
||||
// to trim away formatting such as an initial '*'.
|
||||
// We also don't want to trim away a tab character, which is
|
||||
// used to denote a code block. Code blocks can also be denoted
|
||||
// by four spaces, but we don't want to trim those away either.
|
||||
// We only want to trim a single space character from the start of
|
||||
// a line, and only if it's the first character.
|
||||
let new = s
|
||||
.chars()
|
||||
.enumerate()
|
||||
.flat_map(|(idx, c)| {
|
||||
if idx == 0 {
|
||||
if c == ' ' {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
Some(c)
|
||||
})
|
||||
.collect::<String>()
|
||||
.trim_end()
|
||||
.to_string();
|
||||
let s = new.as_str();
|
||||
|
||||
if idx == 0 {
|
||||
s.trim_start().trim_end()
|
||||
s
|
||||
} else {
|
||||
let trimmed = s.trim_start().trim_end();
|
||||
trimmed
|
||||
.strip_prefix("* ")
|
||||
.unwrap_or_else(|| trimmed.strip_prefix('*').unwrap_or(trimmed))
|
||||
s.strip_prefix("* ").unwrap_or_else(|| s.strip_prefix('*').unwrap_or(s))
|
||||
}
|
||||
.to_string()
|
||||
})
|
||||
.map(ToString::to_string)
|
||||
.collect()
|
||||
}
|
||||
|
||||
@ -575,319 +729,59 @@ fn parse_array_type(type_name: &str) -> Option<(&str, usize)> {
|
||||
Some((inner_type.as_str(), length))
|
||||
}
|
||||
|
||||
// Unbox a syn::Type that is boxed to the inner object.
|
||||
fn unbox(t: syn::Type) -> syn::Type {
|
||||
match t {
|
||||
syn::Type::Path(syn::TypePath { ref path, .. }) => {
|
||||
let path = &path.segments;
|
||||
if path.len() == 1 {
|
||||
let seg = &path[0];
|
||||
if seg.ident == "Box" {
|
||||
if let syn::PathArguments::AngleBracketed(syn::AngleBracketedGenericArguments { args, .. }) =
|
||||
&seg.arguments
|
||||
{
|
||||
if args.len() == 1 {
|
||||
let mut args = args.iter();
|
||||
let ok = args.next().unwrap();
|
||||
if let syn::GenericArgument::Type(ty) = ok {
|
||||
return ty.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// For each kcl code block, we want to generate a test that checks that the
|
||||
// code block is valid kcl code and compiles and executes.
|
||||
fn generate_code_block_test(fn_name: &str, code_block: &str, index: usize) -> proc_macro2::TokenStream {
|
||||
let test_name = format_ident!("serial_test_example_{}{}", fn_name, index);
|
||||
|
||||
// TODO: We ignore import for now, because the files don't exist and we just want
|
||||
// to show easy imports.
|
||||
let ignored = if fn_name == "import" {
|
||||
quote! { #[ignore] }
|
||||
} else {
|
||||
quote! {}
|
||||
};
|
||||
|
||||
quote! {
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
#ignored
|
||||
async fn #test_name() {
|
||||
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
|
||||
let http_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
// For file conversions we need this to be long.
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60));
|
||||
let ws_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
// For file conversions we need this to be long.
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60))
|
||||
.connection_verbose(true)
|
||||
.tcp_keepalive(std::time::Duration::from_secs(600))
|
||||
.http1_only();
|
||||
|
||||
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
|
||||
|
||||
// Create the client.
|
||||
let client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
|
||||
let ws = client
|
||||
.modeling()
|
||||
.commands_ws(None, None, None, None, None, Some(false))
|
||||
.await.unwrap();
|
||||
|
||||
let tokens = crate::token::lexer(#code_block);
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut mem: crate::executor::ProgramMemory = Default::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(crate::engine::conn::EngineConnection::new(ws).await.unwrap())),
|
||||
fs: crate::fs::FileManager::new(),
|
||||
stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
|
||||
units: kittycad::types::UnitLength::Mm,
|
||||
};
|
||||
|
||||
crate::executor::execute(program, &mut mem, crate::executor::BodyType::Root, &ctx).await.unwrap();
|
||||
}
|
||||
_ => {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
t
|
||||
}
|
||||
|
||||
// For a Vec<Box<T>> return Vec<T>.
|
||||
// For a Vec<T> return Vec<T>.
|
||||
// For a Box<T> return T.
|
||||
fn unbox_vec(t: syn::Type) -> syn::Type {
|
||||
match t {
|
||||
syn::Type::Path(syn::TypePath { ref path, .. }) => {
|
||||
let path = &path.segments;
|
||||
if path.len() == 1 {
|
||||
let seg = &path[0];
|
||||
if seg.ident == "Vec" {
|
||||
if let syn::PathArguments::AngleBracketed(syn::AngleBracketedGenericArguments { args, .. }) =
|
||||
&seg.arguments
|
||||
{
|
||||
if args.len() == 1 {
|
||||
let mut args = args.iter();
|
||||
let ok = args.next().unwrap();
|
||||
if let syn::GenericArgument::Type(ty) = ok {
|
||||
let unboxed = unbox(ty.clone());
|
||||
// Wrap it back in a vec.
|
||||
let wrapped = syn::Type::Path(syn::TypePath {
|
||||
qself: None,
|
||||
path: syn::Path {
|
||||
leading_colon: None,
|
||||
segments: {
|
||||
let mut segments = syn::punctuated::Punctuated::new();
|
||||
segments.push_value(syn::PathSegment {
|
||||
ident: syn::Ident::new("Vec", proc_macro2::Span::call_site()),
|
||||
arguments: syn::PathArguments::AngleBracketed(
|
||||
syn::AngleBracketedGenericArguments {
|
||||
colon2_token: None,
|
||||
lt_token: syn::token::Lt::default(),
|
||||
args: {
|
||||
let mut args = syn::punctuated::Punctuated::new();
|
||||
args.push_value(syn::GenericArgument::Type(unboxed));
|
||||
args
|
||||
},
|
||||
gt_token: syn::token::Gt::default(),
|
||||
},
|
||||
),
|
||||
});
|
||||
segments
|
||||
},
|
||||
},
|
||||
});
|
||||
return wrapped;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
t
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
use quote::quote;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_get_inner_array_type() {
|
||||
for (expected, input) in [
|
||||
(Some(("f64", 2)), "[f64;2]"),
|
||||
(Some(("String", 2)), "[String; 2]"),
|
||||
(Some(("Option<String>", 12)), "[Option<String>;12]"),
|
||||
(Some(("Option<String>", 12)), "[Option<String>; 12]"),
|
||||
] {
|
||||
let actual = parse_array_type(input);
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_line_to() {
|
||||
let (item, errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "lineTo",
|
||||
},
|
||||
quote! {
|
||||
fn inner_line_to(
|
||||
data: LineToData,
|
||||
sketch_group: SketchGroup,
|
||||
args: &Args,
|
||||
) -> Result<SketchGroup, KclError> {
|
||||
Ok(())
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
let _expected = quote! {};
|
||||
|
||||
assert!(errors.is_empty());
|
||||
expectorate::assert_contents("tests/lineTo.gen", &openapitor::types::get_text_fmt(&item).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_min() {
|
||||
let (item, errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "min",
|
||||
},
|
||||
quote! {
|
||||
fn inner_min(
|
||||
/// The args to do shit to.
|
||||
args: Vec<f64>
|
||||
) -> f64 {
|
||||
let mut min = std::f64::MAX;
|
||||
for arg in args.iter() {
|
||||
if *arg < min {
|
||||
min = *arg;
|
||||
}
|
||||
}
|
||||
|
||||
min
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
let _expected = quote! {};
|
||||
|
||||
assert!(errors.is_empty());
|
||||
expectorate::assert_contents("tests/min.gen", &openapitor::types::get_text_fmt(&item).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_show() {
|
||||
let (item, errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "show",
|
||||
},
|
||||
quote! {
|
||||
fn inner_show(
|
||||
/// The args to do shit to.
|
||||
_args: Vec<f64>
|
||||
) {
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
let _expected = quote! {};
|
||||
|
||||
assert!(errors.is_empty());
|
||||
expectorate::assert_contents("tests/show.gen", &openapitor::types::get_text_fmt(&item).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_box() {
|
||||
let (item, errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "show",
|
||||
},
|
||||
quote! {
|
||||
fn inner_show(
|
||||
/// The args to do shit to.
|
||||
args: Box<f64>
|
||||
) -> Box<f64> {
|
||||
args
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
let _expected = quote! {};
|
||||
|
||||
assert!(errors.is_empty());
|
||||
expectorate::assert_contents("tests/box.gen", &openapitor::types::get_text_fmt(&item).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_option() {
|
||||
let (item, errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "show",
|
||||
},
|
||||
quote! {
|
||||
fn inner_show(
|
||||
/// The args to do shit to.
|
||||
args: Option<f64>
|
||||
) -> Result<Box<f64>> {
|
||||
args
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert!(errors.is_empty());
|
||||
expectorate::assert_contents("tests/option.gen", &openapitor::types::get_text_fmt(&item).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_array() {
|
||||
let (item, errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "show",
|
||||
},
|
||||
quote! {
|
||||
fn inner_show(
|
||||
/// The args to do shit to.
|
||||
args: [f64; 2]
|
||||
) -> Result<Box<f64>> {
|
||||
args
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert!(errors.is_empty());
|
||||
expectorate::assert_contents("tests/array.gen", &openapitor::types::get_text_fmt(&item).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_option_input_format() {
|
||||
let (item, errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "import",
|
||||
},
|
||||
quote! {
|
||||
fn inner_import(
|
||||
/// The args to do shit to.
|
||||
args: Option<kittycad::types::InputFormat>
|
||||
) -> Result<Box<f64>> {
|
||||
args
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert!(errors.is_empty());
|
||||
expectorate::assert_contents(
|
||||
"tests/option_input_format.gen",
|
||||
&openapitor::types::get_text_fmt(&item).unwrap(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_return_vec_sketch_group() {
|
||||
let (item, errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "import",
|
||||
},
|
||||
quote! {
|
||||
fn inner_import(
|
||||
/// The args to do shit to.
|
||||
args: Option<kittycad::types::InputFormat>
|
||||
) -> Result<Vec<SketchGroup>> {
|
||||
args
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert!(errors.is_empty());
|
||||
expectorate::assert_contents(
|
||||
"tests/return_vec_sketch_group.gen",
|
||||
&openapitor::types::get_text_fmt(&item).unwrap(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_return_vec_box_sketch_group() {
|
||||
let (item, errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "import",
|
||||
},
|
||||
quote! {
|
||||
fn inner_import(
|
||||
/// The args to do shit to.
|
||||
args: Option<kittycad::types::InputFormat>
|
||||
) -> Result<Vec<Box<SketchGroup>>> {
|
||||
args
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert!(errors.is_empty());
|
||||
expectorate::assert_contents(
|
||||
"tests/return_vec_box_sketch_group.gen",
|
||||
&openapitor::types::get_text_fmt(&item).unwrap(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
461
src/wasm-lib/derive-docs/src/tests.rs
Normal file
461
src/wasm-lib/derive-docs/src/tests.rs
Normal file
@ -0,0 +1,461 @@
|
||||
use quote::quote;
|
||||
|
||||
use crate::{do_stdlib, parse_array_type};
|
||||
|
||||
#[test]
|
||||
fn test_get_inner_array_type() {
|
||||
for (expected, input) in [
|
||||
(Some(("f64", 2)), "[f64;2]"),
|
||||
(Some(("String", 2)), "[String; 2]"),
|
||||
(Some(("Option<String>", 12)), "[Option<String>;12]"),
|
||||
(Some(("Option<String>", 12)), "[Option<String>; 12]"),
|
||||
] {
|
||||
let actual = parse_array_type(input);
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_line_to() {
|
||||
let (item, errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "lineTo",
|
||||
},
|
||||
quote! {
|
||||
/// This is some function.
|
||||
/// It does shit.
|
||||
///
|
||||
/// This is code.
|
||||
/// It does other shit.
|
||||
/// lineTo
|
||||
///
|
||||
/// ```
|
||||
/// This is another code block.
|
||||
/// yes sirrr.
|
||||
/// lineTo
|
||||
/// ```
|
||||
fn inner_line_to(
|
||||
data: LineToData,
|
||||
sketch_group: SketchGroup,
|
||||
args: &Args,
|
||||
) -> Result<SketchGroup, KclError> {
|
||||
Ok(())
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
let _expected = quote! {};
|
||||
|
||||
assert!(errors.is_empty());
|
||||
expectorate::assert_contents("tests/lineTo.gen", &openapitor::types::get_text_fmt(&item).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_min() {
|
||||
let (item, errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "min",
|
||||
},
|
||||
quote! {
|
||||
/// This is some function.
|
||||
/// It does shit.
|
||||
///
|
||||
/// This is code.
|
||||
/// It does other shit.
|
||||
/// min
|
||||
///
|
||||
/// ```
|
||||
/// This is another code block.
|
||||
/// yes sirrr.
|
||||
/// min
|
||||
/// ```
|
||||
fn inner_min(
|
||||
/// The args to do shit to.
|
||||
args: Vec<f64>
|
||||
) -> f64 {
|
||||
let mut min = std::f64::MAX;
|
||||
for arg in args.iter() {
|
||||
if *arg < min {
|
||||
min = *arg;
|
||||
}
|
||||
}
|
||||
|
||||
min
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
let _expected = quote! {};
|
||||
|
||||
assert!(errors.is_empty());
|
||||
expectorate::assert_contents("tests/min.gen", &openapitor::types::get_text_fmt(&item).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_show() {
|
||||
let (item, errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "show",
|
||||
},
|
||||
quote! {
|
||||
/// This is some function.
|
||||
/// It does shit.
|
||||
///
|
||||
/// This is code.
|
||||
/// It does other shit.
|
||||
/// show
|
||||
fn inner_show(
|
||||
/// The args to do shit to.
|
||||
_args: Vec<f64>
|
||||
) {
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
let _expected = quote! {};
|
||||
|
||||
assert!(errors.is_empty());
|
||||
expectorate::assert_contents("tests/show.gen", &openapitor::types::get_text_fmt(&item).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_box() {
|
||||
let (item, errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "show",
|
||||
},
|
||||
quote! {
|
||||
/// This is some function.
|
||||
/// It does shit.
|
||||
///
|
||||
/// This is code.
|
||||
/// It does other shit.
|
||||
/// show
|
||||
fn inner_show(
|
||||
/// The args to do shit to.
|
||||
args: Box<f64>
|
||||
) -> Box<f64> {
|
||||
args
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
let _expected = quote! {};
|
||||
|
||||
assert!(errors.is_empty());
|
||||
expectorate::assert_contents("tests/box.gen", &openapitor::types::get_text_fmt(&item).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_option() {
|
||||
let (item, errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "show",
|
||||
},
|
||||
quote! {
|
||||
/// This is some function.
|
||||
/// It does shit.
|
||||
///
|
||||
/// This is code.
|
||||
/// It does other shit.
|
||||
/// show
|
||||
fn inner_show(
|
||||
/// The args to do shit to.
|
||||
args: Option<f64>
|
||||
) -> Result<Box<f64>> {
|
||||
args
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert!(errors.is_empty());
|
||||
expectorate::assert_contents("tests/option.gen", &openapitor::types::get_text_fmt(&item).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_array() {
|
||||
let (item, errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "show",
|
||||
},
|
||||
quote! {
|
||||
/// This is some function.
|
||||
/// It does shit.
|
||||
///
|
||||
/// This is code.
|
||||
/// It does other shit.
|
||||
/// show
|
||||
///
|
||||
/// ```
|
||||
/// This is another code block.
|
||||
/// yes sirrr.
|
||||
/// show
|
||||
/// ```
|
||||
fn inner_show(
|
||||
/// The args to do shit to.
|
||||
args: [f64; 2]
|
||||
) -> Result<Box<f64>> {
|
||||
args
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert!(errors.is_empty());
|
||||
expectorate::assert_contents("tests/array.gen", &openapitor::types::get_text_fmt(&item).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_option_input_format() {
|
||||
let (item, errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "import",
|
||||
},
|
||||
quote! {
|
||||
/// This is some function.
|
||||
/// It does shit.
|
||||
///
|
||||
/// This is code.
|
||||
/// It does other shit.
|
||||
/// import
|
||||
fn inner_import(
|
||||
/// The args to do shit to.
|
||||
args: Option<kittycad::types::InputFormat>
|
||||
) -> Result<Box<f64>> {
|
||||
args
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert!(errors.is_empty());
|
||||
expectorate::assert_contents(
|
||||
"tests/option_input_format.gen",
|
||||
&openapitor::types::get_text_fmt(&item).unwrap(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_return_vec_sketch_group() {
|
||||
let (item, errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "import",
|
||||
},
|
||||
quote! {
|
||||
/// This is some function.
|
||||
/// It does shit.
|
||||
///
|
||||
/// This is code.
|
||||
/// It does other shit.
|
||||
/// import
|
||||
fn inner_import(
|
||||
/// The args to do shit to.
|
||||
args: Option<kittycad::types::InputFormat>
|
||||
) -> Result<Vec<SketchGroup>> {
|
||||
args
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert!(errors.is_empty());
|
||||
expectorate::assert_contents(
|
||||
"tests/return_vec_sketch_group.gen",
|
||||
&openapitor::types::get_text_fmt(&item).unwrap(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_return_vec_box_sketch_group() {
|
||||
let (item, errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "import",
|
||||
},
|
||||
quote! {
|
||||
/// This is some function.
|
||||
/// It does shit.
|
||||
///
|
||||
/// This is code.
|
||||
/// It does other shit.
|
||||
/// import
|
||||
fn inner_import(
|
||||
/// The args to do shit to.
|
||||
args: Option<kittycad::types::InputFormat>
|
||||
) -> Result<Vec<Box<SketchGroup>>> {
|
||||
args
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert!(errors.is_empty());
|
||||
expectorate::assert_contents(
|
||||
"tests/return_vec_box_sketch_group.gen",
|
||||
&openapitor::types::get_text_fmt(&item).unwrap(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_doc_comment_with_code() {
|
||||
let (item, errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "myFunc",
|
||||
},
|
||||
quote! {
|
||||
/// This is some function.
|
||||
/// It does shit.
|
||||
///
|
||||
/// This is code.
|
||||
/// It does other shit.
|
||||
/// myFunc
|
||||
///
|
||||
/// ```
|
||||
/// This is another code block.
|
||||
/// yes sirrr.
|
||||
/// myFunc
|
||||
/// ```
|
||||
fn inner_my_func(
|
||||
/// The args to do shit to.
|
||||
args: Option<kittycad::types::InputFormat>
|
||||
) -> Result<Vec<Box<SketchGroup>>> {
|
||||
args
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert!(errors.is_empty());
|
||||
expectorate::assert_contents(
|
||||
"tests/doc_comment_with_code.gen",
|
||||
&openapitor::types::get_text_fmt(&item).unwrap(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_doc_comment_with_code_on_ignored_function() {
|
||||
let (item, errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "import",
|
||||
},
|
||||
quote! {
|
||||
/// This is some function.
|
||||
/// It does shit.
|
||||
///
|
||||
/// This is code.
|
||||
/// It does other shit.
|
||||
/// import
|
||||
///
|
||||
/// ```
|
||||
/// This is another code block.
|
||||
/// yes sirrr.
|
||||
/// import
|
||||
/// ```
|
||||
fn inner_import(
|
||||
/// The args to do shit to.
|
||||
args: Option<kittycad::types::InputFormat>
|
||||
) -> Result<Vec<Box<SketchGroup>>> {
|
||||
args
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert!(errors.is_empty());
|
||||
expectorate::assert_contents(
|
||||
"tests/doc_comment_with_code_on_ignored_function.gen",
|
||||
&openapitor::types::get_text_fmt(&item).unwrap(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_fail_non_camel_case() {
|
||||
let (_, errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "import_thing",
|
||||
},
|
||||
quote! {
|
||||
/// This is some function.
|
||||
/// It does shit.
|
||||
///
|
||||
/// This is code.
|
||||
/// It does other shit.
|
||||
///
|
||||
/// ```
|
||||
/// This is another code block.
|
||||
/// yes sirrr.
|
||||
/// ```
|
||||
fn inner_import_thing(
|
||||
/// The args to do shit to.
|
||||
args: Option<kittycad::types::InputFormat>
|
||||
) -> Result<Vec<Box<SketchGroup>>> {
|
||||
args
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert!(!errors.is_empty());
|
||||
assert_eq!(
|
||||
errors[1].to_string(),
|
||||
"stdlib function names must be in camel case: `import_thing`"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_fail_no_code_block() {
|
||||
let (_, errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "import",
|
||||
},
|
||||
quote! {
|
||||
fn inner_import(
|
||||
/// The args to do shit to.
|
||||
args: Option<kittycad::types::InputFormat>
|
||||
) -> Result<Vec<Box<SketchGroup>>> {
|
||||
args
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert!(!errors.is_empty());
|
||||
assert_eq!(
|
||||
errors[1].to_string(),
|
||||
"stdlib functions must have at least one code block"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdlib_fail_name_not_in_code_block() {
|
||||
let (_, errors) = do_stdlib(
|
||||
quote! {
|
||||
name = "import",
|
||||
},
|
||||
quote! {
|
||||
/// This is some function.
|
||||
/// It does shit.
|
||||
///
|
||||
/// This is code.
|
||||
/// It does other shit.
|
||||
///
|
||||
/// ```
|
||||
/// This is another code block.
|
||||
/// yes sirrr.
|
||||
/// ```
|
||||
fn inner_import(
|
||||
/// The args to do shit to.
|
||||
args: Option<kittycad::types::InputFormat>
|
||||
) -> Result<Vec<Box<SketchGroup>>> {
|
||||
args
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert!(!errors.is_empty());
|
||||
assert_eq!(
|
||||
errors[1].to_string(),
|
||||
"stdlib functions must have the function name `import` in the code block"
|
||||
);
|
||||
}
|
91
src/wasm-lib/derive-docs/src/unbox.rs
Normal file
91
src/wasm-lib/derive-docs/src/unbox.rs
Normal file
@ -0,0 +1,91 @@
|
||||
// Unbox a Vec<Box<T>> to Vec<T>.
|
||||
// Unbox a Box<T> to T.
|
||||
pub(crate) fn unbox(t: syn::Type) -> syn::Type {
|
||||
unbox_inner(unbox_vec(t))
|
||||
}
|
||||
|
||||
// Unbox a syn::Type that is boxed to the inner object.
|
||||
fn unbox_inner(t: syn::Type) -> syn::Type {
|
||||
match t {
|
||||
syn::Type::Path(syn::TypePath { ref path, .. }) => {
|
||||
let path = &path.segments;
|
||||
if path.len() == 1 {
|
||||
let seg = &path[0];
|
||||
if seg.ident == "Box" {
|
||||
if let syn::PathArguments::AngleBracketed(syn::AngleBracketedGenericArguments { args, .. }) =
|
||||
&seg.arguments
|
||||
{
|
||||
if args.len() == 1 {
|
||||
let mut args = args.iter();
|
||||
let ok = args.next().unwrap();
|
||||
if let syn::GenericArgument::Type(ty) = ok {
|
||||
return ty.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
t
|
||||
}
|
||||
|
||||
// For a Vec<Box<T>> return Vec<T>.
|
||||
// For a Vec<T> return Vec<T>.
|
||||
fn unbox_vec(t: syn::Type) -> syn::Type {
|
||||
match t {
|
||||
syn::Type::Path(syn::TypePath { ref path, .. }) => {
|
||||
let path = &path.segments;
|
||||
if path.len() == 1 {
|
||||
let seg = &path[0];
|
||||
if seg.ident == "Vec" {
|
||||
if let syn::PathArguments::AngleBracketed(syn::AngleBracketedGenericArguments { args, .. }) =
|
||||
&seg.arguments
|
||||
{
|
||||
if args.len() == 1 {
|
||||
let mut args = args.iter();
|
||||
let ok = args.next().unwrap();
|
||||
if let syn::GenericArgument::Type(ty) = ok {
|
||||
let unboxed = unbox(ty.clone());
|
||||
// Wrap it back in a vec.
|
||||
let wrapped = syn::Type::Path(syn::TypePath {
|
||||
qself: None,
|
||||
path: syn::Path {
|
||||
leading_colon: None,
|
||||
segments: {
|
||||
let mut segments = syn::punctuated::Punctuated::new();
|
||||
segments.push_value(syn::PathSegment {
|
||||
ident: syn::Ident::new("Vec", proc_macro2::Span::call_site()),
|
||||
arguments: syn::PathArguments::AngleBracketed(
|
||||
syn::AngleBracketedGenericArguments {
|
||||
colon2_token: None,
|
||||
lt_token: syn::token::Lt::default(),
|
||||
args: {
|
||||
let mut args = syn::punctuated::Punctuated::new();
|
||||
args.push_value(syn::GenericArgument::Type(unboxed));
|
||||
args
|
||||
},
|
||||
gt_token: syn::token::Gt::default(),
|
||||
},
|
||||
),
|
||||
});
|
||||
segments
|
||||
},
|
||||
},
|
||||
});
|
||||
return wrapped;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
t
|
||||
}
|
@ -1,11 +1,94 @@
|
||||
#[cfg(test)]
|
||||
mod test_examples_show {
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
async fn serial_test_example_show0() {
|
||||
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
|
||||
let http_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60));
|
||||
let ws_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60))
|
||||
.connection_verbose(true)
|
||||
.tcp_keepalive(std::time::Duration::from_secs(600))
|
||||
.http1_only();
|
||||
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
|
||||
let client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
|
||||
let ws = client
|
||||
.modeling()
|
||||
.commands_ws(None, None, None, None, None, Some(false))
|
||||
.await
|
||||
.unwrap();
|
||||
let tokens = crate::token::lexer("This is another code block.\nyes sirrr.\nshow");
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut mem: crate::executor::ProgramMemory = Default::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn::EngineConnection::new(ws)
|
||||
.await
|
||||
.unwrap(),
|
||||
)),
|
||||
fs: crate::fs::FileManager::new(),
|
||||
stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
|
||||
units: kittycad::types::UnitLength::Mm,
|
||||
};
|
||||
crate::executor::execute(program, &mut mem, crate::executor::BodyType::Root, &ctx)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
async fn serial_test_example_show1() {
|
||||
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
|
||||
let http_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60));
|
||||
let ws_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60))
|
||||
.connection_verbose(true)
|
||||
.tcp_keepalive(std::time::Duration::from_secs(600))
|
||||
.http1_only();
|
||||
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
|
||||
let client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
|
||||
let ws = client
|
||||
.modeling()
|
||||
.commands_ws(None, None, None, None, None, Some(false))
|
||||
.await
|
||||
.unwrap();
|
||||
let tokens = crate::token::lexer("This is code.\nIt does other shit.\nshow");
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut mem: crate::executor::ProgramMemory = Default::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn::EngineConnection::new(ws)
|
||||
.await
|
||||
.unwrap(),
|
||||
)),
|
||||
fs: crate::fs::FileManager::new(),
|
||||
stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
|
||||
units: kittycad::types::UnitLength::Mm,
|
||||
};
|
||||
crate::executor::execute(program, &mut mem, crate::executor::BodyType::Root, &ctx)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types, missing_docs)]
|
||||
#[doc = "Std lib function: show"]
|
||||
#[doc = "Std lib function: show\nThis is some function.\nIt does shit."]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, schemars :: JsonSchema, ts_rs :: TS)]
|
||||
#[ts(export)]
|
||||
pub(crate) struct Show {}
|
||||
|
||||
#[allow(non_upper_case_globals, missing_docs)]
|
||||
#[doc = "Std lib function: show"]
|
||||
#[doc = "Std lib function: show\nThis is some function.\nIt does shit."]
|
||||
pub(crate) const Show: Show = Show {};
|
||||
fn boxed_show(
|
||||
args: crate::std::Args,
|
||||
@ -25,11 +108,11 @@ impl crate::docs::StdLibFn for Show {
|
||||
}
|
||||
|
||||
fn summary(&self) -> String {
|
||||
"".to_string()
|
||||
"This is some function.".to_string()
|
||||
}
|
||||
|
||||
fn description(&self) -> String {
|
||||
"".to_string()
|
||||
"It does shit.".to_string()
|
||||
}
|
||||
|
||||
fn tags(&self) -> Vec<String> {
|
||||
@ -68,6 +151,24 @@ impl crate::docs::StdLibFn for Show {
|
||||
false
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<String> {
|
||||
let code_blocks = vec![
|
||||
"This is another code block.\nyes sirrr.\nshow",
|
||||
"This is code.\nIt does other shit.\nshow",
|
||||
];
|
||||
code_blocks
|
||||
.iter()
|
||||
.map(|cb| {
|
||||
let tokens = crate::token::lexer(cb);
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut options: crate::ast::types::FormatOptions = Default::default();
|
||||
options.insert_final_newline = false;
|
||||
program.recast(&options, 0)
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
}
|
||||
|
||||
fn std_lib_fn(&self) -> crate::std::StdFn {
|
||||
boxed_show
|
||||
}
|
||||
@ -77,6 +178,18 @@ impl crate::docs::StdLibFn for Show {
|
||||
}
|
||||
}
|
||||
|
||||
#[doc = r" This is some function."]
|
||||
#[doc = r" It does shit."]
|
||||
#[doc = r""]
|
||||
#[doc = r" This is code."]
|
||||
#[doc = r" It does other shit."]
|
||||
#[doc = r" show"]
|
||||
#[doc = r""]
|
||||
#[doc = r" ```"]
|
||||
#[doc = r" This is another code block."]
|
||||
#[doc = r" yes sirrr."]
|
||||
#[doc = r" show"]
|
||||
#[doc = r" ```"]
|
||||
fn inner_show(#[doc = r" The args to do shit to."] args: [f64; 2]) -> Result<Box<f64>> {
|
||||
args
|
||||
}
|
||||
|
@ -1,11 +1,54 @@
|
||||
#[cfg(test)]
|
||||
mod test_examples_show {
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
async fn serial_test_example_show0() {
|
||||
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
|
||||
let http_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60));
|
||||
let ws_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60))
|
||||
.connection_verbose(true)
|
||||
.tcp_keepalive(std::time::Duration::from_secs(600))
|
||||
.http1_only();
|
||||
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
|
||||
let client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
|
||||
let ws = client
|
||||
.modeling()
|
||||
.commands_ws(None, None, None, None, None, Some(false))
|
||||
.await
|
||||
.unwrap();
|
||||
let tokens = crate::token::lexer("This is code.\nIt does other shit.\nshow");
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut mem: crate::executor::ProgramMemory = Default::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn::EngineConnection::new(ws)
|
||||
.await
|
||||
.unwrap(),
|
||||
)),
|
||||
fs: crate::fs::FileManager::new(),
|
||||
stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
|
||||
units: kittycad::types::UnitLength::Mm,
|
||||
};
|
||||
crate::executor::execute(program, &mut mem, crate::executor::BodyType::Root, &ctx)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types, missing_docs)]
|
||||
#[doc = "Std lib function: show"]
|
||||
#[doc = "Std lib function: show\nThis is some function.\nIt does shit."]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, schemars :: JsonSchema, ts_rs :: TS)]
|
||||
#[ts(export)]
|
||||
pub(crate) struct Show {}
|
||||
|
||||
#[allow(non_upper_case_globals, missing_docs)]
|
||||
#[doc = "Std lib function: show"]
|
||||
#[doc = "Std lib function: show\nThis is some function.\nIt does shit."]
|
||||
pub(crate) const Show: Show = Show {};
|
||||
fn boxed_show(
|
||||
args: crate::std::Args,
|
||||
@ -25,11 +68,11 @@ impl crate::docs::StdLibFn for Show {
|
||||
}
|
||||
|
||||
fn summary(&self) -> String {
|
||||
"".to_string()
|
||||
"This is some function.".to_string()
|
||||
}
|
||||
|
||||
fn description(&self) -> String {
|
||||
"".to_string()
|
||||
"It does shit.".to_string()
|
||||
}
|
||||
|
||||
fn tags(&self) -> Vec<String> {
|
||||
@ -68,6 +111,21 @@ impl crate::docs::StdLibFn for Show {
|
||||
false
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<String> {
|
||||
let code_blocks = vec!["This is code.\nIt does other shit.\nshow"];
|
||||
code_blocks
|
||||
.iter()
|
||||
.map(|cb| {
|
||||
let tokens = crate::token::lexer(cb);
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut options: crate::ast::types::FormatOptions = Default::default();
|
||||
options.insert_final_newline = false;
|
||||
program.recast(&options, 0)
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
}
|
||||
|
||||
fn std_lib_fn(&self) -> crate::std::StdFn {
|
||||
boxed_show
|
||||
}
|
||||
@ -77,6 +135,12 @@ impl crate::docs::StdLibFn for Show {
|
||||
}
|
||||
}
|
||||
|
||||
#[doc = r" This is some function."]
|
||||
#[doc = r" It does shit."]
|
||||
#[doc = r""]
|
||||
#[doc = r" This is code."]
|
||||
#[doc = r" It does other shit."]
|
||||
#[doc = r" show"]
|
||||
fn inner_show(#[doc = r" The args to do shit to."] args: Box<f64>) -> Box<f64> {
|
||||
args
|
||||
}
|
||||
|
197
src/wasm-lib/derive-docs/tests/doc_comment_with_code.gen
Normal file
197
src/wasm-lib/derive-docs/tests/doc_comment_with_code.gen
Normal file
@ -0,0 +1,197 @@
|
||||
#[cfg(test)]
|
||||
mod test_examples_my_func {
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
async fn serial_test_example_my_func0() {
|
||||
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
|
||||
let http_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60));
|
||||
let ws_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60))
|
||||
.connection_verbose(true)
|
||||
.tcp_keepalive(std::time::Duration::from_secs(600))
|
||||
.http1_only();
|
||||
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
|
||||
let client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
|
||||
let ws = client
|
||||
.modeling()
|
||||
.commands_ws(None, None, None, None, None, Some(false))
|
||||
.await
|
||||
.unwrap();
|
||||
let tokens = crate::token::lexer("This is another code block.\nyes sirrr.\nmyFunc");
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut mem: crate::executor::ProgramMemory = Default::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn::EngineConnection::new(ws)
|
||||
.await
|
||||
.unwrap(),
|
||||
)),
|
||||
fs: crate::fs::FileManager::new(),
|
||||
stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
|
||||
units: kittycad::types::UnitLength::Mm,
|
||||
};
|
||||
crate::executor::execute(program, &mut mem, crate::executor::BodyType::Root, &ctx)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
async fn serial_test_example_my_func1() {
|
||||
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
|
||||
let http_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60));
|
||||
let ws_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60))
|
||||
.connection_verbose(true)
|
||||
.tcp_keepalive(std::time::Duration::from_secs(600))
|
||||
.http1_only();
|
||||
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
|
||||
let client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
|
||||
let ws = client
|
||||
.modeling()
|
||||
.commands_ws(None, None, None, None, None, Some(false))
|
||||
.await
|
||||
.unwrap();
|
||||
let tokens = crate::token::lexer("This is code.\nIt does other shit.\nmyFunc");
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut mem: crate::executor::ProgramMemory = Default::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn::EngineConnection::new(ws)
|
||||
.await
|
||||
.unwrap(),
|
||||
)),
|
||||
fs: crate::fs::FileManager::new(),
|
||||
stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
|
||||
units: kittycad::types::UnitLength::Mm,
|
||||
};
|
||||
crate::executor::execute(program, &mut mem, crate::executor::BodyType::Root, &ctx)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types, missing_docs)]
|
||||
#[doc = "Std lib function: myFunc\nThis is some function.\nIt does shit."]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, schemars :: JsonSchema, ts_rs :: TS)]
|
||||
#[ts(export)]
|
||||
pub(crate) struct MyFunc {}
|
||||
|
||||
#[allow(non_upper_case_globals, missing_docs)]
|
||||
#[doc = "Std lib function: myFunc\nThis is some function.\nIt does shit."]
|
||||
pub(crate) const MyFunc: MyFunc = MyFunc {};
|
||||
fn boxed_my_func(
|
||||
args: crate::std::Args,
|
||||
) -> std::pin::Pin<
|
||||
Box<
|
||||
dyn std::future::Future<
|
||||
Output = anyhow::Result<crate::executor::MemoryItem, crate::errors::KclError>,
|
||||
>,
|
||||
>,
|
||||
> {
|
||||
Box::pin(my_func(args))
|
||||
}
|
||||
|
||||
impl crate::docs::StdLibFn for MyFunc {
|
||||
fn name(&self) -> String {
|
||||
"myFunc".to_string()
|
||||
}
|
||||
|
||||
fn summary(&self) -> String {
|
||||
"This is some function.".to_string()
|
||||
}
|
||||
|
||||
fn description(&self) -> String {
|
||||
"It does shit.".to_string()
|
||||
}
|
||||
|
||||
fn tags(&self) -> Vec<String> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn args(&self) -> Vec<crate::docs::StdLibFnArg> {
|
||||
let mut settings = schemars::gen::SchemaSettings::openapi3();
|
||||
settings.inline_subschemas = true;
|
||||
let mut generator = schemars::gen::SchemaGenerator::new(settings);
|
||||
vec![crate::docs::StdLibFnArg {
|
||||
name: "args".to_string(),
|
||||
type_: "kittycad::types::InputFormat".to_string(),
|
||||
schema: <Option<kittycad::types::InputFormat>>::json_schema(&mut generator),
|
||||
required: false,
|
||||
}]
|
||||
}
|
||||
|
||||
fn return_value(&self) -> Option<crate::docs::StdLibFnArg> {
|
||||
let mut settings = schemars::gen::SchemaSettings::openapi3();
|
||||
settings.inline_subschemas = true;
|
||||
let mut generator = schemars::gen::SchemaGenerator::new(settings);
|
||||
Some(crate::docs::StdLibFnArg {
|
||||
name: "".to_string(),
|
||||
type_: "[SketchGroup]".to_string(),
|
||||
schema: <Vec<SketchGroup>>::json_schema(&mut generator),
|
||||
required: true,
|
||||
})
|
||||
}
|
||||
|
||||
fn unpublished(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn deprecated(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<String> {
|
||||
let code_blocks = vec![
|
||||
"This is another code block.\nyes sirrr.\nmyFunc",
|
||||
"This is code.\nIt does other shit.\nmyFunc",
|
||||
];
|
||||
code_blocks
|
||||
.iter()
|
||||
.map(|cb| {
|
||||
let tokens = crate::token::lexer(cb);
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut options: crate::ast::types::FormatOptions = Default::default();
|
||||
options.insert_final_newline = false;
|
||||
program.recast(&options, 0)
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
}
|
||||
|
||||
fn std_lib_fn(&self) -> crate::std::StdFn {
|
||||
boxed_my_func
|
||||
}
|
||||
|
||||
fn clone_box(&self) -> Box<dyn crate::docs::StdLibFn> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
#[doc = r" This is some function."]
|
||||
#[doc = r" It does shit."]
|
||||
#[doc = r""]
|
||||
#[doc = r" This is code."]
|
||||
#[doc = r" It does other shit."]
|
||||
#[doc = r" myFunc"]
|
||||
#[doc = r""]
|
||||
#[doc = r" ```"]
|
||||
#[doc = r" This is another code block."]
|
||||
#[doc = r" yes sirrr."]
|
||||
#[doc = r" myFunc"]
|
||||
#[doc = r" ```"]
|
||||
fn inner_my_func(
|
||||
#[doc = r" The args to do shit to."] args: Option<kittycad::types::InputFormat>,
|
||||
) -> Result<Vec<Box<SketchGroup>>> {
|
||||
args
|
||||
}
|
@ -0,0 +1,199 @@
|
||||
#[cfg(test)]
|
||||
mod test_examples_import {
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
#[ignore]
|
||||
async fn serial_test_example_import0() {
|
||||
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
|
||||
let http_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60));
|
||||
let ws_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60))
|
||||
.connection_verbose(true)
|
||||
.tcp_keepalive(std::time::Duration::from_secs(600))
|
||||
.http1_only();
|
||||
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
|
||||
let client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
|
||||
let ws = client
|
||||
.modeling()
|
||||
.commands_ws(None, None, None, None, None, Some(false))
|
||||
.await
|
||||
.unwrap();
|
||||
let tokens = crate::token::lexer("This is another code block.\nyes sirrr.\nimport");
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut mem: crate::executor::ProgramMemory = Default::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn::EngineConnection::new(ws)
|
||||
.await
|
||||
.unwrap(),
|
||||
)),
|
||||
fs: crate::fs::FileManager::new(),
|
||||
stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
|
||||
units: kittycad::types::UnitLength::Mm,
|
||||
};
|
||||
crate::executor::execute(program, &mut mem, crate::executor::BodyType::Root, &ctx)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
#[ignore]
|
||||
async fn serial_test_example_import1() {
|
||||
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
|
||||
let http_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60));
|
||||
let ws_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60))
|
||||
.connection_verbose(true)
|
||||
.tcp_keepalive(std::time::Duration::from_secs(600))
|
||||
.http1_only();
|
||||
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
|
||||
let client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
|
||||
let ws = client
|
||||
.modeling()
|
||||
.commands_ws(None, None, None, None, None, Some(false))
|
||||
.await
|
||||
.unwrap();
|
||||
let tokens = crate::token::lexer("This is code.\nIt does other shit.\nimport");
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut mem: crate::executor::ProgramMemory = Default::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn::EngineConnection::new(ws)
|
||||
.await
|
||||
.unwrap(),
|
||||
)),
|
||||
fs: crate::fs::FileManager::new(),
|
||||
stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
|
||||
units: kittycad::types::UnitLength::Mm,
|
||||
};
|
||||
crate::executor::execute(program, &mut mem, crate::executor::BodyType::Root, &ctx)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types, missing_docs)]
|
||||
#[doc = "Std lib function: import\nThis is some function.\nIt does shit."]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, schemars :: JsonSchema, ts_rs :: TS)]
|
||||
#[ts(export)]
|
||||
pub(crate) struct Import {}
|
||||
|
||||
#[allow(non_upper_case_globals, missing_docs)]
|
||||
#[doc = "Std lib function: import\nThis is some function.\nIt does shit."]
|
||||
pub(crate) const Import: Import = Import {};
|
||||
fn boxed_import(
|
||||
args: crate::std::Args,
|
||||
) -> std::pin::Pin<
|
||||
Box<
|
||||
dyn std::future::Future<
|
||||
Output = anyhow::Result<crate::executor::MemoryItem, crate::errors::KclError>,
|
||||
>,
|
||||
>,
|
||||
> {
|
||||
Box::pin(import(args))
|
||||
}
|
||||
|
||||
impl crate::docs::StdLibFn for Import {
|
||||
fn name(&self) -> String {
|
||||
"import".to_string()
|
||||
}
|
||||
|
||||
fn summary(&self) -> String {
|
||||
"This is some function.".to_string()
|
||||
}
|
||||
|
||||
fn description(&self) -> String {
|
||||
"It does shit.".to_string()
|
||||
}
|
||||
|
||||
fn tags(&self) -> Vec<String> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn args(&self) -> Vec<crate::docs::StdLibFnArg> {
|
||||
let mut settings = schemars::gen::SchemaSettings::openapi3();
|
||||
settings.inline_subschemas = true;
|
||||
let mut generator = schemars::gen::SchemaGenerator::new(settings);
|
||||
vec![crate::docs::StdLibFnArg {
|
||||
name: "args".to_string(),
|
||||
type_: "kittycad::types::InputFormat".to_string(),
|
||||
schema: <Option<kittycad::types::InputFormat>>::json_schema(&mut generator),
|
||||
required: false,
|
||||
}]
|
||||
}
|
||||
|
||||
fn return_value(&self) -> Option<crate::docs::StdLibFnArg> {
|
||||
let mut settings = schemars::gen::SchemaSettings::openapi3();
|
||||
settings.inline_subschemas = true;
|
||||
let mut generator = schemars::gen::SchemaGenerator::new(settings);
|
||||
Some(crate::docs::StdLibFnArg {
|
||||
name: "".to_string(),
|
||||
type_: "[SketchGroup]".to_string(),
|
||||
schema: <Vec<SketchGroup>>::json_schema(&mut generator),
|
||||
required: true,
|
||||
})
|
||||
}
|
||||
|
||||
fn unpublished(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn deprecated(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<String> {
|
||||
let code_blocks = vec![
|
||||
"This is another code block.\nyes sirrr.\nimport",
|
||||
"This is code.\nIt does other shit.\nimport",
|
||||
];
|
||||
code_blocks
|
||||
.iter()
|
||||
.map(|cb| {
|
||||
let tokens = crate::token::lexer(cb);
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut options: crate::ast::types::FormatOptions = Default::default();
|
||||
options.insert_final_newline = false;
|
||||
program.recast(&options, 0)
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
}
|
||||
|
||||
fn std_lib_fn(&self) -> crate::std::StdFn {
|
||||
boxed_import
|
||||
}
|
||||
|
||||
fn clone_box(&self) -> Box<dyn crate::docs::StdLibFn> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
#[doc = r" This is some function."]
|
||||
#[doc = r" It does shit."]
|
||||
#[doc = r""]
|
||||
#[doc = r" This is code."]
|
||||
#[doc = r" It does other shit."]
|
||||
#[doc = r" import"]
|
||||
#[doc = r""]
|
||||
#[doc = r" ```"]
|
||||
#[doc = r" This is another code block."]
|
||||
#[doc = r" yes sirrr."]
|
||||
#[doc = r" import"]
|
||||
#[doc = r" ```"]
|
||||
fn inner_import(
|
||||
#[doc = r" The args to do shit to."] args: Option<kittycad::types::InputFormat>,
|
||||
) -> Result<Vec<Box<SketchGroup>>> {
|
||||
args
|
||||
}
|
@ -1,11 +1,94 @@
|
||||
#[cfg(test)]
|
||||
mod test_examples_line_to {
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
async fn serial_test_example_line_to0() {
|
||||
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
|
||||
let http_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60));
|
||||
let ws_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60))
|
||||
.connection_verbose(true)
|
||||
.tcp_keepalive(std::time::Duration::from_secs(600))
|
||||
.http1_only();
|
||||
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
|
||||
let client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
|
||||
let ws = client
|
||||
.modeling()
|
||||
.commands_ws(None, None, None, None, None, Some(false))
|
||||
.await
|
||||
.unwrap();
|
||||
let tokens = crate::token::lexer("This is another code block.\nyes sirrr.\nlineTo");
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut mem: crate::executor::ProgramMemory = Default::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn::EngineConnection::new(ws)
|
||||
.await
|
||||
.unwrap(),
|
||||
)),
|
||||
fs: crate::fs::FileManager::new(),
|
||||
stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
|
||||
units: kittycad::types::UnitLength::Mm,
|
||||
};
|
||||
crate::executor::execute(program, &mut mem, crate::executor::BodyType::Root, &ctx)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
async fn serial_test_example_line_to1() {
|
||||
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
|
||||
let http_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60));
|
||||
let ws_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60))
|
||||
.connection_verbose(true)
|
||||
.tcp_keepalive(std::time::Duration::from_secs(600))
|
||||
.http1_only();
|
||||
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
|
||||
let client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
|
||||
let ws = client
|
||||
.modeling()
|
||||
.commands_ws(None, None, None, None, None, Some(false))
|
||||
.await
|
||||
.unwrap();
|
||||
let tokens = crate::token::lexer("This is code.\nIt does other shit.\nlineTo");
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut mem: crate::executor::ProgramMemory = Default::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn::EngineConnection::new(ws)
|
||||
.await
|
||||
.unwrap(),
|
||||
)),
|
||||
fs: crate::fs::FileManager::new(),
|
||||
stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
|
||||
units: kittycad::types::UnitLength::Mm,
|
||||
};
|
||||
crate::executor::execute(program, &mut mem, crate::executor::BodyType::Root, &ctx)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types, missing_docs)]
|
||||
#[doc = "Std lib function: lineTo"]
|
||||
#[doc = "Std lib function: lineTo\nThis is some function.\nIt does shit."]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, schemars :: JsonSchema, ts_rs :: TS)]
|
||||
#[ts(export)]
|
||||
pub(crate) struct LineTo {}
|
||||
|
||||
#[allow(non_upper_case_globals, missing_docs)]
|
||||
#[doc = "Std lib function: lineTo"]
|
||||
#[doc = "Std lib function: lineTo\nThis is some function.\nIt does shit."]
|
||||
pub(crate) const LineTo: LineTo = LineTo {};
|
||||
fn boxed_line_to(
|
||||
args: crate::std::Args,
|
||||
@ -25,11 +108,11 @@ impl crate::docs::StdLibFn for LineTo {
|
||||
}
|
||||
|
||||
fn summary(&self) -> String {
|
||||
"".to_string()
|
||||
"This is some function.".to_string()
|
||||
}
|
||||
|
||||
fn description(&self) -> String {
|
||||
"".to_string()
|
||||
"It does shit.".to_string()
|
||||
}
|
||||
|
||||
fn tags(&self) -> Vec<String> {
|
||||
@ -76,6 +159,24 @@ impl crate::docs::StdLibFn for LineTo {
|
||||
false
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<String> {
|
||||
let code_blocks = vec![
|
||||
"This is another code block.\nyes sirrr.\nlineTo",
|
||||
"This is code.\nIt does other shit.\nlineTo",
|
||||
];
|
||||
code_blocks
|
||||
.iter()
|
||||
.map(|cb| {
|
||||
let tokens = crate::token::lexer(cb);
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut options: crate::ast::types::FormatOptions = Default::default();
|
||||
options.insert_final_newline = false;
|
||||
program.recast(&options, 0)
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
}
|
||||
|
||||
fn std_lib_fn(&self) -> crate::std::StdFn {
|
||||
boxed_line_to
|
||||
}
|
||||
@ -85,6 +186,18 @@ impl crate::docs::StdLibFn for LineTo {
|
||||
}
|
||||
}
|
||||
|
||||
#[doc = r" This is some function."]
|
||||
#[doc = r" It does shit."]
|
||||
#[doc = r""]
|
||||
#[doc = r" This is code."]
|
||||
#[doc = r" It does other shit."]
|
||||
#[doc = r" lineTo"]
|
||||
#[doc = r""]
|
||||
#[doc = r" ```"]
|
||||
#[doc = r" This is another code block."]
|
||||
#[doc = r" yes sirrr."]
|
||||
#[doc = r" lineTo"]
|
||||
#[doc = r" ```"]
|
||||
fn inner_line_to(
|
||||
data: LineToData,
|
||||
sketch_group: SketchGroup,
|
||||
|
@ -1,11 +1,94 @@
|
||||
#[cfg(test)]
|
||||
mod test_examples_min {
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
async fn serial_test_example_min0() {
|
||||
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
|
||||
let http_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60));
|
||||
let ws_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60))
|
||||
.connection_verbose(true)
|
||||
.tcp_keepalive(std::time::Duration::from_secs(600))
|
||||
.http1_only();
|
||||
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
|
||||
let client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
|
||||
let ws = client
|
||||
.modeling()
|
||||
.commands_ws(None, None, None, None, None, Some(false))
|
||||
.await
|
||||
.unwrap();
|
||||
let tokens = crate::token::lexer("This is another code block.\nyes sirrr.\nmin");
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut mem: crate::executor::ProgramMemory = Default::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn::EngineConnection::new(ws)
|
||||
.await
|
||||
.unwrap(),
|
||||
)),
|
||||
fs: crate::fs::FileManager::new(),
|
||||
stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
|
||||
units: kittycad::types::UnitLength::Mm,
|
||||
};
|
||||
crate::executor::execute(program, &mut mem, crate::executor::BodyType::Root, &ctx)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
async fn serial_test_example_min1() {
|
||||
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
|
||||
let http_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60));
|
||||
let ws_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60))
|
||||
.connection_verbose(true)
|
||||
.tcp_keepalive(std::time::Duration::from_secs(600))
|
||||
.http1_only();
|
||||
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
|
||||
let client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
|
||||
let ws = client
|
||||
.modeling()
|
||||
.commands_ws(None, None, None, None, None, Some(false))
|
||||
.await
|
||||
.unwrap();
|
||||
let tokens = crate::token::lexer("This is code.\nIt does other shit.\nmin");
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut mem: crate::executor::ProgramMemory = Default::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn::EngineConnection::new(ws)
|
||||
.await
|
||||
.unwrap(),
|
||||
)),
|
||||
fs: crate::fs::FileManager::new(),
|
||||
stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
|
||||
units: kittycad::types::UnitLength::Mm,
|
||||
};
|
||||
crate::executor::execute(program, &mut mem, crate::executor::BodyType::Root, &ctx)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types, missing_docs)]
|
||||
#[doc = "Std lib function: min"]
|
||||
#[doc = "Std lib function: min\nThis is some function.\nIt does shit."]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, schemars :: JsonSchema, ts_rs :: TS)]
|
||||
#[ts(export)]
|
||||
pub(crate) struct Min {}
|
||||
|
||||
#[allow(non_upper_case_globals, missing_docs)]
|
||||
#[doc = "Std lib function: min"]
|
||||
#[doc = "Std lib function: min\nThis is some function.\nIt does shit."]
|
||||
pub(crate) const Min: Min = Min {};
|
||||
fn boxed_min(
|
||||
args: crate::std::Args,
|
||||
@ -25,11 +108,11 @@ impl crate::docs::StdLibFn for Min {
|
||||
}
|
||||
|
||||
fn summary(&self) -> String {
|
||||
"".to_string()
|
||||
"This is some function.".to_string()
|
||||
}
|
||||
|
||||
fn description(&self) -> String {
|
||||
"".to_string()
|
||||
"It does shit.".to_string()
|
||||
}
|
||||
|
||||
fn tags(&self) -> Vec<String> {
|
||||
@ -68,6 +151,24 @@ impl crate::docs::StdLibFn for Min {
|
||||
false
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<String> {
|
||||
let code_blocks = vec![
|
||||
"This is another code block.\nyes sirrr.\nmin",
|
||||
"This is code.\nIt does other shit.\nmin",
|
||||
];
|
||||
code_blocks
|
||||
.iter()
|
||||
.map(|cb| {
|
||||
let tokens = crate::token::lexer(cb);
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut options: crate::ast::types::FormatOptions = Default::default();
|
||||
options.insert_final_newline = false;
|
||||
program.recast(&options, 0)
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
}
|
||||
|
||||
fn std_lib_fn(&self) -> crate::std::StdFn {
|
||||
boxed_min
|
||||
}
|
||||
@ -77,6 +178,18 @@ impl crate::docs::StdLibFn for Min {
|
||||
}
|
||||
}
|
||||
|
||||
#[doc = r" This is some function."]
|
||||
#[doc = r" It does shit."]
|
||||
#[doc = r""]
|
||||
#[doc = r" This is code."]
|
||||
#[doc = r" It does other shit."]
|
||||
#[doc = r" min"]
|
||||
#[doc = r""]
|
||||
#[doc = r" ```"]
|
||||
#[doc = r" This is another code block."]
|
||||
#[doc = r" yes sirrr."]
|
||||
#[doc = r" min"]
|
||||
#[doc = r" ```"]
|
||||
fn inner_min(#[doc = r" The args to do shit to."] args: Vec<f64>) -> f64 {
|
||||
let mut min = std::f64::MAX;
|
||||
for arg in args.iter() {
|
||||
|
@ -1,11 +1,54 @@
|
||||
#[cfg(test)]
|
||||
mod test_examples_show {
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
async fn serial_test_example_show0() {
|
||||
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
|
||||
let http_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60));
|
||||
let ws_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60))
|
||||
.connection_verbose(true)
|
||||
.tcp_keepalive(std::time::Duration::from_secs(600))
|
||||
.http1_only();
|
||||
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
|
||||
let client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
|
||||
let ws = client
|
||||
.modeling()
|
||||
.commands_ws(None, None, None, None, None, Some(false))
|
||||
.await
|
||||
.unwrap();
|
||||
let tokens = crate::token::lexer("This is code.\nIt does other shit.\nshow");
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut mem: crate::executor::ProgramMemory = Default::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn::EngineConnection::new(ws)
|
||||
.await
|
||||
.unwrap(),
|
||||
)),
|
||||
fs: crate::fs::FileManager::new(),
|
||||
stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
|
||||
units: kittycad::types::UnitLength::Mm,
|
||||
};
|
||||
crate::executor::execute(program, &mut mem, crate::executor::BodyType::Root, &ctx)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types, missing_docs)]
|
||||
#[doc = "Std lib function: show"]
|
||||
#[doc = "Std lib function: show\nThis is some function.\nIt does shit."]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, schemars :: JsonSchema, ts_rs :: TS)]
|
||||
#[ts(export)]
|
||||
pub(crate) struct Show {}
|
||||
|
||||
#[allow(non_upper_case_globals, missing_docs)]
|
||||
#[doc = "Std lib function: show"]
|
||||
#[doc = "Std lib function: show\nThis is some function.\nIt does shit."]
|
||||
pub(crate) const Show: Show = Show {};
|
||||
fn boxed_show(
|
||||
args: crate::std::Args,
|
||||
@ -25,11 +68,11 @@ impl crate::docs::StdLibFn for Show {
|
||||
}
|
||||
|
||||
fn summary(&self) -> String {
|
||||
"".to_string()
|
||||
"This is some function.".to_string()
|
||||
}
|
||||
|
||||
fn description(&self) -> String {
|
||||
"".to_string()
|
||||
"It does shit.".to_string()
|
||||
}
|
||||
|
||||
fn tags(&self) -> Vec<String> {
|
||||
@ -68,6 +111,21 @@ impl crate::docs::StdLibFn for Show {
|
||||
false
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<String> {
|
||||
let code_blocks = vec!["This is code.\nIt does other shit.\nshow"];
|
||||
code_blocks
|
||||
.iter()
|
||||
.map(|cb| {
|
||||
let tokens = crate::token::lexer(cb);
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut options: crate::ast::types::FormatOptions = Default::default();
|
||||
options.insert_final_newline = false;
|
||||
program.recast(&options, 0)
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
}
|
||||
|
||||
fn std_lib_fn(&self) -> crate::std::StdFn {
|
||||
boxed_show
|
||||
}
|
||||
@ -77,6 +135,12 @@ impl crate::docs::StdLibFn for Show {
|
||||
}
|
||||
}
|
||||
|
||||
#[doc = r" This is some function."]
|
||||
#[doc = r" It does shit."]
|
||||
#[doc = r""]
|
||||
#[doc = r" This is code."]
|
||||
#[doc = r" It does other shit."]
|
||||
#[doc = r" show"]
|
||||
fn inner_show(#[doc = r" The args to do shit to."] args: Option<f64>) -> Result<Box<f64>> {
|
||||
args
|
||||
}
|
||||
|
@ -1,11 +1,55 @@
|
||||
#[cfg(test)]
|
||||
mod test_examples_import {
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
#[ignore]
|
||||
async fn serial_test_example_import0() {
|
||||
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
|
||||
let http_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60));
|
||||
let ws_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60))
|
||||
.connection_verbose(true)
|
||||
.tcp_keepalive(std::time::Duration::from_secs(600))
|
||||
.http1_only();
|
||||
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
|
||||
let client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
|
||||
let ws = client
|
||||
.modeling()
|
||||
.commands_ws(None, None, None, None, None, Some(false))
|
||||
.await
|
||||
.unwrap();
|
||||
let tokens = crate::token::lexer("This is code.\nIt does other shit.\nimport");
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut mem: crate::executor::ProgramMemory = Default::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn::EngineConnection::new(ws)
|
||||
.await
|
||||
.unwrap(),
|
||||
)),
|
||||
fs: crate::fs::FileManager::new(),
|
||||
stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
|
||||
units: kittycad::types::UnitLength::Mm,
|
||||
};
|
||||
crate::executor::execute(program, &mut mem, crate::executor::BodyType::Root, &ctx)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types, missing_docs)]
|
||||
#[doc = "Std lib function: import"]
|
||||
#[doc = "Std lib function: import\nThis is some function.\nIt does shit."]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, schemars :: JsonSchema, ts_rs :: TS)]
|
||||
#[ts(export)]
|
||||
pub(crate) struct Import {}
|
||||
|
||||
#[allow(non_upper_case_globals, missing_docs)]
|
||||
#[doc = "Std lib function: import"]
|
||||
#[doc = "Std lib function: import\nThis is some function.\nIt does shit."]
|
||||
pub(crate) const Import: Import = Import {};
|
||||
fn boxed_import(
|
||||
args: crate::std::Args,
|
||||
@ -25,11 +69,11 @@ impl crate::docs::StdLibFn for Import {
|
||||
}
|
||||
|
||||
fn summary(&self) -> String {
|
||||
"".to_string()
|
||||
"This is some function.".to_string()
|
||||
}
|
||||
|
||||
fn description(&self) -> String {
|
||||
"".to_string()
|
||||
"It does shit.".to_string()
|
||||
}
|
||||
|
||||
fn tags(&self) -> Vec<String> {
|
||||
@ -68,6 +112,21 @@ impl crate::docs::StdLibFn for Import {
|
||||
false
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<String> {
|
||||
let code_blocks = vec!["This is code.\nIt does other shit.\nimport"];
|
||||
code_blocks
|
||||
.iter()
|
||||
.map(|cb| {
|
||||
let tokens = crate::token::lexer(cb);
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut options: crate::ast::types::FormatOptions = Default::default();
|
||||
options.insert_final_newline = false;
|
||||
program.recast(&options, 0)
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
}
|
||||
|
||||
fn std_lib_fn(&self) -> crate::std::StdFn {
|
||||
boxed_import
|
||||
}
|
||||
@ -77,6 +136,12 @@ impl crate::docs::StdLibFn for Import {
|
||||
}
|
||||
}
|
||||
|
||||
#[doc = r" This is some function."]
|
||||
#[doc = r" It does shit."]
|
||||
#[doc = r""]
|
||||
#[doc = r" This is code."]
|
||||
#[doc = r" It does other shit."]
|
||||
#[doc = r" import"]
|
||||
fn inner_import(
|
||||
#[doc = r" The args to do shit to."] args: Option<kittycad::types::InputFormat>,
|
||||
) -> Result<Box<f64>> {
|
||||
|
@ -1,11 +1,55 @@
|
||||
#[cfg(test)]
|
||||
mod test_examples_import {
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
#[ignore]
|
||||
async fn serial_test_example_import0() {
|
||||
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
|
||||
let http_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60));
|
||||
let ws_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60))
|
||||
.connection_verbose(true)
|
||||
.tcp_keepalive(std::time::Duration::from_secs(600))
|
||||
.http1_only();
|
||||
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
|
||||
let client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
|
||||
let ws = client
|
||||
.modeling()
|
||||
.commands_ws(None, None, None, None, None, Some(false))
|
||||
.await
|
||||
.unwrap();
|
||||
let tokens = crate::token::lexer("This is code.\nIt does other shit.\nimport");
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut mem: crate::executor::ProgramMemory = Default::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn::EngineConnection::new(ws)
|
||||
.await
|
||||
.unwrap(),
|
||||
)),
|
||||
fs: crate::fs::FileManager::new(),
|
||||
stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
|
||||
units: kittycad::types::UnitLength::Mm,
|
||||
};
|
||||
crate::executor::execute(program, &mut mem, crate::executor::BodyType::Root, &ctx)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types, missing_docs)]
|
||||
#[doc = "Std lib function: import"]
|
||||
#[doc = "Std lib function: import\nThis is some function.\nIt does shit."]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, schemars :: JsonSchema, ts_rs :: TS)]
|
||||
#[ts(export)]
|
||||
pub(crate) struct Import {}
|
||||
|
||||
#[allow(non_upper_case_globals, missing_docs)]
|
||||
#[doc = "Std lib function: import"]
|
||||
#[doc = "Std lib function: import\nThis is some function.\nIt does shit."]
|
||||
pub(crate) const Import: Import = Import {};
|
||||
fn boxed_import(
|
||||
args: crate::std::Args,
|
||||
@ -25,11 +69,11 @@ impl crate::docs::StdLibFn for Import {
|
||||
}
|
||||
|
||||
fn summary(&self) -> String {
|
||||
"".to_string()
|
||||
"This is some function.".to_string()
|
||||
}
|
||||
|
||||
fn description(&self) -> String {
|
||||
"".to_string()
|
||||
"It does shit.".to_string()
|
||||
}
|
||||
|
||||
fn tags(&self) -> Vec<String> {
|
||||
@ -68,6 +112,21 @@ impl crate::docs::StdLibFn for Import {
|
||||
false
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<String> {
|
||||
let code_blocks = vec!["This is code.\nIt does other shit.\nimport"];
|
||||
code_blocks
|
||||
.iter()
|
||||
.map(|cb| {
|
||||
let tokens = crate::token::lexer(cb);
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut options: crate::ast::types::FormatOptions = Default::default();
|
||||
options.insert_final_newline = false;
|
||||
program.recast(&options, 0)
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
}
|
||||
|
||||
fn std_lib_fn(&self) -> crate::std::StdFn {
|
||||
boxed_import
|
||||
}
|
||||
@ -77,6 +136,12 @@ impl crate::docs::StdLibFn for Import {
|
||||
}
|
||||
}
|
||||
|
||||
#[doc = r" This is some function."]
|
||||
#[doc = r" It does shit."]
|
||||
#[doc = r""]
|
||||
#[doc = r" This is code."]
|
||||
#[doc = r" It does other shit."]
|
||||
#[doc = r" import"]
|
||||
fn inner_import(
|
||||
#[doc = r" The args to do shit to."] args: Option<kittycad::types::InputFormat>,
|
||||
) -> Result<Vec<Box<SketchGroup>>> {
|
||||
|
@ -1,11 +1,55 @@
|
||||
#[cfg(test)]
|
||||
mod test_examples_import {
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
#[ignore]
|
||||
async fn serial_test_example_import0() {
|
||||
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
|
||||
let http_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60));
|
||||
let ws_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60))
|
||||
.connection_verbose(true)
|
||||
.tcp_keepalive(std::time::Duration::from_secs(600))
|
||||
.http1_only();
|
||||
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
|
||||
let client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
|
||||
let ws = client
|
||||
.modeling()
|
||||
.commands_ws(None, None, None, None, None, Some(false))
|
||||
.await
|
||||
.unwrap();
|
||||
let tokens = crate::token::lexer("This is code.\nIt does other shit.\nimport");
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut mem: crate::executor::ProgramMemory = Default::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn::EngineConnection::new(ws)
|
||||
.await
|
||||
.unwrap(),
|
||||
)),
|
||||
fs: crate::fs::FileManager::new(),
|
||||
stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
|
||||
units: kittycad::types::UnitLength::Mm,
|
||||
};
|
||||
crate::executor::execute(program, &mut mem, crate::executor::BodyType::Root, &ctx)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types, missing_docs)]
|
||||
#[doc = "Std lib function: import"]
|
||||
#[doc = "Std lib function: import\nThis is some function.\nIt does shit."]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, schemars :: JsonSchema, ts_rs :: TS)]
|
||||
#[ts(export)]
|
||||
pub(crate) struct Import {}
|
||||
|
||||
#[allow(non_upper_case_globals, missing_docs)]
|
||||
#[doc = "Std lib function: import"]
|
||||
#[doc = "Std lib function: import\nThis is some function.\nIt does shit."]
|
||||
pub(crate) const Import: Import = Import {};
|
||||
fn boxed_import(
|
||||
args: crate::std::Args,
|
||||
@ -25,11 +69,11 @@ impl crate::docs::StdLibFn for Import {
|
||||
}
|
||||
|
||||
fn summary(&self) -> String {
|
||||
"".to_string()
|
||||
"This is some function.".to_string()
|
||||
}
|
||||
|
||||
fn description(&self) -> String {
|
||||
"".to_string()
|
||||
"It does shit.".to_string()
|
||||
}
|
||||
|
||||
fn tags(&self) -> Vec<String> {
|
||||
@ -68,6 +112,21 @@ impl crate::docs::StdLibFn for Import {
|
||||
false
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<String> {
|
||||
let code_blocks = vec!["This is code.\nIt does other shit.\nimport"];
|
||||
code_blocks
|
||||
.iter()
|
||||
.map(|cb| {
|
||||
let tokens = crate::token::lexer(cb);
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut options: crate::ast::types::FormatOptions = Default::default();
|
||||
options.insert_final_newline = false;
|
||||
program.recast(&options, 0)
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
}
|
||||
|
||||
fn std_lib_fn(&self) -> crate::std::StdFn {
|
||||
boxed_import
|
||||
}
|
||||
@ -77,6 +136,12 @@ impl crate::docs::StdLibFn for Import {
|
||||
}
|
||||
}
|
||||
|
||||
#[doc = r" This is some function."]
|
||||
#[doc = r" It does shit."]
|
||||
#[doc = r""]
|
||||
#[doc = r" This is code."]
|
||||
#[doc = r" It does other shit."]
|
||||
#[doc = r" import"]
|
||||
fn inner_import(
|
||||
#[doc = r" The args to do shit to."] args: Option<kittycad::types::InputFormat>,
|
||||
) -> Result<Vec<SketchGroup>> {
|
||||
|
@ -1,11 +1,54 @@
|
||||
#[cfg(test)]
|
||||
mod test_examples_show {
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
|
||||
async fn serial_test_example_show0() {
|
||||
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
|
||||
let http_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60));
|
||||
let ws_client = reqwest::Client::builder()
|
||||
.user_agent(user_agent)
|
||||
.timeout(std::time::Duration::from_secs(600))
|
||||
.connect_timeout(std::time::Duration::from_secs(60))
|
||||
.connection_verbose(true)
|
||||
.tcp_keepalive(std::time::Duration::from_secs(600))
|
||||
.http1_only();
|
||||
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
|
||||
let client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
|
||||
let ws = client
|
||||
.modeling()
|
||||
.commands_ws(None, None, None, None, None, Some(false))
|
||||
.await
|
||||
.unwrap();
|
||||
let tokens = crate::token::lexer("This is code.\nIt does other shit.\nshow");
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut mem: crate::executor::ProgramMemory = Default::default();
|
||||
let ctx = crate::executor::ExecutorContext {
|
||||
engine: std::sync::Arc::new(Box::new(
|
||||
crate::engine::conn::EngineConnection::new(ws)
|
||||
.await
|
||||
.unwrap(),
|
||||
)),
|
||||
fs: crate::fs::FileManager::new(),
|
||||
stdlib: std::sync::Arc::new(crate::std::StdLib::new()),
|
||||
units: kittycad::types::UnitLength::Mm,
|
||||
};
|
||||
crate::executor::execute(program, &mut mem, crate::executor::BodyType::Root, &ctx)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types, missing_docs)]
|
||||
#[doc = "Std lib function: show"]
|
||||
#[doc = "Std lib function: show\nThis is some function.\nIt does shit."]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, schemars :: JsonSchema, ts_rs :: TS)]
|
||||
#[ts(export)]
|
||||
pub(crate) struct Show {}
|
||||
|
||||
#[allow(non_upper_case_globals, missing_docs)]
|
||||
#[doc = "Std lib function: show"]
|
||||
#[doc = "Std lib function: show\nThis is some function.\nIt does shit."]
|
||||
pub(crate) const Show: Show = Show {};
|
||||
fn boxed_show(
|
||||
args: crate::std::Args,
|
||||
@ -25,11 +68,11 @@ impl crate::docs::StdLibFn for Show {
|
||||
}
|
||||
|
||||
fn summary(&self) -> String {
|
||||
"".to_string()
|
||||
"This is some function.".to_string()
|
||||
}
|
||||
|
||||
fn description(&self) -> String {
|
||||
"".to_string()
|
||||
"It does shit.".to_string()
|
||||
}
|
||||
|
||||
fn tags(&self) -> Vec<String> {
|
||||
@ -68,6 +111,21 @@ impl crate::docs::StdLibFn for Show {
|
||||
false
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<String> {
|
||||
let code_blocks = vec!["This is code.\nIt does other shit.\nshow"];
|
||||
code_blocks
|
||||
.iter()
|
||||
.map(|cb| {
|
||||
let tokens = crate::token::lexer(cb);
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast().unwrap();
|
||||
let mut options: crate::ast::types::FormatOptions = Default::default();
|
||||
options.insert_final_newline = false;
|
||||
program.recast(&options, 0)
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
}
|
||||
|
||||
fn std_lib_fn(&self) -> crate::std::StdFn {
|
||||
boxed_show
|
||||
}
|
||||
@ -77,4 +135,10 @@ impl crate::docs::StdLibFn for Show {
|
||||
}
|
||||
}
|
||||
|
||||
#[doc = r" This is some function."]
|
||||
#[doc = r" It does shit."]
|
||||
#[doc = r""]
|
||||
#[doc = r" This is code."]
|
||||
#[doc = r" It does other shit."]
|
||||
#[doc = r" show"]
|
||||
fn inner_show(#[doc = r" The args to do shit to."] _args: Vec<f64>) {}
|
||||
|
@ -18,8 +18,8 @@ chrono = "0.4.35"
|
||||
clap = { version = "4.5.2", features = ["cargo", "derive", "env", "unicode"], optional = true }
|
||||
dashmap = "5.5.3"
|
||||
databake = { version = "0.1.7", features = ["derive"] }
|
||||
derive-docs = { version = "0.1.10" }
|
||||
#derive-docs = { path = "../derive-docs" }
|
||||
#derive-docs = { version = "0.1.11" }
|
||||
derive-docs = { path = "../derive-docs" }
|
||||
futures = { version = "0.3.30" }
|
||||
gltf-json = "1.4.0"
|
||||
kittycad = { workspace = true }
|
||||
|
@ -1,12 +1,13 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use kittycad::types::{ModelingCmd, Point3D};
|
||||
|
||||
use super::types::ConstraintLevel;
|
||||
use crate::{
|
||||
ast::types::{
|
||||
ArrayExpression, CallExpression, FormatOptions, Literal, PipeExpression, PipeSubstitution, Program,
|
||||
VariableDeclarator,
|
||||
ArrayExpression, CallExpression, ConstraintLevel, FormatOptions, Literal, PipeExpression, PipeSubstitution,
|
||||
Program, VariableDeclarator,
|
||||
},
|
||||
engine::{EngineConnection, EngineManager},
|
||||
engine::EngineManager,
|
||||
errors::{KclError, KclErrorDetails},
|
||||
executor::{Point2d, SourceRange},
|
||||
};
|
||||
@ -27,7 +28,7 @@ const EPSILON: f64 = 0.015625; // or 2^-6
|
||||
/// Update the AST to reflect the new state of the program after something like
|
||||
/// a move or a new line.
|
||||
pub async fn modify_ast_for_sketch(
|
||||
engine: &mut EngineConnection,
|
||||
engine: &Arc<Box<dyn EngineManager>>,
|
||||
program: &mut Program,
|
||||
// The name of the sketch.
|
||||
sketch_name: &str,
|
||||
|
@ -30,6 +30,9 @@ pub struct StdLibFnData {
|
||||
pub unpublished: bool,
|
||||
/// If the function is deprecated.
|
||||
pub deprecated: bool,
|
||||
/// Code examples.
|
||||
/// These are tested and we know they compile and execute.
|
||||
pub examples: Vec<String>,
|
||||
}
|
||||
|
||||
/// This struct defines a single argument to a stdlib function.
|
||||
@ -105,6 +108,9 @@ pub trait StdLibFn: std::fmt::Debug + Send + Sync {
|
||||
/// If the function is deprecated.
|
||||
fn deprecated(&self) -> bool;
|
||||
|
||||
/// Any example code blocks.
|
||||
fn examples(&self) -> Vec<String>;
|
||||
|
||||
/// The function itself.
|
||||
fn std_lib_fn(&self) -> crate::std::StdFn;
|
||||
|
||||
@ -122,6 +128,7 @@ pub trait StdLibFn: std::fmt::Debug + Send + Sync {
|
||||
return_value: self.return_value(),
|
||||
unpublished: self.unpublished(),
|
||||
deprecated: self.deprecated(),
|
||||
examples: self.examples(),
|
||||
})
|
||||
}
|
||||
|
||||
@ -560,7 +567,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_deserialize_function() {
|
||||
let some_function_string = r#"{"type":"StdLib","func":{"name":"line","summary":"","description":"","tags":[],"returnValue":{"type":"","required":false,"name":"","schema":{}},"args":[],"unpublished":false,"deprecated":false}}"#;
|
||||
let some_function_string = r#"{"type":"StdLib","func":{"name":"line","summary":"","description":"","tags":[],"returnValue":{"type":"","required":false,"name":"","schema":{}},"args":[],"unpublished":false,"deprecated":false, "examples": []}}"#;
|
||||
let some_function: crate::ast::types::Function = serde_json::from_str(some_function_string).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
|
@ -1,38 +1,15 @@
|
||||
//! Functions for managing engine communications.
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
#[cfg(not(test))]
|
||||
#[cfg(feature = "engine")]
|
||||
pub mod conn;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
#[cfg(not(test))]
|
||||
#[cfg(feature = "engine")]
|
||||
pub use conn::EngineConnection;
|
||||
|
||||
pub mod conn_mock;
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[cfg(not(test))]
|
||||
#[cfg(feature = "engine")]
|
||||
pub mod conn_wasm;
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[cfg(not(test))]
|
||||
#[cfg(feature = "engine")]
|
||||
pub use conn_wasm::EngineConnection;
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod conn_mock;
|
||||
#[cfg(test)]
|
||||
pub use conn_mock::EngineConnection;
|
||||
|
||||
#[cfg(not(feature = "engine"))]
|
||||
#[cfg(not(test))]
|
||||
pub mod conn_mock;
|
||||
use anyhow::Result;
|
||||
#[cfg(not(feature = "engine"))]
|
||||
#[cfg(not(test))]
|
||||
pub use conn_mock::EngineConnection;
|
||||
|
||||
#[async_trait::async_trait]
|
||||
pub trait EngineManager: Clone {
|
||||
pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
||||
/// Send a modeling command and wait for the response message.
|
||||
async fn send_modeling_cmd(
|
||||
&self,
|
||||
|
@ -13,7 +13,7 @@ use tower_lsp::lsp_types::{Position as LspPosition, Range as LspRange};
|
||||
|
||||
use crate::{
|
||||
ast::types::{BodyItem, FunctionExpression, KclNone, Value},
|
||||
engine::{EngineConnection, EngineManager},
|
||||
engine::EngineManager,
|
||||
errors::{KclError, KclErrorDetails},
|
||||
fs::FileManager,
|
||||
std::{FunctionKind, StdLib},
|
||||
@ -977,30 +977,19 @@ impl Default for PipeInfo {
|
||||
/// The executor context.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ExecutorContext {
|
||||
pub engine: EngineConnection,
|
||||
pub engine: Arc<Box<dyn EngineManager>>,
|
||||
pub fs: FileManager,
|
||||
pub stdlib: Arc<StdLib>,
|
||||
pub units: kittycad::types::UnitLength,
|
||||
}
|
||||
|
||||
impl ExecutorContext {
|
||||
/// Create a new default executor context.
|
||||
#[cfg(test)]
|
||||
pub async fn new(units: kittycad::types::UnitLength) -> Result<Self> {
|
||||
Ok(Self {
|
||||
engine: EngineConnection::new().await?,
|
||||
fs: FileManager::new(),
|
||||
stdlib: Arc::new(StdLib::new()),
|
||||
units,
|
||||
})
|
||||
}
|
||||
|
||||
/// Create a new default executor context.
|
||||
#[cfg(not(test))]
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub async fn new(ws: reqwest::Upgraded, units: kittycad::types::UnitLength) -> Result<Self> {
|
||||
Ok(Self {
|
||||
engine: EngineConnection::new(ws).await?,
|
||||
engine: Arc::new(Box::new(crate::engine::conn::EngineConnection::new(ws).await?)),
|
||||
fs: FileManager::new(),
|
||||
stdlib: Arc::new(StdLib::new()),
|
||||
units,
|
||||
@ -1290,6 +1279,8 @@ fn assign_args_to_params(
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::sync::Arc;
|
||||
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
use super::*;
|
||||
@ -1300,7 +1291,12 @@ mod tests {
|
||||
let parser = crate::parser::Parser::new(tokens);
|
||||
let program = parser.ast()?;
|
||||
let mut mem: ProgramMemory = Default::default();
|
||||
let ctx = ExecutorContext::new(kittycad::types::UnitLength::Mm).await?;
|
||||
let ctx = ExecutorContext {
|
||||
engine: Arc::new(Box::new(crate::engine::conn_mock::EngineConnection::new().await?)),
|
||||
fs: crate::fs::FileManager::new(),
|
||||
stdlib: Arc::new(crate::std::StdLib::new()),
|
||||
units: kittycad::types::UnitLength::Mm,
|
||||
};
|
||||
let memory = execute(program, &mut mem, BodyType::Root, &ctx).await?;
|
||||
|
||||
Ok(memory)
|
||||
|
@ -24,13 +24,12 @@ use tower_lsp::{
|
||||
LanguageServer,
|
||||
};
|
||||
|
||||
use self::types::{CopilotAcceptCompletionParams, CopilotCompletionTelemetry, CopilotRejectCompletionParams};
|
||||
use crate::lsp::{
|
||||
backend::Backend as _,
|
||||
copilot::types::{CopilotCompletionResponse, CopilotEditorInfo, CopilotLspCompletionParams, DocParams},
|
||||
};
|
||||
|
||||
use self::types::{CopilotAcceptCompletionParams, CopilotCompletionTelemetry, CopilotRejectCompletionParams};
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug)]
|
||||
pub struct Success {
|
||||
success: bool,
|
||||
|
@ -20,6 +20,16 @@ pub async fn extrude(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Extrudes by a given amount.
|
||||
///
|
||||
/// ```no_run
|
||||
/// startSketchOn('XY')
|
||||
/// |> startProfileAt([0, 0], %)
|
||||
/// |> line([0, 10], %)
|
||||
/// |> line([10, 0], %)
|
||||
/// |> line([0, -10], %)
|
||||
/// |> close(%)
|
||||
/// |> extrude(5, %)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "extrude"
|
||||
}]
|
||||
@ -180,6 +190,18 @@ pub async fn get_extrude_wall_transform(args: Args) -> Result<MemoryItem, KclErr
|
||||
}
|
||||
|
||||
/// Returns the extrude wall transform.
|
||||
///
|
||||
/// ```no_run
|
||||
/// const box = startSketchOn('XY')
|
||||
/// |> startProfileAt([0, 0], %)
|
||||
/// |> line([0, 10], %)
|
||||
/// |> line([10, 0], %)
|
||||
/// |> line({to: [0, -10], tag: "surface"}, %)
|
||||
/// |> close(%)
|
||||
/// |> extrude(5, %)
|
||||
///
|
||||
/// const transform = getExtrudeWallTransform('surface', box)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "getExtrudeWallTransform"
|
||||
}]
|
||||
|
@ -44,6 +44,17 @@ pub async fn fillet(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Create fillets on tagged paths.
|
||||
///
|
||||
/// ```no_run
|
||||
/// const part001 = startSketchOn('XY')
|
||||
/// |> startProfileAt([0,0], %)
|
||||
/// |> line({to: [0, 10], tag: "thing"}, %)
|
||||
/// |> line([10, 0], %)
|
||||
/// |> line({to: [0, -10], tag: "thing2"}, %)
|
||||
/// |> close(%)
|
||||
/// |> extrude(10, %)
|
||||
/// |> fillet({radius: 2, tags: ["thing", "thing2"]}, %)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "fillet",
|
||||
}]
|
||||
@ -115,6 +126,17 @@ pub async fn get_opposite_edge(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Get the opposite edge to the edge given.
|
||||
///
|
||||
/// ```no_run
|
||||
/// const part001 = startSketchOn('XY')
|
||||
/// |> startProfileAt([0,0], %)
|
||||
/// |> line({to: [0, 10], tag: "thing"}, %)
|
||||
/// |> line([10, 0], %)
|
||||
/// |> line({to: [0, -10], tag: "thing2"}, %)
|
||||
/// |> close(%)
|
||||
/// |> extrude(10, %)
|
||||
/// |> fillet({radius: 2, tags: ["thing", getOppositeEdge("thing", %)]}, %)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "getOppositeEdge",
|
||||
}]
|
||||
@ -173,6 +195,17 @@ pub async fn get_next_adjacent_edge(args: Args) -> Result<MemoryItem, KclError>
|
||||
}
|
||||
|
||||
/// Get the next adjacent edge to the edge given.
|
||||
///
|
||||
/// ```no_run
|
||||
/// const part001 = startSketchOn('XY')
|
||||
/// |> startProfileAt([0,0], %)
|
||||
/// |> line({to: [0, 10], tag: "thing"}, %)
|
||||
/// |> line({to: [10, 0], tag: "thing1"}, %)
|
||||
/// |> line({to: [0, -10], tag: "thing2"}, %)
|
||||
/// |> close(%)
|
||||
/// |> extrude(10, %)
|
||||
/// |> fillet({radius: 2, tags: [getNextAdjacentEdge("thing", %)]}, %)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "getNextAdjacentEdge",
|
||||
}]
|
||||
@ -240,6 +273,17 @@ pub async fn get_previous_adjacent_edge(args: Args) -> Result<MemoryItem, KclErr
|
||||
}
|
||||
|
||||
/// Get the previous adjacent edge to the edge given.
|
||||
///
|
||||
/// ```no_run
|
||||
/// const part001 = startSketchOn('XY')
|
||||
/// |> startProfileAt([0,0], %)
|
||||
/// |> line({to: [0, 10], tag: "thing"}, %)
|
||||
/// |> line({to: [10, 0], tag: "thing1"}, %)
|
||||
/// |> line({to: [0, -10], tag: "thing2"}, %)
|
||||
/// |> close(%)
|
||||
/// |> extrude(10, %)
|
||||
/// |> fillet({radius: 2, tags: [getPreviousAdjacentEdge("thing2", %)]}, %)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "getPreviousAdjacentEdge",
|
||||
}]
|
||||
|
@ -127,6 +127,26 @@ pub async fn import(args: Args) -> Result<MemoryItem, KclError> {
|
||||
///
|
||||
/// Import paths are relative to the current project directory. This only works in the desktop app
|
||||
/// not in browser.
|
||||
///
|
||||
/// ```no_run
|
||||
/// const model = import("thing.obj")
|
||||
/// ```
|
||||
///
|
||||
/// ```no_run
|
||||
/// const model = import("cube.obj", {type: "obj", units: "m"})
|
||||
/// ```
|
||||
///
|
||||
/// ```no_run
|
||||
/// const model = import("my_model.gltf")
|
||||
/// ```
|
||||
///
|
||||
/// ```no_run
|
||||
/// const model = import("my_model.sldprt")
|
||||
/// ```
|
||||
///
|
||||
/// ```no_run
|
||||
/// const model = import("my_model.step")
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "import",
|
||||
}]
|
||||
|
@ -19,6 +19,10 @@ pub async fn cos(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Computes the sine of a number (in radians).
|
||||
///
|
||||
/// ```no_run
|
||||
/// const anotherVar = cos(2*pi())
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "cos",
|
||||
}]
|
||||
@ -35,6 +39,10 @@ pub async fn sin(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Computes the sine of a number (in radians).
|
||||
///
|
||||
/// ```no_run
|
||||
/// const myVar = sin(2*pi())
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "sin",
|
||||
}]
|
||||
@ -51,6 +59,10 @@ pub async fn tan(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Computes the tangent of a number (in radians).
|
||||
///
|
||||
/// ```no_run
|
||||
/// const myVar = tan(2*pi())
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "tan",
|
||||
}]
|
||||
@ -66,6 +78,10 @@ pub async fn pi(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Return the value of `pi`. Archimedes’ constant (π).
|
||||
///
|
||||
/// ```no_run
|
||||
/// const myVar = pi() * 3.0
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "pi",
|
||||
}]
|
||||
@ -82,6 +98,10 @@ pub async fn sqrt(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Computes the square root of a number.
|
||||
///
|
||||
/// ```no_run
|
||||
/// const myVar = sqrt(4)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "sqrt",
|
||||
}]
|
||||
@ -98,6 +118,10 @@ pub async fn abs(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Computes the absolute value of a number.
|
||||
///
|
||||
/// ```no_run
|
||||
/// const myVar = abs(-4)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "abs",
|
||||
}]
|
||||
@ -114,6 +138,10 @@ pub async fn floor(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Computes the largest integer less than or equal to a number.
|
||||
///
|
||||
/// ```no_run
|
||||
/// const myVar = floor(4.5)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "floor",
|
||||
}]
|
||||
@ -130,6 +158,10 @@ pub async fn ceil(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Computes the smallest integer greater than or equal to a number.
|
||||
///
|
||||
/// ```no_run
|
||||
/// const myVar = ceil(4.5)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "ceil",
|
||||
}]
|
||||
@ -146,6 +178,10 @@ pub async fn min(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Computes the minimum of the given arguments.
|
||||
///
|
||||
/// ```no_run
|
||||
/// const myVar = min(4, 5, 6)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "min",
|
||||
}]
|
||||
@ -169,6 +205,10 @@ pub async fn max(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Computes the maximum of the given arguments.
|
||||
///
|
||||
/// ```no_run
|
||||
/// const myVar = max(4, 5, 6)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "max",
|
||||
}]
|
||||
@ -206,6 +246,10 @@ pub async fn pow(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Computes the number to a power.
|
||||
///
|
||||
/// ```no_run
|
||||
/// const myVar = pow(4, 2)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "pow",
|
||||
}]
|
||||
@ -222,6 +266,10 @@ pub async fn acos(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Computes the arccosine of a number (in radians).
|
||||
///
|
||||
/// ```no_run
|
||||
/// const myVar = acos(0.5)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "acos",
|
||||
}]
|
||||
@ -238,6 +286,10 @@ pub async fn asin(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Computes the arcsine of a number (in radians).
|
||||
///
|
||||
/// ```no_run
|
||||
/// const myVar = asin(0.5)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "asin",
|
||||
}]
|
||||
@ -254,6 +306,10 @@ pub async fn atan(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Computes the arctangent of a number (in radians).
|
||||
///
|
||||
/// ```no_run
|
||||
/// const myVar = atan(1.0)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "atan",
|
||||
}]
|
||||
@ -291,6 +347,10 @@ pub async fn log(args: Args) -> Result<MemoryItem, KclError> {
|
||||
/// The result might not be correctly rounded owing to implementation
|
||||
/// details; `log2()` can produce more accurate results for base 2,
|
||||
/// and `log10()` can produce more accurate results for base 10.
|
||||
///
|
||||
/// ```no_run
|
||||
/// const myVar = log(4, 2)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "log",
|
||||
}]
|
||||
@ -307,6 +367,10 @@ pub async fn log2(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Computes the base 2 logarithm of the number.
|
||||
///
|
||||
/// ```no_run
|
||||
/// const myVar = log2(4)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "log2",
|
||||
}]
|
||||
@ -323,6 +387,10 @@ pub async fn log10(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Computes the base 10 logarithm of the number.
|
||||
///
|
||||
/// ```no_run
|
||||
/// const myVar = log10(4)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "log10",
|
||||
}]
|
||||
@ -339,6 +407,10 @@ pub async fn ln(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Computes the natural logarithm of the number.
|
||||
///
|
||||
/// ```no_run
|
||||
/// const myVar = ln(4)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "ln",
|
||||
}]
|
||||
@ -354,6 +426,10 @@ pub async fn e(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Return the value of Euler’s number `e`.
|
||||
///
|
||||
/// ```no_run
|
||||
/// const myVar = e()
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "e",
|
||||
}]
|
||||
@ -369,6 +445,10 @@ pub async fn tau(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Return the value of `tau`. The full circle constant (τ). Equal to 2π.
|
||||
///
|
||||
/// ```no_run
|
||||
/// const myVar = tau()
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "tau",
|
||||
}]
|
||||
@ -377,33 +457,41 @@ fn inner_tau() -> Result<f64, KclError> {
|
||||
}
|
||||
|
||||
/// Converts a number from degrees to radians.
|
||||
pub async fn deg_to_rad(args: Args) -> Result<MemoryItem, KclError> {
|
||||
pub async fn to_radians(args: Args) -> Result<MemoryItem, KclError> {
|
||||
let num = args.get_number()?;
|
||||
let result = inner_deg_to_rad(num)?;
|
||||
let result = inner_to_radians(num)?;
|
||||
|
||||
args.make_user_val_from_f64(result)
|
||||
}
|
||||
|
||||
/// Converts a number from degrees to radians.
|
||||
///
|
||||
/// ```no_run
|
||||
/// const myVar = toRadians(180)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "to_radians",
|
||||
name = "toRadians",
|
||||
}]
|
||||
fn inner_deg_to_rad(num: f64) -> Result<f64, KclError> {
|
||||
fn inner_to_radians(num: f64) -> Result<f64, KclError> {
|
||||
Ok(num.to_radians())
|
||||
}
|
||||
|
||||
/// Converts a number from radians to degrees.
|
||||
pub async fn rad_to_deg(args: Args) -> Result<MemoryItem, KclError> {
|
||||
pub async fn to_degrees(args: Args) -> Result<MemoryItem, KclError> {
|
||||
let num = args.get_number()?;
|
||||
let result = inner_rad_to_deg(num)?;
|
||||
let result = inner_to_degrees(num)?;
|
||||
|
||||
args.make_user_val_from_f64(result)
|
||||
}
|
||||
|
||||
/// Converts a number from radians to degrees.
|
||||
///
|
||||
/// ```no_run
|
||||
/// const myVar = toDegrees(2 * pi())
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "to_degrees",
|
||||
name = "toDegrees",
|
||||
}]
|
||||
fn inner_rad_to_deg(num: f64) -> Result<f64, KclError> {
|
||||
fn inner_to_degrees(num: f64) -> Result<f64, KclError> {
|
||||
Ok(num.to_degrees())
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ use serde::{Deserialize, Serialize};
|
||||
use crate::{
|
||||
ast::types::parse_json_number_as_f64,
|
||||
docs::StdLibFn,
|
||||
engine::EngineManager,
|
||||
errors::{KclError, KclErrorDetails},
|
||||
executor::{
|
||||
ExecutorContext, ExtrudeGroup, MemoryItem, Metadata, SketchGroup, SketchGroupSet, SketchSurface, SourceRange,
|
||||
@ -760,6 +759,10 @@ pub async fn leg_length(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Returns the length of the given leg.
|
||||
///
|
||||
/// ```no_run
|
||||
/// legLen(5, 3)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "legLen",
|
||||
}]
|
||||
@ -775,6 +778,10 @@ pub async fn leg_angle_x(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Returns the angle of the given leg for x.
|
||||
///
|
||||
/// ```no_run
|
||||
/// legAngX(5, 3)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "legAngX",
|
||||
}]
|
||||
@ -790,6 +797,10 @@ pub async fn leg_angle_y(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Returns the angle of the given leg for y.
|
||||
///
|
||||
/// ```no_run
|
||||
/// legAngY(5, 3)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "legAngY",
|
||||
}]
|
||||
@ -868,6 +879,16 @@ mod tests {
|
||||
fn_docs.push_str(&signature);
|
||||
fn_docs.push_str("\n```\n\n");
|
||||
|
||||
if !internal_fn.examples().is_empty() {
|
||||
fn_docs.push_str("#### Examples\n\n");
|
||||
|
||||
for example in internal_fn.examples() {
|
||||
fn_docs.push_str("```kcl\n");
|
||||
fn_docs.push_str(&example);
|
||||
fn_docs.push_str("\n```\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
fn_docs.push_str("#### Arguments\n\n");
|
||||
for arg in internal_fn.args() {
|
||||
let (format, should_be_indented) = arg.get_type_string().unwrap();
|
||||
|
@ -88,6 +88,12 @@ pub async fn pattern_linear_2d(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// A linear pattern on a 2D sketch.
|
||||
///
|
||||
/// ```no_run
|
||||
/// const part = startSketchOn('XY')
|
||||
/// |> circle([0,0], 2, %)
|
||||
/// |> patternLinear2d({axis: [0,1], repetitions: 12, distance: 2}, %)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "patternLinear2d",
|
||||
}]
|
||||
@ -131,6 +137,17 @@ pub async fn pattern_linear_3d(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// A linear pattern on a 3D model.
|
||||
///
|
||||
/// ```no_run
|
||||
/// const part = startSketchOn('XY')
|
||||
/// |> startProfileAt([0, 0], %)
|
||||
/// |> line([0,1], %)
|
||||
/// |> line([1, 0], %)
|
||||
/// |> line([0, -1], %)
|
||||
/// |> close(%)
|
||||
/// |> extrude(1, %)
|
||||
/// |> patternLinear3d({axis: [1, 0, 1], repetitions: 3, distance: 6}, %)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "patternLinear3d",
|
||||
}]
|
||||
@ -296,6 +313,12 @@ pub async fn pattern_circular_2d(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// A circular pattern on a 2D sketch.
|
||||
///
|
||||
/// ```no_run
|
||||
/// const part = startSketchOn('XY')
|
||||
/// |> circle([0,0], 2, %)
|
||||
/// |> patternCircular2d({center: [20, 20], repetitions: 12, arcDegrees: 210, rotateDuplicates: true}, %)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "patternCircular2d",
|
||||
}]
|
||||
@ -330,6 +353,17 @@ pub async fn pattern_circular_3d(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// A circular pattern on a 3D model.
|
||||
///
|
||||
/// ```no_run
|
||||
/// const part = startSketchOn('XY')
|
||||
/// |> startProfileAt([0, 0], %)
|
||||
/// |> line([0,1], %)
|
||||
/// |> line([1, 0], %)
|
||||
/// |> line([0, -1], %)
|
||||
/// |> close(%)
|
||||
/// |> extrude(1, %)
|
||||
/// |> patternCircular3d({axis: [1,1,0], center: [10, 0, 10], repetitions: 10, arcDegrees: 360, rotateDuplicates: true}, %)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "patternCircular3d",
|
||||
}]
|
||||
|
@ -20,6 +20,16 @@ pub async fn segment_end_x(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Returns the segment end of x.
|
||||
///
|
||||
/// ```no_run
|
||||
/// startSketchOn("YZ")
|
||||
/// |> startProfileAt([0, 0], %)
|
||||
/// |> line({ to: [5, 0], tag: "thing" }, %)
|
||||
/// |> line([5, 5], %)
|
||||
/// |> line([segEndX("thing", %), 5], %)
|
||||
/// |> close(%)
|
||||
/// |> extrude(5, %)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "segEndX",
|
||||
}]
|
||||
@ -46,6 +56,16 @@ pub async fn segment_end_y(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Returns the segment end of y.
|
||||
///
|
||||
/// ```no_run
|
||||
/// startSketchOn("YZ")
|
||||
/// |> startProfileAt([0, 0], %)
|
||||
/// |> line({ to: [5, 0], tag: "thing" }, %)
|
||||
/// |> line([5, 5], %)
|
||||
/// |> line([segEndY("thing", %), 5], %)
|
||||
/// |> close(%)
|
||||
/// |> extrude(5, %)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "segEndY",
|
||||
}]
|
||||
@ -72,6 +92,16 @@ pub async fn last_segment_x(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Returns the last segment of x.
|
||||
///
|
||||
/// ```no_run
|
||||
/// startSketchOn("YZ")
|
||||
/// |> startProfileAt([0, 0], %)
|
||||
/// |> line({ to: [5, 0], tag: "thing" }, %)
|
||||
/// |> line([5, 5], %)
|
||||
/// |> line([0, lastSegX(%)], %)
|
||||
/// |> close(%)
|
||||
/// |> extrude(5, %)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "lastSegX",
|
||||
}]
|
||||
@ -102,6 +132,16 @@ pub async fn last_segment_y(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Returns the last segment of y.
|
||||
///
|
||||
/// ```no_run
|
||||
/// startSketchOn("YZ")
|
||||
/// |> startProfileAt([0, 0], %)
|
||||
/// |> line({ to: [5, 0], tag: "thing" }, %)
|
||||
/// |> line([5, 5], %)
|
||||
/// |> line([0, lastSegY(%)], %)
|
||||
/// |> close(%)
|
||||
/// |> extrude(5, %)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "lastSegY",
|
||||
}]
|
||||
@ -131,6 +171,16 @@ pub async fn segment_length(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Returns the length of the segment.
|
||||
///
|
||||
/// ```no_run
|
||||
/// startSketchOn("YZ")
|
||||
/// |> startProfileAt([0, 0], %)
|
||||
/// |> line({ to: [5, 0], tag: "thing" }, %)
|
||||
/// |> line([5, 5], %)
|
||||
/// |> line([0, segLen("thing", %)], %)
|
||||
/// |> close(%)
|
||||
/// |> extrude(5, %)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "segLen",
|
||||
}]
|
||||
@ -160,6 +210,18 @@ pub async fn segment_angle(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Returns the angle of the segment.
|
||||
///
|
||||
/// ```no_run
|
||||
/// const part001 = startSketchOn('XY')
|
||||
/// |> startProfileAt([4.83, 12.56], %)
|
||||
/// |> line([15.1, 2.48], %)
|
||||
/// |> line({ to: [3.15, -9.85], tag: 'seg01' }, %)
|
||||
/// |> line([-15.17, -4.1], %)
|
||||
/// |> angledLine([segAng('seg01', %), 12.35], %)
|
||||
/// |> line([-13.02, 10.03], %)
|
||||
/// |> close(%)
|
||||
/// |> extrude(4, %)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "segAng",
|
||||
}]
|
||||
@ -188,6 +250,17 @@ pub async fn angle_to_match_length_x(args: Args) -> Result<MemoryItem, KclError>
|
||||
}
|
||||
|
||||
/// Returns the angle to match the given length for x.
|
||||
///
|
||||
/// ```no_run
|
||||
/// const part001 = startSketchOn('XY')
|
||||
/// |> startProfileAt([0, 0], %)
|
||||
/// |> line({ to: [1, 3.82], tag: 'seg01' }, %)
|
||||
/// |> angledLineToX([
|
||||
/// -angleToMatchLengthX('seg01', 10, %),
|
||||
/// 5
|
||||
/// ], %)
|
||||
/// |> close(%)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "angleToMatchLengthX",
|
||||
}]
|
||||
@ -243,6 +316,17 @@ pub async fn angle_to_match_length_y(args: Args) -> Result<MemoryItem, KclError>
|
||||
}
|
||||
|
||||
/// Returns the angle to match the given length for y.
|
||||
///
|
||||
/// ```no_run
|
||||
/// const part001 = startSketchOn('XY')
|
||||
/// |> startProfileAt([0, 0], %)
|
||||
/// |> line({ to: [1, 3.82], tag: 'seg01' }, %)
|
||||
/// |> angledLineToX([
|
||||
/// -angleToMatchLengthY('seg01', 10, %),
|
||||
/// 5
|
||||
/// ], %)
|
||||
/// |> close(%)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "angleToMatchLengthY",
|
||||
}]
|
||||
|
@ -128,6 +128,10 @@ impl StdLibFn for Circle {
|
||||
false
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<String> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn std_lib_fn(&self) -> crate::std::StdFn {
|
||||
todo!()
|
||||
}
|
||||
|
@ -48,6 +48,30 @@ pub async fn line_to(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Draw a line to a point.
|
||||
///
|
||||
/// ```no_run
|
||||
/// fn rectShape = (pos, w, l) => {
|
||||
/// const rr = startSketchOn('YZ')
|
||||
/// |> startProfileAt([pos[0] - (w / 2), pos[1] - (l / 2)], %)
|
||||
/// |> lineTo({
|
||||
/// to: [pos[0] + w / 2, pos[1] - (l / 2)],
|
||||
/// tag: "edge1"
|
||||
/// }, %)
|
||||
/// |> lineTo({
|
||||
/// to: [pos[0] + w / 2, pos[1] + l / 2],
|
||||
/// tag: "edge2"
|
||||
/// }, %)
|
||||
/// |> lineTo({
|
||||
/// to: [pos[0] - (w / 2), pos[1] + l / 2],
|
||||
/// tag: "edge3"
|
||||
/// }, %)
|
||||
/// |> close(%, "edge4")
|
||||
/// return rr
|
||||
/// }
|
||||
///
|
||||
/// // Create the mounting plate extrusion, holes, and fillets
|
||||
/// const part = rectShape([0, 0], 20, 20)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "lineTo",
|
||||
}]
|
||||
@ -127,6 +151,18 @@ pub async fn x_line_to(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Draw a line to a point on the x-axis.
|
||||
///
|
||||
/// ```no_run
|
||||
/// startSketchOn('XY')
|
||||
/// |> startProfileAt([0, 0], %)
|
||||
/// |> xLineTo({
|
||||
/// to: 10,
|
||||
/// tag: "edge1"
|
||||
/// }, %)
|
||||
/// |> line([10, 10], %)
|
||||
/// |> close(%, "edge2")
|
||||
/// |> extrude(10, %)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "xLineTo",
|
||||
}]
|
||||
@ -156,6 +192,19 @@ pub async fn y_line_to(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Draw a line to a point on the y-axis.
|
||||
///
|
||||
/// ```no_run
|
||||
/// startSketchOn('XZ')
|
||||
/// |> startProfileAt([0, 0], %)
|
||||
/// |> yLineTo({
|
||||
/// to: 10,
|
||||
/// tag: "edge1"
|
||||
/// }, %)
|
||||
/// |> line([10, 10], %)
|
||||
/// |> close(%, "edge2")
|
||||
/// |> extrude(10, %)
|
||||
/// |> fillet({radius: 2, tags: ["edge2"]}, %)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "yLineTo",
|
||||
}]
|
||||
@ -200,6 +249,15 @@ pub async fn line(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Draw a line.
|
||||
///
|
||||
/// ```no_run
|
||||
/// startSketchOn('-XY')
|
||||
/// |> startProfileAt([0, 0], %)
|
||||
/// |> line([10, 10], %)
|
||||
/// |> line({to: [20, 10], tag: "edge1"}, %)
|
||||
/// |> close(%, "edge2")
|
||||
/// |> extrude(10, %)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "line",
|
||||
}]
|
||||
@ -278,6 +336,15 @@ pub async fn x_line(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Draw a line on the x-axis.
|
||||
///
|
||||
/// ```no_run
|
||||
/// startSketchOn('YZ')
|
||||
/// |> startProfileAt([0, 0], %)
|
||||
/// |> xLine(10, %)
|
||||
/// |> line([10, 10], %)
|
||||
/// |> close(%, "edge1")
|
||||
/// |> extrude(10, %)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "xLine",
|
||||
}]
|
||||
@ -304,6 +371,15 @@ pub async fn y_line(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Draw a line on the y-axis.
|
||||
///
|
||||
/// ```no_run
|
||||
/// startSketchOn('XY')
|
||||
/// |> startProfileAt([0, 0], %)
|
||||
/// |> yLine(10, %)
|
||||
/// |> line([10, 10], %)
|
||||
/// |> close(%, "edge1")
|
||||
/// |> extrude(10, %)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "yLine",
|
||||
}]
|
||||
@ -358,6 +434,20 @@ pub async fn angled_line(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Draw an angled line.
|
||||
///
|
||||
/// ```no_run
|
||||
/// startSketchOn('XY')
|
||||
/// |> startProfileAt([0, 0], %)
|
||||
/// |> angledLine({
|
||||
/// angle: 45,
|
||||
/// length: 10,
|
||||
/// tag: "edge1"
|
||||
/// }, %)
|
||||
/// |> line([10, 10], %)
|
||||
/// |> line([0, 10], %)
|
||||
/// |> close(%, "edge2")
|
||||
/// |> extrude(10, %)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "angledLine",
|
||||
}]
|
||||
@ -429,6 +519,20 @@ pub async fn angled_line_of_x_length(args: Args) -> Result<MemoryItem, KclError>
|
||||
}
|
||||
|
||||
/// Draw an angled line of a given x length.
|
||||
///
|
||||
/// ```no_run
|
||||
/// startSketchOn('XZ')
|
||||
/// |> startProfileAt([0, 0], %)
|
||||
/// |> angledLineOfXLength({
|
||||
/// angle: 45,
|
||||
/// length: 10,
|
||||
/// tag: "edge1"
|
||||
/// }, %)
|
||||
/// |> line([10, 10], %)
|
||||
/// |> line([0, 10], %)
|
||||
/// |> close(%, "edge2")
|
||||
/// |> extrude(10, %)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "angledLineOfXLength",
|
||||
}]
|
||||
@ -486,6 +590,21 @@ pub async fn angled_line_to_x(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Draw an angled line to a given x coordinate.
|
||||
///
|
||||
/// ```no_run
|
||||
/// startSketchOn('XY')
|
||||
/// |> startProfileAt([0, 0], %)
|
||||
/// |> angledLineToX({
|
||||
/// angle: 45,
|
||||
/// to: 10,
|
||||
/// tag: "edge1"
|
||||
/// }, %)
|
||||
/// |> line([10, 10], %)
|
||||
/// |> line([0, 10], %)
|
||||
/// |> close(%, "edge2")
|
||||
/// |> extrude(10, %)
|
||||
/// |> fillet({radius: 2, tags: ["edge1"]}, %)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "angledLineToX",
|
||||
}]
|
||||
@ -518,6 +637,21 @@ pub async fn angled_line_of_y_length(args: Args) -> Result<MemoryItem, KclError>
|
||||
}
|
||||
|
||||
/// Draw an angled line of a given y length.
|
||||
///
|
||||
/// ```no_run
|
||||
/// startSketchOn('YZ')
|
||||
/// |> startProfileAt([0, 0], %)
|
||||
/// |> angledLineOfYLength({
|
||||
/// angle: 45,
|
||||
/// length: 10,
|
||||
/// tag: "edge1"
|
||||
/// }, %)
|
||||
/// |> line([10, 10], %)
|
||||
/// |> line([0, 10], %)
|
||||
/// |> close(%, "edge2")
|
||||
/// |> extrude(10, %)
|
||||
/// |> fillet({radius: 2, tags: ["edge1"]}, %)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "angledLineOfYLength",
|
||||
}]
|
||||
@ -547,6 +681,20 @@ pub async fn angled_line_to_y(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Draw an angled line to a given y coordinate.
|
||||
///
|
||||
/// ```no_run
|
||||
/// startSketchOn('XY')
|
||||
/// |> startProfileAt([0, 0], %)
|
||||
/// |> angledLineToY({
|
||||
/// angle: 45,
|
||||
/// to: 10,
|
||||
/// tag: "edge1"
|
||||
/// }, %)
|
||||
/// |> line([10, 10], %)
|
||||
/// |> line([0, 10], %)
|
||||
/// |> close(%, "edge2")
|
||||
/// |> extrude(10, %)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "angledLineToY",
|
||||
}]
|
||||
@ -593,6 +741,22 @@ pub async fn angled_line_that_intersects(args: Args) -> Result<MemoryItem, KclEr
|
||||
}
|
||||
|
||||
/// Draw an angled line that intersects with a given line.
|
||||
///
|
||||
/// ```no_run
|
||||
/// const part001 = startSketchOn('XY')
|
||||
/// |> startProfileAt([0, 0], %)
|
||||
/// |> lineTo({to:[2, 2], tag: "yo"}, %)
|
||||
/// |> lineTo([3, 1], %)
|
||||
/// |> angledLineThatIntersects({
|
||||
/// angle: 180,
|
||||
/// intersectTag: 'yo',
|
||||
/// offset: 12,
|
||||
/// tag: "yo2"
|
||||
/// }, %)
|
||||
/// |> line([4, 0], %)
|
||||
/// |> close(%, "yo3")
|
||||
/// |> extrude(10, %)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "angledLineThatIntersects",
|
||||
}]
|
||||
@ -641,6 +805,11 @@ pub async fn start_sketch_at(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Start a sketch at a given point on the 'XY' plane.
|
||||
///
|
||||
/// ```no_run
|
||||
/// startSketchAt([0, 0])
|
||||
/// |> line([10, 10], %)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "startSketchAt",
|
||||
}]
|
||||
@ -785,6 +954,37 @@ pub async fn start_sketch_on(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Start a sketch on a specific plane or face.
|
||||
///
|
||||
/// ```no_run
|
||||
/// startSketchOn('XY')
|
||||
/// |> startProfileAt([0, 0], %)
|
||||
/// |> line([10, 10], %)
|
||||
/// |> line({to: [20, 10], tag: "edge1"}, %)
|
||||
/// |> close(%, "edge2")
|
||||
/// ```
|
||||
///
|
||||
/// ```no_run
|
||||
/// fn cube = (pos, scale) => {
|
||||
/// const sg = startSketchOn('XY')
|
||||
/// |> startProfileAt(pos, %)
|
||||
/// |> line([0, scale], %)
|
||||
/// |> line([scale, 0], %)
|
||||
/// |> line([0, -scale], %)
|
||||
/// |> close(%)
|
||||
/// |> extrude(scale, %)
|
||||
///
|
||||
/// return sg
|
||||
/// }
|
||||
///
|
||||
/// const box = cube([0,0], 20)
|
||||
///
|
||||
/// const part001 = startSketchOn(box, "start")
|
||||
/// |> startProfileAt([0, 0], %)
|
||||
/// |> line([10, 10], %)
|
||||
/// |> line({to: [20, 10], tag: "edge1"}, %)
|
||||
/// |> close(%)
|
||||
/// |> extrude(20, %)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "startSketchOn",
|
||||
}]
|
||||
@ -1011,6 +1211,12 @@ pub async fn start_profile_at(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Start a profile at a given point.
|
||||
///
|
||||
/// ```no_run
|
||||
/// startSketchOn('XY')
|
||||
/// |> startProfileAt([0, 0], %)
|
||||
/// |> line([10, 10], %)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "startProfileAt",
|
||||
}]
|
||||
@ -1081,6 +1287,22 @@ pub async fn close(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Close the current sketch.
|
||||
///
|
||||
/// ```no_run
|
||||
/// startSketchOn('XZ')
|
||||
/// |> startProfileAt([0, 0], %)
|
||||
/// |> line([10, 10], %)
|
||||
/// |> line([10, 0], %)
|
||||
/// |> close(%)
|
||||
/// ```
|
||||
///
|
||||
/// ```no_run
|
||||
/// startSketchOn('YZ')
|
||||
/// |> startProfileAt([0, 0], %)
|
||||
/// |> line([10, 10], %)
|
||||
/// |> line([10, 0], %)
|
||||
/// |> close(%, "edge1")
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "close",
|
||||
}]
|
||||
@ -1165,6 +1387,18 @@ pub async fn arc(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Draw an arc.
|
||||
///
|
||||
/// ```no_run
|
||||
/// startSketchOn('-YZ')
|
||||
/// |> startProfileAt([0, 0], %)
|
||||
/// |> arc({
|
||||
/// angle_start: 0,
|
||||
/// angle_end: 360,
|
||||
/// radius: 10,
|
||||
/// tag: "edge1"
|
||||
/// }, %)
|
||||
/// |> extrude(10, %)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "arc",
|
||||
}]
|
||||
@ -1259,6 +1493,19 @@ pub async fn tangential_arc(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Draw an arc.
|
||||
///
|
||||
/// ```no_run
|
||||
/// startSketchOn('-YZ')
|
||||
/// |> startProfileAt([0, 0], %)
|
||||
/// |> line({to: [10, 10], tag: "edge0"}, %)
|
||||
/// |> tangentialArc({
|
||||
/// radius: 10,
|
||||
/// offset: 90,
|
||||
/// tag: "edge1"
|
||||
/// }, %)
|
||||
/// |> close(%)
|
||||
/// |> extrude(10, %)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "tangentialArc",
|
||||
}]
|
||||
@ -1373,6 +1620,14 @@ pub async fn tangential_arc_to(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Draw an arc.
|
||||
///
|
||||
/// ```no_run
|
||||
/// startSketchOn('-YZ')
|
||||
/// |> startProfileAt([0, 0], %)
|
||||
/// |> line({to: [10, 10], tag: "edge0"}, %)
|
||||
/// |> tangentialArcTo([10, 0], %)
|
||||
/// |> close(%)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "tangentialArcTo",
|
||||
}]
|
||||
@ -1445,6 +1700,19 @@ pub async fn bezier_curve(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Draw a bezier curve.
|
||||
///
|
||||
/// ```no_run
|
||||
/// startSketchOn('XY')
|
||||
/// |> startProfileAt([0, 0], %)
|
||||
/// |> bezierCurve({
|
||||
/// to: [10, 10],
|
||||
/// control1: [5, 0],
|
||||
/// control2: [5, 10],
|
||||
/// tag: "edge1"
|
||||
/// }, %)
|
||||
/// |> close(%)
|
||||
/// |> extrude(10, %)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "bezierCurve",
|
||||
}]
|
||||
@ -1514,6 +1782,18 @@ pub async fn hole(args: Args) -> Result<MemoryItem, KclError> {
|
||||
}
|
||||
|
||||
/// Use a sketch to cut a hole in another sketch.
|
||||
///
|
||||
/// ```no_run
|
||||
/// const square = startSketchOn('XY')
|
||||
/// |> startProfileAt([0, 0], %)
|
||||
/// |> line([0, 10], %)
|
||||
/// |> line([10, 0], %)
|
||||
/// |> line([0, -10], %)
|
||||
/// |> close(%)
|
||||
/// |> hole(circle([2, 2], .5, startSketchOn('XY')), %)
|
||||
/// |> hole(circle([2, 8], .5, startSketchOn('XY')), %)
|
||||
/// |> extrude(2, %)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "hole",
|
||||
}]
|
||||
|
@ -7,6 +7,7 @@ use std::{
|
||||
|
||||
use futures::stream::TryStreamExt;
|
||||
use gloo_utils::format::JsValueSerdeExt;
|
||||
use kcl_lib::engine::EngineManager;
|
||||
use tower_lsp::{LspService, Server};
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
@ -27,12 +28,12 @@ pub async fn execute_wasm(
|
||||
let mut mem: kcl_lib::executor::ProgramMemory = serde_json::from_str(memory_str).map_err(|e| e.to_string())?;
|
||||
let units = kittycad::types::UnitLength::from_str(units).map_err(|e| e.to_string())?;
|
||||
|
||||
let engine = kcl_lib::engine::EngineConnection::new(engine_manager)
|
||||
let engine = kcl_lib::engine::conn_wasm::EngineConnection::new(engine_manager)
|
||||
.await
|
||||
.map_err(|e| format!("{:?}", e))?;
|
||||
let fs = kcl_lib::fs::FileManager::new(fs_manager);
|
||||
let ctx = ExecutorContext {
|
||||
engine,
|
||||
engine: Arc::new(Box::new(engine)),
|
||||
fs,
|
||||
stdlib: std::sync::Arc::new(kcl_lib::std::StdLib::new()),
|
||||
units,
|
||||
@ -62,12 +63,14 @@ pub async fn modify_ast_for_sketch_wasm(
|
||||
|
||||
let plane: kcl_lib::executor::PlaneType = serde_json::from_str(plane_type).map_err(|e| e.to_string())?;
|
||||
|
||||
let mut engine = kcl_lib::engine::EngineConnection::new(manager)
|
||||
.await
|
||||
.map_err(|e| format!("{:?}", e))?;
|
||||
let engine: Arc<Box<dyn EngineManager>> = Arc::new(Box::new(
|
||||
kcl_lib::engine::conn_wasm::EngineConnection::new(manager)
|
||||
.await
|
||||
.map_err(|e| format!("{:?}", e))?,
|
||||
));
|
||||
|
||||
let _ = kcl_lib::ast::modify::modify_ast_for_sketch(
|
||||
&mut engine,
|
||||
&engine,
|
||||
&mut program,
|
||||
sketch_name,
|
||||
plane,
|
||||
|
@ -1,5 +1,4 @@
|
||||
use anyhow::Result;
|
||||
use kcl_lib::engine::EngineManager;
|
||||
|
||||
/// Executes a kcl program and takes a snapshot of the result.
|
||||
/// This returns the bytes of the snapshot.
|
||||
|
@ -1,7 +1,6 @@
|
||||
use anyhow::Result;
|
||||
use kcl_lib::{
|
||||
ast::{modify::modify_ast_for_sketch, types::Program},
|
||||
engine::EngineManager,
|
||||
executor::{ExecutorContext, MemoryItem, PlaneType, SourceRange},
|
||||
};
|
||||
use kittycad::types::{ModelingCmd, Point3D};
|
||||
@ -105,9 +104,9 @@ async fn serial_test_modify_sketch_part001() {
|
||||
name
|
||||
);
|
||||
|
||||
let (mut ctx, program, sketch_id) = setup(&code, name).await.unwrap();
|
||||
let (ctx, program, sketch_id) = setup(&code, name).await.unwrap();
|
||||
let mut new_program = program.clone();
|
||||
let new_code = modify_ast_for_sketch(&mut ctx.engine, &mut new_program, name, PlaneType::XY, sketch_id)
|
||||
let new_code = modify_ast_for_sketch(&ctx.engine, &mut new_program, name, PlaneType::XY, sketch_id)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
@ -130,9 +129,9 @@ async fn serial_test_modify_sketch_part002() {
|
||||
name
|
||||
);
|
||||
|
||||
let (mut ctx, program, sketch_id) = setup(&code, name).await.unwrap();
|
||||
let (ctx, program, sketch_id) = setup(&code, name).await.unwrap();
|
||||
let mut new_program = program.clone();
|
||||
let new_code = modify_ast_for_sketch(&mut ctx.engine, &mut new_program, name, PlaneType::XY, sketch_id)
|
||||
let new_code = modify_ast_for_sketch(&ctx.engine, &mut new_program, name, PlaneType::XY, sketch_id)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
@ -157,9 +156,9 @@ async fn serial_test_modify_close_sketch() {
|
||||
name
|
||||
);
|
||||
|
||||
let (mut ctx, program, sketch_id) = setup(&code, name).await.unwrap();
|
||||
let (ctx, program, sketch_id) = setup(&code, name).await.unwrap();
|
||||
let mut new_program = program.clone();
|
||||
let new_code = modify_ast_for_sketch(&mut ctx.engine, &mut new_program, name, PlaneType::XY, sketch_id)
|
||||
let new_code = modify_ast_for_sketch(&ctx.engine, &mut new_program, name, PlaneType::XY, sketch_id)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
@ -183,9 +182,9 @@ async fn serial_test_modify_line_to_close_sketch() {
|
||||
name
|
||||
);
|
||||
|
||||
let (mut ctx, program, sketch_id) = setup(&code, name).await.unwrap();
|
||||
let (ctx, program, sketch_id) = setup(&code, name).await.unwrap();
|
||||
let mut new_program = program.clone();
|
||||
let new_code = modify_ast_for_sketch(&mut ctx.engine, &mut new_program, name, PlaneType::XY, sketch_id)
|
||||
let new_code = modify_ast_for_sketch(&ctx.engine, &mut new_program, name, PlaneType::XY, sketch_id)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
@ -220,9 +219,9 @@ const {} = startSketchOn("XY")
|
||||
name
|
||||
);
|
||||
|
||||
let (mut ctx, program, sketch_id) = setup(&code, name).await.unwrap();
|
||||
let (ctx, program, sketch_id) = setup(&code, name).await.unwrap();
|
||||
let mut new_program = program.clone();
|
||||
let result = modify_ast_for_sketch(&mut ctx.engine, &mut new_program, name, PlaneType::XY, sketch_id).await;
|
||||
let result = modify_ast_for_sketch(&ctx.engine, &mut new_program, name, PlaneType::XY, sketch_id).await;
|
||||
|
||||
assert!(result.is_err());
|
||||
assert_eq!(
|
||||
@ -245,9 +244,9 @@ async fn serial_test_modify_line_should_close_sketch() {
|
||||
name
|
||||
);
|
||||
|
||||
let (mut ctx, program, sketch_id) = setup(&code, name).await.unwrap();
|
||||
let (ctx, program, sketch_id) = setup(&code, name).await.unwrap();
|
||||
let mut new_program = program.clone();
|
||||
let new_code = modify_ast_for_sketch(&mut ctx.engine, &mut new_program, name, PlaneType::XY, sketch_id)
|
||||
let new_code = modify_ast_for_sketch(&ctx.engine, &mut new_program, name, PlaneType::XY, sketch_id)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
|
Reference in New Issue
Block a user