Helper functions for meta settings (get/update) (#5200)

* get the units back out

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

* updates

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

* edit

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

* updates

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

* updates

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

* add to wasmts

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

* fmt

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

* updates

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

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
This commit is contained in:
Jess Frazelle
2025-01-31 13:11:15 -08:00
committed by GitHub
parent 27ce9f8aa4
commit 2f72a8ef14
16 changed files with 270 additions and 36 deletions

View File

@ -18,6 +18,7 @@ import {
default_project_settings, default_project_settings,
base64_decode, base64_decode,
clear_scene_and_bust_cache, clear_scene_and_bust_cache,
change_kcl_settings,
reloadModule, reloadModule,
} from 'lib/wasm_lib_wrapper' } from 'lib/wasm_lib_wrapper'
@ -56,6 +57,7 @@ import { ArtifactGraph as RustArtifactGraph } from 'wasm-lib/kcl/bindings/Artifa
import { Artifact } from './std/artifactGraph' import { Artifact } from './std/artifactGraph'
import { getNodePathFromSourceRange } from 'lang/queryAstNodePathUtils' import { getNodePathFromSourceRange } from 'lang/queryAstNodePathUtils'
import { NumericSuffix } from 'wasm-lib/kcl/bindings/NumericSuffix' import { NumericSuffix } from 'wasm-lib/kcl/bindings/NumericSuffix'
import { MetaSettings } from 'wasm-lib/kcl/bindings/MetaSettings'
export type { Artifact } from 'wasm-lib/kcl/bindings/Artifact' export type { Artifact } from 'wasm-lib/kcl/bindings/Artifact'
export type { ArtifactCommand } from 'wasm-lib/kcl/bindings/Artifact' export type { ArtifactCommand } from 'wasm-lib/kcl/bindings/Artifact'
@ -844,3 +846,17 @@ export function base64Decode(base64: string): ArrayBuffer | Error {
return new Error('Caught error decoding base64 string: ' + e) return new Error('Caught error decoding base64 string: ' + e)
} }
} }
/// Change the meta settings for the kcl file.
/// Returns the new kcl string with the updated settings.
export function changeKclSettings(
kcl: string,
settings: MetaSettings
): string | Error {
try {
return change_kcl_settings(kcl, JSON.stringify(settings))
} catch (e) {
console.error('Caught error changing kcl settings: ' + e)
return new Error('Caught error changing kcl settings: ' + e)
}
}

View File

@ -26,6 +26,7 @@ import {
default_project_settings as DefaultProjectSettings, default_project_settings as DefaultProjectSettings,
base64_decode as Base64Decode, base64_decode as Base64Decode,
clear_scene_and_bust_cache as ClearSceneAndBustCache, clear_scene_and_bust_cache as ClearSceneAndBustCache,
change_kcl_settings as ChangeKclSettings,
} from '../wasm-lib/pkg/wasm_lib' } from '../wasm-lib/pkg/wasm_lib'
type ModuleType = typeof import('../wasm-lib/pkg/wasm_lib') type ModuleType = typeof import('../wasm-lib/pkg/wasm_lib')
@ -110,3 +111,6 @@ export const clear_scene_and_bust_cache: typeof ClearSceneAndBustCache = (
) => { ) => {
return getModule().clear_scene_and_bust_cache(...args) return getModule().clear_scene_and_bust_cache(...args)
} }
export const change_kcl_settings: typeof ChangeKclSettings = (...args) => {
return getModule().change_kcl_settings(...args)
}

View File

@ -1710,7 +1710,7 @@ dependencies = [
[[package]] [[package]]
name = "kcl-lib" name = "kcl-lib"
version = "0.2.32" version = "0.2.33"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"approx 0.5.1", "approx 0.5.1",

View File

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

View File

@ -13,9 +13,7 @@ use tower_lsp::lsp_types::{
MarkupKind, ParameterInformation, ParameterLabel, SignatureHelp, SignatureInformation, MarkupKind, ParameterInformation, ParameterLabel, SignatureHelp, SignatureInformation,
}; };
use crate::execution::Sketch; use crate::{execution::Sketch, std::Primitive};
use crate::std::Primitive;
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, JsonSchema, ts_rs::TS)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, JsonSchema, ts_rs::TS)]
#[ts(export)] #[ts(export)]

View File

@ -7,9 +7,9 @@ use crate::{
KclError, SourceRange, KclError, SourceRange,
}; };
pub(super) const SETTINGS: &str = "settings"; pub(crate) const SETTINGS: &str = "settings";
pub(super) const SETTINGS_UNIT_LENGTH: &str = "defaultLengthUnit"; pub(crate) const SETTINGS_UNIT_LENGTH: &str = "defaultLengthUnit";
pub(super) const SETTINGS_UNIT_ANGLE: &str = "defaultAngleUnit"; pub(crate) const SETTINGS_UNIT_ANGLE: &str = "defaultAngleUnit";
#[derive(Copy, Clone, Debug, Eq, PartialEq)] #[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub(super) enum AnnotationScope { pub(super) enum AnnotationScope {

View File

@ -2,6 +2,7 @@ use std::collections::HashMap;
use async_recursion::async_recursion; use async_recursion::async_recursion;
use super::cad_op::{OpArg, Operation};
use crate::{ use crate::{
errors::{KclError, KclErrorDetails}, errors::{KclError, KclErrorDetails},
execution::{ execution::{
@ -19,8 +20,6 @@ use crate::{
}, },
}; };
use super::cad_op::{OpArg, Operation};
impl BinaryPart { impl BinaryPart {
#[async_recursion] #[async_recursion]
pub async fn get_result(&self, exec_state: &mut ExecState, ctx: &ExecutorContext) -> Result<KclValue, KclError> { pub async fn get_result(&self, exec_state: &mut ExecState, ctx: &ExecutorContext) -> Result<KclValue, KclError> {

View File

@ -15,6 +15,7 @@ use kittycad_modeling_cmds as kcmc;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use uuid::Uuid; use uuid::Uuid;
use super::ExecutorContext;
use crate::{ use crate::{
errors::{KclError, KclErrorDetails}, errors::{KclError, KclErrorDetails},
execution::{ExecState, ImportedGeometry}, execution::{ExecState, ImportedGeometry},
@ -22,8 +23,6 @@ use crate::{
source_range::SourceRange, source_range::SourceRange,
}; };
use super::ExecutorContext;
// Zoo co-ordinate system. // Zoo co-ordinate system.
// //
// * Forward: -Y // * Forward: -Y

View File

@ -581,10 +581,11 @@ impl KclValue {
} }
// TODO called UnitLen so as not to clash with UnitLength in settings) // TODO called UnitLen so as not to clash with UnitLength in settings)
#[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, Eq)] #[derive(Debug, Default, Clone, Copy, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, Eq)]
#[ts(export)] #[ts(export)]
#[serde(tag = "type")] #[serde(tag = "type")]
pub enum UnitLen { pub enum UnitLen {
#[default]
Mm, Mm,
Cm, Cm,
M, M,
@ -593,6 +594,19 @@ pub enum UnitLen {
Yards, Yards,
} }
impl std::fmt::Display for UnitLen {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
UnitLen::Mm => write!(f, "mm"),
UnitLen::Cm => write!(f, "cm"),
UnitLen::M => write!(f, "m"),
UnitLen::Inches => write!(f, "in"),
UnitLen::Feet => write!(f, "ft"),
UnitLen::Yards => write!(f, "yd"),
}
}
}
impl TryFrom<NumericSuffix> for UnitLen { impl TryFrom<NumericSuffix> for UnitLen {
type Error = (); type Error = ();
@ -644,6 +658,15 @@ pub enum UnitAngle {
Radians, Radians,
} }
impl std::fmt::Display for UnitAngle {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
UnitAngle::Degrees => write!(f, "deg"),
UnitAngle::Radians => write!(f, "rad"),
}
}
}
impl TryFrom<NumericSuffix> for UnitAngle { impl TryFrom<NumericSuffix> for UnitAngle {
type Error = (); type Error = ();

View File

@ -13,8 +13,7 @@ use kcmc::{
websocket::{ModelingSessionData, OkWebSocketResponseData}, websocket::{ModelingSessionData, OkWebSocketResponseData},
ImageFormat, ModelingCmd, ImageFormat, ModelingCmd,
}; };
use kittycad_modeling_cmds::length_unit::LengthUnit; use kittycad_modeling_cmds::{self as kcmc, length_unit::LengthUnit, websocket::WebSocketResponse};
use kittycad_modeling_cmds::{self as kcmc, websocket::WebSocketResponse};
use parse_display::{Display, FromStr}; use parse_display::{Display, FromStr};
use schemars::JsonSchema; use schemars::JsonSchema;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -27,14 +26,18 @@ pub(crate) use import::{import_foreign, send_to_engine as send_import_to_engine,
pub use kcl_value::{KclObjectFields, KclValue, UnitAngle, UnitLen}; pub use kcl_value::{KclObjectFields, KclValue, UnitAngle, UnitLen};
use uuid::Uuid; use uuid::Uuid;
mod annotations; pub(crate) mod annotations;
mod artifact; mod artifact;
pub(crate) mod cache; pub(crate) mod cache;
mod cad_op; mod cad_op;
mod exec_ast; mod exec_ast;
mod function_param; mod function_param;
mod import; mod import;
mod kcl_value; pub(crate) mod kcl_value;
// Re-exports.
pub use artifact::{Artifact, ArtifactCommand, ArtifactGraph, ArtifactId};
pub use cad_op::Operation;
use crate::{ use crate::{
engine::{EngineManager, ExecutionKind}, engine::{EngineManager, ExecutionKind},
@ -52,10 +55,6 @@ use crate::{
ExecError, KclErrorWithOutputs, Program, ExecError, KclErrorWithOutputs, Program,
}; };
// Re-exports.
pub use artifact::{Artifact, ArtifactCommand, ArtifactGraph, ArtifactId};
pub use cad_op::Operation;
/// State for executing a program. /// State for executing a program.
#[derive(Debug, Clone, Deserialize, Serialize)] #[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
@ -247,7 +246,7 @@ impl ModuleState {
} }
} }
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)] #[derive(Debug, Default, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)] #[ts(export)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct MetaSettings { pub struct MetaSettings {
@ -256,7 +255,11 @@ pub struct MetaSettings {
} }
impl MetaSettings { impl MetaSettings {
fn update_from_annotation(&mut self, annotation: &NonCodeValue, source_range: SourceRange) -> Result<(), KclError> { pub fn update_from_annotation(
&mut self,
annotation: &NonCodeValue,
source_range: SourceRange,
) -> Result<(), KclError> {
let properties = annotations::expect_properties(annotations::SETTINGS, annotation, source_range)?; let properties = annotations::expect_properties(annotations::SETTINGS, annotation, source_range)?;
for p in properties { for p in properties {

View File

@ -84,7 +84,7 @@ pub use engine::{EngineManager, ExecutionKind};
pub use errors::{CompilationError, ConnectionError, ExecError, KclError, KclErrorWithOutputs}; pub use errors::{CompilationError, ConnectionError, ExecError, KclError, KclErrorWithOutputs};
pub use execution::{ pub use execution::{
cache::{CacheInformation, OldAstState}, cache::{CacheInformation, OldAstState},
ExecState, ExecutorContext, ExecutorSettings, Point2d, ExecState, ExecutorContext, ExecutorSettings, MetaSettings, Point2d,
}; };
pub use lsp::{ pub use lsp::{
copilot::Backend as CopilotLspBackend, copilot::Backend as CopilotLspBackend,
@ -121,8 +121,7 @@ pub mod std_utils {
} }
pub mod pretty { pub mod pretty {
pub use crate::parsing::token::NumericSuffix; pub use crate::{parsing::token::NumericSuffix, unparser::format_number};
pub use crate::unparser::format_number;
} }
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -162,6 +161,18 @@ impl Program {
self.ast.compute_digest() self.ast.compute_digest()
} }
/// Get the meta settings for the kcl file from the annotations.
pub fn get_meta_settings(&self) -> Result<Option<crate::MetaSettings>, KclError> {
self.ast.get_meta_settings()
}
/// Change the meta settings for the kcl file.
pub fn change_meta_settings(&mut self, settings: crate::MetaSettings) -> Result<Self, KclError> {
Ok(Self {
ast: self.ast.change_meta_settings(settings)?,
})
}
pub fn lint_all(&self) -> Result<Vec<lint::Discovered>, anyhow::Error> { pub fn lint_all(&self) -> Result<Vec<lint::Discovered>, anyhow::Error> {
self.ast.lint_all() self.ast.lint_all()
} }

View File

@ -6,6 +6,7 @@ use kcmc::{
}; };
use kittycad_modeling_cmds as kcmc; use kittycad_modeling_cmds as kcmc;
use super::types::LiteralValue;
use crate::{ use crate::{
engine::EngineManager, engine::EngineManager,
errors::{KclError, KclErrorDetails}, errors::{KclError, KclErrorDetails},
@ -18,8 +19,6 @@ use crate::{
Program, Program,
}; };
use super::types::LiteralValue;
type Point3d = kcmc::shared::Point3d<f64>; type Point3d = kcmc::shared::Point3d<f64>;
#[derive(Debug)] #[derive(Debug)]

View File

@ -17,7 +17,6 @@ use tower_lsp::lsp_types::{
CompletionItem, CompletionItemKind, DocumentSymbol, FoldingRange, FoldingRangeKind, Range as LspRange, SymbolKind, CompletionItem, CompletionItemKind, DocumentSymbol, FoldingRange, FoldingRangeKind, Range as LspRange, SymbolKind,
}; };
use super::digest::Digest;
pub use crate::parsing::ast::types::{ pub use crate::parsing::ast::types::{
condition::{ElseIf, IfExpression}, condition::{ElseIf, IfExpression},
literal_value::LiteralValue, literal_value::LiteralValue,
@ -26,7 +25,8 @@ pub use crate::parsing::ast::types::{
use crate::{ use crate::{
docs::StdLibFn, docs::StdLibFn,
errors::KclError, errors::KclError,
execution::{KclValue, Metadata, TagIdentifier}, execution::{annotations, KclValue, Metadata, TagIdentifier},
parsing::ast::digest::Digest,
parsing::PIPE_OPERATOR, parsing::PIPE_OPERATOR,
source_range::{ModuleId, SourceRange}, source_range::{ModuleId, SourceRange},
}; };
@ -254,6 +254,52 @@ impl Node<Program> {
} }
Ok(findings) Ok(findings)
} }
/// Get the annotations for the meta settings from the kcl file.
pub fn get_meta_settings(&self) -> Result<Option<crate::execution::MetaSettings>, KclError> {
let annotations = self
.non_code_meta
.start_nodes
.iter()
.filter_map(|n| n.annotation().map(|result| (result, n.as_source_range())));
for (annotation, source_range) in annotations {
if annotation.annotation_name() == Some(annotations::SETTINGS) {
let mut meta_settings = crate::execution::MetaSettings::default();
meta_settings.update_from_annotation(annotation, source_range)?;
return Ok(Some(meta_settings));
}
}
Ok(None)
}
pub fn change_meta_settings(&mut self, settings: crate::execution::MetaSettings) -> Result<Self, KclError> {
let mut new_program = self.clone();
let mut found = false;
for node in &mut new_program.non_code_meta.start_nodes {
if let Some(annotation) = node.annotation() {
if annotation.annotation_name() == Some(annotations::SETTINGS) {
let annotation = NonCodeValue::new_from_meta_settings(&settings);
*node = Node::no_src(NonCodeNode {
value: annotation,
digest: None,
});
found = true;
break;
}
}
}
if !found {
let annotation = NonCodeValue::new_from_meta_settings(&settings);
new_program.non_code_meta.start_nodes.push(Node::no_src(NonCodeNode {
value: annotation,
digest: None,
}));
}
Ok(new_program)
}
} }
impl Program { impl Program {
@ -1078,6 +1124,24 @@ impl NonCodeValue {
_ => None, _ => None,
} }
} }
pub fn new_from_meta_settings(settings: &crate::execution::MetaSettings) -> NonCodeValue {
let mut properties: Vec<Node<ObjectProperty>> = vec![ObjectProperty::new(
Identifier::new(annotations::SETTINGS_UNIT_LENGTH),
Expr::Identifier(Box::new(Identifier::new(&settings.default_length_units.to_string()))),
)];
if settings.default_angle_units != Default::default() {
properties.push(ObjectProperty::new(
Identifier::new(annotations::SETTINGS_UNIT_ANGLE),
Expr::Identifier(Box::new(Identifier::new(&settings.default_angle_units.to_string()))),
));
}
NonCodeValue::Annotation {
name: Identifier::new(annotations::SETTINGS),
properties: Some(properties),
}
}
} }
#[derive(Debug, Default, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)] #[derive(Debug, Default, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
@ -2337,6 +2401,14 @@ impl Node<ObjectProperty> {
} }
impl ObjectProperty { impl ObjectProperty {
pub fn new(key: Node<Identifier>, value: Expr) -> Node<Self> {
Node::no_src(Self {
key,
value,
digest: None,
})
}
/// Returns a hover value that includes the given character position. /// Returns a hover value that includes the given character position.
pub fn get_hover_value_for_position(&self, pos: usize, code: &str) -> Option<Hover> { pub fn get_hover_value_for_position(&self, pos: usize, code: &str) -> Option<Hover> {
let value_source_range: SourceRange = self.value.clone().into(); let value_source_range: SourceRange = self.value.clone().into();
@ -3756,4 +3828,98 @@ const cylinder = startSketchOn('-XZ')
assert_eq!(l.raw, "false"); assert_eq!(l.raw, "false");
} }
#[tokio::test(flavor = "multi_thread")]
async fn test_parse_get_meta_settings_inch() {
let some_program_string = r#"@settings(defaultLengthUnit = inch)
startSketchOn('XY')"#;
let program = crate::parsing::top_level_parse(some_program_string).unwrap();
let result = program.get_meta_settings().unwrap();
assert!(result.is_some());
let meta_settings = result.unwrap();
assert_eq!(
meta_settings.default_length_units,
crate::execution::kcl_value::UnitLen::Inches
);
}
#[tokio::test(flavor = "multi_thread")]
async fn test_parse_get_meta_settings_inch_to_mm() {
let some_program_string = r#"@settings(defaultLengthUnit = inch)
startSketchOn('XY')"#;
let mut program = crate::parsing::top_level_parse(some_program_string).unwrap();
let result = program.get_meta_settings().unwrap();
assert!(result.is_some());
let meta_settings = result.unwrap();
assert_eq!(
meta_settings.default_length_units,
crate::execution::kcl_value::UnitLen::Inches
);
// Edit the ast.
let new_program = program
.change_meta_settings(crate::execution::MetaSettings {
default_length_units: crate::execution::kcl_value::UnitLen::Mm,
..Default::default()
})
.unwrap();
let result = new_program.get_meta_settings().unwrap();
assert!(result.is_some());
let meta_settings = result.unwrap();
assert_eq!(
meta_settings.default_length_units,
crate::execution::kcl_value::UnitLen::Mm
);
let formatted = new_program.recast(&Default::default(), 0);
assert_eq!(
formatted,
r#"@settings(defaultLengthUnit = mm)
startSketchOn('XY')
"#
);
}
#[tokio::test(flavor = "multi_thread")]
async fn test_parse_get_meta_settings_nothing_to_mm() {
let some_program_string = r#"startSketchOn('XY')"#;
let mut program = crate::parsing::top_level_parse(some_program_string).unwrap();
let result = program.get_meta_settings().unwrap();
assert!(result.is_none());
// Edit the ast.
let new_program = program
.change_meta_settings(crate::execution::MetaSettings {
default_length_units: crate::execution::kcl_value::UnitLen::Mm,
..Default::default()
})
.unwrap();
let result = new_program.get_meta_settings().unwrap();
assert!(result.is_some());
let meta_settings = result.unwrap();
assert_eq!(
meta_settings.default_length_units,
crate::execution::kcl_value::UnitLen::Mm
);
let formatted = new_program.recast(&Default::default(), 0);
assert_eq!(
formatted,
r#"@settings(defaultLengthUnit = mm)
startSketchOn('XY')
"#
);
}
} }

View File

@ -3,14 +3,13 @@
use anyhow::Result; use anyhow::Result;
use derive_docs::stdlib; use derive_docs::stdlib;
use super::args::FromArgs;
use crate::{ use crate::{
errors::{KclError, KclErrorDetails}, errors::{KclError, KclErrorDetails},
execution::{ExecState, KclValue}, execution::{ExecState, KclValue},
std::Args, std::Args,
}; };
use super::args::FromArgs;
/// Compute the remainder after dividing `num` by `div`. /// Compute the remainder after dividing `num` by `div`.
/// If `num` is negative, the result will be too. /// If `num` is negative, the result will be too.
pub async fn rem(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> { pub async fn rem(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {

View File

@ -11,12 +11,11 @@ use parse_display::{Display, FromStr};
use schemars::JsonSchema; use schemars::JsonSchema;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::execution::{Artifact, ArtifactId};
use crate::{ use crate::{
errors::{KclError, KclErrorDetails}, errors::{KclError, KclErrorDetails},
execution::{ execution::{
BasePath, ExecState, Face, GeoMeta, KclValue, Path, Plane, Point2d, Point3d, Sketch, SketchSet, SketchSurface, Artifact, ArtifactId, BasePath, ExecState, Face, GeoMeta, KclValue, Path, Plane, Point2d, Point3d, Sketch,
Solid, TagEngineInfo, TagIdentifier, SketchSet, SketchSurface, Solid, TagEngineInfo, TagIdentifier,
}, },
parsing::ast::types::TagNode, parsing::ast::types::TagNode,
std::{ std::{
@ -2250,7 +2249,10 @@ mod tests {
use pretty_assertions::assert_eq; use pretty_assertions::assert_eq;
use crate::{execution::TagIdentifier, std::sketch::PlaneData, std::utils::calculate_circle_center}; use crate::{
execution::TagIdentifier,
std::{sketch::PlaneData, utils::calculate_circle_center},
};
#[test] #[test]
fn test_deserialize_plane_data() { fn test_deserialize_plane_data() {

View File

@ -614,3 +614,18 @@ pub fn calculate_circle_from_3_points(ax: f64, ay: f64, bx: f64, by: f64, cx: f6
radius: result.radius, radius: result.radius,
} }
} }
/// Takes a kcl string and Meta settings and changes the meta settings in the kcl string.
#[wasm_bindgen]
pub fn change_kcl_settings(code: &str, settings_str: &str) -> Result<String, String> {
console_error_panic_hook::set_once();
let settings: kcl_lib::MetaSettings = serde_json::from_str(settings_str).map_err(|e| e.to_string())?;
let mut program = Program::parse_no_errs(code).map_err(|e| e.to_string())?;
let new_program = program.change_meta_settings(settings).map_err(|e| e.to_string())?;
let formatted = new_program.recast();
Ok(formatted)
}