Allow people to set format options (#389)
* better naming Signed-off-by: Jess Frazelle <github@jessfraz.com> * fixes Signed-off-by: Jess Frazelle <github@jessfraz.com> * up[dates Signed-off-by: Jess Frazelle <github@jessfraz.com> * bump version Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix tests Signed-off-by: Jess Frazelle <github@jessfraz.com> * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * whitespace Signed-off-by: Jess Frazelle <github@jessfraz.com> --------- Signed-off-by: Jess Frazelle <github@jessfraz.com>
This commit is contained in:
@ -1564,7 +1564,7 @@ const key = 'c'`
|
|||||||
start: code.indexOf('\n// this is a comment'),
|
start: code.indexOf('\n// this is a comment'),
|
||||||
end: code.indexOf('const key'),
|
end: code.indexOf('const key'),
|
||||||
value: {
|
value: {
|
||||||
type: 'block',
|
type: 'blockComment',
|
||||||
value: 'this is a comment',
|
value: 'this is a comment',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -1602,7 +1602,7 @@ const key = 'c'`
|
|||||||
start: 106,
|
start: 106,
|
||||||
end: 166,
|
end: 166,
|
||||||
value: {
|
value: {
|
||||||
type: 'block',
|
type: 'blockComment',
|
||||||
value: 'this is\n a comment\n spanning a few lines',
|
value: 'this is\n a comment\n spanning a few lines',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ -1625,7 +1625,7 @@ const key = 'c'`
|
|||||||
start: 125,
|
start: 125,
|
||||||
end: 141,
|
end: 141,
|
||||||
value: {
|
value: {
|
||||||
type: 'block',
|
type: 'blockComment',
|
||||||
value: 'a comment',
|
value: 'a comment',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -318,9 +318,9 @@ describe('it recasts wrapped object expressions in pipe bodies with correct inde
|
|||||||
|> line({ to: [0.62, 4.15], tag: 'seg01' }, %)
|
|> line({ to: [0.62, 4.15], tag: 'seg01' }, %)
|
||||||
|> line([2.77, -1.24], %)
|
|> line([2.77, -1.24], %)
|
||||||
|> angledLineThatIntersects({
|
|> angledLineThatIntersects({
|
||||||
angle: 201,
|
angle: 201,
|
||||||
offset: -1.35,
|
offset: -1.35,
|
||||||
intersectTag: 'seg01'
|
intersectTag: 'seg01'
|
||||||
}, %)
|
}, %)
|
||||||
|> line([-0.42, -1.72], %)
|
|> line([-0.42, -1.72], %)
|
||||||
show(part001)`
|
show(part001)`
|
||||||
|
@ -59,19 +59,19 @@ describe('testing swaping out sketch calls with xLine/xLineTo', () => {
|
|||||||
` |> lineTo({ to: [1, 1], tag: 'abc1' }, %)`,
|
` |> lineTo({ to: [1, 1], tag: 'abc1' }, %)`,
|
||||||
` |> line({ to: [-2.04, -0.7], tag: 'abc2' }, %)`,
|
` |> line({ to: [-2.04, -0.7], tag: 'abc2' }, %)`,
|
||||||
` |> angledLine({`,
|
` |> angledLine({`,
|
||||||
` angle: 157,`,
|
` angle: 157,`,
|
||||||
` length: 1.69,`,
|
` length: 1.69,`,
|
||||||
` tag: 'abc3'`,
|
` tag: 'abc3'`,
|
||||||
` }, %)`,
|
` }, %)`,
|
||||||
` |> angledLineOfXLength({`,
|
` |> angledLineOfXLength({`,
|
||||||
` angle: 217,`,
|
` angle: 217,`,
|
||||||
` length: 0.86,`,
|
` length: 0.86,`,
|
||||||
` tag: 'abc4'`,
|
` tag: 'abc4'`,
|
||||||
` }, %)`,
|
` }, %)`,
|
||||||
` |> angledLineOfYLength({`,
|
` |> angledLineOfYLength({`,
|
||||||
` angle: 104,`,
|
` angle: 104,`,
|
||||||
` length: 1.58,`,
|
` length: 1.58,`,
|
||||||
` tag: 'abc5'`,
|
` tag: 'abc5'`,
|
||||||
` }, %)`,
|
` }, %)`,
|
||||||
` |> angledLineToX({ angle: 55, to: -2.89, tag: 'abc6' }, %)`,
|
` |> angledLineToX({ angle: 55, to: -2.89, tag: 'abc6' }, %)`,
|
||||||
` |> angledLineToY({ angle: 330, to: 2.53, tag: 'abc7' }, %)`,
|
` |> angledLineToY({ angle: 330, to: 2.53, tag: 'abc7' }, %)`,
|
||||||
@ -144,9 +144,9 @@ describe('testing swaping out sketch calls with xLine/xLineTo', () => {
|
|||||||
inputCode: bigExample,
|
inputCode: bigExample,
|
||||||
callToSwap: [
|
callToSwap: [
|
||||||
`angledLine({`,
|
`angledLine({`,
|
||||||
` angle: 157,`,
|
` angle: 157,`,
|
||||||
` length: 1.69,`,
|
` length: 1.69,`,
|
||||||
` tag: 'abc3'`,
|
` tag: 'abc3'`,
|
||||||
` }, %)`,
|
` }, %)`,
|
||||||
].join('\n'),
|
].join('\n'),
|
||||||
constraintType: 'horizontal',
|
constraintType: 'horizontal',
|
||||||
@ -172,9 +172,9 @@ describe('testing swaping out sketch calls with xLine/xLineTo', () => {
|
|||||||
inputCode: bigExample,
|
inputCode: bigExample,
|
||||||
callToSwap: [
|
callToSwap: [
|
||||||
`angledLineOfXLength({`,
|
`angledLineOfXLength({`,
|
||||||
` angle: 217,`,
|
` angle: 217,`,
|
||||||
` length: 0.86,`,
|
` length: 0.86,`,
|
||||||
` tag: 'abc4'`,
|
` tag: 'abc4'`,
|
||||||
` }, %)`,
|
` }, %)`,
|
||||||
].join('\n'),
|
].join('\n'),
|
||||||
constraintType: 'horizontal',
|
constraintType: 'horizontal',
|
||||||
@ -201,9 +201,9 @@ describe('testing swaping out sketch calls with xLine/xLineTo', () => {
|
|||||||
inputCode: bigExample,
|
inputCode: bigExample,
|
||||||
callToSwap: [
|
callToSwap: [
|
||||||
`angledLineOfYLength({`,
|
`angledLineOfYLength({`,
|
||||||
` angle: 104,`,
|
` angle: 104,`,
|
||||||
` length: 1.58,`,
|
` length: 1.58,`,
|
||||||
` tag: 'abc5'`,
|
` tag: 'abc5'`,
|
||||||
` }, %)`,
|
` }, %)`,
|
||||||
].join('\n'),
|
].join('\n'),
|
||||||
constraintType: 'vertical',
|
constraintType: 'vertical',
|
||||||
|
@ -133,64 +133,64 @@ const myAng2 = 134
|
|||||||
const part001 = startSketchAt([0, 0])
|
const part001 = startSketchAt([0, 0])
|
||||||
|> line({ to: [1, 3.82], tag: 'seg01' }, %) // ln-should-get-tag
|
|> line({ to: [1, 3.82], tag: 'seg01' }, %) // ln-should-get-tag
|
||||||
|> angledLineToX([
|
|> angledLineToX([
|
||||||
-angleToMatchLengthX('seg01', myVar, %),
|
-angleToMatchLengthX('seg01', myVar, %),
|
||||||
myVar
|
myVar
|
||||||
], %) // ln-lineTo-xAbsolute should use angleToMatchLengthX helper
|
], %) // ln-lineTo-xAbsolute should use angleToMatchLengthX helper
|
||||||
|> angledLineToY([
|
|> angledLineToY([
|
||||||
-angleToMatchLengthY('seg01', myVar, %),
|
-angleToMatchLengthY('seg01', myVar, %),
|
||||||
myVar
|
myVar
|
||||||
], %) // ln-lineTo-yAbsolute should use angleToMatchLengthY helper
|
], %) // ln-lineTo-yAbsolute should use angleToMatchLengthY helper
|
||||||
|> angledLine([45, segLen('seg01', %)], %) // ln-lineTo-free should become angledLine
|
|> angledLine([45, segLen('seg01', %)], %) // ln-lineTo-free should become angledLine
|
||||||
|> angledLine([45, segLen('seg01', %)], %) // ln-angledLineToX-free should become angledLine
|
|> angledLine([45, segLen('seg01', %)], %) // ln-angledLineToX-free should become angledLine
|
||||||
|> angledLine([myAng, segLen('seg01', %)], %) // ln-angledLineToX-angle should become angledLine
|
|> angledLine([myAng, segLen('seg01', %)], %) // ln-angledLineToX-angle should become angledLine
|
||||||
|> angledLineToX([
|
|> angledLineToX([
|
||||||
angleToMatchLengthX('seg01', myVar2, %),
|
angleToMatchLengthX('seg01', myVar2, %),
|
||||||
myVar2
|
myVar2
|
||||||
], %) // ln-angledLineToX-xAbsolute should use angleToMatchLengthX to get angle
|
], %) // ln-angledLineToX-xAbsolute should use angleToMatchLengthX to get angle
|
||||||
|> angledLine([-45, segLen('seg01', %)], %) // ln-angledLineToY-free should become angledLine
|
|> angledLine([-45, segLen('seg01', %)], %) // ln-angledLineToY-free should become angledLine
|
||||||
|> angledLine([myAng2, segLen('seg01', %)], %) // ln-angledLineToY-angle should become angledLine
|
|> angledLine([myAng2, segLen('seg01', %)], %) // ln-angledLineToY-angle should become angledLine
|
||||||
|> angledLineToY([
|
|> angledLineToY([
|
||||||
angleToMatchLengthY('seg01', myVar3, %),
|
angleToMatchLengthY('seg01', myVar3, %),
|
||||||
myVar3
|
myVar3
|
||||||
], %) // ln-angledLineToY-yAbsolute should use angleToMatchLengthY to get angle
|
], %) // ln-angledLineToY-yAbsolute should use angleToMatchLengthY to get angle
|
||||||
|> line([
|
|> line([
|
||||||
min(segLen('seg01', %), myVar),
|
min(segLen('seg01', %), myVar),
|
||||||
legLen(segLen('seg01', %), myVar)
|
legLen(segLen('seg01', %), myVar)
|
||||||
], %) // ln-should use legLen for y
|
], %) // ln-should use legLen for y
|
||||||
|> line([
|
|> line([
|
||||||
min(segLen('seg01', %), myVar),
|
min(segLen('seg01', %), myVar),
|
||||||
-legLen(segLen('seg01', %), myVar)
|
-legLen(segLen('seg01', %), myVar)
|
||||||
], %) // ln-legLen but negative
|
], %) // ln-legLen but negative
|
||||||
|> angledLine([-112, segLen('seg01', %)], %) // ln-should become angledLine
|
|> angledLine([-112, segLen('seg01', %)], %) // ln-should become angledLine
|
||||||
|> angledLine([myVar, segLen('seg01', %)], %) // ln-use segLen for secound arg
|
|> angledLine([myVar, segLen('seg01', %)], %) // ln-use segLen for secound arg
|
||||||
|> angledLine([45, segLen('seg01', %)], %) // ln-segLen again
|
|> angledLine([45, segLen('seg01', %)], %) // ln-segLen again
|
||||||
|> angledLine([54, segLen('seg01', %)], %) // ln-should be transformed to angledLine
|
|> angledLine([54, segLen('seg01', %)], %) // ln-should be transformed to angledLine
|
||||||
|> angledLineOfXLength([
|
|> angledLineOfXLength([
|
||||||
legAngX(segLen('seg01', %), myVar),
|
legAngX(segLen('seg01', %), myVar),
|
||||||
min(segLen('seg01', %), myVar)
|
min(segLen('seg01', %), myVar)
|
||||||
], %) // ln-should use legAngX to calculate angle
|
], %) // ln-should use legAngX to calculate angle
|
||||||
|> angledLineOfXLength([
|
|> angledLineOfXLength([
|
||||||
180 + legAngX(segLen('seg01', %), myVar),
|
180 + legAngX(segLen('seg01', %), myVar),
|
||||||
min(segLen('seg01', %), myVar)
|
min(segLen('seg01', %), myVar)
|
||||||
], %) // ln-same as above but should have + 180 to match original quadrant
|
], %) // ln-same as above but should have + 180 to match original quadrant
|
||||||
|> line([
|
|> line([
|
||||||
legLen(segLen('seg01', %), myVar),
|
legLen(segLen('seg01', %), myVar),
|
||||||
min(segLen('seg01', %), myVar)
|
min(segLen('seg01', %), myVar)
|
||||||
], %) // ln-legLen again but yRelative
|
], %) // ln-legLen again but yRelative
|
||||||
|> line([
|
|> line([
|
||||||
-legLen(segLen('seg01', %), myVar),
|
-legLen(segLen('seg01', %), myVar),
|
||||||
min(segLen('seg01', %), myVar)
|
min(segLen('seg01', %), myVar)
|
||||||
], %) // ln-negative legLen yRelative
|
], %) // ln-negative legLen yRelative
|
||||||
|> angledLine([58, segLen('seg01', %)], %) // ln-angledLineOfYLength-free should become angledLine
|
|> angledLine([58, segLen('seg01', %)], %) // ln-angledLineOfYLength-free should become angledLine
|
||||||
|> angledLine([myAng, segLen('seg01', %)], %) // ln-angledLineOfYLength-angle should become angledLine
|
|> angledLine([myAng, segLen('seg01', %)], %) // ln-angledLineOfYLength-angle should become angledLine
|
||||||
|> angledLineOfXLength([
|
|> angledLineOfXLength([
|
||||||
legAngY(segLen('seg01', %), myVar),
|
legAngY(segLen('seg01', %), myVar),
|
||||||
min(segLen('seg01', %), myVar)
|
min(segLen('seg01', %), myVar)
|
||||||
], %) // ln-angledLineOfYLength-yRelative use legAngY
|
], %) // ln-angledLineOfYLength-yRelative use legAngY
|
||||||
|> angledLineOfXLength([
|
|> angledLineOfXLength([
|
||||||
270 + legAngY(segLen('seg01', %), myVar),
|
270 + legAngY(segLen('seg01', %), myVar),
|
||||||
min(segLen('seg01', %), myVar)
|
min(segLen('seg01', %), myVar)
|
||||||
], %) // ln-angledLineOfYLength-yRelative with angle > 90 use binExp
|
], %) // ln-angledLineOfYLength-yRelative with angle > 90 use binExp
|
||||||
|> xLine(segLen('seg01', %), %) // ln-xLine-free should sub in segLen
|
|> xLine(segLen('seg01', %), %) // ln-xLine-free should sub in segLen
|
||||||
|> yLine(segLen('seg01', %), %) // ln-yLine-free should sub in segLen
|
|> yLine(segLen('seg01', %), %) // ln-yLine-free should sub in segLen
|
||||||
|> xLine(segLen('seg01', %), %) // ln-xLineTo-free should convert to xLine
|
|> xLine(segLen('seg01', %), %) // ln-xLineTo-free should convert to xLine
|
||||||
@ -406,9 +406,9 @@ show(part001)`
|
|||||||
'setVertDistance'
|
'setVertDistance'
|
||||||
)
|
)
|
||||||
expect(expectedCode).toContain(`|> lineTo([
|
expect(expectedCode).toContain(`|> lineTo([
|
||||||
lastSegX(%) + myVar,
|
lastSegX(%) + myVar,
|
||||||
segEndY('seg01', %) + 2.93
|
segEndY('seg01', %) + 2.93
|
||||||
], %) // xRelative`)
|
], %) // xRelative`)
|
||||||
})
|
})
|
||||||
it('testing for yRelative to horizontal distance', async () => {
|
it('testing for yRelative to horizontal distance', async () => {
|
||||||
const expectedCode = await helperThing(
|
const expectedCode = await helperThing(
|
||||||
@ -417,9 +417,9 @@ show(part001)`
|
|||||||
'setHorzDistance'
|
'setHorzDistance'
|
||||||
)
|
)
|
||||||
expect(expectedCode).toContain(`|> lineTo([
|
expect(expectedCode).toContain(`|> lineTo([
|
||||||
segEndX('seg01', %) + 2.6,
|
segEndX('seg01', %) + 2.6,
|
||||||
lastSegY(%) + myVar
|
lastSegY(%) + myVar
|
||||||
], %) // yRelative`)
|
], %) // yRelative`)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
2
src/wasm-lib/Cargo.lock
generated
2
src/wasm-lib/Cargo.lock
generated
@ -1094,7 +1094,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kcl-lib"
|
name = "kcl-lib"
|
||||||
version = "0.1.20"
|
version = "0.1.21"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bson",
|
"bson",
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "kcl-lib"
|
name = "kcl-lib"
|
||||||
description = "KittyCAD Language"
|
description = "KittyCAD Language"
|
||||||
version = "0.1.20"
|
version = "0.1.21"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|
||||||
|
@ -27,12 +27,16 @@ pub struct Program {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Program {
|
impl Program {
|
||||||
pub fn recast(&self, indentation: &str, is_with_block: bool) -> String {
|
pub fn recast(&self, options: &FormatOptions, indentation_level: usize) -> String {
|
||||||
self.body
|
let indentation = options.get_indentation(indentation_level);
|
||||||
|
let result = self
|
||||||
|
.body
|
||||||
.iter()
|
.iter()
|
||||||
.map(|statement| match statement.clone() {
|
.map(|statement| match statement.clone() {
|
||||||
BodyItem::ExpressionStatement(expression_statement) => {
|
BodyItem::ExpressionStatement(expression_statement) => {
|
||||||
expression_statement.expression.recast(indentation, false)
|
expression_statement
|
||||||
|
.expression
|
||||||
|
.recast(options, indentation_level, false)
|
||||||
}
|
}
|
||||||
BodyItem::VariableDeclaration(variable_declaration) => variable_declaration
|
BodyItem::VariableDeclaration(variable_declaration) => variable_declaration
|
||||||
.declarations
|
.declarations
|
||||||
@ -43,56 +47,44 @@ impl Program {
|
|||||||
indentation,
|
indentation,
|
||||||
variable_declaration.kind,
|
variable_declaration.kind,
|
||||||
declaration.id.name,
|
declaration.id.name,
|
||||||
declaration.init.recast("", false)
|
declaration.init.recast(options, 0, false)
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.collect::<String>(),
|
.collect::<String>(),
|
||||||
BodyItem::ReturnStatement(return_statement) => {
|
BodyItem::ReturnStatement(return_statement) => {
|
||||||
format!("{}return {}", indentation, return_statement.argument.recast("", false))
|
format!(
|
||||||
|
"{}return {}",
|
||||||
|
indentation,
|
||||||
|
return_statement.argument.recast(options, 0, false)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(index, recast_str)| {
|
.map(|(index, recast_str)| {
|
||||||
let is_legit_custom_whitespace_or_comment = |s: String| s != " " && s != "\n" && s != " " && s != "\t";
|
let start_string = if index == 0 {
|
||||||
|
// We need to indent.
|
||||||
// determine the value of startString
|
|
||||||
let last_white_space_or_comment = if index > 0 {
|
|
||||||
let tmp = if let Some(non_code_node) = self.non_code_meta.none_code_nodes.get(&(index - 1)) {
|
|
||||||
non_code_node.format(indentation)
|
|
||||||
} else {
|
|
||||||
" ".to_string()
|
|
||||||
};
|
|
||||||
tmp
|
|
||||||
} else {
|
|
||||||
" ".to_string()
|
|
||||||
};
|
|
||||||
// indentation of this line will be covered by the previous if we're using a custom whitespace or comment
|
|
||||||
let mut start_string = if is_legit_custom_whitespace_or_comment(last_white_space_or_comment) {
|
|
||||||
String::new()
|
|
||||||
} else {
|
|
||||||
indentation.to_owned()
|
|
||||||
};
|
|
||||||
if index == 0 {
|
|
||||||
if let Some(start) = self.non_code_meta.start.clone() {
|
if let Some(start) = self.non_code_meta.start.clone() {
|
||||||
start_string = start.format(indentation);
|
start.format(&indentation)
|
||||||
} else {
|
} else {
|
||||||
start_string = indentation.to_owned();
|
indentation.to_string()
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
|
// Do nothing, we already applied the indentation elsewhere.
|
||||||
|
String::new()
|
||||||
|
};
|
||||||
|
|
||||||
// determine the value of endString
|
// determine the value of the end string
|
||||||
let maybe_line_break: String = if index == self.body.len() - 1 && !is_with_block {
|
// basically if we are inside a nested function we want to end with a new line
|
||||||
|
let maybe_line_break: String = if index == self.body.len() - 1 && indentation_level == 0 {
|
||||||
String::new()
|
String::new()
|
||||||
} else {
|
} else {
|
||||||
"\n".to_string()
|
"\n".to_string()
|
||||||
};
|
};
|
||||||
let mut custom_white_space_or_comment = match self.non_code_meta.none_code_nodes.get(&index) {
|
|
||||||
Some(custom_white_space_or_comment) => custom_white_space_or_comment.format(indentation),
|
let custom_white_space_or_comment = match self.non_code_meta.none_code_nodes.get(&index) {
|
||||||
|
Some(custom_white_space_or_comment) => custom_white_space_or_comment.format(&indentation),
|
||||||
None => String::new(),
|
None => String::new(),
|
||||||
};
|
};
|
||||||
if !is_legit_custom_whitespace_or_comment(custom_white_space_or_comment.clone()) {
|
|
||||||
custom_white_space_or_comment = String::new();
|
|
||||||
}
|
|
||||||
let end_string = if custom_white_space_or_comment.is_empty() {
|
let end_string = if custom_white_space_or_comment.is_empty() {
|
||||||
maybe_line_break
|
maybe_line_break
|
||||||
} else {
|
} else {
|
||||||
@ -103,7 +95,14 @@ impl Program {
|
|||||||
})
|
})
|
||||||
.collect::<String>()
|
.collect::<String>()
|
||||||
.trim()
|
.trim()
|
||||||
.to_string()
|
.to_string();
|
||||||
|
|
||||||
|
// Insert a final new line if the user wants it.
|
||||||
|
if options.insert_final_newline {
|
||||||
|
format!("{}\n", result)
|
||||||
|
} else {
|
||||||
|
result
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the body item that includes the given character position.
|
/// Returns the body item that includes the given character position.
|
||||||
@ -249,19 +248,18 @@ pub enum Value {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Value {
|
impl Value {
|
||||||
fn recast(&self, indentation: &str, is_in_pipe_expression: bool) -> String {
|
fn recast(&self, options: &FormatOptions, indentation_level: usize, is_in_pipe: bool) -> String {
|
||||||
let indentation = indentation.to_string() + if is_in_pipe_expression { " " } else { "" };
|
|
||||||
match &self {
|
match &self {
|
||||||
Value::BinaryExpression(bin_exp) => bin_exp.recast(),
|
Value::BinaryExpression(bin_exp) => bin_exp.recast(options),
|
||||||
Value::ArrayExpression(array_exp) => array_exp.recast(&indentation, is_in_pipe_expression),
|
Value::ArrayExpression(array_exp) => array_exp.recast(options, indentation_level, is_in_pipe),
|
||||||
Value::ObjectExpression(ref obj_exp) => obj_exp.recast(&indentation, is_in_pipe_expression),
|
Value::ObjectExpression(ref obj_exp) => obj_exp.recast(options, indentation_level, is_in_pipe),
|
||||||
Value::MemberExpression(mem_exp) => mem_exp.recast(),
|
Value::MemberExpression(mem_exp) => mem_exp.recast(),
|
||||||
Value::Literal(literal) => literal.recast(),
|
Value::Literal(literal) => literal.recast(),
|
||||||
Value::FunctionExpression(func_exp) => func_exp.recast(&indentation),
|
Value::FunctionExpression(func_exp) => func_exp.recast(options, indentation_level),
|
||||||
Value::CallExpression(call_exp) => call_exp.recast(&indentation, is_in_pipe_expression),
|
Value::CallExpression(call_exp) => call_exp.recast(options, indentation_level, is_in_pipe),
|
||||||
Value::Identifier(ident) => ident.name.to_string(),
|
Value::Identifier(ident) => ident.name.to_string(),
|
||||||
Value::PipeExpression(pipe_exp) => pipe_exp.recast(&indentation),
|
Value::PipeExpression(pipe_exp) => pipe_exp.recast(options, indentation_level),
|
||||||
Value::UnaryExpression(unary_exp) => unary_exp.recast(),
|
Value::UnaryExpression(unary_exp) => unary_exp.recast(options),
|
||||||
Value::PipeSubstitution(_) => crate::parser::PIPE_SUBSTITUTION_OPERATOR.to_string(),
|
Value::PipeSubstitution(_) => crate::parser::PIPE_SUBSTITUTION_OPERATOR.to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -355,13 +353,13 @@ impl From<&BinaryPart> for crate::executor::SourceRange {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl BinaryPart {
|
impl BinaryPart {
|
||||||
fn recast(&self, indentation: &str) -> String {
|
fn recast(&self, options: &FormatOptions, indentation_level: usize) -> String {
|
||||||
match &self {
|
match &self {
|
||||||
BinaryPart::Literal(literal) => literal.recast(),
|
BinaryPart::Literal(literal) => literal.recast(),
|
||||||
BinaryPart::Identifier(identifier) => identifier.name.to_string(),
|
BinaryPart::Identifier(identifier) => identifier.name.to_string(),
|
||||||
BinaryPart::BinaryExpression(binary_expression) => binary_expression.recast(),
|
BinaryPart::BinaryExpression(binary_expression) => binary_expression.recast(options),
|
||||||
BinaryPart::CallExpression(call_expression) => call_expression.recast(indentation, false),
|
BinaryPart::CallExpression(call_expression) => call_expression.recast(options, indentation_level, false),
|
||||||
BinaryPart::UnaryExpression(unary_expression) => unary_expression.recast(),
|
BinaryPart::UnaryExpression(unary_expression) => unary_expression.recast(options),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -436,17 +434,17 @@ pub struct NoneCodeNode {
|
|||||||
impl NoneCodeNode {
|
impl NoneCodeNode {
|
||||||
pub fn value(&self) -> String {
|
pub fn value(&self) -> String {
|
||||||
match &self.value {
|
match &self.value {
|
||||||
NoneCodeValue::Inline { value } => value.clone(),
|
NoneCodeValue::InlineComment { value } => value.clone(),
|
||||||
NoneCodeValue::Block { value } => value.clone(),
|
NoneCodeValue::BlockComment { value } => value.clone(),
|
||||||
NoneCodeValue::NewLineBlock { value } => value.clone(),
|
NoneCodeValue::NewLineBlockComment { value } => value.clone(),
|
||||||
NoneCodeValue::NewLine => "\n\n".to_string(),
|
NoneCodeValue::NewLine => "\n\n".to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn format(&self, indentation: &str) -> String {
|
pub fn format(&self, indentation: &str) -> String {
|
||||||
match &self.value {
|
match &self.value {
|
||||||
NoneCodeValue::Inline { value } => format!(" // {}\n", value),
|
NoneCodeValue::InlineComment { value } => format!(" // {}\n", value),
|
||||||
NoneCodeValue::Block { value } => {
|
NoneCodeValue::BlockComment { value } => {
|
||||||
let add_start_new_line = if self.start == 0 { "" } else { "\n" };
|
let add_start_new_line = if self.start == 0 { "" } else { "\n" };
|
||||||
if value.contains('\n') {
|
if value.contains('\n') {
|
||||||
format!("{}{}/* {} */\n", add_start_new_line, indentation, value)
|
format!("{}{}/* {} */\n", add_start_new_line, indentation, value)
|
||||||
@ -454,7 +452,7 @@ impl NoneCodeNode {
|
|||||||
format!("{}{}// {}\n", add_start_new_line, indentation, value)
|
format!("{}{}// {}\n", add_start_new_line, indentation, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NoneCodeValue::NewLineBlock { value } => {
|
NoneCodeValue::NewLineBlockComment { value } => {
|
||||||
let add_start_new_line = if self.start == 0 { "" } else { "\n\n" };
|
let add_start_new_line = if self.start == 0 { "" } else { "\n\n" };
|
||||||
if value.contains('\n') {
|
if value.contains('\n') {
|
||||||
format!("{}{}/* {} */\n", add_start_new_line, indentation, value)
|
format!("{}{}/* {} */\n", add_start_new_line, indentation, value)
|
||||||
@ -471,9 +469,29 @@ impl NoneCodeNode {
|
|||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
#[serde(tag = "type", rename_all = "camelCase")]
|
#[serde(tag = "type", rename_all = "camelCase")]
|
||||||
pub enum NoneCodeValue {
|
pub enum NoneCodeValue {
|
||||||
Inline { value: String },
|
/// An inline comment.
|
||||||
Block { value: String },
|
/// An example of this is the following: `1 + 1 // This is an inline comment`.
|
||||||
NewLineBlock { value: String },
|
InlineComment {
|
||||||
|
value: String,
|
||||||
|
},
|
||||||
|
/// A block comment.
|
||||||
|
/// An example of this is the following:
|
||||||
|
/// ```python,no_run
|
||||||
|
/// /* This is a
|
||||||
|
/// block comment */
|
||||||
|
/// 1 + 1
|
||||||
|
/// ```
|
||||||
|
/// Now this is important. The block comment is attached to the next line.
|
||||||
|
/// This is always the case. Also the block comment doesnt have a new line above it.
|
||||||
|
/// If it did it would be a `NewLineBlockComment`.
|
||||||
|
BlockComment {
|
||||||
|
value: String,
|
||||||
|
},
|
||||||
|
/// A block comment that has a new line above it.
|
||||||
|
/// The user explicitly added a new line above the block comment.
|
||||||
|
NewLineBlockComment {
|
||||||
|
value: String,
|
||||||
|
},
|
||||||
// A new line like `\n\n` NOT a new line like `\n`.
|
// A new line like `\n\n` NOT a new line like `\n`.
|
||||||
// This is also not a comment.
|
// This is also not a comment.
|
||||||
NewLine,
|
NewLine,
|
||||||
@ -539,13 +557,13 @@ pub struct CallExpression {
|
|||||||
impl_value_meta!(CallExpression);
|
impl_value_meta!(CallExpression);
|
||||||
|
|
||||||
impl CallExpression {
|
impl CallExpression {
|
||||||
fn recast(&self, indentation: &str, is_in_pipe_expression: bool) -> String {
|
fn recast(&self, options: &FormatOptions, indentation_level: usize, is_in_pipe: bool) -> String {
|
||||||
format!(
|
format!(
|
||||||
"{}({})",
|
"{}({})",
|
||||||
self.callee.name,
|
self.callee.name,
|
||||||
self.arguments
|
self.arguments
|
||||||
.iter()
|
.iter()
|
||||||
.map(|arg| arg.recast(indentation, is_in_pipe_expression))
|
.map(|arg| arg.recast(options, indentation_level, is_in_pipe))
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
.join(", ")
|
.join(", ")
|
||||||
)
|
)
|
||||||
@ -923,27 +941,35 @@ pub struct ArrayExpression {
|
|||||||
impl_value_meta!(ArrayExpression);
|
impl_value_meta!(ArrayExpression);
|
||||||
|
|
||||||
impl ArrayExpression {
|
impl ArrayExpression {
|
||||||
fn recast(&self, indentation: &str, is_in_pipe_expression: bool) -> String {
|
fn recast(&self, options: &FormatOptions, indentation_level: usize, is_in_pipe: bool) -> String {
|
||||||
let flat_recast = format!(
|
let flat_recast = format!(
|
||||||
"[{}]",
|
"[{}]",
|
||||||
self.elements
|
self.elements
|
||||||
.iter()
|
.iter()
|
||||||
.map(|el| el.recast("", false))
|
.map(|el| el.recast(options, 0, false))
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
.join(", ")
|
.join(", ")
|
||||||
);
|
);
|
||||||
let max_array_length = 40;
|
let max_array_length = 40;
|
||||||
if flat_recast.len() > max_array_length {
|
if flat_recast.len() > max_array_length {
|
||||||
let indentation = indentation.to_string() + " ";
|
let inner_indentation = if is_in_pipe {
|
||||||
|
options.get_indentation_offset_pipe(indentation_level + 1)
|
||||||
|
} else {
|
||||||
|
options.get_indentation(indentation_level + 1)
|
||||||
|
};
|
||||||
format!(
|
format!(
|
||||||
"[\n{}{}\n{}]",
|
"[\n{}{}\n{}]",
|
||||||
indentation,
|
inner_indentation,
|
||||||
self.elements
|
self.elements
|
||||||
.iter()
|
.iter()
|
||||||
.map(|el| el.recast(&indentation, false))
|
.map(|el| el.recast(options, indentation_level, false))
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
.join(format!(",\n{}", indentation).as_str()),
|
.join(format!(",\n{}", inner_indentation).as_str()),
|
||||||
if is_in_pipe_expression { " " } else { "" }
|
if is_in_pipe {
|
||||||
|
options.get_indentation_offset_pipe(indentation_level)
|
||||||
|
} else {
|
||||||
|
options.get_indentation(indentation_level)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
flat_recast
|
flat_recast
|
||||||
@ -1031,27 +1057,35 @@ pub struct ObjectExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ObjectExpression {
|
impl ObjectExpression {
|
||||||
fn recast(&self, indentation: &str, is_in_pipe_expression: bool) -> String {
|
fn recast(&self, options: &FormatOptions, indentation_level: usize, is_in_pipe: bool) -> String {
|
||||||
let flat_recast = format!(
|
let flat_recast = format!(
|
||||||
"{{ {} }}",
|
"{{ {} }}",
|
||||||
self.properties
|
self.properties
|
||||||
.iter()
|
.iter()
|
||||||
.map(|prop| { format!("{}: {}", prop.key.name, prop.value.recast("", false)) })
|
.map(|prop| { format!("{}: {}", prop.key.name, prop.value.recast(options, 0, false)) })
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
.join(", ")
|
.join(", ")
|
||||||
);
|
);
|
||||||
let max_array_length = 40;
|
let max_array_length = 40;
|
||||||
if flat_recast.len() > max_array_length {
|
if flat_recast.len() > max_array_length {
|
||||||
let indentation = indentation.to_owned() + " ";
|
let inner_indentation = if is_in_pipe {
|
||||||
|
options.get_indentation_offset_pipe(indentation_level + 1)
|
||||||
|
} else {
|
||||||
|
options.get_indentation(indentation_level + 1)
|
||||||
|
};
|
||||||
format!(
|
format!(
|
||||||
"{{\n{}{}\n{}}}",
|
"{{\n{}{}\n{}}}",
|
||||||
indentation,
|
inner_indentation,
|
||||||
self.properties
|
self.properties
|
||||||
.iter()
|
.iter()
|
||||||
.map(|prop| { format!("{}: {}", prop.key.name, prop.value.recast("", is_in_pipe_expression)) })
|
.map(|prop| { format!("{}: {}", prop.key.name, prop.value.recast(options, 0, false)) })
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
.join(format!(",\n{}", indentation).as_str()),
|
.join(format!(",\n{}", inner_indentation).as_str()),
|
||||||
if is_in_pipe_expression { " " } else { "" }
|
if is_in_pipe {
|
||||||
|
options.get_indentation_offset_pipe(indentation_level)
|
||||||
|
} else {
|
||||||
|
options.get_indentation(indentation_level)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
flat_recast
|
flat_recast
|
||||||
@ -1370,7 +1404,7 @@ impl BinaryExpression {
|
|||||||
self.operator.precedence()
|
self.operator.precedence()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn recast(&self) -> String {
|
fn recast(&self, options: &FormatOptions) -> String {
|
||||||
let maybe_wrap_it = |a: String, doit: bool| -> String {
|
let maybe_wrap_it = |a: String, doit: bool| -> String {
|
||||||
if doit {
|
if doit {
|
||||||
format!("({})", a)
|
format!("({})", a)
|
||||||
@ -1393,9 +1427,9 @@ impl BinaryExpression {
|
|||||||
|
|
||||||
format!(
|
format!(
|
||||||
"{} {} {}",
|
"{} {} {}",
|
||||||
maybe_wrap_it(self.left.recast(""), should_wrap_left),
|
maybe_wrap_it(self.left.recast(options, 0), should_wrap_left),
|
||||||
self.operator,
|
self.operator,
|
||||||
maybe_wrap_it(self.right.recast(""), should_wrap_right)
|
maybe_wrap_it(self.right.recast(options, 0), should_wrap_right)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1532,8 +1566,8 @@ pub struct UnaryExpression {
|
|||||||
impl_value_meta!(UnaryExpression);
|
impl_value_meta!(UnaryExpression);
|
||||||
|
|
||||||
impl UnaryExpression {
|
impl UnaryExpression {
|
||||||
fn recast(&self) -> String {
|
fn recast(&self, options: &FormatOptions) -> String {
|
||||||
format!("{}{}", &self.operator, self.argument.recast(""))
|
format!("{}{}", &self.operator, self.argument.recast(options, 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_result(
|
pub fn get_result(
|
||||||
@ -1595,13 +1629,13 @@ pub struct PipeExpression {
|
|||||||
impl_value_meta!(PipeExpression);
|
impl_value_meta!(PipeExpression);
|
||||||
|
|
||||||
impl PipeExpression {
|
impl PipeExpression {
|
||||||
fn recast(&self, indentation: &str) -> String {
|
fn recast(&self, options: &FormatOptions, indentation_level: usize) -> String {
|
||||||
self.body
|
self.body
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(index, statement)| {
|
.map(|(index, statement)| {
|
||||||
let indentation = indentation.to_string() + " ";
|
let indentation = options.get_indentation(indentation_level + 1);
|
||||||
let mut s = statement.recast(&indentation, true);
|
let mut s = statement.recast(options, indentation_level + 1, true);
|
||||||
let non_code_meta = self.non_code_meta.clone();
|
let non_code_meta = self.non_code_meta.clone();
|
||||||
if let Some(non_code_meta_value) = non_code_meta.none_code_nodes.get(&index) {
|
if let Some(non_code_meta_value) = non_code_meta.none_code_nodes.get(&index) {
|
||||||
s += non_code_meta_value.format(&indentation).trim_end_matches('\n')
|
s += non_code_meta_value.format(&indentation).trim_end_matches('\n')
|
||||||
@ -1706,17 +1740,16 @@ pub struct FunctionExpression {
|
|||||||
impl_value_meta!(FunctionExpression);
|
impl_value_meta!(FunctionExpression);
|
||||||
|
|
||||||
impl FunctionExpression {
|
impl FunctionExpression {
|
||||||
pub fn recast(&self, indentation: &str) -> String {
|
pub fn recast(&self, options: &FormatOptions, indentation_level: usize) -> String {
|
||||||
format!(
|
format!(
|
||||||
"({}) => {{\n{}{}{}\n}}",
|
"({}) => {{\n{}{}\n}}",
|
||||||
self.params
|
self.params
|
||||||
.iter()
|
.iter()
|
||||||
.map(|param| param.name.clone())
|
.map(|param| param.name.clone())
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
.join(", "),
|
.join(", "),
|
||||||
indentation,
|
options.get_indentation(indentation_level + 1),
|
||||||
" ",
|
self.body.recast(options, indentation_level + 1)
|
||||||
self.body.recast(" ", true)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1756,6 +1789,58 @@ pub enum Hover {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Format options.
|
||||||
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
|
#[ts(export)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct FormatOptions {
|
||||||
|
/// Size of a tab in spaces.
|
||||||
|
pub tab_size: usize,
|
||||||
|
/// Prefer tabs over spaces.
|
||||||
|
pub use_tabs: bool,
|
||||||
|
/// How to handle the final newline in the file.
|
||||||
|
/// If true, ensure file ends with a newline.
|
||||||
|
/// If false, ensure file does not end with a newline.
|
||||||
|
pub insert_final_newline: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for FormatOptions {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FormatOptions {
|
||||||
|
/// Define the default format options.
|
||||||
|
/// We use 2 spaces for indentation.
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
tab_size: 2,
|
||||||
|
use_tabs: false,
|
||||||
|
insert_final_newline: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the indentation string for the given level.
|
||||||
|
pub fn get_indentation(&self, level: usize) -> String {
|
||||||
|
if self.use_tabs {
|
||||||
|
"\t".repeat(level)
|
||||||
|
} else {
|
||||||
|
" ".repeat(level * self.tab_size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the indentation string for the given level.
|
||||||
|
/// But offset the pipe operator (and a space) by one level.
|
||||||
|
pub fn get_indentation_offset_pipe(&self, level: usize) -> String {
|
||||||
|
if self.use_tabs {
|
||||||
|
"\t".repeat(level + 1)
|
||||||
|
} else {
|
||||||
|
" ".repeat(level * self.tab_size) + " ".repeat(PIPE_OPERATOR.len() + 1).as_str()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -1797,7 +1882,7 @@ show(part001)"#;
|
|||||||
let some_program: crate::abstract_syntax_tree_types::Program =
|
let some_program: crate::abstract_syntax_tree_types::Program =
|
||||||
serde_json::from_str(some_program_string).unwrap();
|
serde_json::from_str(some_program_string).unwrap();
|
||||||
|
|
||||||
let recasted = some_program.recast("", false);
|
let recasted = some_program.recast(&Default::default(), 0);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
recasted,
|
recasted,
|
||||||
r#"const part001 = startSketchAt('default')
|
r#"const part001 = startSketchAt('default')
|
||||||
@ -1816,7 +1901,7 @@ show(part001)"#
|
|||||||
let parser = crate::parser::Parser::new(tokens);
|
let parser = crate::parser::Parser::new(tokens);
|
||||||
let program = parser.ast().unwrap();
|
let program = parser.ast().unwrap();
|
||||||
|
|
||||||
let recasted = program.recast("", false);
|
let recasted = program.recast(&Default::default(), 0);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
recasted,
|
recasted,
|
||||||
r#"const part001 = startSketchAt([0.0, 5.0])
|
r#"const part001 = startSketchAt([0.0, 5.0])
|
||||||
@ -1834,7 +1919,7 @@ show(part001)"#
|
|||||||
let parser = crate::parser::Parser::new(tokens);
|
let parser = crate::parser::Parser::new(tokens);
|
||||||
let program = parser.ast().unwrap();
|
let program = parser.ast().unwrap();
|
||||||
|
|
||||||
let recasted = program.recast("", false);
|
let recasted = program.recast(&Default::default(), 0);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
recasted,
|
recasted,
|
||||||
r#"const part001 = startSketchAt([0.0, 5.0])
|
r#"const part001 = startSketchAt([0.0, 5.0])
|
||||||
@ -1852,7 +1937,7 @@ show(part001)"#
|
|||||||
let parser = crate::parser::Parser::new(tokens);
|
let parser = crate::parser::Parser::new(tokens);
|
||||||
let program = parser.ast().unwrap();
|
let program = parser.ast().unwrap();
|
||||||
|
|
||||||
let recasted = program.recast("", false);
|
let recasted = program.recast(&Default::default(), 0);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
recasted,
|
recasted,
|
||||||
r#"const part001 = startSketchAt([0.0, 5.0])
|
r#"const part001 = startSketchAt([0.0, 5.0])
|
||||||
@ -1877,7 +1962,7 @@ show(part001)"#
|
|||||||
let parser = crate::parser::Parser::new(tokens);
|
let parser = crate::parser::Parser::new(tokens);
|
||||||
let program = parser.ast().unwrap();
|
let program = parser.ast().unwrap();
|
||||||
|
|
||||||
let recasted = program.recast("", false);
|
let recasted = program.recast(&Default::default(), 0);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
recasted,
|
recasted,
|
||||||
r#"const myFn = () => {
|
r#"const myFn = () => {
|
||||||
@ -1913,7 +1998,7 @@ const mySk1 = startSketchAt([0, 0])
|
|||||||
let parser = crate::parser::Parser::new(tokens);
|
let parser = crate::parser::Parser::new(tokens);
|
||||||
let program = parser.ast().unwrap();
|
let program = parser.ast().unwrap();
|
||||||
|
|
||||||
let recasted = program.recast("", false);
|
let recasted = program.recast(&Default::default(), 0);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
recasted,
|
recasted,
|
||||||
r#"// comment at start
|
r#"// comment at start
|
||||||
@ -1940,9 +2025,9 @@ a comment between pipe expression statements */
|
|||||||
|> line({ to: [0.62, 4.15], tag: 'seg01' }, %)
|
|> line({ to: [0.62, 4.15], tag: 'seg01' }, %)
|
||||||
|> line([2.77, -1.24], %)
|
|> line([2.77, -1.24], %)
|
||||||
|> angledLineThatIntersects({
|
|> angledLineThatIntersects({
|
||||||
angle: 201,
|
angle: 201,
|
||||||
offset: -1.35,
|
offset: -1.35,
|
||||||
intersectTag: 'seg01'
|
intersectTag: 'seg01'
|
||||||
}, %)
|
}, %)
|
||||||
|> line([-0.42, -1.72], %)
|
|> line([-0.42, -1.72], %)
|
||||||
|
|
||||||
@ -1951,7 +2036,7 @@ show(part001)"#;
|
|||||||
let parser = crate::parser::Parser::new(tokens);
|
let parser = crate::parser::Parser::new(tokens);
|
||||||
let program = parser.ast().unwrap();
|
let program = parser.ast().unwrap();
|
||||||
|
|
||||||
let recasted = program.recast("", false);
|
let recasted = program.recast(&Default::default(), 0);
|
||||||
assert_eq!(recasted, some_program_string);
|
assert_eq!(recasted, some_program_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1964,12 +2049,19 @@ const yo = {
|
|||||||
anum: 2,
|
anum: 2,
|
||||||
identifier: three,
|
identifier: three,
|
||||||
binExp: 4 + 5
|
binExp: 4 + 5
|
||||||
}"#;
|
}
|
||||||
|
const yo = [
|
||||||
|
1,
|
||||||
|
" 2,",
|
||||||
|
"three",
|
||||||
|
4 + 5,
|
||||||
|
" hey oooooo really long long long"
|
||||||
|
]"#;
|
||||||
let tokens = crate::tokeniser::lexer(some_program_string);
|
let tokens = crate::tokeniser::lexer(some_program_string);
|
||||||
let parser = crate::parser::Parser::new(tokens);
|
let parser = crate::parser::Parser::new(tokens);
|
||||||
let program = parser.ast().unwrap();
|
let program = parser.ast().unwrap();
|
||||||
|
|
||||||
let recasted = program.recast("", false);
|
let recasted = program.recast(&Default::default(), 0);
|
||||||
assert_eq!(recasted, some_program_string);
|
assert_eq!(recasted, some_program_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1987,7 +2079,7 @@ const things = "things"
|
|||||||
let parser = crate::parser::Parser::new(tokens);
|
let parser = crate::parser::Parser::new(tokens);
|
||||||
let program = parser.ast().unwrap();
|
let program = parser.ast().unwrap();
|
||||||
|
|
||||||
let recasted = program.recast("", false);
|
let recasted = program.recast(&Default::default(), 0);
|
||||||
assert_eq!(recasted, some_program_string.trim());
|
assert_eq!(recasted, some_program_string.trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2005,7 +2097,65 @@ const things = "things"
|
|||||||
let parser = crate::parser::Parser::new(tokens);
|
let parser = crate::parser::Parser::new(tokens);
|
||||||
let program = parser.ast().unwrap();
|
let program = parser.ast().unwrap();
|
||||||
|
|
||||||
let recasted = program.recast("", false);
|
let recasted = program.recast(&Default::default(), 0);
|
||||||
assert_eq!(recasted, some_program_string.trim());
|
assert_eq!(recasted, some_program_string.trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_recast_array_new_line_in_pipe() {
|
||||||
|
let some_program_string = r#"const myVar = 3
|
||||||
|
const myVar2 = 5
|
||||||
|
const myVar3 = 6
|
||||||
|
const myAng = 40
|
||||||
|
const myAng2 = 134
|
||||||
|
const part001 = startSketchAt([0, 0])
|
||||||
|
|> line({ to: [1, 3.82], tag: 'seg01' }, %) // ln-should-get-tag
|
||||||
|
|> angledLineToX([
|
||||||
|
-angleToMatchLengthX('seg01', myVar, %),
|
||||||
|
myVar
|
||||||
|
], %) // ln-lineTo-xAbsolute should use angleToMatchLengthX helper
|
||||||
|
|> angledLineToY([
|
||||||
|
-angleToMatchLengthY('seg01', myVar, %),
|
||||||
|
myVar
|
||||||
|
], %) // ln-lineTo-yAbsolute should use angleToMatchLengthY helper"#;
|
||||||
|
let tokens = crate::tokeniser::lexer(some_program_string);
|
||||||
|
let parser = crate::parser::Parser::new(tokens);
|
||||||
|
let program = parser.ast().unwrap();
|
||||||
|
|
||||||
|
let recasted = program.recast(&Default::default(), 0);
|
||||||
|
assert_eq!(recasted, some_program_string);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_recast_array_new_line_in_pipe_custom() {
|
||||||
|
let some_program_string = r#"const myVar = 3
|
||||||
|
const myVar2 = 5
|
||||||
|
const myVar3 = 6
|
||||||
|
const myAng = 40
|
||||||
|
const myAng2 = 134
|
||||||
|
const part001 = startSketchAt([0, 0])
|
||||||
|
|> line({ to: [1, 3.82], tag: 'seg01' }, %) // ln-should-get-tag
|
||||||
|
|> angledLineToX([
|
||||||
|
-angleToMatchLengthX('seg01', myVar, %),
|
||||||
|
myVar
|
||||||
|
], %) // ln-lineTo-xAbsolute should use angleToMatchLengthX helper
|
||||||
|
|> angledLineToY([
|
||||||
|
-angleToMatchLengthY('seg01', myVar, %),
|
||||||
|
myVar
|
||||||
|
], %) // ln-lineTo-yAbsolute should use angleToMatchLengthY helper
|
||||||
|
"#;
|
||||||
|
let tokens = crate::tokeniser::lexer(some_program_string);
|
||||||
|
let parser = crate::parser::Parser::new(tokens);
|
||||||
|
let program = parser.ast().unwrap();
|
||||||
|
|
||||||
|
let recasted = program.recast(
|
||||||
|
&FormatOptions {
|
||||||
|
tab_size: 3,
|
||||||
|
use_tabs: false,
|
||||||
|
insert_final_newline: true,
|
||||||
|
},
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
assert_eq!(recasted, some_program_string);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -336,11 +336,11 @@ impl Parser {
|
|||||||
value: if start_end_string.starts_with("\n\n") && is_new_line_comment {
|
value: if start_end_string.starts_with("\n\n") && is_new_line_comment {
|
||||||
// Preserve if they want a whitespace line before the comment.
|
// Preserve if they want a whitespace line before the comment.
|
||||||
// But let's just allow one.
|
// But let's just allow one.
|
||||||
NoneCodeValue::NewLineBlock { value: full_string }
|
NoneCodeValue::NewLineBlockComment { value: full_string }
|
||||||
} else if is_new_line_comment {
|
} else if is_new_line_comment {
|
||||||
NoneCodeValue::Block { value: full_string }
|
NoneCodeValue::BlockComment { value: full_string }
|
||||||
} else {
|
} else {
|
||||||
NoneCodeValue::Inline { value: full_string }
|
NoneCodeValue::InlineComment { value: full_string }
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
Ok((Some(node), end_index - 1))
|
Ok((Some(node), end_index - 1))
|
||||||
@ -1665,7 +1665,7 @@ const key = 'c'"#,
|
|||||||
Some(NoneCodeNode {
|
Some(NoneCodeNode {
|
||||||
start: 38,
|
start: 38,
|
||||||
end: 60,
|
end: 60,
|
||||||
value: NoneCodeValue::Block {
|
value: NoneCodeValue::BlockComment {
|
||||||
value: "this is a comment".to_string(),
|
value: "this is a comment".to_string(),
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@ -1687,7 +1687,7 @@ const key = 'c'"#,
|
|||||||
Some(NoneCodeNode {
|
Some(NoneCodeNode {
|
||||||
start: 106,
|
start: 106,
|
||||||
end: 166,
|
end: 166,
|
||||||
value: NoneCodeValue::Block {
|
value: NoneCodeValue::BlockComment {
|
||||||
value: "this is\n a comment\n spanning a few lines".to_string(),
|
value: "this is\n a comment\n spanning a few lines".to_string(),
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
@ -552,19 +552,14 @@ impl LanguageServer for Backend {
|
|||||||
return Ok(None);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
// Now recast it.
|
// Now recast it.
|
||||||
// Make spaces for the tab size.
|
let recast = ast.recast(
|
||||||
/*let mut tab_size = String::new();
|
&crate::abstract_syntax_tree_types::FormatOptions {
|
||||||
for _ in 0..params.options.tab_size {
|
tab_size: params.options.tab_size as usize,
|
||||||
tab_size.push(' ');
|
insert_final_newline: params.options.insert_final_newline.unwrap_or(false),
|
||||||
}*/
|
use_tabs: !params.options.insert_spaces,
|
||||||
// TODO: use the tab size.
|
},
|
||||||
let mut recast = ast.recast("", false).trim().to_string();
|
0,
|
||||||
if let Some(insert_final_newline) = params.options.insert_final_newline {
|
);
|
||||||
if insert_final_newline {
|
|
||||||
recast.push('\n');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let source_range = SourceRange([0, current_code.len() - 1]);
|
let source_range = SourceRange([0, current_code.len() - 1]);
|
||||||
let range = source_range.to_lsp_range(¤t_code);
|
let range = source_range.to_lsp_range(¤t_code);
|
||||||
Ok(Some(vec![TextEdit {
|
Ok(Some(vec![TextEdit {
|
||||||
|
@ -76,7 +76,8 @@ pub fn recast_wasm(json_str: &str) -> Result<JsValue, JsError> {
|
|||||||
let program: kcl_lib::abstract_syntax_tree_types::Program =
|
let program: kcl_lib::abstract_syntax_tree_types::Program =
|
||||||
serde_json::from_str(json_str).map_err(JsError::from)?;
|
serde_json::from_str(json_str).map_err(JsError::from)?;
|
||||||
|
|
||||||
let result = program.recast("", false);
|
// Use the default options until we integrate into the UI the ability to change them.
|
||||||
|
let result = program.recast(&Default::default(), 0);
|
||||||
Ok(JsValue::from_serde(&result)?)
|
Ok(JsValue::from_serde(&result)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user