Give a warning when using per-project default units (#5956)
* Give a warning when using per-project default units Signed-off-by: Nick Cameron <nrc@ncameron.org> * Factor non-settings out of MetaSettings Signed-off-by: Nick Cameron <nrc@ncameron.org> * Fix formatting * Fix code pane e2e test * Fix callstack blowup in edit flow * Avoid dumb timeout issue with command registration in test * Use a safer way to wait for modeling command registration in test --------- Signed-off-by: Nick Cameron <nrc@ncameron.org> Co-authored-by: Nick Cameron <nrc@ncameron.org> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Pierre Jacquier <pierre@zoo.dev> Co-authored-by: Frank Noirot <frankjohnson1993@gmail.com>
@ -21,7 +21,8 @@ test.describe('Code pane and errors', { tag: ['@skipWin'] }, () => {
|
|||||||
await page.addInitScript(() => {
|
await page.addInitScript(() => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
`// Extruded Triangle
|
`@settings(defaultLengthUnit = in)
|
||||||
|
// Extruded Triangle
|
||||||
sketch001 = startSketchOn(XZ)
|
sketch001 = startSketchOn(XZ)
|
||||||
|> startProfileAt([0, 0], %)
|
|> startProfileAt([0, 0], %)
|
||||||
|> line(end = [10, 0])
|
|> line(end = [10, 0])
|
||||||
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 53 KiB |
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 53 KiB |
Before Width: | Height: | Size: 126 KiB After Width: | Height: | Size: 131 KiB |
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 76 KiB |
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 71 KiB |
@ -927,9 +927,8 @@ fn get_autocomplete_string_from_schema(schema: &schemars::schema::Schema) -> Res
|
|||||||
mod tests {
|
mod tests {
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
use crate::docs::kcl_doc::{self, DocData};
|
|
||||||
|
|
||||||
use super::StdLibFn;
|
use super::StdLibFn;
|
||||||
|
use crate::docs::kcl_doc::{self, DocData};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_serialize_function() {
|
fn test_serialize_function() {
|
||||||
|
@ -3,6 +3,7 @@ use std::collections::HashMap;
|
|||||||
use async_recursion::async_recursion;
|
use async_recursion::async_recursion;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
|
|
||||||
|
use super::kcl_value::TypeDef;
|
||||||
use crate::{
|
use crate::{
|
||||||
engine::ExecutionKind,
|
engine::ExecutionKind,
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
@ -31,8 +32,6 @@ use crate::{
|
|||||||
CompilationError,
|
CompilationError,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::kcl_value::TypeDef;
|
|
||||||
|
|
||||||
enum StatementKind<'a> {
|
enum StatementKind<'a> {
|
||||||
Declaration { name: &'a str },
|
Declaration { name: &'a str },
|
||||||
Expression,
|
Expression,
|
||||||
@ -59,7 +58,9 @@ impl ExecutorContext {
|
|||||||
for annotation in annotations {
|
for annotation in annotations {
|
||||||
if annotation.name() == Some(annotations::SETTINGS) {
|
if annotation.name() == Some(annotations::SETTINGS) {
|
||||||
if matches!(body_type, BodyType::Root) {
|
if matches!(body_type, BodyType::Root) {
|
||||||
exec_state.mod_local.settings.update_from_annotation(annotation)?;
|
if exec_state.mod_local.settings.update_from_annotation(annotation)? {
|
||||||
|
exec_state.mod_local.explicit_length_units = true;
|
||||||
|
}
|
||||||
let new_units = exec_state.length_unit();
|
let new_units = exec_state.length_unit();
|
||||||
if !self.engine.execution_kind().await.is_isolated() {
|
if !self.engine.execution_kind().await.is_isolated() {
|
||||||
self.engine
|
self.engine
|
||||||
@ -299,7 +300,7 @@ impl ExecutorContext {
|
|||||||
let impl_kind = annotations::get_impl(&ty.outer_attrs, metadata.source_range)?.unwrap_or_default();
|
let impl_kind = annotations::get_impl(&ty.outer_attrs, metadata.source_range)?.unwrap_or_default();
|
||||||
match impl_kind {
|
match impl_kind {
|
||||||
annotations::Impl::Rust => {
|
annotations::Impl::Rust => {
|
||||||
let std_path = match &exec_state.mod_local.settings.std_path {
|
let std_path = match &exec_state.mod_local.std_path {
|
||||||
Some(p) => p,
|
Some(p) => p,
|
||||||
None => {
|
None => {
|
||||||
return Err(KclError::Semantic(KclErrorDetails {
|
return Err(KclError::Semantic(KclErrorDetails {
|
||||||
@ -585,7 +586,7 @@ impl ExecutorContext {
|
|||||||
) -> Result<KclValue, KclError> {
|
) -> Result<KclValue, KclError> {
|
||||||
let item = match init {
|
let item = match init {
|
||||||
Expr::None(none) => KclValue::from(none),
|
Expr::None(none) => KclValue::from(none),
|
||||||
Expr::Literal(literal) => KclValue::from_literal((**literal).clone(), &exec_state.mod_local.settings),
|
Expr::Literal(literal) => KclValue::from_literal((**literal).clone(), exec_state),
|
||||||
Expr::TagDeclarator(tag) => tag.execute(exec_state).await?,
|
Expr::TagDeclarator(tag) => tag.execute(exec_state).await?,
|
||||||
Expr::Name(name) => {
|
Expr::Name(name) => {
|
||||||
let value = name.get_result(exec_state, self).await?.clone();
|
let value = name.get_result(exec_state, self).await?.clone();
|
||||||
@ -616,7 +617,7 @@ impl ExecutorContext {
|
|||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
|
|
||||||
if rust_impl {
|
if rust_impl {
|
||||||
if let Some(std_path) = &exec_state.mod_local.settings.std_path {
|
if let Some(std_path) = &exec_state.mod_local.std_path {
|
||||||
let (func, props) = crate::std::std_fn(std_path, statement_kind.expect_name());
|
let (func, props) = crate::std::std_fn(std_path, statement_kind.expect_name());
|
||||||
KclValue::Function {
|
KclValue::Function {
|
||||||
value: FunctionSource::Std {
|
value: FunctionSource::Std {
|
||||||
@ -719,10 +720,7 @@ 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> {
|
||||||
match self {
|
match self {
|
||||||
BinaryPart::Literal(literal) => Ok(KclValue::from_literal(
|
BinaryPart::Literal(literal) => Ok(KclValue::from_literal((**literal).clone(), exec_state)),
|
||||||
(**literal).clone(),
|
|
||||||
&exec_state.mod_local.settings,
|
|
||||||
)),
|
|
||||||
BinaryPart::Name(name) => name.get_result(exec_state, ctx).await.cloned(),
|
BinaryPart::Name(name) => name.get_result(exec_state, ctx).await.cloned(),
|
||||||
BinaryPart::BinaryExpression(binary_expression) => binary_expression.get_result(exec_state, ctx).await,
|
BinaryPart::BinaryExpression(binary_expression) => binary_expression.get_result(exec_state, ctx).await,
|
||||||
BinaryPart::CallExpression(call_expression) => call_expression.execute(exec_state, ctx).await,
|
BinaryPart::CallExpression(call_expression) => call_expression.execute(exec_state, ctx).await,
|
||||||
@ -1854,15 +1852,12 @@ fn assign_args_to_params(
|
|||||||
return Err(err_wrong_number_args);
|
return Err(err_wrong_number_args);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mem = &mut exec_state.mod_local.stack;
|
|
||||||
let settings = &exec_state.mod_local.settings;
|
|
||||||
|
|
||||||
// Add the arguments to the memory. A new call frame should have already
|
// Add the arguments to the memory. A new call frame should have already
|
||||||
// been created.
|
// been created.
|
||||||
for (index, param) in function_expression.params.iter().enumerate() {
|
for (index, param) in function_expression.params.iter().enumerate() {
|
||||||
if let Some(arg) = args.get(index) {
|
if let Some(arg) = args.get(index) {
|
||||||
// Argument was provided.
|
// Argument was provided.
|
||||||
mem.add(
|
exec_state.mut_stack().add(
|
||||||
param.identifier.name.clone(),
|
param.identifier.name.clone(),
|
||||||
arg.value.clone(),
|
arg.value.clone(),
|
||||||
(¶m.identifier).into(),
|
(¶m.identifier).into(),
|
||||||
@ -1872,11 +1867,10 @@ fn assign_args_to_params(
|
|||||||
if let Some(ref default_val) = param.default_value {
|
if let Some(ref default_val) = param.default_value {
|
||||||
// If the corresponding parameter is optional,
|
// If the corresponding parameter is optional,
|
||||||
// then it's fine, the user doesn't need to supply it.
|
// then it's fine, the user doesn't need to supply it.
|
||||||
mem.add(
|
let value = KclValue::from_default_param(default_val.clone(), exec_state);
|
||||||
param.identifier.name.clone(),
|
exec_state
|
||||||
KclValue::from_default_param(default_val.clone(), settings),
|
.mut_stack()
|
||||||
(¶m.identifier).into(),
|
.add(param.identifier.name.clone(), value, (¶m.identifier).into())?;
|
||||||
)?;
|
|
||||||
} else {
|
} else {
|
||||||
// But if the corresponding parameter was required,
|
// But if the corresponding parameter was required,
|
||||||
// then the user has called with too few arguments.
|
// then the user has called with too few arguments.
|
||||||
@ -1916,8 +1910,6 @@ fn assign_args_to_params_kw(
|
|||||||
// Add the arguments to the memory. A new call frame should have already
|
// Add the arguments to the memory. A new call frame should have already
|
||||||
// been created.
|
// been created.
|
||||||
let source_ranges = vec![function_expression.into()];
|
let source_ranges = vec![function_expression.into()];
|
||||||
let mem = &mut exec_state.mod_local.stack;
|
|
||||||
let settings = &exec_state.mod_local.settings;
|
|
||||||
|
|
||||||
for param in function_expression.params.iter() {
|
for param in function_expression.params.iter() {
|
||||||
if param.labeled {
|
if param.labeled {
|
||||||
@ -1925,7 +1917,7 @@ fn assign_args_to_params_kw(
|
|||||||
let arg_val = match arg {
|
let arg_val = match arg {
|
||||||
Some(arg) => arg.value.clone(),
|
Some(arg) => arg.value.clone(),
|
||||||
None => match param.default_value {
|
None => match param.default_value {
|
||||||
Some(ref default_val) => KclValue::from_default_param(default_val.clone(), settings),
|
Some(ref default_val) => KclValue::from_default_param(default_val.clone(), exec_state),
|
||||||
None => {
|
None => {
|
||||||
return Err(KclError::Semantic(KclErrorDetails {
|
return Err(KclError::Semantic(KclErrorDetails {
|
||||||
source_ranges,
|
source_ranges,
|
||||||
@ -1937,7 +1929,9 @@ fn assign_args_to_params_kw(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
mem.add(param.identifier.name.clone(), arg_val, (¶m.identifier).into())?;
|
exec_state
|
||||||
|
.mut_stack()
|
||||||
|
.add(param.identifier.name.clone(), arg_val, (¶m.identifier).into())?;
|
||||||
} else {
|
} else {
|
||||||
let Some(unlabeled) = args.unlabeled.take() else {
|
let Some(unlabeled) = args.unlabeled.take() else {
|
||||||
let param_name = ¶m.identifier.name;
|
let param_name = ¶m.identifier.name;
|
||||||
@ -1954,7 +1948,7 @@ fn assign_args_to_params_kw(
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
mem.add(
|
exec_state.mut_stack().add(
|
||||||
param.identifier.name.clone(),
|
param.identifier.name.clone(),
|
||||||
unlabeled.value.clone(),
|
unlabeled.value.clone(),
|
||||||
(¶m.identifier).into(),
|
(¶m.identifier).into(),
|
||||||
|
@ -4,10 +4,11 @@ use anyhow::Result;
|
|||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use super::{memory::EnvironmentRef, MetaSettings};
|
use super::{types::UnitLen, EnvironmentRef, ExecState, MetaSettings};
|
||||||
use crate::{
|
use crate::{
|
||||||
errors::KclErrorDetails,
|
errors::KclErrorDetails,
|
||||||
execution::{
|
execution::{
|
||||||
|
annotations::{SETTINGS, SETTINGS_UNIT_LENGTH},
|
||||||
types::{NumericType, PrimitiveType, RuntimeType},
|
types::{NumericType, PrimitiveType, RuntimeType},
|
||||||
Face, Helix, ImportedGeometry, Metadata, Plane, Sketch, Solid, TagIdentifier,
|
Face, Helix, ImportedGeometry, Metadata, Plane, Sketch, Solid, TagIdentifier,
|
||||||
},
|
},
|
||||||
@ -15,7 +16,7 @@ use crate::{
|
|||||||
DefaultParamVal, FunctionExpression, KclNone, Literal, LiteralValue, Node, TagDeclarator, TagNode,
|
DefaultParamVal, FunctionExpression, KclNone, Literal, LiteralValue, Node, TagDeclarator, TagNode,
|
||||||
},
|
},
|
||||||
std::StdFnProps,
|
std::StdFnProps,
|
||||||
KclError, ModuleId, SourceRange,
|
CompilationError, KclError, ModuleId, SourceRange,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub type KclObjectFields = HashMap<String, KclValue>;
|
pub type KclObjectFields = HashMap<String, KclValue>;
|
||||||
@ -308,22 +309,38 @@ impl KclValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn from_literal(literal: Node<Literal>, settings: &MetaSettings) -> Self {
|
pub(crate) fn from_literal(literal: Node<Literal>, exec_state: &mut ExecState) -> Self {
|
||||||
let meta = vec![literal.metadata()];
|
let meta = vec![literal.metadata()];
|
||||||
match literal.inner.value {
|
match literal.inner.value {
|
||||||
LiteralValue::Number { value, suffix } => KclValue::Number {
|
LiteralValue::Number { value, suffix } => {
|
||||||
value,
|
let ty = NumericType::from_parsed(suffix, &exec_state.mod_local.settings);
|
||||||
meta,
|
if let NumericType::Default { len, .. } = &ty {
|
||||||
ty: NumericType::from_parsed(suffix, settings),
|
if !exec_state.mod_local.explicit_length_units && *len != UnitLen::Mm {
|
||||||
},
|
exec_state.warn(
|
||||||
|
CompilationError::err(
|
||||||
|
literal.as_source_range(),
|
||||||
|
"Project-wide units are deprecated. Prefer to use per-file default units.",
|
||||||
|
)
|
||||||
|
.with_suggestion(
|
||||||
|
"Fix by adding per-file settings",
|
||||||
|
format!("@{SETTINGS}({SETTINGS_UNIT_LENGTH} = {len})\n"),
|
||||||
|
// Insert at the start of the file.
|
||||||
|
Some(SourceRange::new(0, 0, literal.module_id)),
|
||||||
|
crate::errors::Tag::Deprecated,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
KclValue::Number { value, meta, ty }
|
||||||
|
}
|
||||||
LiteralValue::String(value) => KclValue::String { value, meta },
|
LiteralValue::String(value) => KclValue::String { value, meta },
|
||||||
LiteralValue::Bool(value) => KclValue::Bool { value, meta },
|
LiteralValue::Bool(value) => KclValue::Bool { value, meta },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn from_default_param(param: DefaultParamVal, settings: &MetaSettings) -> Self {
|
pub(crate) fn from_default_param(param: DefaultParamVal, exec_state: &mut ExecState) -> Self {
|
||||||
match param {
|
match param {
|
||||||
DefaultParamVal::Literal(lit) => Self::from_literal(lit, settings),
|
DefaultParamVal::Literal(lit) => Self::from_literal(lit, exec_state),
|
||||||
DefaultParamVal::KclNone(none) => KclValue::KclNone {
|
DefaultParamVal::KclNone(none) => KclValue::KclNone {
|
||||||
value: none,
|
value: none,
|
||||||
meta: Default::default(),
|
meta: Default::default(),
|
||||||
|
@ -992,7 +992,11 @@ mod tests {
|
|||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{errors::KclErrorDetails, execution::memory::Stack, ModuleId};
|
use crate::{
|
||||||
|
errors::{KclErrorDetails, Severity},
|
||||||
|
execution::memory::Stack,
|
||||||
|
ModuleId,
|
||||||
|
};
|
||||||
|
|
||||||
/// Convenience function to get a JSON value from memory and unwrap.
|
/// Convenience function to get a JSON value from memory and unwrap.
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
@ -1595,6 +1599,34 @@ const inInches = 2.0 * inch()"#;
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
|
async fn test_unit_suggest() {
|
||||||
|
let src = "foo = 42";
|
||||||
|
let program = crate::Program::parse_no_errs(src).unwrap();
|
||||||
|
let ctx = ExecutorContext {
|
||||||
|
engine: Arc::new(Box::new(
|
||||||
|
crate::engine::conn_mock::EngineConnection::new().await.unwrap(),
|
||||||
|
)),
|
||||||
|
fs: Arc::new(crate::fs::FileManager::new()),
|
||||||
|
stdlib: Arc::new(crate::std::StdLib::new()),
|
||||||
|
settings: ExecutorSettings {
|
||||||
|
units: UnitLength::Ft,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
context_type: ContextType::Mock,
|
||||||
|
};
|
||||||
|
let mut exec_state = ExecState::new(&ctx);
|
||||||
|
ctx.run(&program, &mut exec_state).await.unwrap();
|
||||||
|
let errs = exec_state.errors();
|
||||||
|
assert_eq!(errs.len(), 1, "{errs:?}");
|
||||||
|
let warn = &errs[0];
|
||||||
|
assert_eq!(warn.severity, Severity::Warning);
|
||||||
|
assert_eq!(
|
||||||
|
warn.apply_suggestion(src).unwrap(),
|
||||||
|
"@settings(defaultLengthUnit = ft)\nfoo = 42"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread")]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
async fn test_zero_param_fn() {
|
async fn test_zero_param_fn() {
|
||||||
let ast = r#"const sigmaAllow = 35000 // psi
|
let ast = r#"const sigmaAllow = 35000 // psi
|
||||||
|
@ -72,6 +72,8 @@ pub(super) struct ModuleState {
|
|||||||
pub module_exports: Vec<String>,
|
pub module_exports: Vec<String>,
|
||||||
/// Settings specified from annotations.
|
/// Settings specified from annotations.
|
||||||
pub settings: MetaSettings,
|
pub settings: MetaSettings,
|
||||||
|
pub(super) explicit_length_units: bool,
|
||||||
|
pub(super) std_path: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExecState {
|
impl ExecState {
|
||||||
@ -296,10 +298,11 @@ impl ModuleState {
|
|||||||
stack: memory.new_stack(),
|
stack: memory.new_stack(),
|
||||||
pipe_value: Default::default(),
|
pipe_value: Default::default(),
|
||||||
module_exports: Default::default(),
|
module_exports: Default::default(),
|
||||||
|
explicit_length_units: false,
|
||||||
|
std_path,
|
||||||
settings: MetaSettings {
|
settings: MetaSettings {
|
||||||
default_length_units: exec_settings.units.into(),
|
default_length_units: exec_settings.units.into(),
|
||||||
default_angle_units: Default::default(),
|
default_angle_units: Default::default(),
|
||||||
std_path,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -311,22 +314,23 @@ impl ModuleState {
|
|||||||
pub struct MetaSettings {
|
pub struct MetaSettings {
|
||||||
pub default_length_units: types::UnitLen,
|
pub default_length_units: types::UnitLen,
|
||||||
pub default_angle_units: types::UnitAngle,
|
pub default_angle_units: types::UnitAngle,
|
||||||
pub std_path: Option<String>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MetaSettings {
|
impl MetaSettings {
|
||||||
pub(crate) fn update_from_annotation(
|
pub(crate) fn update_from_annotation(
|
||||||
&mut self,
|
&mut self,
|
||||||
annotation: &crate::parsing::ast::types::Node<Annotation>,
|
annotation: &crate::parsing::ast::types::Node<Annotation>,
|
||||||
) -> Result<(), KclError> {
|
) -> Result<bool, KclError> {
|
||||||
let properties = annotations::expect_properties(annotations::SETTINGS, annotation)?;
|
let properties = annotations::expect_properties(annotations::SETTINGS, annotation)?;
|
||||||
|
|
||||||
|
let mut updated_len = false;
|
||||||
for p in properties {
|
for p in properties {
|
||||||
match &*p.inner.key.name {
|
match &*p.inner.key.name {
|
||||||
annotations::SETTINGS_UNIT_LENGTH => {
|
annotations::SETTINGS_UNIT_LENGTH => {
|
||||||
let value = annotations::expect_ident(&p.inner.value)?;
|
let value = annotations::expect_ident(&p.inner.value)?;
|
||||||
let value = types::UnitLen::from_str(value, annotation.as_source_range())?;
|
let value = types::UnitLen::from_str(value, annotation.as_source_range())?;
|
||||||
self.default_length_units = value;
|
self.default_length_units = value;
|
||||||
|
updated_len = true;
|
||||||
}
|
}
|
||||||
annotations::SETTINGS_UNIT_ANGLE => {
|
annotations::SETTINGS_UNIT_ANGLE => {
|
||||||
let value = annotations::expect_ident(&p.inner.value)?;
|
let value = annotations::expect_ident(&p.inner.value)?;
|
||||||
@ -346,6 +350,6 @@ impl MetaSettings {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(updated_len)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,13 @@ use dhat::{HeapStats, Profiler};
|
|||||||
use web_time::Instant;
|
use web_time::Instant;
|
||||||
|
|
||||||
const LOG_ENV_VAR: &str = "ZOO_LOG";
|
const LOG_ENV_VAR: &str = "ZOO_LOG";
|
||||||
|
const FORCE_LOGGING: bool = false;
|
||||||
|
|
||||||
lazy_static::lazy_static! {
|
lazy_static::lazy_static! {
|
||||||
static ref ENABLED: bool = {
|
static ref ENABLED: bool = {
|
||||||
|
if FORCE_LOGGING {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
let env_var = env::var(LOG_ENV_VAR);
|
let env_var = env::var(LOG_ENV_VAR);
|
||||||
let Ok(env_var) = env_var else {
|
let Ok(env_var) = env_var else {
|
||||||
return false;
|
return false;
|
||||||
|
@ -151,7 +151,6 @@ pub async fn sweep(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
|
|||||||
///
|
///
|
||||||
/// sweep(circleSketch, path = sweepPath, sectional = true)
|
/// sweep(circleSketch, path = sweepPath, sectional = true)
|
||||||
/// ```
|
/// ```
|
||||||
///
|
|
||||||
|
|
||||||
#[stdlib {
|
#[stdlib {
|
||||||
name = "sweep",
|
name = "sweep",
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
@no_std
|
@no_std
|
||||||
|
@settings(defaultLengthUnit = mm)
|
||||||
|
|
||||||
/// The value of `pi`, Archimedes’ constant (π).
|
/// The value of `pi`, Archimedes’ constant (π).
|
||||||
///
|
///
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
@no_std
|
@no_std
|
||||||
|
@settings(defaultLengthUnit = mm)
|
||||||
|
|
||||||
// Note that everything in the prelude is treated as exported.
|
// Note that everything in the prelude is treated as exported.
|
||||||
|
|
||||||
|
@ -58,7 +58,6 @@ export function UnitsMenu() {
|
|||||||
const newCode = changeKclSettings(codeManager.code, {
|
const newCode = changeKclSettings(codeManager.code, {
|
||||||
defaultLengthUnits: unitLengthToUnitLen(unit),
|
defaultLengthUnits: unitLengthToUnitLen(unit),
|
||||||
defaultAngleUnits: { type: 'Degrees' },
|
defaultAngleUnits: { type: 'Degrees' },
|
||||||
stdPath: null,
|
|
||||||
})
|
})
|
||||||
if (err(newCode)) {
|
if (err(newCode)) {
|
||||||
toast.error(
|
toast.error(
|
||||||
|