From a88f19d6b809cf1788bd5a1685c6c251452c5230 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Thu, 29 Aug 2024 10:17:12 -0500 Subject: [PATCH 01/39] init --- Cargo.lock | 11 ++++++++++ Cargo.toml | 1 + topiary-cli/Cargo.toml | 3 +++ topiary-cli/src/io.rs | 3 +++ topiary-config/Cargo.toml | 3 +++ topiary-config/languages.ncl | 32 +++++++++++++++------------- topiary-config/src/language.rs | 6 ++++++ topiary-queries/Cargo.toml | 1 + topiary-queries/queries/openscad.scm | 3 +++ topiary-queries/src/lib.rs | 6 ++++++ 10 files changed, 54 insertions(+), 15 deletions(-) create mode 100644 topiary-queries/queries/openscad.scm diff --git a/Cargo.lock b/Cargo.lock index d3a3790c..a8e4bddc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1887,6 +1887,7 @@ dependencies = [ "tree-sitter-nickel", "tree-sitter-ocaml", "tree-sitter-ocamllex", + "tree-sitter-openscad", "tree-sitter-query", "tree-sitter-rust", "tree-sitter-toml", @@ -1911,6 +1912,7 @@ dependencies = [ "tree-sitter-nickel", "tree-sitter-ocaml", "tree-sitter-ocamllex", + "tree-sitter-openscad", "tree-sitter-query", "tree-sitter-rust", "tree-sitter-toml", @@ -2041,6 +2043,15 @@ dependencies = [ "tree-sitter", ] +[[package]] +name = "tree-sitter-openscad" +version = "0.5.1" +source = "git+https://github.com/mkatychev/tree-sitter-openscad?rev=a7ac1a1d28495d009df76415f98b32c2cacbccd3#a7ac1a1d28495d009df76415f98b32c2cacbccd3" +dependencies = [ + "cc", + "tree-sitter", +] + [[package]] name = "tree-sitter-query" version = "0.2.0" diff --git a/Cargo.toml b/Cargo.toml index 2235f8c5..86fa2227 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -80,6 +80,7 @@ tree-sitter-ocamllex = { git = "https://github.com/314eter/tree-sitter-ocamllex. tree-sitter-query = { git = "https://github.com/nvim-treesitter/tree-sitter-query", rev = "a0ccc351e5e868ec1f8135e97aa3b53c663cf2df" } tree-sitter-rust = { git = "https://github.com/tree-sitter/tree-sitter-rust.git", rev = "e0e8b6de6e4aa354749c794f5f36a906dcccda74" } tree-sitter-toml = { git = "https://github.com/tree-sitter/tree-sitter-toml.git", rev = "342d9be207c2dba869b9967124c679b5e6fd0ebe" } +tree-sitter-openscad = { git = "https://github.com/mkatychev/tree-sitter-openscad", rev = "a7ac1a1d28495d009df76415f98b32c2cacbccd3" } unescape = "0.1" wasm-bindgen = "=0.2.91" wasm-bindgen-futures = "0.4" diff --git a/topiary-cli/Cargo.toml b/topiary-cli/Cargo.toml index e2a0e696..1a40063a 100644 --- a/topiary-cli/Cargo.toml +++ b/topiary-cli/Cargo.toml @@ -51,6 +51,7 @@ tree-sitter-nickel = { workspace = true, optional = true } tree-sitter-query = { workspace = true, optional = true } tree-sitter-ocaml = { workspace = true, optional = true } tree-sitter-ocamllex = { workspace = true, optional = true } +tree-sitter-openscad = { workspace = true, optional = true } [dev-dependencies] assert_cmd = { workspace = true } @@ -71,6 +72,7 @@ default = [ # Included by default contributed = [ "css" + "openscad", ] # Excluded by default @@ -86,6 +88,7 @@ nickel = ["dep:tree-sitter-nickel", "topiary-config/nickel", "topiary-queries/ni ocaml = ["dep:tree-sitter-ocaml", "topiary-config/ocaml", "topiary-queries/ocaml"] ocaml_interface = ["dep:tree-sitter-ocaml", "topiary-config/ocaml_interface", "topiary-queries/ocaml_interface"] ocamllex = ["dep:tree-sitter-ocamllex", "topiary-config/ocamllex", "topiary-queries/ocamllex"] +openscad = ["dep:tree-sitter-openscad", "topiary-config/openscad", "topiary-queries/openscad"] rust = ["dep:tree-sitter-rust", "topiary-config/rust", "topiary-queries/rust"] toml = ["dep:tree-sitter-toml", "topiary-config/toml", "topiary-queries/toml"] tree_sitter_query = ["dep:tree-sitter-query", "topiary-config/tree_sitter_query", "topiary-queries/tree_sitter_query"] diff --git a/topiary-cli/src/io.rs b/topiary-cli/src/io.rs index 0c3a7753..5bdc11da 100644 --- a/topiary-cli/src/io.rs +++ b/topiary-cli/src/io.rs @@ -344,6 +344,9 @@ where #[cfg(feature = "ocamllex")] "ocamllex" => Ok(topiary_queries::ocamllex().into()), + #[cfg(feature = "openscad")] + "openscad" => Ok(topiary_queries::openscad().into()), + #[cfg(feature = "rust")] "rust" => Ok(topiary_queries::rust().into()), diff --git a/topiary-config/Cargo.toml b/topiary-config/Cargo.toml index 7203c401..54888a35 100644 --- a/topiary-config/Cargo.toml +++ b/topiary-config/Cargo.toml @@ -31,6 +31,7 @@ tree-sitter-nickel = { workspace = true, optional = true } tree-sitter-query = { workspace = true, optional = true } tree-sitter-ocaml = { workspace = true, optional = true } tree-sitter-ocamllex = { workspace = true, optional = true } +tree-sitter-openscad = { workspace = true, optional = true } [target.'cfg(not(target_family = "wasm"))'.dependencies] clap = { workspace = true, features = ["derive"] } @@ -43,6 +44,7 @@ nickel = ["dep:tree-sitter-nickel"] ocaml = ["dep:tree-sitter-ocaml"] ocaml_interface = ["dep:tree-sitter-ocaml"] ocamllex = ["dep:tree-sitter-ocamllex"] +openscad = ["dep:tree-sitter-openscad"] rust = ["dep:tree-sitter-rust"] toml = ["dep:tree-sitter-toml"] tree_sitter_query = ["dep:tree-sitter-query"] @@ -57,6 +59,7 @@ all = [ "ocaml", "ocaml_interface", "ocamllex", + "openscad", "rust", "toml", "tree_sitter_query" diff --git a/topiary-config/languages.ncl b/topiary-config/languages.ncl index 868dd413..1ebf82cb 100644 --- a/topiary-config/languages.ncl +++ b/topiary-config/languages.ncl @@ -5,21 +5,21 @@ css.extensions = ["css"], json.extensions = [ - "json", - "avsc", - "geojson", - "gltf", - "har", - "ice", - "JSON-tmLanguage", - "jsonl", - "mcmeta", - "tfstate", - "tfstate.backup", - "topojson", - "webapp", - "webmanifest" - ], + "json", + "avsc", + "geojson", + "gltf", + "har", + "ice", + "JSON-tmLanguage", + "jsonl", + "mcmeta", + "tfstate", + "tfstate.backup", + "topojson", + "webapp", + "webmanifest" + ], nickel.extensions = ["ncl"], @@ -36,6 +36,8 @@ toml.extensions = ["toml"], + openscad.extensions = ["scad", "openscad"], + tree_sitter_query.extensions = ["scm"], }, } diff --git a/topiary-config/src/language.rs b/topiary-config/src/language.rs index 938dcbd7..4463ec75 100644 --- a/topiary-config/src/language.rs +++ b/topiary-config/src/language.rs @@ -66,6 +66,9 @@ impl Language { #[cfg(feature = "toml")] "toml" => "toml", + #[cfg(feature = "openscad")] + "openscad" => "openscad", + #[cfg(feature = "tree_sitter_query")] "tree_sitter_query" => "tree-sitter-query", @@ -119,6 +122,9 @@ impl Language { #[cfg(feature = "toml")] "toml" => tree_sitter_toml::language(), + #[cfg(feature = "openscad")] + "openscad" => tree_sitter_openscad::language(), + #[cfg(feature = "tree_sitter_query")] "tree_sitter_query" => tree_sitter_query::language(), diff --git a/topiary-queries/Cargo.toml b/topiary-queries/Cargo.toml index 45969a10..2920f7ea 100644 --- a/topiary-queries/Cargo.toml +++ b/topiary-queries/Cargo.toml @@ -22,6 +22,7 @@ nickel = [] ocaml = [] ocaml_interface = [] ocamllex = [] +openscad = [] rust = [] toml = [] tree_sitter_query = [] diff --git a/topiary-queries/queries/openscad.scm b/topiary-queries/queries/openscad.scm new file mode 100644 index 00000000..0fd0a537 --- /dev/null +++ b/topiary-queries/queries/openscad.scm @@ -0,0 +1,3 @@ +(include_statement) @append_empty_softline +(assignment) @prepend_empty_softline +(identifier) @append_space diff --git a/topiary-queries/src/lib.rs b/topiary-queries/src/lib.rs index 42379d51..fe93405e 100644 --- a/topiary-queries/src/lib.rs +++ b/topiary-queries/src/lib.rs @@ -40,6 +40,12 @@ pub fn ocamllex() -> &'static str { include_str!("../queries/ocamllex.scm") } +/// Returns the Topiary-compatible query file for Ocamllex. +#[cfg(feature = "openscad")] +pub fn openscad() -> &'static str { + include_str!("../queries/openscad.scm") +} + /// Returns the Topiary-compatible query file for Rust. #[cfg(feature = "rust")] pub fn rust() -> &'static str { From a44493ec98f1080c8d4adcbb07c32ca7e4c314c2 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Tue, 7 Jan 2025 20:01:17 -0600 Subject: [PATCH 02/39] initial input test file --- topiary-cli/tests/samples/input/openscad.scad | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 topiary-cli/tests/samples/input/openscad.scad diff --git a/topiary-cli/tests/samples/input/openscad.scad b/topiary-cli/tests/samples/input/openscad.scad new file mode 100644 index 00000000..02b4611b --- /dev/null +++ b/topiary-cli/tests/samples/input/openscad.scad @@ -0,0 +1,75 @@ +include +use + + $fn = 360; +E = 2.71828182845904523536028747135266249775724709369995; // Natural number. + +/** + * Computes the exponent of a base and a power. + * + * @param base The number to be multiplied power times. + * @param power The number of times to multiply the base together. + * @return The base risen the the power. + */ +function MTH_power(base, power) = pow(base, power); // exp(ln(base) * power); + +/** + * Measures the distance between two 3D vectors. + * + * @param vector_a The first 3D vector to compare. + * @param vector_b The second 3D vector to compare. + * @return The distance between vector_a and vector_b. + */ +function MTH_distance3D(vector_a, vector_b) = + sqrt((vector_a[0] - vector_b[0]) * (vector_a[0] - vector_b[0]) + + (vector_a[1] - vector_b[1]) * (vector_a[1] - vector_b[1]) + + (vector_a[2] - vector_b[2]) * (vector_a[2] - vector_b[2])); + +/** + * Measures the distance between two 2D vectors. + * + * @param vector_a The first 2D vector to compare. + * @param vector_b The second 2D vector to compare. + * @return The distance between vector_a and vector_b. + */ +function MTH_distance2D(vector_a, vector_b) = + sqrt((vector_a[0] - vector_b[0]) * (vector_a[0] - vector_b[0]) + + (vector_a[1] - vector_b[1]) * (vector_a[1] - vector_b[1])); + +function MTH_distance1D(vector_a, vector_b) = abs(vector_a - vector_b); +function MTH_normalize(vector) = + norm(vector); // vector / (max(MTH_distance3D(ORIGIN, vector), EPSILON)); +function MTH_normalVectorAngle(vector) = [ + 0, + -1 * atan2(vector[2], MTH_distance1D([ vector[0], vector[1] ])), + atan2(vector[1], vector[0]) +]; + +module my_module() +{ +include + echo(TST_equal("Equality", [ 1, 2, 4, 8 ], [ 1, 2, 4, 8 ])); + echo(TST_notEqual("Non-equality", [ 1, 2, 4, 8 ], [ 0, 1, 1, 2 ])); + echo(TST_true("Truthiness", 1 + 1 == 2)); + echo(TST_false("Falseness", 1 + 1 == 3)); + echo(TST_in("Presence", 4, [ 1, 2, 4, 8 ])); + echo(TST_notIn("Absence", 16, [ 1, 2, 4, 8 ])); + echo(TST_approximately("Approximately Equal", 15 + (EPSILON / 2), 15)); +} + +for (i = [10:50]) +{ + let (angle = i*360/20, r= i*2, distance = r*5) + { + rotate(angle, [1, 0, 0]) + translate([0, distance, 0]) + sphere(r = r); + } +} + + if (test1) + if (test2) {scope2.1} + else {scope2.2} + else + if (test3) {scope3.1} + else {scope3.2} From 961cdf780d0244e99be579402de49fce7a9b90ee Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Thu, 9 Jan 2025 12:48:21 -0600 Subject: [PATCH 03/39] handled unnested function formatting --- .../tests/samples/expected/openscad.scad | 92 +++++++++++ topiary-cli/tests/samples/input/openscad.scad | 146 ++++++++++-------- topiary-config/languages.ncl | 2 +- topiary-queries/queries/openscad.scm | 132 +++++++++++++++- 4 files changed, 305 insertions(+), 67 deletions(-) create mode 100644 topiary-cli/tests/samples/expected/openscad.scad diff --git a/topiary-cli/tests/samples/expected/openscad.scad b/topiary-cli/tests/samples/expected/openscad.scad new file mode 100644 index 00000000..21d4a8f2 --- /dev/null +++ b/topiary-cli/tests/samples/expected/openscad.scad @@ -0,0 +1,92 @@ +include +use +// variables +rr = a_vector[2]; // member of vector +range1 = [-1.5:0.5:3]; // for() loop range +xx = [0:5]; // alternate for() loop range + $fn = 360; // special variable +E = 2.71828182845904523536028747135266249775724709369995; // constant +cond_var ="is_true"?true:false; + +function line(point1, point2, width = 1) = + +let(angle = 90 - atan((point2[1] - point1[1]) / (point2[0] - point1[0]))) + +let(offset_x = 0.5 * width * cos(angle), offset_y = 0.5 * width * sin(angle)) + +let(offset1 = [-offset_x, offset_y], offset2 = [offset_x, -offset_y]) + +// [P1a, P2a, P2b, P1b] +[point1 + offset1, point2 + offset1, point2 + offset2, point1 + offset2]; + + +// ================================================================================ +// Transformations +// ================================================================================ +cylinder(); +cylinder( + d=5, + h=100, +); + +rotate([90, 0, 0]) cylinder(); +translate([1, 0, 0]) { + difference() { + rotate([0, 90, 0]) cylinder(); + cube(); + } +} + +// ================================================================================ +// Nested Items +// ================================================================================ +module big_module() { + function inner_function() = undef; + module inner_module() cube(); +} + +module extern_module() include + +for (i = [10:50]) +{ + let (angle = i*360/20, r= i*2, distance = r*5) + { + rotate(angle, [1, 0, 0]) + translate([0, distance, 0]) + sphere(r = r); + } +} + +if ($preview) + if (false) + sphere(); + else + translate([2, 0, 0]) cube(); + +for (i = [1:2:7]) { + let (x = i ^ 2, y = x - 1) { + translate([x, y, 0]) sphere(r = i); + } +} + +intersection_for (i = [1, 2, 3]) { + if (i > 1) { + translate([0, i, 0]) cube(); + } +} + +// ================================================================================ +// Comments +// ================================================================================ +/* ignored [Customizer Group] ignored */ +my_parameter = 5; + +function math(x) = /*do math stuff*/ x + 2 // done with math +; + +module my_cylinder() { + // here we create a cylinder + cylinder(); /* done ! */ + cube(); +} + diff --git a/topiary-cli/tests/samples/input/openscad.scad b/topiary-cli/tests/samples/input/openscad.scad index 02b4611b..8014eda8 100644 --- a/topiary-cli/tests/samples/input/openscad.scad +++ b/topiary-cli/tests/samples/input/openscad.scad @@ -1,75 +1,95 @@ include use +// variables +rr = a_vector[2]; // member of vector +range1 = [-1.5:0.5:3]; // for() loop range +xx = [0:5]; // alternate for() loop range + $fn = 360; // special variable +E = 2.71828182845904523536028747135266249775724709369995; // constant +cond_var ="is_true"?true:false; - $fn = 360; -E = 2.71828182845904523536028747135266249775724709369995; // Natural number. +function line(point1, point2, width = 1) = -/** - * Computes the exponent of a base and a power. - * - * @param base The number to be multiplied power times. - * @param power The number of times to multiply the base together. - * @return The base risen the the power. - */ -function MTH_power(base, power) = pow(base, power); // exp(ln(base) * power); +let(angle = 90 - atan((point2[1] - point1[1]) / (point2[0] - point1[0]))) -/** - * Measures the distance between two 3D vectors. - * - * @param vector_a The first 3D vector to compare. - * @param vector_b The second 3D vector to compare. - * @return The distance between vector_a and vector_b. - */ -function MTH_distance3D(vector_a, vector_b) = - sqrt((vector_a[0] - vector_b[0]) * (vector_a[0] - vector_b[0]) + - (vector_a[1] - vector_b[1]) * (vector_a[1] - vector_b[1]) + - (vector_a[2] - vector_b[2]) * (vector_a[2] - vector_b[2])); +let(offset_x = 0.5 * width * cos(angle), offset_y = 0.5 * width * sin(angle)) -/** - * Measures the distance between two 2D vectors. - * - * @param vector_a The first 2D vector to compare. - * @param vector_b The second 2D vector to compare. - * @return The distance between vector_a and vector_b. - */ -function MTH_distance2D(vector_a, vector_b) = - sqrt((vector_a[0] - vector_b[0]) * (vector_a[0] - vector_b[0]) + - (vector_a[1] - vector_b[1]) * (vector_a[1] - vector_b[1])); +let(offset1 = [-offset_x, offset_y], offset2 = [offset_x, -offset_y]) -function MTH_distance1D(vector_a, vector_b) = abs(vector_a - vector_b); -function MTH_normalize(vector) = - norm(vector); // vector / (max(MTH_distance3D(ORIGIN, vector), EPSILON)); -function MTH_normalVectorAngle(vector) = [ - 0, - -1 * atan2(vector[2], MTH_distance1D([ vector[0], vector[1] ])), - atan2(vector[1], vector[0]) -]; +// [P1a, P2a, P2b, P1b] +[point1 + offset1, point2 + offset1, point2 + offset2, point1 + offset2]; -module my_module() -{ -include - echo(TST_equal("Equality", [ 1, 2, 4, 8 ], [ 1, 2, 4, 8 ])); - echo(TST_notEqual("Non-equality", [ 1, 2, 4, 8 ], [ 0, 1, 1, 2 ])); - echo(TST_true("Truthiness", 1 + 1 == 2)); - echo(TST_false("Falseness", 1 + 1 == 3)); - echo(TST_in("Presence", 4, [ 1, 2, 4, 8 ])); - echo(TST_notIn("Absence", 16, [ 1, 2, 4, 8 ])); - echo(TST_approximately("Approximately Equal", 15 + (EPSILON / 2), 15)); -} -for (i = [10:50]) -{ - let (angle = i*360/20, r= i*2, distance = r*5) - { - rotate(angle, [1, 0, 0]) - translate([0, distance, 0]) - sphere(r = r); +// ================================================================================ +// Transformations +// ================================================================================ +cylinder(); +cylinder( + d=5, + h=100, +); + +rotate([90, 0, 0]) cylinder(); +translate([1, 0, 0]) { + difference() { + rotate([0, 90, 0]) cylinder(); + cube(); } } - if (test1) - if (test2) {scope2.1} - else {scope2.2} - else - if (test3) {scope3.1} - else {scope3.2} +// ================================================================================ +// Nested Items +// ================================================================================ +module big_module() { + function inner_function() = undef; + module inner_module() cube(); +} + +// module extern_module() include +// +// for (i = [10:50]) +// { +// let (angle = i*360/20, r= i*2, distance = r*5) +// { +// rotate(angle, [1, 0, 0]) +// translate([0, distance, 0]) +// sphere(r = r); +// } +// } +// +// if ($preview) +// if (false) +// sphere(); +// else +// translate([2, 0, 0]) cube(); +// +// for (i = [1:2:7]) { +// let (x = i ^ 2, y = x - 1) { +// translate([x, y, 0]) sphere(r = i); +// } +// } +// +// intersection_for (i = [1, 2, 3]) { +// if (i > 1) { +// translate([0, i, 0]) cube(); +// } +// } +// +// // ================================================================================ +// // Comments +// // ================================================================================ +// /* ignored [Customizer Group] ignored */ +// /* Multiline +// comment +// here +// */ +// my_parameter = 5; +// +// function math(x) = /*do math stuff*/ x + 2 // done with math +// ; +// +// module my_cylinder() { +// // here we create a cylinder +// cylinder(); /* done ! */ +// cube(); +// } diff --git a/topiary-config/languages.ncl b/topiary-config/languages.ncl index 5e530c8b..8a9e5ad2 100644 --- a/topiary-config/languages.ncl +++ b/topiary-config/languages.ncl @@ -77,7 +77,7 @@ extensions = ["scad"], grammar.source.git = { git = "https://github.com/mkatychev/tree-sitter-openscad.git", - rev = "5810de67549363bf9ff420f1c907fc0e1ff0f5d7", + rev = "0efdd5e8cfd021d3f35b2fc1fec0d42f7b4d82ea", }, }, diff --git a/topiary-queries/queries/openscad.scm b/topiary-queries/queries/openscad.scm index 0fd0a537..bfba75cf 100644 --- a/topiary-queries/queries/openscad.scm +++ b/topiary-queries/queries/openscad.scm @@ -1,3 +1,129 @@ -(include_statement) @append_empty_softline -(assignment) @prepend_empty_softline -(identifier) @append_space +; Sometimes we want to indicate that certain parts of our source text should +; not be formatted, but taken as is. We use the leaf capture name to inform the +; tool of this. +[ + (block_comment) + (line_comment) + (string) +] @leaf + +; Allow blank line before +[ + (use_statement) + (include_statement) + (block_comment) + (line_comment) + (function_item) + (transform_chain) + (module_declaration) + (expression) +] @allow_blank_line_before + +; Keywords + +; Surround spaces +[ + "module" + "function" + "let" + "include" + "assign" + "use" + "each" + "||" + "&&" + "==" + "!=" + "<" + ">" + "<=" + ">=" + "+" + "-" + "*" + "/" + "%" + "^" + "!" + "=" + "?" + ":" +] @prepend_space @append_space + +; Colon should have whitespace trimmed in a range delimiter +(range ":" @prepend_antispace @append_antispace) + +; Input softlines before and after all comments. This means that the input +; decides if a comment should have line breaks before or after. A line comment +; always ends with a line break. +[ + (block_comment) + (line_comment) +] @prepend_input_softline + +; Append line breaks. If there is a comment following, we don't add anything, +; because the input softlines and spaces above will already have sorted out the +; formatting. +( + [ + (assignment) + (use_statement) + (include_statement) + (function_item) + (module_declaration) + (transform_chain) + ] @append_spaced_softline + . + [ + (block_comment) + (line_comment) + ]* @do_nothing +) + +(line_comment) @append_hardline + +(block_comment) @multi_line_indent_all + +; Allow line break after block comments +( + (block_comment) + . + _ @prepend_input_softline +) + +; indent the body of a function +(function_item + (parameters_declaration) + . + "=" @append_spaced_softline @append_indent_start + (expression) + ";" @prepend_indent_end +) + +; Append softlines, unless followed by comments. +( + [ + "," + ";" + ] @append_spaced_softline + . + [(block_comment) (line_comment)]* @do_nothing +) + +; Never put a space before a comma +( + "," @prepend_antispace +) + +; Don't insert spaces between the operator and their expression operand +(unary_expression + _ @append_antispace + . + (expression) +) + +; Don't insert spaces between the starting '[' and ending ']' of an index expression +(index_expression + value: _ @append_antispace + index: _ @prepend_antispace @append_antispace +) From 69c8b3f296af203f99b41214e63e62e2c9acc475 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Thu, 9 Jan 2025 12:55:39 -0600 Subject: [PATCH 04/39] tree_sitter_query changes: * prevent invalid formatting of `field_definition` that followed an `identifier` * `predicates` parameters are now separated by a `spaced_softline` allowing long predicates to be broken up --- topiary-queries/queries/tree_sitter_query.scm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/topiary-queries/queries/tree_sitter_query.scm b/topiary-queries/queries/tree_sitter_query.scm index 2d58f617..35562d1f 100644 --- a/topiary-queries/queries/tree_sitter_query.scm +++ b/topiary-queries/queries/tree_sitter_query.scm @@ -38,6 +38,7 @@ (grouping) (list) (named_node) + (field_definition) "." "(" "[" @@ -53,7 +54,7 @@ ; zero-byte nodes, so we just need to set the spacing correctly. (predicate (parameters - _ @prepend_space + _ @prepend_spaced_softline ) ) From 4fe4b25ace1d5714c2958215d39c232d22adddb7 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Thu, 9 Jan 2025 13:23:54 -0600 Subject: [PATCH 05/39] added to changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 22190c10..109fbab4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,6 +59,8 @@ This name should be decided amongst the team before the release. ### Fixed - [#779](https://github.com/tweag/topiary/pull/779) Load relevant grammars before CLI tests - [#799](https://github.com/tweag/topiary/pull/799) Line break after table-less pairs in TOML +- tree-sitter-query: Long predicate parameters now retain newline separation +- tree-sitter-query: Prevent invalid concatenation of `field_definition`s that followed an `identifier` ## v0.5.1 - Fragrant Frangipani - 2024-10-22 From ca60f427182323b61b4651e514464097a1d73c62 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Thu, 9 Jan 2025 21:51:06 -0600 Subject: [PATCH 06/39] added var_declaration to openscad query --- topiary-config/languages.ncl | 2 +- topiary-queries/queries/openscad.scm | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/topiary-config/languages.ncl b/topiary-config/languages.ncl index 8a9e5ad2..ee0a4ab4 100644 --- a/topiary-config/languages.ncl +++ b/topiary-config/languages.ncl @@ -77,7 +77,7 @@ extensions = ["scad"], grammar.source.git = { git = "https://github.com/mkatychev/tree-sitter-openscad.git", - rev = "0efdd5e8cfd021d3f35b2fc1fec0d42f7b4d82ea", + rev = "92bc2c3470e7babd67477fb8d4c24e342bdd9bc46", }, }, diff --git a/topiary-queries/queries/openscad.scm b/topiary-queries/queries/openscad.scm index bfba75cf..73f5a49e 100644 --- a/topiary-queries/queries/openscad.scm +++ b/topiary-queries/queries/openscad.scm @@ -15,7 +15,7 @@ (line_comment) (function_item) (transform_chain) - (module_declaration) + (module_item) (expression) ] @allow_blank_line_before @@ -66,11 +66,11 @@ ; formatting. ( [ - (assignment) + (var_declaration) (use_statement) (include_statement) (function_item) - (module_declaration) + (module_item) (transform_chain) ] @append_spaced_softline . @@ -93,7 +93,7 @@ ; indent the body of a function (function_item - (parameters_declaration) + (parameters) . "=" @append_spaced_softline @append_indent_start (expression) From 79c559bd15c272b11567081b83f451af1fbffa43 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Fri, 10 Jan 2025 15:33:48 -0600 Subject: [PATCH 07/39] Update CHANGELOG.md Co-authored-by: Christopher Harrison --- CHANGELOG.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 109fbab4..247e34c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,8 +59,7 @@ This name should be decided amongst the team before the release. ### Fixed - [#779](https://github.com/tweag/topiary/pull/779) Load relevant grammars before CLI tests - [#799](https://github.com/tweag/topiary/pull/799) Line break after table-less pairs in TOML -- tree-sitter-query: Long predicate parameters now retain newline separation -- tree-sitter-query: Prevent invalid concatenation of `field_definition`s that followed an `identifier` +- [#826](https://github.com/tweag/topiary/pull/799) Various Tree-sitter query fixes, thanks to @mkatychev ## v0.5.1 - Fragrant Frangipani - 2024-10-22 From df5b28de1d191457e178e7a81a6c03a65919e552 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Fri, 10 Jan 2025 20:32:05 -0600 Subject: [PATCH 08/39] interim commit --- Cargo.lock | 77 +------------------ topiary-cli/tests/samples/input/openscad.scad | 29 ++++--- topiary-queries/queries/openscad.scm | 24 +++++- topiary-queries/queries/tree_sitter_query.scm | 5 ++ 4 files changed, 39 insertions(+), 96 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 70f52abc..d02f755a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" @@ -1971,19 +1971,6 @@ dependencies = [ "topiary-core", "topiary-queries", "topiary-tree-sitter-facade", -<<<<<<< HEAD - "tree-sitter-bash", - "tree-sitter-css", - "tree-sitter-json", - "tree-sitter-nickel", - "tree-sitter-ocaml", - "tree-sitter-ocamllex", - "tree-sitter-openscad", - "tree-sitter-query", - "tree-sitter-rust", - "tree-sitter-toml", -======= ->>>>>>> main ] [[package]] @@ -2003,21 +1990,8 @@ dependencies = [ "toml 0.8.14", "topiary-tree-sitter-facade", "topiary-web-tree-sitter-sys", -<<<<<<< HEAD - "tree-sitter-bash", - "tree-sitter-css", - "tree-sitter-json", - "tree-sitter-nickel", - "tree-sitter-ocaml", - "tree-sitter-ocamllex", - "tree-sitter-openscad", - "tree-sitter-query", - "tree-sitter-rust", - "tree-sitter-toml", -======= "tree-sitter", "tree-sitter-language", ->>>>>>> main ] [[package]] @@ -2167,56 +2141,7 @@ version = "0.23.2" source = "git+https://github.com/tree-sitter/tree-sitter-ocaml.git?rev=98c2130c59ca7553b47086f91c5d22180151ad55#98c2130c59ca7553b47086f91c5d22180151ad55" dependencies = [ "cc", -<<<<<<< HEAD - "tree-sitter", -] - -[[package]] -name = "tree-sitter-ocamllex" -version = "0.20.2" -source = "git+https://github.com/314eter/tree-sitter-ocamllex.git?rev=4b9898ccbf198602bb0dec9cd67cc1d2c0a4fad2#4b9898ccbf198602bb0dec9cd67cc1d2c0a4fad2" -dependencies = [ - "cc", - "tree-sitter", -] - -[[package]] -name = "tree-sitter-openscad" -version = "0.5.1" -source = "git+https://github.com/mkatychev/tree-sitter-openscad?rev=a7ac1a1d28495d009df76415f98b32c2cacbccd3#a7ac1a1d28495d009df76415f98b32c2cacbccd3" -dependencies = [ - "cc", - "tree-sitter", -] - -[[package]] -name = "tree-sitter-query" -version = "0.2.0" -source = "git+https://github.com/nvim-treesitter/tree-sitter-query?rev=a0ccc351e5e868ec1f8135e97aa3b53c663cf2df#a0ccc351e5e868ec1f8135e97aa3b53c663cf2df" -dependencies = [ - "cc", - "tree-sitter", -] - -[[package]] -name = "tree-sitter-rust" -version = "0.20.4" -source = "git+https://github.com/tree-sitter/tree-sitter-rust.git?rev=e0e8b6de6e4aa354749c794f5f36a906dcccda74#e0e8b6de6e4aa354749c794f5f36a906dcccda74" -dependencies = [ - "cc", - "tree-sitter", -] - -[[package]] -name = "tree-sitter-toml" -version = "0.5.1" -source = "git+https://github.com/tree-sitter/tree-sitter-toml.git?rev=342d9be207c2dba869b9967124c679b5e6fd0ebe#342d9be207c2dba869b9967124c679b5e6fd0ebe" -dependencies = [ - "cc", - "tree-sitter", -======= "tree-sitter-language", ->>>>>>> main ] [[package]] diff --git a/topiary-cli/tests/samples/input/openscad.scad b/topiary-cli/tests/samples/input/openscad.scad index 8014eda8..41c58645 100644 --- a/topiary-cli/tests/samples/input/openscad.scad +++ b/topiary-cli/tests/samples/input/openscad.scad @@ -1,34 +1,32 @@ include use // variables -rr = a_vector[2]; // member of vector +rr = a_vector[2]; // member of vector range1 = [-1.5:0.5:3]; // for() loop range -xx = [0:5]; // alternate for() loop range - $fn = 360; // special variable +xx = [0:5]; // alternate for() loop range +$fn = 360; // special variable E = 2.71828182845904523536028747135266249775724709369995; // constant -cond_var ="is_true"?true:false; +cond_var = "is_true" ? true : false; function line(point1, point2, width = 1) = -let(angle = 90 - atan((point2[1] - point1[1]) / (point2[0] - point1[0]))) + let (angle = 90 - atan((point2[1] - point1[1]) / (point2[0] - point1[0]))) -let(offset_x = 0.5 * width * cos(angle), offset_y = 0.5 * width * sin(angle)) + let (offset_x = 0.5 * width * cos(angle), offset_y = 0.5 * width * sin(angle)) -let(offset1 = [-offset_x, offset_y], offset2 = [offset_x, -offset_y]) - -// [P1a, P2a, P2b, P1b] -[point1 + offset1, point2 + offset1, point2 + offset2, point1 + offset2]; + let (offset1 = [ -offset_x, offset_y], offset2 = [offset_x, -offset_y]) + // [P1a, P2a, P2b, P1b] + [point1 + offset1, point2 + offset1, point2 + offset2, point1 + offset2]; // ================================================================================ // Transformations // ================================================================================ cylinder(); cylinder( - d=5, - h=100, + d = 5, + h = 100, ); - rotate([90, 0, 0]) cylinder(); translate([1, 0, 0]) { difference() { @@ -40,9 +38,8 @@ translate([1, 0, 0]) { // ================================================================================ // Nested Items // ================================================================================ -module big_module() { - function inner_function() = undef; - module inner_module() cube(); +module big_module(){ function inner_function() = undef; +module inner_module()cube(); } // module extern_module() include diff --git a/topiary-queries/queries/openscad.scm b/topiary-queries/queries/openscad.scm index 73f5a49e..10016d0f 100644 --- a/topiary-queries/queries/openscad.scm +++ b/topiary-queries/queries/openscad.scm @@ -100,6 +100,22 @@ ";" @prepend_indent_end ) +(arguments + "(" @append_empty_softline @append_indent_start + "," @append_input_softline + ")" @prepend_indent_end +) + +(arguments + (assignment + "=" @append_antispace @prepend_antispace + ) +) + +; (function_call +; "=" @prepend_antispace @append_antispace +; ) + ; Append softlines, unless followed by comments. ( [ @@ -123,7 +139,7 @@ ) ; Don't insert spaces between the starting '[' and ending ']' of an index expression -(index_expression - value: _ @append_antispace - index: _ @prepend_antispace @append_antispace -) +; (index_expression +; value: _ @append_antispace +; index: _ @prepend_antispace @append_antispace +; ) diff --git a/topiary-queries/queries/tree_sitter_query.scm b/topiary-queries/queries/tree_sitter_query.scm index 2d58f617..c3c16bc6 100644 --- a/topiary-queries/queries/tree_sitter_query.scm +++ b/topiary-queries/queries/tree_sitter_query.scm @@ -47,6 +47,9 @@ (anonymous_node (capture) @prepend_space ) +; (grouping +; (capture) @prepend_space +; ) ; The grammar always includes a (parameters) child node under ; (predicate), even when there are none. Topiary will deal with the @@ -81,6 +84,7 @@ ( [ (anonymous_node) + (grouping) (field_definition) (list) (named_node) @@ -90,6 +94,7 @@ . [ (anonymous_node) + (grouping) (field_definition) (list) (named_node) From 2dea7e7e154bef420f6e8548b25fe5a6c4586e83 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Fri, 10 Jan 2025 22:34:49 -0600 Subject: [PATCH 09/39] handle indentation of predicate parameters --- .../samples/expected/tree_sitter_query.scm | 82 +++++++++++-------- .../tests/samples/input/tree_sitter_query.scm | 11 +++ topiary-queries/queries/tree_sitter_query.scm | 6 +- 3 files changed, 65 insertions(+), 34 deletions(-) diff --git a/topiary-cli/tests/samples/expected/tree_sitter_query.scm b/topiary-cli/tests/samples/expected/tree_sitter_query.scm index e31588ab..5a1596f0 100644 --- a/topiary-cli/tests/samples/expected/tree_sitter_query.scm +++ b/topiary-cli/tests/samples/expected/tree_sitter_query.scm @@ -1,5 +1,5 @@ ; Configuration -(#language! ocaml) +(#language!ocaml) ; This query file is used to format trees produced by two different grammars: ; - the grammar for OCaml interface files `tree_sitter_ocaml::language_ocaml_interface()` @@ -746,7 +746,7 @@ (fun_expression "->" @append_spaced_scoped_softline ) @append_end_scope - (#scope_id! "fun_definition") + (#scope_id!"fun_definition") ) ; The same as above holds for single-line `function`. @@ -770,23 +770,23 @@ (function_expression "function" @append_spaced_scoped_softline ) @append_end_scope - (#scope_id! "function_definition") + (#scope_id!"function_definition") ) (parenthesized_expression (function_expression) @prepend_begin_scope @append_end_scope - (#scope_id! "function_definition") + (#scope_id!"function_definition") ) (function_expression "|"* @do_nothing . (match_case) @prepend_spaced_scoped_softline - (#scope_id! "function_definition") + (#scope_id!"function_definition") ) (function_expression "|"* @prepend_spaced_scoped_softline . (match_case) - (#scope_id! "function_definition") + (#scope_id!"function_definition") ) (value_definition @@ -886,7 +886,7 @@ ]* . ";" @delete - (#delimiter! ";") + (#delimiter!";") ) (record_declaration @@ -903,7 +903,7 @@ ; [@and again]; (* and a last one *) ; } (record_declaration - (#scope_id! "field_declaration") + (#scope_id!"field_declaration") [ (field_declaration) (attribute) @@ -913,7 +913,7 @@ (field_declaration) @prepend_begin_scope ) (record_declaration - (#scope_id! "field_declaration") + (#scope_id!"field_declaration") [ (field_declaration) (attribute) @@ -924,7 +924,7 @@ ) (record_declaration (attribute) @prepend_indent_start @prepend_spaced_scoped_softline @append_indent_end - (#scope_id! "field_declaration") + (#scope_id!"field_declaration") ) ; Duplicate the same logic as above for record *expressions* @@ -937,7 +937,7 @@ ]* . ";" @delete - (#delimiter! ";") + (#delimiter!";") ) (record_expression @@ -945,7 +945,7 @@ ) (record_expression - (#scope_id! "field_expression") + (#scope_id!"field_expression") [ (field_expression) (attribute) @@ -955,7 +955,7 @@ (field_expression) @prepend_begin_scope ) (record_expression - (#scope_id! "field_expression") + (#scope_id!"field_expression") [ (field_expression) (attribute) @@ -966,7 +966,7 @@ ) (record_expression (attribute) @prepend_indent_start @prepend_spaced_scoped_softline @append_indent_end - (#scope_id! "field_expression") + (#scope_id!"field_expression") ) ; Start an indented block after these @@ -1217,16 +1217,16 @@ . (_) @prepend_begin_scope "=" @append_end_scope - (#scope_id! "let_binding_before_equal") + (#scope_id!"let_binding_before_equal") ) (let_binding (parameter) @prepend_spaced_scoped_softline - (#scope_id! "let_binding_before_equal") + (#scope_id!"let_binding_before_equal") ) (let_binding ":"? @prepend_spaced_scoped_softline "=" @prepend_spaced_scoped_softline - (#scope_id! "let_binding_before_equal") + (#scope_id!"let_binding_before_equal") ) ; Indent and allow softlines in anonymous function definitions, such as @@ -1247,16 +1247,16 @@ . "fun" @prepend_begin_scope "->" @append_end_scope - (#scope_id! "fun_expr_before_arrow") + (#scope_id!"fun_expr_before_arrow") ) (fun_expression (parameter) @prepend_spaced_scoped_softline - (#scope_id! "fun_expr_before_arrow") + (#scope_id!"fun_expr_before_arrow") ) (fun_expression ":"? @prepend_spaced_scoped_softline "->" @prepend_spaced_scoped_softline - (#scope_id! "fun_expr_before_arrow") + (#scope_id!"fun_expr_before_arrow") ) ; Indent and allow softlines in tuples, such as @@ -1290,11 +1290,11 @@ (product_expression) @prepend_begin_scope @append_end_scope . ","? @do_nothing - (#scope_id! "tuple") + (#scope_id!"tuple") ) (product_expression "," @append_spaced_scoped_softline - (#scope_id! "tuple") + (#scope_id!"tuple") ) ; Allow softlines in function types, such as @@ -1322,11 +1322,11 @@ "->"? @do_nothing . (function_type) @prepend_begin_scope @append_end_scope - (#scope_id! "function_type") + (#scope_id!"function_type") ) (function_type "->" @append_spaced_scoped_softline - (#scope_id! "function_type") + (#scope_id!"function_type") ) ; Allow softlines in infix expressions, such as @@ -1347,7 +1347,7 @@ )? @do_nothing . (infix_expression) @prepend_begin_scope @append_end_scope - (#scope_id! "infix_expression") + (#scope_id!"infix_expression") ) (infix_expression (infix_operator @@ -1356,7 +1356,7 @@ "&&" ] ) @prepend_spaced_scoped_softline - (#scope_id! "infix_expression") + (#scope_id!"infix_expression") ) ; Allow softlines in sequences and ppx sequences, such as @@ -1377,11 +1377,11 @@ . "%"? @do_nothing ) @prepend_begin_scope @append_end_scope - (#scope_id! "sequence_expression") + (#scope_id!"sequence_expression") ) (sequence_expression ";" @append_spaced_scoped_softline - (#scope_id! "sequence_expression") + (#scope_id!"sequence_expression") ) ( @@ -1399,7 +1399,7 @@ . "%" ) @prepend_begin_scope @append_end_scope - (#scope_id! "ppx_sequence_expression") + (#scope_id!"ppx_sequence_expression") ) (sequence_expression ";" @@ -1407,7 +1407,7 @@ "%" . (attribute_id) @append_spaced_scoped_softline - (#scope_id! "ppx_sequence_expression") + (#scope_id!"ppx_sequence_expression") ) ; Indent and add softlines in lists and arrays, such as @@ -1457,11 +1457,11 @@ (module_binding (module_name) @append_indent_start @prepend_begin_scope "=" @prepend_empty_scoped_softline @prepend_indent_end @append_end_scope - (#scope_id! "module_binding_before_equal") + (#scope_id!"module_binding_before_equal") ) ; if a module binding has no equal sign and isn't just a signature, everything enters the scope (module_binding - (#scope_id! "module_binding_before_equal") + (#scope_id!"module_binding_before_equal") (module_name) @append_indent_start @prepend_begin_scope "="? @do_nothing (signature)? @do_nothing @@ -1469,7 +1469,7 @@ (module_binding (module_name) @append_empty_scoped_softline (module_parameter) @prepend_spaced_scoped_softline - (#scope_id! "module_binding_before_equal") + (#scope_id!"module_binding_before_equal") ) ; Try block formatting @@ -1508,3 +1508,19 @@ . ["," ";"]* @do_nothing ) + +; ================================================================================ +; Test cases +; ================================================================================ + +; retain predicate parameter newline delimitation after capture groups and identifiers +(#any-of? @function.builtin + "union" + "difference" + "intersection" + "circle" +) + +(#set! injection.language + "doxygen" +) diff --git a/topiary-cli/tests/samples/input/tree_sitter_query.scm b/topiary-cli/tests/samples/input/tree_sitter_query.scm index 53da9663..c08dbc03 100644 --- a/topiary-cli/tests/samples/input/tree_sitter_query.scm +++ b/topiary-cli/tests/samples/input/tree_sitter_query.scm @@ -1509,3 +1509,14 @@ . [ "," ";" ]* @do_nothing ) + +; ================================================================================ +; Predicate parameter newline separatation and indentation +; ================================================================================ + +(#any-of? @function.builtin "union" "difference" "intersection" +"circle") + +(#set! +injection.language +"doxygen") diff --git a/topiary-queries/queries/tree_sitter_query.scm b/topiary-queries/queries/tree_sitter_query.scm index 35562d1f..553c35a1 100644 --- a/topiary-queries/queries/tree_sitter_query.scm +++ b/topiary-queries/queries/tree_sitter_query.scm @@ -52,9 +52,13 @@ ; The grammar always includes a (parameters) child node under ; (predicate), even when there are none. Topiary will deal with the ; zero-byte nodes, so we just need to set the spacing correctly. +; Add softlines and indentation after parameter capture groups and identifiers. (predicate (parameters - _ @prepend_spaced_softline + [(identifier) (capture)]+ @append_spaced_softline @prepend_space @append_indent_start + (_)* @append_spaced_softline + (_) @append_indent_end @append_empty_softline + . ) ) From 2aaaf38826c047c59763bc72d431b63fda4a0290 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Fri, 10 Jan 2025 22:36:20 -0600 Subject: [PATCH 10/39] fixup expected header --- topiary-cli/tests/samples/expected/tree_sitter_query.scm | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/topiary-cli/tests/samples/expected/tree_sitter_query.scm b/topiary-cli/tests/samples/expected/tree_sitter_query.scm index 5a1596f0..0952d774 100644 --- a/topiary-cli/tests/samples/expected/tree_sitter_query.scm +++ b/topiary-cli/tests/samples/expected/tree_sitter_query.scm @@ -1510,10 +1510,9 @@ ) ; ================================================================================ -; Test cases +; Predicate parameter newline separatation and indentation ; ================================================================================ -; retain predicate parameter newline delimitation after capture groups and identifiers (#any-of? @function.builtin "union" "difference" From 2add1425f725b98c51e6cb1b1a27ac9bbe48fae6 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Fri, 10 Jan 2025 22:43:06 -0600 Subject: [PATCH 11/39] handle predicate_type spacing --- .../samples/expected/tree_sitter_query.scm | 66 +++++++++---------- topiary-queries/queries/tree_sitter_query.scm | 6 +- 2 files changed, 38 insertions(+), 34 deletions(-) diff --git a/topiary-cli/tests/samples/expected/tree_sitter_query.scm b/topiary-cli/tests/samples/expected/tree_sitter_query.scm index 0952d774..44a54f95 100644 --- a/topiary-cli/tests/samples/expected/tree_sitter_query.scm +++ b/topiary-cli/tests/samples/expected/tree_sitter_query.scm @@ -1,5 +1,5 @@ ; Configuration -(#language!ocaml) +(#language! ocaml) ; This query file is used to format trees produced by two different grammars: ; - the grammar for OCaml interface files `tree_sitter_ocaml::language_ocaml_interface()` @@ -746,7 +746,7 @@ (fun_expression "->" @append_spaced_scoped_softline ) @append_end_scope - (#scope_id!"fun_definition") + (#scope_id! "fun_definition") ) ; The same as above holds for single-line `function`. @@ -770,23 +770,23 @@ (function_expression "function" @append_spaced_scoped_softline ) @append_end_scope - (#scope_id!"function_definition") + (#scope_id! "function_definition") ) (parenthesized_expression (function_expression) @prepend_begin_scope @append_end_scope - (#scope_id!"function_definition") + (#scope_id! "function_definition") ) (function_expression "|"* @do_nothing . (match_case) @prepend_spaced_scoped_softline - (#scope_id!"function_definition") + (#scope_id! "function_definition") ) (function_expression "|"* @prepend_spaced_scoped_softline . (match_case) - (#scope_id!"function_definition") + (#scope_id! "function_definition") ) (value_definition @@ -886,7 +886,7 @@ ]* . ";" @delete - (#delimiter!";") + (#delimiter! ";") ) (record_declaration @@ -903,7 +903,7 @@ ; [@and again]; (* and a last one *) ; } (record_declaration - (#scope_id!"field_declaration") + (#scope_id! "field_declaration") [ (field_declaration) (attribute) @@ -913,7 +913,7 @@ (field_declaration) @prepend_begin_scope ) (record_declaration - (#scope_id!"field_declaration") + (#scope_id! "field_declaration") [ (field_declaration) (attribute) @@ -924,7 +924,7 @@ ) (record_declaration (attribute) @prepend_indent_start @prepend_spaced_scoped_softline @append_indent_end - (#scope_id!"field_declaration") + (#scope_id! "field_declaration") ) ; Duplicate the same logic as above for record *expressions* @@ -937,7 +937,7 @@ ]* . ";" @delete - (#delimiter!";") + (#delimiter! ";") ) (record_expression @@ -945,7 +945,7 @@ ) (record_expression - (#scope_id!"field_expression") + (#scope_id! "field_expression") [ (field_expression) (attribute) @@ -955,7 +955,7 @@ (field_expression) @prepend_begin_scope ) (record_expression - (#scope_id!"field_expression") + (#scope_id! "field_expression") [ (field_expression) (attribute) @@ -966,7 +966,7 @@ ) (record_expression (attribute) @prepend_indent_start @prepend_spaced_scoped_softline @append_indent_end - (#scope_id!"field_expression") + (#scope_id! "field_expression") ) ; Start an indented block after these @@ -1217,16 +1217,16 @@ . (_) @prepend_begin_scope "=" @append_end_scope - (#scope_id!"let_binding_before_equal") + (#scope_id! "let_binding_before_equal") ) (let_binding (parameter) @prepend_spaced_scoped_softline - (#scope_id!"let_binding_before_equal") + (#scope_id! "let_binding_before_equal") ) (let_binding ":"? @prepend_spaced_scoped_softline "=" @prepend_spaced_scoped_softline - (#scope_id!"let_binding_before_equal") + (#scope_id! "let_binding_before_equal") ) ; Indent and allow softlines in anonymous function definitions, such as @@ -1247,16 +1247,16 @@ . "fun" @prepend_begin_scope "->" @append_end_scope - (#scope_id!"fun_expr_before_arrow") + (#scope_id! "fun_expr_before_arrow") ) (fun_expression (parameter) @prepend_spaced_scoped_softline - (#scope_id!"fun_expr_before_arrow") + (#scope_id! "fun_expr_before_arrow") ) (fun_expression ":"? @prepend_spaced_scoped_softline "->" @prepend_spaced_scoped_softline - (#scope_id!"fun_expr_before_arrow") + (#scope_id! "fun_expr_before_arrow") ) ; Indent and allow softlines in tuples, such as @@ -1290,11 +1290,11 @@ (product_expression) @prepend_begin_scope @append_end_scope . ","? @do_nothing - (#scope_id!"tuple") + (#scope_id! "tuple") ) (product_expression "," @append_spaced_scoped_softline - (#scope_id!"tuple") + (#scope_id! "tuple") ) ; Allow softlines in function types, such as @@ -1322,11 +1322,11 @@ "->"? @do_nothing . (function_type) @prepend_begin_scope @append_end_scope - (#scope_id!"function_type") + (#scope_id! "function_type") ) (function_type "->" @append_spaced_scoped_softline - (#scope_id!"function_type") + (#scope_id! "function_type") ) ; Allow softlines in infix expressions, such as @@ -1347,7 +1347,7 @@ )? @do_nothing . (infix_expression) @prepend_begin_scope @append_end_scope - (#scope_id!"infix_expression") + (#scope_id! "infix_expression") ) (infix_expression (infix_operator @@ -1356,7 +1356,7 @@ "&&" ] ) @prepend_spaced_scoped_softline - (#scope_id!"infix_expression") + (#scope_id! "infix_expression") ) ; Allow softlines in sequences and ppx sequences, such as @@ -1377,11 +1377,11 @@ . "%"? @do_nothing ) @prepend_begin_scope @append_end_scope - (#scope_id!"sequence_expression") + (#scope_id! "sequence_expression") ) (sequence_expression ";" @append_spaced_scoped_softline - (#scope_id!"sequence_expression") + (#scope_id! "sequence_expression") ) ( @@ -1399,7 +1399,7 @@ . "%" ) @prepend_begin_scope @append_end_scope - (#scope_id!"ppx_sequence_expression") + (#scope_id! "ppx_sequence_expression") ) (sequence_expression ";" @@ -1407,7 +1407,7 @@ "%" . (attribute_id) @append_spaced_scoped_softline - (#scope_id!"ppx_sequence_expression") + (#scope_id! "ppx_sequence_expression") ) ; Indent and add softlines in lists and arrays, such as @@ -1457,11 +1457,11 @@ (module_binding (module_name) @append_indent_start @prepend_begin_scope "=" @prepend_empty_scoped_softline @prepend_indent_end @append_end_scope - (#scope_id!"module_binding_before_equal") + (#scope_id! "module_binding_before_equal") ) ; if a module binding has no equal sign and isn't just a signature, everything enters the scope (module_binding - (#scope_id!"module_binding_before_equal") + (#scope_id! "module_binding_before_equal") (module_name) @append_indent_start @prepend_begin_scope "="? @do_nothing (signature)? @do_nothing @@ -1469,7 +1469,7 @@ (module_binding (module_name) @append_empty_scoped_softline (module_parameter) @prepend_spaced_scoped_softline - (#scope_id!"module_binding_before_equal") + (#scope_id! "module_binding_before_equal") ) ; Try block formatting diff --git a/topiary-queries/queries/tree_sitter_query.scm b/topiary-queries/queries/tree_sitter_query.scm index 553c35a1..803769f7 100644 --- a/topiary-queries/queries/tree_sitter_query.scm +++ b/topiary-queries/queries/tree_sitter_query.scm @@ -55,12 +55,16 @@ ; Add softlines and indentation after parameter capture groups and identifiers. (predicate (parameters - [(identifier) (capture)]+ @append_spaced_softline @prepend_space @append_indent_start + [(identifier) (capture)]+ @append_spaced_softline @append_indent_start (_)* @append_spaced_softline + . (_) @append_indent_end @append_empty_softline . ) ) +(predicate + (predicate_type) @append_space +) ; Line breaks and indentation in multi-line lists and nodes (list From a71e62cba417958568064f2a2119c093b6be7e06 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Sun, 12 Jan 2025 12:19:39 -0600 Subject: [PATCH 12/39] formatted if/else block without union --- topiary-cli/tests/samples/input/openscad.scad | 79 ++++++++-------- topiary-config/languages.ncl | 5 +- topiary-queries/queries/openscad.scm | 89 ++++++++++++------- 3 files changed, 101 insertions(+), 72 deletions(-) diff --git a/topiary-cli/tests/samples/input/openscad.scad b/topiary-cli/tests/samples/input/openscad.scad index 41c58645..583d1e98 100644 --- a/topiary-cli/tests/samples/input/openscad.scad +++ b/topiary-cli/tests/samples/input/openscad.scad @@ -24,53 +24,58 @@ function line(point1, point2, width = 1) = // ================================================================================ cylinder(); cylinder( - d = 5, - h = 100, + d=5, + h=100, ); rotate([90, 0, 0]) cylinder(); translate([1, 0, 0]) { - difference() { - rotate([0, 90, 0]) cylinder(); - cube(); - } + difference() { + translate([0, 1, 0]) translate([1, 0, 0]) + rotate([0, 90, 0]) cylinder(); + cube(); + } } // ================================================================================ // Nested Items // ================================================================================ -module big_module(){ function inner_function() = undef; -module inner_module()cube(); +module big_module() { + function inner_function() = undef; + module inner_module() cube(); } -// module extern_module() include -// -// for (i = [10:50]) -// { -// let (angle = i*360/20, r= i*2, distance = r*5) -// { -// rotate(angle, [1, 0, 0]) -// translate([0, distance, 0]) -// sphere(r = r); -// } -// } -// -// if ($preview) -// if (false) -// sphere(); -// else -// translate([2, 0, 0]) cube(); -// -// for (i = [1:2:7]) { -// let (x = i ^ 2, y = x - 1) { -// translate([x, y, 0]) sphere(r = i); -// } -// } -// -// intersection_for (i = [1, 2, 3]) { -// if (i > 1) { -// translate([0, i, 0]) cube(); -// } -// } +module extern_module() include + +for (i = [10:50]) +{ + let (angle = i*360/20, r= i*2, distance = r*5) + { + rotate(angle, [1, 0, 0]) + translate([0, distance, 0]) + sphere(r = r); + } +} + +if ($preview) + if (false) + sphere(); + else + translate([2, 0, 0]) cube(); + +for (i = [1:2:7]) { + let (x = i ^ 2, y = x - 1) + { + translate([x, y, 0]) sphere(r = i); + } +} + +intersection_for (i = [1, 2, 3]) { + if (i > 1) { + translate([0, i, 0]) cube(); + } else { + translate([0, i, 0]) cube(); + } +} // // // ================================================================================ // // Comments diff --git a/topiary-config/languages.ncl b/topiary-config/languages.ncl index ee0a4ab4..fc1fc50f 100644 --- a/topiary-config/languages.ncl +++ b/topiary-config/languages.ncl @@ -75,10 +75,7 @@ openscad = { extensions = ["scad"], - grammar.source.git = { - git = "https://github.com/mkatychev/tree-sitter-openscad.git", - rev = "92bc2c3470e7babd67477fb8d4c24e342bdd9bc46", - }, + grammar.source.path = "/Users/mkatychev/Documents/tree-sitter/openscad/parser.so", }, rust = { diff --git a/topiary-queries/queries/openscad.scm b/topiary-queries/queries/openscad.scm index 10016d0f..4ccd49d0 100644 --- a/topiary-queries/queries/openscad.scm +++ b/topiary-queries/queries/openscad.scm @@ -10,11 +10,10 @@ ; Allow blank line before [ (use_statement) - (include_statement) - (block_comment) + (statement) (line_comment) + (block_comment) (function_item) - (transform_chain) (module_item) (expression) ] @allow_blank_line_before @@ -68,10 +67,9 @@ [ (var_declaration) (use_statement) - (include_statement) (function_item) (module_item) - (transform_chain) + (statement) ] @append_spaced_softline . [ @@ -91,6 +89,29 @@ _ @prepend_input_softline ) +; Append softlines, unless followed by comments. +( + [ + "," + ";" + ] @append_spaced_softline + . + [(block_comment) (line_comment)]* @do_nothing +) + +; Never put a space before a comma +( + "," @prepend_antispace +) + +; Don't insert spaces between the operator and their expression operand +; '-x' v.s. '- x' +(unary_expression _ @append_antispace . (expression)) + +; ================================================================================ +; functions & modules +; ================================================================================ + ; indent the body of a function (function_item (parameters) @@ -100,46 +121,52 @@ ";" @prepend_indent_end ) +; module calls in a transformation chain will follow each other +; sometimes staying on the same line and sometimes having a linebreak, +; each linebreak typically also starts an indent scope +(transform_chain) @prepend_input_softline +(transform_chain + (module_call) @append_indent_start + (transform_chain) @append_indent_end +) +; (function_call +; "=" @prepend_antispace @append_antispace +; ) + +; ================================================================================ +; blocks & expressions +; ================================================================================ (arguments "(" @append_empty_softline @append_indent_start "," @append_input_softline ")" @prepend_indent_end ) +; differentiate parameter definitions from parameter invocation, +; module/function definitions have param separation while +; module/function calls have none, this space on chained function/module calls +; and provides visual distinction between definitions and calls (arguments (assignment "=" @append_antispace @prepend_antispace ) ) -; (function_call -; "=" @prepend_antispace @append_antispace -; ) - -; Append softlines, unless followed by comments. -( - [ - "," - ";" - ] @append_spaced_softline +(union_block + . + "{" @append_spaced_softline @append_indent_start @prepend_space + _ + "}" @prepend_spaced_softline @prepend_indent_end . - [(block_comment) (line_comment)]* @do_nothing ) -; Never put a space before a comma -( - "," @prepend_antispace +; everything except `union_block` after a for/if/else statement should be a spaced_softline +; but a union +(if_block + condition: (_) @prepend_space @append_spaced_softline @append_indent_start + consequence: (_) @append_spaced_softline @append_indent_end ) - -; Don't insert spaces between the operator and their expression operand -(unary_expression - _ @append_antispace - . - (expression) +(if_block + "else" @append_spaced_softline @append_indent_start + alternative: (_) @append_spaced_softline @append_indent_end ) - -; Don't insert spaces between the starting '[' and ending ']' of an index expression -; (index_expression -; value: _ @append_antispace -; index: _ @prepend_antispace @append_antispace -; ) From 68a7c1cfeb27ffcd73fcd6d0624d45d7697d1dcb Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Sun, 12 Jan 2025 12:23:19 -0600 Subject: [PATCH 13/39] inital else/if with union block case --- topiary-cli/tests/samples/input/openscad.scad | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/topiary-cli/tests/samples/input/openscad.scad b/topiary-cli/tests/samples/input/openscad.scad index 583d1e98..b0d111a3 100644 --- a/topiary-cli/tests/samples/input/openscad.scad +++ b/topiary-cli/tests/samples/input/openscad.scad @@ -62,6 +62,30 @@ if ($preview) else translate([2, 0, 0]) cube(); + + if (len(bevel) > 0) { + offset = (centroid(bevpaths[0])); + } + else if (is_vector(shape)){ + attachable(anchor = anchor) { + down(ht/2) + linear_extrude(height = ht, convexity=8) { + _honeycomb(shp, spacing = spacing, hex_wall = strut); + offset_stroke(shp, width=[-frame, 0], closed=true); + } + children(); + } + } + else { + anchors = [ + named_anchor("zcenter", [0,0,0], UP), + named_anchor("base", [0,0,-ht/2], UP), + named_anchor("top", [0,0,ht/2], UP) + ]; + children(); + } + + for (i = [1:2:7]) { let (x = i ^ 2, y = x - 1) { From 7e97d2da6b66436c30fa13f1ab108cdab00f9963 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Sun, 12 Jan 2025 13:04:07 -0600 Subject: [PATCH 14/39] added unionless if else case --- topiary-queries/queries/openscad.scm | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/topiary-queries/queries/openscad.scm b/topiary-queries/queries/openscad.scm index 4ccd49d0..3d47b3d0 100644 --- a/topiary-queries/queries/openscad.scm +++ b/topiary-queries/queries/openscad.scm @@ -29,6 +29,7 @@ "assign" "use" "each" + "if" "||" "&&" "==" @@ -73,6 +74,7 @@ ] @append_spaced_softline . [ + "else" (block_comment) (line_comment) ]* @do_nothing @@ -160,13 +162,20 @@ . ) +((union_block) @append_space . "else") + ; everything except `union_block` after a for/if/else statement should be a spaced_softline ; but a union (if_block - condition: (_) @prepend_space @append_spaced_softline @append_indent_start - consequence: (_) @append_spaced_softline @append_indent_end -) -(if_block - "else" @append_spaced_softline @append_indent_start - alternative: (_) @append_spaced_softline @append_indent_end + (parenthesized_expression) @append_spaced_softline @append_indent_start + . + (union_block)? @do_nothing +) @append_indent_end +( + "else" @append_spaced_softline + . + [ + (union_block) + (if_block) + ]? @do_nothing ) From d9216501f1168ff5f0c6526067cf29b540a92cc3 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Tue, 14 Jan 2025 13:06:51 -0600 Subject: [PATCH 15/39] else edge cases --- topiary-queries/queries/openscad.scm | 38 ++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/topiary-queries/queries/openscad.scm b/topiary-queries/queries/openscad.scm index 3d47b3d0..2e95c8bf 100644 --- a/topiary-queries/queries/openscad.scm +++ b/topiary-queries/queries/openscad.scm @@ -29,6 +29,7 @@ "assign" "use" "each" + "else" "if" "||" "&&" @@ -70,7 +71,7 @@ (use_statement) (function_item) (module_item) - (statement) + (if_block) ] @append_spaced_softline . [ @@ -96,7 +97,7 @@ [ "," ";" - ] @append_spaced_softline + ] . [(block_comment) (line_comment)]* @do_nothing ) @@ -162,20 +163,37 @@ . ) -((union_block) @append_space . "else") +;{ ... } else { +; ((union_block) @append_space . "else") ; everything except `union_block` after a for/if/else statement should be a spaced_softline ; but a union (if_block (parenthesized_expression) @append_spaced_softline @append_indent_start . - (union_block)? @do_nothing -) @append_indent_end -( - "else" @append_spaced_softline - . [ - (union_block) + (for_block) + (intersection_for_block) (if_block) - ]? @do_nothing + (let_block) + (assign_block) + (modifier_chain) + (transform_chain) + (include_statement) + (assert_statement) + ] @append_indent_end @append_spaced_softline ) +( + "else" @append_spaced_softline @append_indent_start + . + [ + (for_block) + (intersection_for_block) + (let_block) + (assign_block) + (modifier_chain) + (transform_chain) + (include_statement) + (assert_statement) + ] @append_indent_end +) @prepend_spaced_softline From e76c94983ca55153a5d75ef42012a5c080830248 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Wed, 15 Jan 2025 14:04:57 -0600 Subject: [PATCH 16/39] added if_block test cases --- topiary-cli/tests/samples/input/openscad.scad | 50 ++++--------------- topiary-queries/queries/openscad.scm | 33 ++++++++++++ 2 files changed, 43 insertions(+), 40 deletions(-) diff --git a/topiary-cli/tests/samples/input/openscad.scad b/topiary-cli/tests/samples/input/openscad.scad index b0d111a3..16f326fd 100644 --- a/topiary-cli/tests/samples/input/openscad.scad +++ b/topiary-cli/tests/samples/input/openscad.scad @@ -56,50 +56,20 @@ for (i = [10:50]) } } -if ($preview) - if (false) - sphere(); - else - translate([2, 0, 0]) cube(); +// newline indent propagates from innermost if_block +if ($preview) if(true) foo(); else if(true) if + (false) foo(false); else translate([2,0,0]) foo(); else bar(); - - if (len(bevel) > 0) { - offset = (centroid(bevpaths[0])); - } - else if (is_vector(shape)){ - attachable(anchor = anchor) { - down(ht/2) - linear_extrude(height = ht, convexity=8) { - _honeycomb(shp, spacing = spacing, hex_wall = strut); - offset_stroke(shp, width=[-frame, 0], closed=true); - } - children(); - } - } - else { - anchors = [ - named_anchor("zcenter", [0,0,0], UP), - named_anchor("base", [0,0,-ht/2], UP), - named_anchor("top", [0,0,ht/2], UP) - ]; - children(); - } +// format propagates from first union_block +if (true) { + } else if (true) { } else if (false) {foo();}else if (fn_foo(true)) { } else { children(); } -for (i = [1:2:7]) { - let (x = i ^ 2, y = x - 1) - { - translate([x, y, 0]) sphere(r = i); - } -} +for(i = [1:2:7]) { let (x = i ^ 2,y = x - 1) { + translate([x,y,0]) sphere(r=i); } } -intersection_for (i = [1, 2, 3]) { - if (i > 1) { - translate([0, i, 0]) cube(); - } else { - translate([0, i, 0]) cube(); - } -} +intersection_for(i = [1,2,3]) { if (i > 1) { + translate([0,i,0]) cube(); } else { translate([0,i,0]) cube(); } } // // // ================================================================================ // // Comments diff --git a/topiary-queries/queries/openscad.scm b/topiary-queries/queries/openscad.scm index 2e95c8bf..73f96873 100644 --- a/topiary-queries/queries/openscad.scm +++ b/topiary-queries/queries/openscad.scm @@ -197,3 +197,36 @@ (assert_statement) ] @append_indent_end ) @prepend_spaced_softline + +; scope is triggered by the presence of a (union_block) consequce on the intersection_for_block; +; and extends to the "else if" and "else" portions +( + "else"? @do_nothing + (if_block + (#scope_id! "if_union") + (#query_name! "if_union scope") + ) @prepend_begin_scope @append_end_scope +) + +(if_block + (#scope_id! "if_union") + (#query_name! "if_union outer") + (_ + . + "{" @append_spaced_scoped_softline + "}" @prepend_spaced_scoped_softline + . + ) +) +(if_block + (#query_name! "if_union inner") + (#scope_id! "if_union") + (if_block + (_ + . + "{" @append_spaced_scoped_softline + "}" @prepend_spaced_scoped_softline + . + ) + ) +) From 8c43e148102d0d1c4fc491e8764f2aad6bd5ae8e Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Wed, 15 Jan 2025 14:22:43 -0600 Subject: [PATCH 17/39] simplified if_block test case --- topiary-cli/tests/samples/input/openscad.scad | 88 ++++++++++--------- topiary-queries/queries/openscad.scm | 16 +--- 2 files changed, 47 insertions(+), 57 deletions(-) diff --git a/topiary-cli/tests/samples/input/openscad.scad b/topiary-cli/tests/samples/input/openscad.scad index 16f326fd..769e34d1 100644 --- a/topiary-cli/tests/samples/input/openscad.scad +++ b/topiary-cli/tests/samples/input/openscad.scad @@ -1,3 +1,6 @@ +// ================================================================================ +// Basic Items +// ================================================================================ include use // variables @@ -23,37 +26,28 @@ function line(point1, point2, width = 1) = // Transformations // ================================================================================ cylinder(); -cylinder( - d=5, - h=100, -); -rotate([90, 0, 0]) cylinder(); +cylinder( d = 5, h=100,); +rotate([90, 0, 0]) +cylinder(); translate([1, 0, 0]) { - difference() { - translate([0, 1, 0]) translate([1, 0, 0]) - rotate([0, 90, 0]) cylinder(); - cube(); - } -} + difference() { translate([0, 1, 0]) + translate([1, 0, 0]) rotate([0, 90, 0]) + cylinder(); cube(); } } // ================================================================================ // Nested Items // ================================================================================ -module big_module() { - function inner_function() = undef; - module inner_module() cube(); +module big_module() { function inner_function() = undef; module inner_module() cube(); } module extern_module() include -for (i = [10:50]) -{ - let (angle = i*360/20, r= i*2, distance = r*5) - { - rotate(angle, [1, 0, 0]) - translate([0, distance, 0]) - sphere(r = r); - } +// ================================================================================ +// Control Flow +// ================================================================================ +for (i = [10:50]) { let (angle = i*360/20, r= i*2, distance = r*5) { + rotate(angle, [1, 0, 0]) translate([0, distance, 0]) + sphere(r = r); } } // newline indent propagates from innermost if_block @@ -62,7 +56,7 @@ if ($preview) if(true) foo(); else if(true) if // format propagates from first union_block if (true) { - } else if (true) { } else if (false) {foo();}else if (fn_foo(true)) { } else { children(); } + } else if (fn(true)) { foo();} else if (false) { bar();} else { baz(); } for(i = [1:2:7]) { let (x = i ^ 2,y = x - 1) { @@ -70,22 +64,32 @@ for(i = [1:2:7]) { let (x = i ^ 2,y = x - 1) { intersection_for(i = [1,2,3]) { if (i > 1) { translate([0,i,0]) cube(); } else { translate([0,i,0]) cube(); } } -// -// // ================================================================================ -// // Comments -// // ================================================================================ -// /* ignored [Customizer Group] ignored */ -// /* Multiline -// comment -// here -// */ -// my_parameter = 5; -// -// function math(x) = /*do math stuff*/ x + 2 // done with math -// ; -// -// module my_cylinder() { -// // here we create a cylinder -// cylinder(); /* done ! */ -// cube(); -// } + +// ================================================================================ +// Comments +// ================================================================================ + +/* ignored [Customizer Group] ignored */ +/* Multiline +comment +here +*/ +my_parameter = /*inline block*/ 5; + +function math(x) = /*do math stuff*/ x + 2 // done with math +; + +module my_cylinder() { + // here we create a cylinder + cylinder(); /* done ! */ + cube(); +} + +// ================================================================================ +// Modifiers +// ================================================================================ +! cylinder(); +* linear_extrude(4) text("Hello"); +rotate([0, 90, 0]) # cylinder(); +% cube(); + diff --git a/topiary-queries/queries/openscad.scm b/topiary-queries/queries/openscad.scm index 73f96873..d7b51c72 100644 --- a/topiary-queries/queries/openscad.scm +++ b/topiary-queries/queries/openscad.scm @@ -71,7 +71,7 @@ (use_statement) (function_item) (module_item) - (if_block) + (statement) ] @append_spaced_softline . [ @@ -204,13 +204,11 @@ "else"? @do_nothing (if_block (#scope_id! "if_union") - (#query_name! "if_union scope") ) @prepend_begin_scope @append_end_scope ) (if_block (#scope_id! "if_union") - (#query_name! "if_union outer") (_ . "{" @append_spaced_scoped_softline @@ -218,15 +216,3 @@ . ) ) -(if_block - (#query_name! "if_union inner") - (#scope_id! "if_union") - (if_block - (_ - . - "{" @append_spaced_scoped_softline - "}" @prepend_spaced_scoped_softline - . - ) - ) -) From 29c96c5bdc766029b8ad6d604ae3f0193ca1a8c3 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Wed, 15 Jan 2025 15:00:57 -0600 Subject: [PATCH 18/39] initial modifier queries --- topiary-cli/tests/samples/input/openscad.scad | 13 +++++++++---- topiary-queries/queries/openscad.scm | 8 ++++++-- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/topiary-cli/tests/samples/input/openscad.scad b/topiary-cli/tests/samples/input/openscad.scad index 769e34d1..aa726b18 100644 --- a/topiary-cli/tests/samples/input/openscad.scad +++ b/topiary-cli/tests/samples/input/openscad.scad @@ -88,8 +88,13 @@ module my_cylinder() { // ================================================================================ // Modifiers // ================================================================================ -! cylinder(); +!cylinder(); * linear_extrude(4) text("Hello"); -rotate([0, 90, 0]) # cylinder(); -% cube(); - +rotate([0,90,0])# cylinder(); +%cube(); +// multi modifier +translate(1) # ! cube(); +rotate([90]) % +translate() +# +cube(); diff --git a/topiary-queries/queries/openscad.scm b/topiary-queries/queries/openscad.scm index d7b51c72..a730d261 100644 --- a/topiary-queries/queries/openscad.scm +++ b/topiary-queries/queries/openscad.scm @@ -129,6 +129,7 @@ ; each linebreak typically also starts an indent scope (transform_chain) @prepend_input_softline (transform_chain + (modifier)* (module_call) @append_indent_start (transform_chain) @append_indent_end ) @@ -177,7 +178,6 @@ (if_block) (let_block) (assign_block) - (modifier_chain) (transform_chain) (include_statement) (assert_statement) @@ -191,7 +191,6 @@ (intersection_for_block) (let_block) (assign_block) - (modifier_chain) (transform_chain) (include_statement) (assert_statement) @@ -216,3 +215,8 @@ . ) ) + +; modifiers +(modifier) @append_antispace +; (transform_chain +; (modifier)+ From dbffcb468d2d06ba18e874633a85ee762c3040e3 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Wed, 15 Jan 2025 15:20:31 -0600 Subject: [PATCH 19/39] added initial assertion test case --- topiary-cli/tests/samples/input/openscad.scad | 10 ++++++++++ topiary-queries/queries/openscad.scm | 10 +++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/topiary-cli/tests/samples/input/openscad.scad b/topiary-cli/tests/samples/input/openscad.scad index aa726b18..fb4bec9f 100644 --- a/topiary-cli/tests/samples/input/openscad.scad +++ b/topiary-cli/tests/samples/input/openscad.scad @@ -98,3 +98,13 @@ rotate([90]) % translate() # cube(); + +// ================================================================================ +// Assertions +// ================================================================================ +x = 10; +assert(x < 20) cube(); +for (y = [3:5]) + assert(assert() y < x, "message") + cylinder(); + diff --git a/topiary-queries/queries/openscad.scm b/topiary-queries/queries/openscad.scm index a730d261..adb1a886 100644 --- a/topiary-queries/queries/openscad.scm +++ b/topiary-queries/queries/openscad.scm @@ -71,7 +71,15 @@ (use_statement) (function_item) (module_item) - (statement) + (intersection_for_block) + (for_block) + (if_block) + (let_block) + (assign_block) + (union_block) + (transform_chain) + (include_statement) + (assert_statement) ] @append_spaced_softline . [ From 8bca52d4afa15cd6a4e39e30ebf90352a7b9d6ff Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Thu, 16 Jan 2025 13:01:30 -0600 Subject: [PATCH 20/39] initial assertions pass --- topiary-cli/tests/samples/input/openscad.scad | 14 +++-- topiary-queries/queries/openscad.scm | 55 +++++++++++++++++-- 2 files changed, 57 insertions(+), 12 deletions(-) diff --git a/topiary-cli/tests/samples/input/openscad.scad b/topiary-cli/tests/samples/input/openscad.scad index fb4bec9f..d6c25d3c 100644 --- a/topiary-cli/tests/samples/input/openscad.scad +++ b/topiary-cli/tests/samples/input/openscad.scad @@ -102,9 +102,11 @@ cube(); // ================================================================================ // Assertions // ================================================================================ -x = 10; -assert(x < 20) cube(); -for (y = [3:5]) - assert(assert() y < x, "message") - cylinder(); - +assert(); +assert(10 < 20) cube(); +for(y = [3:5]) assert(assert() y < x, "message") + cylinder(); +assert(true) assert() cylinder(); +val = assert(true, "strut must be positive") +assert(true, "frame must be nonnegative") +undef; diff --git a/topiary-queries/queries/openscad.scm b/topiary-queries/queries/openscad.scm index adb1a886..fd893e71 100644 --- a/topiary-queries/queries/openscad.scm +++ b/topiary-queries/queries/openscad.scm @@ -10,7 +10,15 @@ ; Allow blank line before [ (use_statement) - (statement) + (intersection_for_block) + (for_block) + (if_block) + (let_block) + (assign_block) + (union_block) + (transform_chain) + (include_statement) + (assert_statement) (line_comment) (block_comment) (function_item) @@ -77,7 +85,7 @@ (let_block) (assign_block) (union_block) - (transform_chain) + (transform_chain ";" .) (include_statement) (assert_statement) ] @append_spaced_softline @@ -101,11 +109,18 @@ ) ; Append softlines, unless followed by comments. +; When binding multiple values in a let block, allow new lines between the bindings. +(list + "[" @append_indent_start @append_empty_softline + "]" @prepend_indent_end @prepend_empty_softline +) +(list + "," @append_spaced_softline + . + [(block_comment) (line_comment)]* @do_nothing +) ( - [ - "," - ";" - ] + ";" @append_spaced_softline . [(block_comment) (line_comment)]* @do_nothing ) @@ -131,6 +146,16 @@ (expression) ";" @prepend_indent_end ) +; indent the body of a function +(var_declaration + (assignment + . + _ + "=" @append_indent_start @append_spaced_softline + ) + ";" @prepend_indent_end + . +) ; module calls in a transformation chain will follow each other ; sometimes staying on the same line and sometimes having a linebreak, @@ -224,7 +249,25 @@ ) ) +(for_block + (assignments) @append_spaced_softline @append_indent_start + . + [ + (for_block) + (intersection_for_block) + (if_block) + (let_block) + (assign_block) + (transform_chain) + (include_statement) + (assert_statement) + ] @append_indent_end @append_spaced_softline +) + ; modifiers (modifier) @append_antispace ; (transform_chain ; (modifier)+ + +(assert_expression expression: (_) @prepend_spaced_softline) +(assert_statement statement: (_) @prepend_spaced_softline) From 6f9f523039a7c6a93e80f2babe4d4fcd57cd0c75 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Thu, 16 Jan 2025 14:40:07 -0600 Subject: [PATCH 21/39] handled --- Cargo.toml | 2 +- topiary-core/src/atom_collection.rs | 86 ++++++++++++++++++++--------- 2 files changed, 60 insertions(+), 28 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c37e61c2..e1cad0e5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,7 +62,7 @@ futures = "0.3.28" itertools = "0.11" js-sys = "0.3" libloading = "0.8.4" -log = "0.4" +log = { version = "0.4", features = ["kv"] } nickel-lang-core = { version = "0.8.0", default-features = false } predicates = "3.0" pretty_assertions = "1.3" diff --git a/topiary-core/src/atom_collection.rs b/topiary-core/src/atom_collection.rs index 574cd05d..d4e4542a 100644 --- a/topiary-core/src/atom_collection.rs +++ b/topiary-core/src/atom_collection.rs @@ -226,6 +226,15 @@ impl AtomCollection { node, predicates, ), + "append_multiline_delimiter" => { + if self.in_multiline_context(node) { + self.append( + Atom::Literal(requires_delimiter()?.to_string()), + node, + predicates, + ) + } + } "append_empty_softline" => { self.append(Atom::Softline { spaced: false }, node, predicates); } @@ -251,6 +260,15 @@ impl AtomCollection { node, predicates, ), + "prepend_multiline_delimiter" => { + if self.in_multiline_context(node) { + self.prepend( + Atom::Literal(requires_delimiter()?.to_string()), + node, + predicates, + ) + } + } "prepend_empty_softline" => { self.prepend(Atom::Softline { spaced: false }, node, predicates); } @@ -591,6 +609,22 @@ impl AtomCollection { self.append.entry(target_node.id()).or_default().push(atom); } + /// Indicates whether we are in a multiline context or not. + /// # Arguments + /// + /// * `node` - The node to which the atom applies. + /// # Returns + /// + /// A boolean indicating whether a given node has a a parent labelled as multi-line. + /// If the provided node has no parent, the function returns `false`. + fn in_multiline_context(&self, node: &Node) -> bool { + let parent_id = node.parent().map(|p| p.id()); + + parent_id + .map(|pid| self.multi_line_nodes.contains(&pid)) + .unwrap_or(false) + } + /// Expands a softline atom to a hardline, space or empty atom depending on /// if we are in a multiline context or not. /// @@ -612,34 +646,32 @@ impl AtomCollection { /// /// A new atom after expanding the softline if applicable. fn expand_multiline(&self, atom: Atom, node: &Node) -> Atom { - if let Atom::Softline { spaced } = atom { - if let Some(parent) = node.parent() { - let parent_id = parent.id(); - - if self.multi_line_nodes.contains(&parent_id) { - log::debug!( - "Expanding softline to hardline in node {} with parent {}: {}", - node.display_one_based(), - parent_id, - parent.display_one_based() - ); - Atom::Hardline - } else if spaced { - log::debug!( - "Expanding softline to space in node {} with parent {}: {}", - node.display_one_based(), - parent_id, - parent.display_one_based() - ); - Atom::Space - } else { - Atom::Empty - } - } else { - Atom::Empty - } + let Atom::Softline { spaced } = atom else { + return atom; + }; + let Some(parent) = node.parent() else { + return Atom::Empty; + }; + let parent_id = parent.id(); + + if self.multi_line_nodes.contains(&parent_id) { + log::debug!( + parent_id; + "Expanding softline to hardline in node {}: {}", + node.display_one_based(), + parent.display_one_based() + ); + Atom::Hardline + } else if spaced { + log::debug!( + parent_id; + "Expanding softline to space in node {}: {}", + node.display_one_based(), + parent.display_one_based() + ); + Atom::Space } else { - atom + Atom::Empty } } From df70038c4c8c930e878f73cffaf7451a3d7334a7 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Mon, 20 Jan 2025 11:21:28 -0600 Subject: [PATCH 22/39] partial list handling --- topiary-cli/tests/samples/input/openscad.scad | 16 +++ topiary-queries/queries/openscad.scm | 104 ++++++++++++------ 2 files changed, 84 insertions(+), 36 deletions(-) diff --git a/topiary-cli/tests/samples/input/openscad.scad b/topiary-cli/tests/samples/input/openscad.scad index d6c25d3c..09b6d9cc 100644 --- a/topiary-cli/tests/samples/input/openscad.scad +++ b/topiary-cli/tests/samples/input/openscad.scad @@ -110,3 +110,19 @@ assert(true) assert() cylinder(); val = assert(true, "strut must be positive") assert(true, "frame must be nonnegative") undef; + +// ================================================================================ +// Assignments +// ================================================================================ + list1 = [ + 1, + 2, 3 + ]; + my_fn = fn1([ + 1, + 2, + 3, + ], + true + ); + diff --git a/topiary-queries/queries/openscad.scm b/topiary-queries/queries/openscad.scm index fd893e71..eb9c8722 100644 --- a/topiary-queries/queries/openscad.scm +++ b/topiary-queries/queries/openscad.scm @@ -48,12 +48,11 @@ "<=" ">=" "+" - "-" + (binary_expression "-") "*" "/" "%" "^" - "!" "=" "?" ":" @@ -111,21 +110,19 @@ ; Append softlines, unless followed by comments. ; When binding multiple values in a let block, allow new lines between the bindings. (list - "[" @append_indent_start @append_empty_softline - "]" @prepend_indent_end @prepend_empty_softline + "[" @append_indent_start @append_empty_softline @append_antispace + "]" @prepend_indent_end @prepend_empty_softline @prepend_antispace ) -(list - "," @append_spaced_softline - . - [(block_comment) (line_comment)]* @do_nothing -) -( - ";" @append_spaced_softline - . - [(block_comment) (line_comment)]* @do_nothing +(range + "[" @append_antispace + "]" @prepend_antispace ) +(list "," @append_spaced_softline . [(block_comment) (line_comment)]* @do_nothing) +(assignments "," @append_spaced_softline . [(block_comment) (line_comment)]* @do_nothing) +(parameters "," @append_spaced_softline . [(block_comment) (line_comment)]* @do_nothing) +(";" @append_spaced_softline . [(block_comment) (line_comment)]* @do_nothing) -; Never put a space before a comma +; Never put a space before a comma or square bracket ( "," @prepend_antispace ) @@ -146,16 +143,6 @@ (expression) ";" @prepend_indent_end ) -; indent the body of a function -(var_declaration - (assignment - . - _ - "=" @append_indent_start @append_spaced_softline - ) - ";" @prepend_indent_end - . -) ; module calls in a transformation chain will follow each other ; sometimes staying on the same line and sometimes having a linebreak, @@ -166,17 +153,62 @@ (module_call) @append_indent_start (transform_chain) @append_indent_end ) -; (function_call -; "=" @prepend_antispace @append_antispace -; ) ; ================================================================================ -; blocks & expressions +; blocks/expressions/statements ; ================================================================================ +(assignments) @append_space +; indent variable newlines +; (var_declaration +; . +; (assignment . (identifier) . "=" @append_indent_start @append_input_softline) +; ";" @prepend_indent_end +; . +; ) + +(arguments "," @append_input_softline) +(arguments "," @delete . ")" . (#single_line_only!)) +(list "," @delete . "]" . (#single_line_only!)) +(list + (_) @append_delimiter + . + ","? @do_nothing + . + "]" + . + (#delimiter! ",") + (#multi_line_only!) +) (arguments + . "(" @append_empty_softline @append_indent_start - "," @append_input_softline - ")" @prepend_indent_end + ")" @prepend_indent_end @prepend_empty_softline + . +) +(arguments + (#delimiter! ",") + (_) @append_multiline_delimiter + . + ","? @do_nothing + . + ")" + . +) + +(parameters "," @append_input_softline) +(parameters "," @delete . ")" . (#single_line_only!)) +(parameters + . + "(" @append_empty_softline @append_indent_start + ")" @prepend_indent_end @prepend_empty_softline + . +) + +(parenthesized_expression + . + "(" @append_empty_softline @append_indent_start + ")" @prepend_indent_end @prepend_empty_softline + . ) ; differentiate parameter definitions from parameter invocation, @@ -197,9 +229,6 @@ . ) -;{ ... } else { -; ((union_block) @append_space . "else") - ; everything except `union_block` after a for/if/else statement should be a spaced_softline ; but a union (if_block @@ -263,11 +292,14 @@ (assert_statement) ] @append_indent_end @append_spaced_softline ) - ; modifiers (modifier) @append_antispace -; (transform_chain -; (modifier)+ (assert_expression expression: (_) @prepend_spaced_softline) (assert_statement statement: (_) @prepend_spaced_softline) +(echo_expression expression: (_) @prepend_spaced_softline) + +; ternary expressions +(ternary_expression + ":" @prepend_spaced_softline +) From d4cb8ab2a05581f46b7f690f226598eb88e2fd5e Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Tue, 21 Jan 2025 11:40:00 -0600 Subject: [PATCH 23/39] added ternary test case --- topiary-cli/tests/samples/input/openscad.scad | 25 +++++++++++++++++++ topiary-queries/queries/openscad.scm | 21 ++++++++++------ 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/topiary-cli/tests/samples/input/openscad.scad b/topiary-cli/tests/samples/input/openscad.scad index 09b6d9cc..dc14d76f 100644 --- a/topiary-cli/tests/samples/input/openscad.scad +++ b/topiary-cli/tests/samples/input/openscad.scad @@ -126,3 +126,28 @@ undef; true ); + +// ================================================================================ +// Ternary +// ================================================================================ +function affine3d_rot_from_to(from, to) = + assert(is_vector(from)) + assert(is_vector(to)) + assert(len(from) == len(to)) + let ( + from = unit(point3d(from)), + to = unit(point3d(to)) + ) approx(from, to) ? affine3d_identity() + : from.z == 0 && to.z == 0 ? affine3d_zrot(v_theta(point2d(to)) - v_theta(point2d(from))) + : let ( + u = vector_axis(from, to), + ang = vector_angle(from, to), + c = cos(ang), + c2 = 1 - c, + s = sin(ang) + ) [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [0, 0, 0, 1], + ]; diff --git a/topiary-queries/queries/openscad.scm b/topiary-queries/queries/openscad.scm index eb9c8722..71051ed9 100644 --- a/topiary-queries/queries/openscad.scm +++ b/topiary-queries/queries/openscad.scm @@ -48,7 +48,7 @@ "<=" ">=" "+" - (binary_expression "-") + "-" "*" "/" "%" @@ -158,13 +158,20 @@ ; blocks/expressions/statements ; ================================================================================ (assignments) @append_space +(assignments + . + "(" @append_empty_softline @append_indent_start + ")" @prepend_indent_end @prepend_empty_softline + . +) +(assignments "," @append_spaced_softline) ; indent variable newlines -; (var_declaration -; . -; (assignment . (identifier) . "=" @append_indent_start @append_input_softline) -; ";" @prepend_indent_end -; . -; ) +(var_declaration + . + (assignment . (identifier) . "=" @append_indent_start @append_input_softline) + ";" @prepend_indent_end + . +) (arguments "," @append_input_softline) (arguments "," @delete . ")" . (#single_line_only!)) From 97a6ac7e0364b2b3c596fcac0f7e92cd8bce4cf9 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Tue, 21 Jan 2025 12:39:49 -0600 Subject: [PATCH 24/39] added more ternary cases --- .editorconfig | 2 +- topiary-cli/tests/samples/input/openscad.scad | 15 +++++++------ topiary-queries/queries/openscad.scm | 22 +++++++++++++++++++ 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/.editorconfig b/.editorconfig index 959a8c0d..1821765b 100644 --- a/.editorconfig +++ b/.editorconfig @@ -8,6 +8,6 @@ insert_final_newline = true indent_style = space indent_size = 4 -[*.{json,nix,scm}] +[*.{json,nix,scm,scad}] indent_style = space indent_size = 2 diff --git a/topiary-cli/tests/samples/input/openscad.scad b/topiary-cli/tests/samples/input/openscad.scad index dc14d76f..6a8bea78 100644 --- a/topiary-cli/tests/samples/input/openscad.scad +++ b/topiary-cli/tests/samples/input/openscad.scad @@ -112,7 +112,7 @@ assert(true, "frame must be nonnegative") undef; // ================================================================================ -// Assignments +// Lists/Ternaries // ================================================================================ list1 = [ 1, @@ -126,10 +126,6 @@ undef; true ); - -// ================================================================================ -// Ternary -// ================================================================================ function affine3d_rot_from_to(from, to) = assert(is_vector(from)) assert(is_vector(to)) @@ -139,15 +135,20 @@ function affine3d_rot_from_to(from, to) = to = unit(point3d(to)) ) approx(from, to) ? affine3d_identity() : from.z == 0 && to.z == 0 ? affine3d_zrot(v_theta(point2d(to)) - v_theta(point2d(from))) - : let ( - u = vector_axis(from, to), + : let (u = vector_axis(from, to), ang = vector_angle(from, to), c = cos(ang), c2 = 1 - c, s = sin(ang) + // double indent a list preceded by list expression ) [ [1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1], ]; +// Prettier style ternaries https://prettier.io/blog/2023/11/13/curious-ternaries +x = foo() ? bar() + : baz() ? + qux() + : true; diff --git a/topiary-queries/queries/openscad.scm b/topiary-queries/queries/openscad.scm index 71051ed9..4b9ba811 100644 --- a/topiary-queries/queries/openscad.scm +++ b/topiary-queries/queries/openscad.scm @@ -113,6 +113,23 @@ "[" @append_indent_start @append_empty_softline @append_antispace "]" @prepend_indent_end @prepend_empty_softline @prepend_antispace ) +; to avoid having a list that directly follows a let_expression look visually unindented, +; add another level of indentation: +; let ( +; u = true, +; )[ +; [1, 0, 0, 0], +; [0, 1, 0, 0], +; [0, 0, 1, 0], +; [0, 0, 0, 1], +; ]; +(let_expression + (list + "[" @append_indent_start + "]" @prepend_indent_end + ) +) + (range "[" @append_antispace "]" @prepend_antispace @@ -310,3 +327,8 @@ (ternary_expression ":" @prepend_spaced_softline ) +; Prettier style ternaries https://prettier.io/blog/2023/11/13/curious-ternaries +(ternary_expression + "?" @append_input_softline @append_indent_start + ":" @prepend_indent_end +) From 4a72741e20f36b4c7a9b4bf8a9b88b54d2e230fa Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Tue, 21 Jan 2025 13:24:58 -0600 Subject: [PATCH 25/39] handled semicolon use statements --- topiary-cli/tests/samples/input/openscad.scad | 4 +- topiary-queries/queries/openscad.scm | 60 +++++++++++-------- 2 files changed, 37 insertions(+), 27 deletions(-) diff --git a/topiary-cli/tests/samples/input/openscad.scad b/topiary-cli/tests/samples/input/openscad.scad index 6a8bea78..4cc03816 100644 --- a/topiary-cli/tests/samples/input/openscad.scad +++ b/topiary-cli/tests/samples/input/openscad.scad @@ -1,8 +1,8 @@ // ================================================================================ // Basic Items // ================================================================================ -include -use +include ; +use ; include use // variables rr = a_vector[2]; // member of vector range1 = [-1.5:0.5:3]; // for() loop range diff --git a/topiary-queries/queries/openscad.scm b/topiary-queries/queries/openscad.scm index 4b9ba811..8f5ced84 100644 --- a/topiary-queries/queries/openscad.scm +++ b/topiary-queries/queries/openscad.scm @@ -75,7 +75,6 @@ ( [ (var_declaration) - (use_statement) (function_item) (module_item) (intersection_for_block) @@ -84,7 +83,7 @@ (let_block) (assign_block) (union_block) - (transform_chain ";" .) + (use_statement) (include_statement) (assert_statement) ] @append_spaced_softline @@ -139,10 +138,9 @@ (parameters "," @append_spaced_softline . [(block_comment) (line_comment)]* @do_nothing) (";" @append_spaced_softline . [(block_comment) (line_comment)]* @do_nothing) -; Never put a space before a comma or square bracket -( - "," @prepend_antispace -) +; Never put a space before a comma +("," @prepend_antispace) +(";" @prepend_antispace) ; Don't insert spaces between the operator and their expression operand ; '-x' v.s. '- x' @@ -174,35 +172,33 @@ ; ================================================================================ ; blocks/expressions/statements ; ================================================================================ +; Let child nodes handle indentation +(var_declaration . (assignment . (identifier) . "=" @append_input_softline)) + (assignments) @append_space (assignments + (#delimiter! ",") + (assignment) @append_delimiter . - "(" @append_empty_softline @append_indent_start - ")" @prepend_indent_end @prepend_empty_softline + ","? @do_nothing + . + (line_comment)* + . + ")" . + (#multi_line_only!) ) -(assignments "," @append_spaced_softline) -; indent variable newlines -(var_declaration +(assignments . - (assignment . (identifier) . "=" @append_indent_start @append_input_softline) - ";" @prepend_indent_end + "(" @append_empty_softline @append_indent_start + ")" @prepend_indent_end @prepend_empty_softline . ) +(assignments "," @delete . ")" . (#single_line_only!)) +(assignments "," @append_spaced_softline) (arguments "," @append_input_softline) (arguments "," @delete . ")" . (#single_line_only!)) -(list "," @delete . "]" . (#single_line_only!)) -(list - (_) @append_delimiter - . - ","? @do_nothing - . - "]" - . - (#delimiter! ",") - (#multi_line_only!) -) (arguments . "(" @append_empty_softline @append_indent_start @@ -211,12 +207,15 @@ ) (arguments (#delimiter! ",") - (_) @append_multiline_delimiter + (_) @append_delimiter . ","? @do_nothing . + (line_comment)* + . ")" . + (#multi_line_only!) ) (parameters "," @append_input_softline) @@ -234,6 +233,17 @@ ")" @prepend_indent_end @prepend_empty_softline . ) +(list "," @delete . "]" . (#single_line_only!)) +(list + (#delimiter! ",") + (_) @append_delimiter + . + ","? @do_nothing + . + "]" + . + (#multi_line_only!) +) ; differentiate parameter definitions from parameter invocation, ; module/function definitions have param separation while From fd4beeb0e49f9eddc65fb8a125cd08e126a8e117 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Tue, 21 Jan 2025 13:29:19 -0600 Subject: [PATCH 26/39] added comprehension cases --- topiary-cli/tests/samples/input/openscad.scad | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/topiary-cli/tests/samples/input/openscad.scad b/topiary-cli/tests/samples/input/openscad.scad index 4cc03816..8def5943 100644 --- a/topiary-cli/tests/samples/input/openscad.scad +++ b/topiary-cli/tests/samples/input/openscad.scad @@ -152,3 +152,20 @@ x = foo() ? bar() : baz() ? qux() : true; + +// ================================================================================ +// Comprehensions +// ================================================================================ +conditionless = [for (x = [1:10]) x]; +conditioned = [for (x = [1:10]) if ($preview) x]; +ifelse = [for (x = [1:10]) if ($preview) x else ln(x)]; +if_for_ifelse = [for (x = 0) if (x < 0) for (y = 2) if (y == 2) y else x]; +complex_condition = [ + for (x = [1:10]) if (x % 2 == 0) x else if (x < 5) x - 1 else 0 +]; +spliced = [for (x = [1:10]) x, for (y = [1, 2, 3]) y, for (z = [4, 5, 6]) z]; +nested = [for (x = [1:10]) for (y = [1, 2, 3]) for (z = [4, 5, 6]) x * y * z]; +grouped = [if (x < 7) (for (y = [1:10]) if (y > x) y) else x]; +let_each = [for(i = [0:1]) let(a=90) each arc(angle=a)]; +let_for = [let (i=[0:1]) for(i = i) let(a=90) each arc(angle=a)]; +let_if = [for(i = [0:1]) let(a=360) if (is_def(isect)) isect]; From 669bb4fd9d5d00389ec88858d3c8985de210fa3b Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Tue, 21 Jan 2025 13:51:33 -0600 Subject: [PATCH 27/39] added function literal test cases --- topiary-cli/tests/samples/input/openscad.scad | 16 +++++++++++++++- topiary-queries/queries/openscad.scm | 9 ++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/topiary-cli/tests/samples/input/openscad.scad b/topiary-cli/tests/samples/input/openscad.scad index 8def5943..2da0f902 100644 --- a/topiary-cli/tests/samples/input/openscad.scad +++ b/topiary-cli/tests/samples/input/openscad.scad @@ -11,6 +11,9 @@ $fn = 360; // special variable E = 2.71828182845904523536028747135266249775724709369995; // constant cond_var = "is_true" ? true : false; +// ================================================================================ +// Functions +// ================================================================================ function line(point1, point2, width = 1) = let (angle = 90 - atan((point2[1] - point1[1]) / (point2[0] - point1[0]))) @@ -22,6 +25,8 @@ function line(point1, point2, width = 1) = // [P1a, P2a, P2b, P1b] [point1 + offset1, point2 + offset1, point2 + offset2, point1 + offset2]; +eager = (function(z) identity)(4); + // ================================================================================ // Transformations // ================================================================================ @@ -100,7 +105,7 @@ translate() cube(); // ================================================================================ -// Assertions +// Assertions/Echoes // ================================================================================ assert(); assert(10 < 20) cube(); @@ -111,6 +116,14 @@ val = assert(true, "strut must be positive") assert(true, "frame must be nonnegative") undef; +function foo() = +echo("this can precede an expression") true; + + +fn = function(x) echo("this is x") x; +echo(fn ? "truthy" : "falsey"); +echo(function(y) y ? "first" : "second"); + // ================================================================================ // Lists/Ternaries // ================================================================================ @@ -169,3 +182,4 @@ grouped = [if (x < 7) (for (y = [1:10]) if (y > x) y) else x]; let_each = [for(i = [0:1]) let(a=90) each arc(angle=a)]; let_for = [let (i=[0:1]) for(i = i) let(a=90) each arc(angle=a)]; let_if = [for(i = [0:1]) let(a=360) if (is_def(isect)) isect]; +fn_list = [each function ()10]; diff --git a/topiary-queries/queries/openscad.scm b/topiary-queries/queries/openscad.scm index 8f5ced84..497ed253 100644 --- a/topiary-queries/queries/openscad.scm +++ b/topiary-queries/queries/openscad.scm @@ -24,6 +24,7 @@ (function_item) (module_item) (expression) + (var_declaration) ] @allow_blank_line_before ; Keywords @@ -31,7 +32,6 @@ ; Surround spaces [ "module" - "function" "let" "include" "assign" @@ -56,6 +56,8 @@ "=" "?" ":" + (parenthesized_expression) + (assignments) ] @prepend_space @append_space ; Colon should have whitespace trimmed in a range delimiter @@ -149,6 +151,7 @@ ; ================================================================================ ; functions & modules ; ================================================================================ +(function_item "function" @append_space) ; indent the body of a function (function_item @@ -342,3 +345,7 @@ "?" @append_input_softline @append_indent_start ":" @prepend_indent_end ) + +; function literals +(function_lit (parameters) @append_spaced_softline) +(function_call (parenthesized_expression) @append_antispace (arguments)) From 8809a240ef04c7b8e4f986a4148d9c45618ddd5d Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Tue, 21 Jan 2025 14:12:11 -0600 Subject: [PATCH 28/39] * Added README documentation for OpenSCAD * Added indentation for variables that start with assert/echo --- README.md | 2 + topiary-cli/tests/sample-tester.rs | 3 + .../tests/samples/expected/openscad.scad | 203 ++++++++++++++---- topiary-cli/tests/samples/input/openscad.scad | 2 +- topiary-config/languages.ncl | 5 +- topiary-config/languages_nix.ncl | 5 + topiary-queries/queries/openscad.scm | 22 +- 7 files changed, 198 insertions(+), 44 deletions(-) diff --git a/README.md b/README.md index 8d1abd9f..35a06e82 100644 --- a/README.md +++ b/README.md @@ -103,6 +103,7 @@ external contributors. They are built in, by default, so are exposed in the same way as supported languages. * [CSS] by @lavigneer +* [OpenSCAD] by @mkatychev #### Experimental @@ -1736,6 +1737,7 @@ of choice open in another. [ocamlformat]: https://github.com/ocaml-ppx/ocamlformat [ocamllex]: https://v2.ocaml.org/manual/lexyacc.html [ocp-indent]: https://www.typerex.org/ocp-indent.html +[openscad]: https://en.wikipedia.org/wiki/OpenSCAD [ormolu]: https://github.com/tweag/ormolu [prettier]: https://prettier.io/ [rust]: https://www.rust-lang.org diff --git a/topiary-cli/tests/sample-tester.rs b/topiary-cli/tests/sample-tester.rs index ebb69def..05766393 100644 --- a/topiary-cli/tests/sample-tester.rs +++ b/topiary-cli/tests/sample-tester.rs @@ -87,6 +87,9 @@ fn input_output_tester() { #[cfg(feature = "ocamllex")] io_test("ocamllex.mll"); + #[cfg(feature = "openscad")] + io_test("openscad.scad"); + #[cfg(feature = "rust")] io_test("rust.rs"); diff --git a/topiary-cli/tests/samples/expected/openscad.scad b/topiary-cli/tests/samples/expected/openscad.scad index 21d4a8f2..6aaa288e 100644 --- a/topiary-cli/tests/samples/expected/openscad.scad +++ b/topiary-cli/tests/samples/expected/openscad.scad @@ -1,40 +1,47 @@ +// ================================================================================ +// Variables/Imports +// ================================================================================ +include ; +use ; include use // variables -rr = a_vector[2]; // member of vector +rr = a_vector[2]; // member of vector range1 = [-1.5:0.5:3]; // for() loop range -xx = [0:5]; // alternate for() loop range - $fn = 360; // special variable +xx = [0:5]; // alternate for() loop range +$fn = 360; // special variable E = 2.71828182845904523536028747135266249775724709369995; // constant -cond_var ="is_true"?true:false; +cond_var = "is_true" ? true : false; +// ================================================================================ +// Functions +// ================================================================================ function line(point1, point2, width = 1) = -let(angle = 90 - atan((point2[1] - point1[1]) / (point2[0] - point1[0]))) + let (angle = 90 - atan( (point2[1] - point1[1]) / (point2[0] - point1[0]) )) -let(offset_x = 0.5 * width * cos(angle), offset_y = 0.5 * width * sin(angle)) + let (offset_x = 0.5 * width * cos(angle), offset_y = 0.5 * width * sin(angle)) -let(offset1 = [-offset_x, offset_y], offset2 = [offset_x, -offset_y]) + let (offset1 = [-offset_x, offset_y], offset2 = [offset_x, -offset_y]) -// [P1a, P2a, P2b, P1b] -[point1 + offset1, point2 + offset1, point2 + offset2, point1 + offset2]; + // [P1a, P2a, P2b, P1b] + [point1 + offset1, point2 + offset1, point2 + offset2, point1 + offset2]; +eager = (function(z) identity)(4); // ================================================================================ // Transformations // ================================================================================ cylinder(); -cylinder( - d=5, - h=100, -); - -rotate([90, 0, 0]) cylinder(); +cylinder(d=5, h=100); +rotate([90, 0, 0]) + cylinder(); translate([1, 0, 0]) { - difference() { - rotate([0, 90, 0]) cylinder(); - cube(); - } + difference() { + translate([0, 1, 0]) + translate([1, 0, 0]) rotate([0, 90, 0]) + cylinder(); cube(); + } } // ================================================================================ @@ -47,41 +54,65 @@ module big_module() { module extern_module() include -for (i = [10:50]) -{ - let (angle = i*360/20, r= i*2, distance = r*5) - { - rotate(angle, [1, 0, 0]) - translate([0, distance, 0]) - sphere(r = r); - } +// ================================================================================ +// Control Flow +// ================================================================================ +for (i = [10:50]) { + let (angle = i * 360 / 20, r = i * 2, distance = r * 5) { + rotate(angle, [1, 0, 0]) translate([0, distance, 0]) + sphere(r=r); + } } +// newline indent propagates from innermost if_block if ($preview) + if (true) + foo(); + else if (true) if (false) - sphere(); + foo(false); else - translate([2, 0, 0]) cube(); + translate([2, 0, 0]) foo(); + else + bar(); + +// format propagates from first union_block +if (true) { +} else if (fn(true)) { + foo(); +} else if (false) { + bar(); +} else { + baz(); +} for (i = [1:2:7]) { - let (x = i ^ 2, y = x - 1) { - translate([x, y, 0]) sphere(r = i); - } + let (x = i ^ 2, y = x - 1) { + translate([x, y, 0]) sphere(r=i); + } } intersection_for (i = [1, 2, 3]) { - if (i > 1) { - translate([0, i, 0]) cube(); - } + if (i > 1) { + translate([0, i, 0]) cube(); + } else { + translate([0, i, 0]) cube(); + } } // ================================================================================ // Comments // ================================================================================ -/* ignored [Customizer Group] ignored */ -my_parameter = 5; -function math(x) = /*do math stuff*/ x + 2 // done with math +/* ignored [Customizer Group] ignored */ +/* Multiline +comment +here +*/ +my_parameter = /*inline block*/ 5; + +function math(x) = + /*do math stuff*/ x + 2 // done with math ; module my_cylinder() { @@ -90,3 +121,99 @@ module my_cylinder() { cube(); } +// ================================================================================ +// Modifiers +// ================================================================================ +!cylinder(); +*linear_extrude(4) text("Hello"); +rotate([0, 90, 0]) #cylinder(); +%cube(); +// multi modifier +translate(1) #!cube(); +rotate([90]) %translate() + #cube(); + +// ================================================================================ +// Assertions/Echoes +// ================================================================================ +assert(); +assert(10 < 20) cube(); +for (y = [3:5]) + assert(assert() y < x, "message") + cylinder(); +assert(true) assert() cylinder(); +val = + assert(true, "strut must be positive") + assert(true, "frame must be nonnegative") + undef; + +function foo() = + echo("this can precede an expression") true; + +fn = function(x) echo("this is x") x; +echo(fn ? "truthy" : "falsey"); +echo(function(y) y ? "first" : "second"); + +// ================================================================================ +// Lists/Ternaries +// ================================================================================ +list1 = [ + 1, + 2, + 3, +]; +my_fn = fn1( + [ + 1, + 2, + 3, + ], + true, +); + +function affine3d_rot_from_to(from, to) = + assert(is_vector(from)) + assert(is_vector(to)) + assert(len(from) == len(to)) + let ( + from = unit(point3d(from)), + to = unit(point3d(to)), + ) approx(from, to) ? affine3d_identity() + : from.z == 0 && to.z == 0 ? affine3d_zrot(v_theta(point2d(to)) - v_theta(point2d(from))) + : let ( + u = vector_axis(from, to), + ang = vector_angle(from, to), + c = cos(ang), + c2 = 1 - c, + s = sin(ang), + // double indent a list preceded by list expression + ) [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [0, 0, 0, 1], + ]; + +// Prettier style ternaries https://prettier.io/blog/2023/11/13/curious-ternaries +x = foo() ? bar() +: baz() ? + qux() +: true; + +// ================================================================================ +// Comprehensions +// ================================================================================ +conditionless = [for (x = [1:10]) x]; +conditioned = [for (x = [1:10]) if ($preview) x]; +ifelse = [for (x = [1:10]) if ($preview) x else ln(x)]; +if_for_ifelse = [for (x = 0) if (x < 0) for (y = 2) if (y == 2) y else x]; +complex_condition = [ + for (x = [1:10]) if (x % 2 == 0) x else if (x < 5) x - 1 else 0, +]; +spliced = [for (x = [1:10]) x, for (y = [1, 2, 3]) y, for (z = [4, 5, 6]) z]; +nested = [for (x = [1:10]) for (y = [1, 2, 3]) for (z = [4, 5, 6]) x * y * z]; +grouped = [if (x < 7) (for (y = [1:10]) if (y > x) y) else x]; +let_each = [for (i = [0:1]) let (a = 90) each arc(angle=a)]; +let_for = [let (i = [0:1]) for (i = i) let (a = 90) each arc(angle=a)]; +let_if = [for (i = [0:1]) let (a = 360) if (is_def(isect)) isect]; +fn_list = [each function() 10]; diff --git a/topiary-cli/tests/samples/input/openscad.scad b/topiary-cli/tests/samples/input/openscad.scad index 2da0f902..a761f7b6 100644 --- a/topiary-cli/tests/samples/input/openscad.scad +++ b/topiary-cli/tests/samples/input/openscad.scad @@ -1,5 +1,5 @@ // ================================================================================ -// Basic Items +// Variables/Imports // ================================================================================ include ; use ; include use diff --git a/topiary-config/languages.ncl b/topiary-config/languages.ncl index fc1fc50f..f731af0d 100644 --- a/topiary-config/languages.ncl +++ b/topiary-config/languages.ncl @@ -75,7 +75,10 @@ openscad = { extensions = ["scad"], - grammar.source.path = "/Users/mkatychev/Documents/tree-sitter/openscad/parser.so", + grammar.source.git = { + git = "https://github.com/mkatychev/tree-sitter-openscad.git", + rev = "1b3e5fd00245c097f501532611f349c88d5b334b", + }, }, rust = { diff --git a/topiary-config/languages_nix.ncl b/topiary-config/languages_nix.ncl index 57c71c26..a4e85bbc 100644 --- a/topiary-config/languages_nix.ncl +++ b/topiary-config/languages_nix.ncl @@ -10,6 +10,11 @@ grammar.source.path = "@css@", }, + openscad = { + extensions = ["scad"], + grammar.source.path = "@openscad@", + }, + json = { extensions = [ "json", diff --git a/topiary-queries/queries/openscad.scm b/topiary-queries/queries/openscad.scm index 497ed253..97050db4 100644 --- a/topiary-queries/queries/openscad.scm +++ b/topiary-queries/queries/openscad.scm @@ -162,6 +162,10 @@ ";" @prepend_indent_end ) +; function literals +(function_lit (parameters) @append_spaced_softline) +(function_call (parenthesized_expression) @append_antispace (arguments)) + ; module calls in a transformation chain will follow each other ; sometimes staying on the same line and sometimes having a linebreak, ; each linebreak typically also starts an indent scope @@ -175,6 +179,7 @@ ; ================================================================================ ; blocks/expressions/statements ; ================================================================================ + ; Let child nodes handle indentation (var_declaration . (assignment . (identifier) . "=" @append_input_softline)) @@ -332,6 +337,19 @@ ; modifiers (modifier) @append_antispace +; echo/assert statements can often be chained, use indentation on assignment +(var_declaration + (assignment + "=" @append_spaced_softline + value: [ + (assert_expression) + (echo_expression) + ] @prepend_indent_start + ) + ";" @prepend_indent_end + . +) + (assert_expression expression: (_) @prepend_spaced_softline) (assert_statement statement: (_) @prepend_spaced_softline) (echo_expression expression: (_) @prepend_spaced_softline) @@ -345,7 +363,3 @@ "?" @append_input_softline @append_indent_start ":" @prepend_indent_end ) - -; function literals -(function_lit (parameters) @append_spaced_softline) -(function_call (parenthesized_expression) @append_antispace (arguments)) From dabdc42dcea522ded2c9462587ba6df7331f1993 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Tue, 21 Jan 2025 14:17:03 -0600 Subject: [PATCH 29/39] added wasm update and CHANGELOG --- CHANGELOG.md | 1 + bin/update-wasm-grammars.sh | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e22547a1..288d33e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,7 @@ This name should be decided amongst the team before the release. - [#785](https://github.com/tweag/topiary/pull/785) Added the `coverage` command, that checks how much of the query file is used by the input. - [#786](https://github.com/tweag/topiary/pull/786) Re-introduce tests to check that all of the language queries are useful. - [#747](https://github.com/tweag/topiary/pull/747) Added support for specifying paths to prebuilt grammars in Topiary's configuration +- [#845](https://github.com/tweag/topiary/pull/747) Added support for OpenSCAD, @mkatychev ### Changed - [#794](https://github.com/tweag/topiary/pull/794) Bump the `tree-sitter` dependency to 0.24 @ZedThree diff --git a/bin/update-wasm-grammars.sh b/bin/update-wasm-grammars.sh index e02a953e..23f0ad57 100755 --- a/bin/update-wasm-grammars.sh +++ b/bin/update-wasm-grammars.sh @@ -153,7 +153,20 @@ css() { echo -e "${GREEN}CSS: Done${NC}" } +openscad() { + echo -e "${BLUE}OpenSCAD: Fetching${NC}" + REPO=$(repo_for_language "openscad") + git clone "${REPO}" "${WORKDIR}/tree-sitter-openscad" &> /dev/null + REV=$(ref_for_language "opescad") + pushd "${WORKDIR}/tree-sitter-openscad" &> /dev/null + git checkout "$REV" &> /dev/null + popd &> /dev/null + echo -e "${ORANGE}OpenSCAD: Building${NC}" + tree-sitter build --wasm "${WORKDIR}/tree-sitter-openscad" + echo -e "${GREEN}OpenSCAD: Done${NC}" +} + -(trap 'kill 0' SIGINT; json & nickel & ocaml & ocamllex & bash & rust & toml & tree-sitter-query & css & wait) +(trap 'kill 0' SIGINT; json & nickel & ocaml & ocamllex & bash & rust & toml & tree-sitter-query & css & openscad & wait) echo -e "${GREEN}Done! All grammars have been updated${NC}" From 7afe496065b18c12dff8631e8e6a5e94979e19f4 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Tue, 21 Jan 2025 14:31:57 -0600 Subject: [PATCH 30/39] Cargo.lock update --- Cargo.lock | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1a2ad7c8..4c493615 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -262,9 +262,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.9" +version = "1.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8293772165d9345bdaaa39b45b2109591e63fe5e6fbc23c6ff930a048aa310b" +checksum = "13208fcbb66eaeffe09b99fffbe1af420f00a7b35aa99ad683dfc1aa76145229" dependencies = [ "shlex", ] @@ -304,9 +304,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.26" +version = "4.5.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8eb5e908ef3a6efbe1ed62520fb7287959888c88485abe072543190ecc66783" +checksum = "769b0145982b4b48713e01ec42d61614425f27b7058bda7180a3a41f30104796" dependencies = [ "clap_builder", "clap_derive", @@ -314,9 +314,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.26" +version = "4.5.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96b01801b5fc6a0a232407abc821660c9c6d25a1cafc0d4f85f29fb8d9afc121" +checksum = "1b26884eb4b57140e4d2d93652abfa49498b938b3c9179f9fc487b0acc3edad7" dependencies = [ "anstream", "anstyle", @@ -1004,9 +1004,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.7.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" +checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" dependencies = [ "equivalent", "hashbrown 0.15.2", @@ -1433,7 +1433,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.7.0", + "indexmap 2.7.1", ] [[package]] @@ -1735,9 +1735,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "semver" -version = "1.0.24" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" +checksum = "f79dfe2d285b0488816f30e700a7438c5a73d816b5b7d3ac72fbc48b0d185e03" dependencies = [ "serde", ] @@ -1775,11 +1775,11 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.135" +version = "1.0.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b0d7ba2887406110130a978386c4e1befb98c674b4fba677954e4db976630d9" +checksum = "930cfb6e6abf99298aaad7d29abbef7a9999a9a8806a40088f55f0dcec03146b" dependencies = [ - "indexmap 2.7.0", + "indexmap 2.7.1", "itoa", "memchr", "ryu", @@ -1801,7 +1801,7 @@ version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.7.0", + "indexmap 2.7.1", "itoa", "ryu", "serde", @@ -2003,9 +2003,9 @@ checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683" [[package]] name = "test-log" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dffced63c2b5c7be278154d76b479f9f9920ed34e7574201407f0b14e2bbb93" +checksum = "e7f46083d221181166e5b6f6b1e5f1d499f3a76888826e6cb1d057554157cd0f" dependencies = [ "env_logger 0.11.6", "test-log-macros", @@ -2014,9 +2014,9 @@ dependencies = [ [[package]] name = "test-log-macros" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5999e24eaa32083191ba4e425deb75cdf25efefabe5aaccb7446dd0d4122a3f5" +checksum = "888d0c3c6db53c0fdab160d2ed5e12ba745383d3e85813f2ea0f2b1475ab553f" dependencies = [ "proc-macro2", "quote", @@ -2167,7 +2167,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.7.0", + "indexmap 2.7.1", "serde", "serde_spanned", "toml_datetime", @@ -2180,7 +2180,7 @@ version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ - "indexmap 2.7.0", + "indexmap 2.7.1", "serde", "serde_spanned", "toml_datetime", @@ -2509,9 +2509,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "valuable" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" [[package]] name = "version_check" From 1c88871eecdbe48b530ff60f5269f372f8a9d56b Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Wed, 22 Jan 2025 01:16:28 -0600 Subject: [PATCH 31/39] revert rust changes --- Cargo.lock | 10 ++-- Cargo.toml | 2 +- topiary-core/src/atom_collection.rs | 86 +++++++++-------------------- 3 files changed, 33 insertions(+), 65 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4c493615..ff52dc2b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1020,13 +1020,13 @@ checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" [[package]] name = "is-terminal" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" +checksum = "3f187290c0ed3dfe3f7c85bedddd320949b68fc86ca0ceb71adfb05b3dc3af2a" dependencies = [ "hermit-abi", "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1689,9 +1689,9 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustix" -version = "0.38.43" +version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a78891ee6bf2340288408954ac787aa063d8e8817e9f53abb37c695c6d834ef6" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ "bitflags", "errno", diff --git a/Cargo.toml b/Cargo.toml index a9dba0b9..6da14519 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,7 +62,7 @@ futures = "0.3.28" itertools = "0.11" js-sys = "0.3" libloading = "0.8.4" -log = { version = "0.4", features = ["kv"] } +log = "0.4" nickel-lang-core = { version = "0.8.0", default-features = false } predicates = "3.0" pretty_assertions = "1.3" diff --git a/topiary-core/src/atom_collection.rs b/topiary-core/src/atom_collection.rs index 8c075f2a..a1e6d64f 100644 --- a/topiary-core/src/atom_collection.rs +++ b/topiary-core/src/atom_collection.rs @@ -226,15 +226,6 @@ impl AtomCollection { node, predicates, ), - "append_multiline_delimiter" => { - if self.in_multiline_context(node) { - self.append( - Atom::Literal(requires_delimiter()?.to_string()), - node, - predicates, - ) - } - } "append_empty_softline" => { self.append(Atom::Softline { spaced: false }, node, predicates); } @@ -260,15 +251,6 @@ impl AtomCollection { node, predicates, ), - "prepend_multiline_delimiter" => { - if self.in_multiline_context(node) { - self.prepend( - Atom::Literal(requires_delimiter()?.to_string()), - node, - predicates, - ) - } - } "prepend_empty_softline" => { self.prepend(Atom::Softline { spaced: false }, node, predicates); } @@ -609,22 +591,6 @@ impl AtomCollection { self.append.entry(target_node.id()).or_default().push(atom); } - /// Indicates whether we are in a multiline context or not. - /// # Arguments - /// - /// * `node` - The node to which the atom applies. - /// # Returns - /// - /// A boolean indicating whether a given node has a a parent labelled as multi-line. - /// If the provided node has no parent, the function returns `false`. - fn in_multiline_context(&self, node: &Node) -> bool { - let parent_id = node.parent().map(|p| p.id()); - - parent_id - .map(|pid| self.multi_line_nodes.contains(&pid)) - .unwrap_or(false) - } - /// Expands a softline atom to a hardline, space or empty atom depending on /// if we are in a multiline context or not. /// @@ -646,32 +612,34 @@ impl AtomCollection { /// /// A new atom after expanding the softline if applicable. fn expand_multiline(&self, atom: Atom, node: &Node) -> Atom { - let Atom::Softline { spaced } = atom else { - return atom; - }; - let Some(parent) = node.parent() else { - return Atom::Empty; - }; - let parent_id = parent.id(); - - if self.multi_line_nodes.contains(&parent_id) { - log::debug!( - parent_id; - "Expanding softline to hardline in node {}: {}", - node.display_one_based(), - parent.display_one_based() - ); - Atom::Hardline - } else if spaced { - log::debug!( - parent_id; - "Expanding softline to space in node {}: {}", - node.display_one_based(), - parent.display_one_based() - ); - Atom::Space + if let Atom::Softline { spaced } = atom { + if let Some(parent) = node.parent() { + let parent_id = parent.id(); + + if self.multi_line_nodes.contains(&parent_id) { + log::debug!( + "Expanding softline to hardline in node {} with parent {}: {}", + node.display_one_based(), + parent_id, + parent.display_one_based() + ); + Atom::Hardline + } else if spaced { + log::debug!( + "Expanding softline to space in node {} with parent {}: {}", + node.display_one_based(), + parent_id, + parent.display_one_based() + ); + Atom::Space + } else { + Atom::Empty + } + } else { + Atom::Empty + } } else { - Atom::Empty + atom } } From 0ce5fa024dd07563fb78f08954c1afbcad0bc925 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Wed, 22 Jan 2025 01:19:57 -0600 Subject: [PATCH 32/39] revision for query lib docstring --- topiary-queries/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/topiary-queries/src/lib.rs b/topiary-queries/src/lib.rs index af3b7d86..c7d3bbd8 100644 --- a/topiary-queries/src/lib.rs +++ b/topiary-queries/src/lib.rs @@ -40,7 +40,7 @@ pub fn ocamllex() -> &'static str { include_str!("../queries/ocamllex.scm") } -/// Returns the Topiary-compatible query file for Ocamllex. +/// Returns the Topiary-compatible query file for OpenSCAD. #[cfg(feature = "openscad")] pub fn openscad() -> &'static str { include_str!("../queries/openscad.scm") From 93b91075cd80889d3c4f511387fc100dd213afc6 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Wed, 22 Jan 2025 15:04:56 -0600 Subject: [PATCH 33/39] * Added openscad formatting query for handling indentaiton of `module_item` bodies that are not `union_block`s * Added support for `tree-sitter-openscad` flake --- Cargo.lock | 58 +++---- README.md | 2 +- default.nix | 7 +- flake.nix | 8 +- topiary-cli/tests/samples/input/openscad.scad | 148 +++++++++++------- topiary-config/languages.ncl | 7 +- topiary-queries/queries/openscad.scm | 22 ++- 7 files changed, 157 insertions(+), 95 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ff52dc2b..db88fcf5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 4 +version = 3 [[package]] name = "addr2line" @@ -262,9 +262,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.10" +version = "1.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13208fcbb66eaeffe09b99fffbe1af420f00a7b35aa99ad683dfc1aa76145229" +checksum = "c8293772165d9345bdaaa39b45b2109591e63fe5e6fbc23c6ff930a048aa310b" dependencies = [ "shlex", ] @@ -304,9 +304,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.27" +version = "4.5.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "769b0145982b4b48713e01ec42d61614425f27b7058bda7180a3a41f30104796" +checksum = "a8eb5e908ef3a6efbe1ed62520fb7287959888c88485abe072543190ecc66783" dependencies = [ "clap_builder", "clap_derive", @@ -314,9 +314,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.27" +version = "4.5.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b26884eb4b57140e4d2d93652abfa49498b938b3c9179f9fc487b0acc3edad7" +checksum = "96b01801b5fc6a0a232407abc821660c9c6d25a1cafc0d4f85f29fb8d9afc121" dependencies = [ "anstream", "anstyle", @@ -1004,9 +1004,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.7.1" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", "hashbrown 0.15.2", @@ -1020,13 +1020,13 @@ checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" [[package]] name = "is-terminal" -version = "0.4.14" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f187290c0ed3dfe3f7c85bedddd320949b68fc86ca0ceb71adfb05b3dc3af2a" +checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" dependencies = [ "hermit-abi", "libc", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -1433,7 +1433,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.7.1", + "indexmap 2.7.0", ] [[package]] @@ -1689,9 +1689,9 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustix" -version = "0.38.44" +version = "0.38.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +checksum = "a78891ee6bf2340288408954ac787aa063d8e8817e9f53abb37c695c6d834ef6" dependencies = [ "bitflags", "errno", @@ -1735,9 +1735,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "semver" -version = "1.0.25" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f79dfe2d285b0488816f30e700a7438c5a73d816b5b7d3ac72fbc48b0d185e03" +checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" dependencies = [ "serde", ] @@ -1775,11 +1775,11 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.137" +version = "1.0.135" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "930cfb6e6abf99298aaad7d29abbef7a9999a9a8806a40088f55f0dcec03146b" +checksum = "2b0d7ba2887406110130a978386c4e1befb98c674b4fba677954e4db976630d9" dependencies = [ - "indexmap 2.7.1", + "indexmap 2.7.0", "itoa", "memchr", "ryu", @@ -1801,7 +1801,7 @@ version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.7.1", + "indexmap 2.7.0", "itoa", "ryu", "serde", @@ -2003,9 +2003,9 @@ checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683" [[package]] name = "test-log" -version = "0.2.17" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7f46083d221181166e5b6f6b1e5f1d499f3a76888826e6cb1d057554157cd0f" +checksum = "3dffced63c2b5c7be278154d76b479f9f9920ed34e7574201407f0b14e2bbb93" dependencies = [ "env_logger 0.11.6", "test-log-macros", @@ -2014,9 +2014,9 @@ dependencies = [ [[package]] name = "test-log-macros" -version = "0.2.17" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "888d0c3c6db53c0fdab160d2ed5e12ba745383d3e85813f2ea0f2b1475ab553f" +checksum = "5999e24eaa32083191ba4e425deb75cdf25efefabe5aaccb7446dd0d4122a3f5" dependencies = [ "proc-macro2", "quote", @@ -2167,7 +2167,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.7.1", + "indexmap 2.7.0", "serde", "serde_spanned", "toml_datetime", @@ -2180,7 +2180,7 @@ version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ - "indexmap 2.7.1", + "indexmap 2.7.0", "serde", "serde_spanned", "toml_datetime", @@ -2509,9 +2509,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "valuable" -version = "0.1.1" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "version_check" diff --git a/README.md b/README.md index d88f0f28..5fc8a580 100644 --- a/README.md +++ b/README.md @@ -1461,7 +1461,7 @@ The two following steps are enough to jumpstart the formatting of a new language ```nickel c = { extensions = ["c", "h"], - grammar = { + grammar.source.git = { git = "https://github.com/tree-sitter/tree-sitter-c.git", rev = "6c7f459ddc0bcf78b615d3a3f4e8fed87b8b3b1b", }, diff --git a/default.nix b/default.nix index 32f8af3f..4a0ac495 100644 --- a/default.nix +++ b/default.nix @@ -4,11 +4,13 @@ , crane , rust-overlay , craneLib -# tree-sitter-Nickel is packaged in Nixpkgs, but it's an older version at the +# tree-sitter-nickel is packaged in Nixpkgs, but it's an older version at the # time of writing. Since updating it seems non trivial, and we need Topiary to # be compatible with Nickel urgently (it is currently blocking for the CI), we # use the tree-sitter-nickel flake directly. , tree-sitter-nickel +# tree-sitter-openscad is not in nixpkgs so use flake directly +, tree-sitter-openscad }: let inherit (pkgs.lib) fileset; @@ -120,7 +122,7 @@ in preConfigurePhases = pkgs.lib.optional nixSupport "useNixConfiguration"; - # ocamllex is not (yet) packaged in nixpkgs + # ocamllex is not (yet) packaged in nixpkgs: # ocamllex="${pkgs.tree-sitter-grammars.tree-sitter-ocamllex}/parser" \ useNixConfiguration = '' bash="${pkgs.tree-sitter-grammars.tree-sitter-bash}/parser" \ @@ -129,6 +131,7 @@ in nickel="${tree-sitter-nickel}/parser" \ ocaml="${pkgs.tree-sitter-grammars.tree-sitter-ocaml}/parser" \ ocaml_interface="${pkgs.tree-sitter-grammars.tree-sitter-ocaml-interface}/parser" \ + openscad="${tree-sitter-openscad}/parser" \ rust="${pkgs.tree-sitter-grammars.tree-sitter-rust}/parser" \ toml="${pkgs.tree-sitter-grammars.tree-sitter-toml}/parser" \ tree_sitter_query="${pkgs.tree-sitter-grammars.tree-sitter-query}/parser" \ diff --git a/flake.nix b/flake.nix index 7cd64b87..63e279f4 100644 --- a/flake.nix +++ b/flake.nix @@ -29,6 +29,11 @@ url = "github:nickel-lang/tree-sitter-nickel"; inputs.nixpkgs.follows = "nixpkgs"; }; + + tree-sitter-openscad = { + url = "github:mkatychev/tree-sitter-openscad"; + inputs.nixpkgs.follows = "nixpkgs"; + }; }; outputs = { self, nixpkgs, ... }@inputs: @@ -47,7 +52,7 @@ topiaryPkgs = pkgs.callPackage ./default.nix { inherit (inputs) advisory-db crane rust-overlay; - inherit (pkgs.tree-sitter-grammars) tree-sitter-nickel; + inherit (pkgs.tree-sitter-grammars) tree-sitter-nickel tree-sitter-openscad; craneLib = inputs.crane.mkLib pkgs; }; @@ -67,6 +72,7 @@ # Nickel *should* have an overlay like this already tree-sitter-grammars = prev.tree-sitter-grammars // { tree-sitter-nickel = inputs.tree-sitter-nickel.packages.${prev.system}.default; + tree-sitter-openscad = inputs.tree-sitter-openscad.packages.${prev.system}.default; }; }; diff --git a/topiary-cli/tests/samples/input/openscad.scad b/topiary-cli/tests/samples/input/openscad.scad index a761f7b6..54bfc562 100644 --- a/topiary-cli/tests/samples/input/openscad.scad +++ b/topiary-cli/tests/samples/input/openscad.scad @@ -2,7 +2,9 @@ // Variables/Imports // ================================================================================ include ; -use ; include use +use ; +include +use // variables rr = a_vector[2]; // member of vector range1 = [-1.5:0.5:3]; // for() loop range @@ -16,11 +18,11 @@ cond_var = "is_true" ? true : false; // ================================================================================ function line(point1, point2, width = 1) = - let (angle = 90 - atan((point2[1] - point1[1]) / (point2[0] - point1[0]))) + let (angle = 90 - atan( (point2[1] - point1[1]) / (point2[0] - point1[0]) )) let (offset_x = 0.5 * width * cos(angle), offset_y = 0.5 * width * sin(angle)) - let (offset1 = [ -offset_x, offset_y], offset2 = [offset_x, -offset_y]) + let (offset1 = [-offset_x, offset_y], offset2 = [offset_x, -offset_y]) // [P1a, P2a, P2b, P1b] [point1 + offset1, point2 + offset1, point2 + offset2, point1 + offset2]; @@ -31,18 +33,23 @@ eager = (function(z) identity)(4); // Transformations // ================================================================================ cylinder(); -cylinder( d = 5, h=100,); +cylinder(d=5, h=100); rotate([90, 0, 0]) -cylinder(); + cylinder(); translate([1, 0, 0]) { - difference() { translate([0, 1, 0]) - translate([1, 0, 0]) rotate([0, 90, 0]) - cylinder(); cube(); } } + difference() { + translate([0, 1, 0]) + translate([1, 0, 0]) rotate([0, 90, 0]) + cylinder(); cube(); + } +} // ================================================================================ // Nested Items // ================================================================================ -module big_module() { function inner_function() = undef; module inner_module() cube(); +module big_module() { + function inner_function() = undef; + module inner_module() cube(); } module extern_module() include @@ -50,25 +57,48 @@ module extern_module() include // ================================================================================ // Control Flow // ================================================================================ -for (i = [10:50]) { let (angle = i*360/20, r= i*2, distance = r*5) { +for (i = [10:50]) { + let (angle = i * 360 / 20, r = i * 2, distance = r * 5) { rotate(angle, [1, 0, 0]) translate([0, distance, 0]) - sphere(r = r); } + sphere(r=r); + } } // newline indent propagates from innermost if_block -if ($preview) if(true) foo(); else if(true) if - (false) foo(false); else translate([2,0,0]) foo(); else bar(); +if ($preview) + if (true) + foo(); + else if (true) + if (false) + foo(false); + else + translate([2, 0, 0]) foo(); + else + bar(); // format propagates from first union_block if (true) { - } else if (fn(true)) { foo();} else if (false) { bar();} else { baz(); } - +} else if (fn(true)) { + foo(); +} else if (false) { + bar(); +} else { + baz(); +} -for(i = [1:2:7]) { let (x = i ^ 2,y = x - 1) { - translate([x,y,0]) sphere(r=i); } } +for (i = [1:2:7]) { + let (x = i ^ 2, y = x - 1) { + translate([x, y, 0]) sphere(r=i); + } +} -intersection_for(i = [1,2,3]) { if (i > 1) { - translate([0,i,0]) cube(); } else { translate([0,i,0]) cube(); } } +intersection_for (i = [1, 2, 3]) { + if (i > 1) { + translate([0, i, 0]) cube(); + } else { + translate([0, i, 0]) cube(); + } +} // ================================================================================ // Comments @@ -81,7 +111,8 @@ here */ my_parameter = /*inline block*/ 5; -function math(x) = /*do math stuff*/ x + 2 // done with math +function math(x) = + /*do math stuff*/ x + 2 // done with math ; module my_cylinder() { @@ -94,31 +125,30 @@ module my_cylinder() { // Modifiers // ================================================================================ !cylinder(); -* linear_extrude(4) text("Hello"); -rotate([0,90,0])# cylinder(); +*linear_extrude(4) text("Hello"); +rotate([0, 90, 0]) #cylinder(); %cube(); // multi modifier -translate(1) # ! cube(); -rotate([90]) % -translate() -# -cube(); +translate(1) #!cube(); +rotate([90]) %translate() + #cube(); // ================================================================================ // Assertions/Echoes // ================================================================================ assert(); assert(10 < 20) cube(); -for(y = [3:5]) assert(assert() y < x, "message") +for (y = [3:5]) + assert(assert() y < x, "message") cylinder(); assert(true) assert() cylinder(); -val = assert(true, "strut must be positive") -assert(true, "frame must be nonnegative") -undef; +val = + assert(true, "strut must be positive") + assert(true, "frame must be nonnegative") + undef; function foo() = -echo("this can precede an expression") true; - + echo("this can precede an expression") true; fn = function(x) echo("this is x") x; echo(fn ? "truthy" : "falsey"); @@ -127,17 +157,19 @@ echo(function(y) y ? "first" : "second"); // ================================================================================ // Lists/Ternaries // ================================================================================ - list1 = [ +list1 = [ + 1, + 2, + 3, +]; +my_fn = fn1( + [ 1, - 2, 3 - ]; - my_fn = fn1([ - 1, - 2, - 3, - ], - true - ); + 2, + 3, + ], + true, +); function affine3d_rot_from_to(from, to) = assert(is_vector(from)) @@ -145,25 +177,27 @@ function affine3d_rot_from_to(from, to) = assert(len(from) == len(to)) let ( from = unit(point3d(from)), - to = unit(point3d(to)) + to = unit(point3d(to)), ) approx(from, to) ? affine3d_identity() : from.z == 0 && to.z == 0 ? affine3d_zrot(v_theta(point2d(to)) - v_theta(point2d(from))) - : let (u = vector_axis(from, to), + : let ( + u = vector_axis(from, to), ang = vector_angle(from, to), c = cos(ang), c2 = 1 - c, - s = sin(ang) + s = sin(ang), // double indent a list preceded by list expression ) [ - [1, 0, 0, 0], - [0, 1, 0, 0], - [0, 0, 1, 0], - [0, 0, 0, 1], + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [0, 0, 0, 1], ]; // Prettier style ternaries https://prettier.io/blog/2023/11/13/curious-ternaries -x = foo() ? bar() +x = + foo() ? bar() : baz() ? - qux() + qux() : true; // ================================================================================ @@ -174,12 +208,12 @@ conditioned = [for (x = [1:10]) if ($preview) x]; ifelse = [for (x = [1:10]) if ($preview) x else ln(x)]; if_for_ifelse = [for (x = 0) if (x < 0) for (y = 2) if (y == 2) y else x]; complex_condition = [ - for (x = [1:10]) if (x % 2 == 0) x else if (x < 5) x - 1 else 0 + for (x = [1:10]) if (x % 2 == 0) x else if (x < 5) x - 1 else 0, ]; spliced = [for (x = [1:10]) x, for (y = [1, 2, 3]) y, for (z = [4, 5, 6]) z]; nested = [for (x = [1:10]) for (y = [1, 2, 3]) for (z = [4, 5, 6]) x * y * z]; grouped = [if (x < 7) (for (y = [1:10]) if (y > x) y) else x]; -let_each = [for(i = [0:1]) let(a=90) each arc(angle=a)]; -let_for = [let (i=[0:1]) for(i = i) let(a=90) each arc(angle=a)]; -let_if = [for(i = [0:1]) let(a=360) if (is_def(isect)) isect]; -fn_list = [each function ()10]; +let_each = [for (i = [0:1]) let (a = 90) each arc(angle=a)]; +let_for = [let (i = [0:1]) for (i = i) let (a = 90) each arc(angle=a)]; +let_if = [for (i = [0:1]) let (a = 360) if (is_def(isect)) isect]; +fn_list = [each function() 10]; diff --git a/topiary-config/languages.ncl b/topiary-config/languages.ncl index f731af0d..8194a89a 100644 --- a/topiary-config/languages.ncl +++ b/topiary-config/languages.ncl @@ -75,10 +75,9 @@ openscad = { extensions = ["scad"], - grammar.source.git = { - git = "https://github.com/mkatychev/tree-sitter-openscad.git", - rev = "1b3e5fd00245c097f501532611f349c88d5b334b", - }, + grammar.source | priority 1 = { + path = "/Users/mkatychev/Documents/tree-sitter/openscad/parser.dylib", + } }, rust = { diff --git a/topiary-queries/queries/openscad.scm b/topiary-queries/queries/openscad.scm index 97050db4..c17eba9b 100644 --- a/topiary-queries/queries/openscad.scm +++ b/topiary-queries/queries/openscad.scm @@ -162,10 +162,30 @@ ";" @prepend_indent_end ) +; === ; function literals +; === (function_lit (parameters) @append_spaced_softline) (function_call (parenthesized_expression) @append_antispace (arguments)) +; === +; module_item, module_call, and transform_chain +; === + +; everything except `union_block` after a for/if/else statement should be a spaced_softline +(module_item + body: [ + (for_block) + (intersection_for_block) + (if_block) + (let_block) + (assign_block) + (transform_chain) + (include_statement) + (assert_statement) + ] @prepend_indent_start @append_indent_end +) + ; module calls in a transformation chain will follow each other ; sometimes staying on the same line and sometimes having a linebreak, ; each linebreak typically also starts an indent scope @@ -272,7 +292,6 @@ ) ; everything except `union_block` after a for/if/else statement should be a spaced_softline -; but a union (if_block (parenthesized_expression) @append_spaced_softline @append_indent_start . @@ -344,6 +363,7 @@ value: [ (assert_expression) (echo_expression) + (ternary_expression) ] @prepend_indent_start ) ";" @prepend_indent_end From e5324bc999c7bfdf2f6f2d52cbbd7f9dd5f11f9d Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Wed, 22 Jan 2025 15:06:21 -0600 Subject: [PATCH 34/39] nix flake update --- flake.lock | 94 ++++++++++++++++++++++-------------------------------- 1 file changed, 38 insertions(+), 56 deletions(-) diff --git a/flake.lock b/flake.lock index 0e645f9a..03d8cb00 100644 --- a/flake.lock +++ b/flake.lock @@ -3,11 +3,11 @@ "advisory-db": { "flake": false, "locked": { - "lastModified": 1723137097, - "narHash": "sha256-Q/TeuIV610BJ39UkP4zRm6pG6BWEaOCih/WXNR2V9rk=", + "lastModified": 1737565911, + "narHash": "sha256-WxIWw1mSPJVU1JfIcTdIubU5UoIwwR8h7UcXop/6htg=", "owner": "rustsec", "repo": "advisory-db", - "rev": "1d209d3f18c740f104380e988b5aa8eb360190d1", + "rev": "ffa26704690a3dc403edcd94baef103ee48f66eb", "type": "github" }, "original": { @@ -17,17 +17,12 @@ } }, "crane": { - "inputs": { - "nixpkgs": [ - "nixpkgs" - ] - }, "locked": { - "lastModified": 1722960479, - "narHash": "sha256-NhCkJJQhD5GUib8zN9JrmYGMwt4lCRp6ZVNzIiYCl0Y=", + "lastModified": 1737563566, + "narHash": "sha256-GLJvkOG29XCynQm8XWPyykMRqIhxKcBARVu7Ydrz02M=", "owner": "ipetkov", "repo": "crane", - "rev": "4c6c77920b8d44cd6660c1621dea6b3fc4b4c4f4", + "rev": "849376434956794ebc7a6b487d31aace395392ba", "type": "github" }, "original": { @@ -36,31 +31,13 @@ "type": "github" } }, - "flake-utils": { - "inputs": { - "systems": "systems" - }, - "locked": { - "lastModified": 1710146030, - "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, "nixpkgs": { "locked": { - "lastModified": 1723221148, - "narHash": "sha256-7pjpeQlZUNQ4eeVntytU3jkw9dFK3k1Htgk2iuXjaD8=", + "lastModified": 1737525964, + "narHash": "sha256-3wFonKmNRWKq1himW9N3TllbeGIHFACI5vmLpk6moF8=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "154bcb95ad51bc257c2ce4043a725de6ca700ef6", + "rev": "5757bbb8bd7c0630a0cc4bb19c47e588db30b97c", "type": "github" }, "original": { @@ -72,11 +49,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1718428119, - "narHash": "sha256-WdWDpNaq6u1IPtxtYHHWpl5BmabtpmLnMAx0RdJ/vo8=", + "lastModified": 1736320768, + "narHash": "sha256-nIYdTAiKIGnFNugbomgBJR+Xv5F1ZQU+HfaBqJKroC0=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "e6cea36f83499eb4e9cd184c8a8e823296b50ad5", + "rev": "4bc9c909d9ac828a039f288cf872d16d38185db8", "type": "github" }, "original": { @@ -92,7 +69,8 @@ "crane": "crane", "nixpkgs": "nixpkgs", "rust-overlay": "rust-overlay", - "tree-sitter-nickel": "tree-sitter-nickel" + "tree-sitter-nickel": "tree-sitter-nickel", + "tree-sitter-openscad": "tree-sitter-openscad" } }, "rust-overlay": { @@ -100,11 +78,11 @@ "nixpkgs": "nixpkgs_2" }, "locked": { - "lastModified": 1723429325, - "narHash": "sha256-4x/32xTCd+xCwFoI/kKSiCr5LQA2ZlyTRYXKEni5HR8=", + "lastModified": 1737512878, + "narHash": "sha256-dgF6htdmfNnZzVInifks6npnCAyVsIHWSpWNs10RSW0=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "65e3dc0fe079fe8df087cd38f1fe6836a0373aad", + "rev": "06b8ed0eee289fe94c66f1202ced9a6a2c59a14c", "type": "github" }, "original": { @@ -113,39 +91,43 @@ "type": "github" } }, - "systems": { + "tree-sitter-nickel": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "lastModified": 1736157356, + "narHash": "sha256-dQeUoHQHkPYywYIm3TMnTWPXUlh2xh8M5CVUiXASBu8=", + "owner": "nickel-lang", + "repo": "tree-sitter-nickel", + "rev": "25464b33522c3f609fa512aa9651707c0b66d48b", "type": "github" }, "original": { - "owner": "nix-systems", - "repo": "default", + "owner": "nickel-lang", + "repo": "tree-sitter-nickel", "type": "github" } }, - "tree-sitter-nickel": { + "tree-sitter-openscad": { "inputs": { - "flake-utils": "flake-utils", "nixpkgs": [ "nixpkgs" ] }, "locked": { - "lastModified": 1723707504, - "narHash": "sha256-IvlUwNO/wLLPuqCZf0NtSxMdDx+4ASYYOobklY/97aQ=", - "owner": "nickel-lang", - "repo": "tree-sitter-nickel", - "rev": "88d836a24b3b11c8720874a1a9286b8ae838d30a", + "lastModified": 1737579220, + "narHash": "sha256-xi1LIO3VVIYlcNmvF7sqbL9ThLJG+0jhZyMQb3199Q8=", + "owner": "mkatychev", + "repo": "tree-sitter-openscad", + "rev": "ebd9b1c4b6e4f3a8515cdffc49b458857918c9e2", "type": "github" }, "original": { - "owner": "nickel-lang", - "repo": "tree-sitter-nickel", + "owner": "mkatychev", + "repo": "tree-sitter-openscad", "type": "github" } } From dae66d930835f2376dbaf26dce8a4e8e21a67173 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Wed, 22 Jan 2025 15:18:22 -0600 Subject: [PATCH 35/39] updated expected ternary formatting --- topiary-cli/tests/samples/expected/openscad.scad | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/topiary-cli/tests/samples/expected/openscad.scad b/topiary-cli/tests/samples/expected/openscad.scad index 6aaa288e..1bb94d90 100644 --- a/topiary-cli/tests/samples/expected/openscad.scad +++ b/topiary-cli/tests/samples/expected/openscad.scad @@ -195,10 +195,11 @@ function affine3d_rot_from_to(from, to) = ]; // Prettier style ternaries https://prettier.io/blog/2023/11/13/curious-ternaries -x = foo() ? bar() -: baz() ? - qux() -: true; +x = + foo() ? bar() + : baz() ? + qux() + : true; // ================================================================================ // Comprehensions From cc59db4c362c27a36c953b86d4f3d7d1d46895c3 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Wed, 22 Jan 2025 15:20:47 -0600 Subject: [PATCH 36/39] revert local dylib for openscad in languages.ncl --- topiary-config/languages.ncl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/topiary-config/languages.ncl b/topiary-config/languages.ncl index 8194a89a..7315c951 100644 --- a/topiary-config/languages.ncl +++ b/topiary-config/languages.ncl @@ -75,9 +75,10 @@ openscad = { extensions = ["scad"], - grammar.source | priority 1 = { - path = "/Users/mkatychev/Documents/tree-sitter/openscad/parser.dylib", - } + grammar.source.git = { + git = "https://github.com/mkatychev/tree-sitter-openscad.git", + rev = "ebd9b1c4b6e4f3a8515cdffc49b458857918c9e2", + }, }, rust = { From 04cadb16d0429073f37c9e07f3d5090f2930ba70 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Wed, 22 Jan 2025 15:53:05 -0600 Subject: [PATCH 37/39] cargo clippy --fix --- topiary-cli/src/io.rs | 6 +++--- topiary-core/benches/benchmark.rs | 2 +- topiary-core/src/tree_sitter.rs | 6 +++--- topiary-tree-sitter-facade/src/language.rs | 2 +- topiary-tree-sitter-facade/src/node.rs | 10 +++++----- topiary-tree-sitter-facade/src/query_capture.rs | 10 +++++----- topiary-tree-sitter-facade/src/query_predicate.rs | 10 +++++----- topiary-tree-sitter-facade/src/tree_cursor.rs | 6 +++--- 8 files changed, 26 insertions(+), 26 deletions(-) diff --git a/topiary-cli/src/io.rs b/topiary-cli/src/io.rs index 3cb699cc..3480c640 100644 --- a/topiary-cli/src/io.rs +++ b/topiary-cli/src/io.rs @@ -115,7 +115,7 @@ pub struct InputFile<'cfg> { query: QuerySource, } -impl<'cfg> InputFile<'cfg> { +impl InputFile<'_> { /// Convert our `InputFile` into language definition values that Topiary can consume pub async fn to_language(&self) -> CLIResult { let grammar = self.language().grammar()?; @@ -149,7 +149,7 @@ impl<'cfg> InputFile<'cfg> { } } -impl<'cfg> Read for InputFile<'cfg> { +impl Read for InputFile<'_> { fn read(&mut self, buf: &mut [u8]) -> Result { match &mut self.source { InputSource::Stdin => stdin().lock().read(buf), @@ -312,7 +312,7 @@ impl Write for OutputFile { // Convenience conversion: // * stdin maps to stdout // * Files map to themselves (i.e., for in-place updates) -impl<'cfg> TryFrom<&InputFile<'cfg>> for OutputFile { +impl TryFrom<&InputFile<'_>> for OutputFile { type Error = TopiaryError; fn try_from(input: &InputFile) -> CLIResult { diff --git a/topiary-core/benches/benchmark.rs b/topiary-core/benches/benchmark.rs index f25b9b53..6fd12c7a 100644 --- a/topiary-core/benches/benchmark.rs +++ b/topiary-core/benches/benchmark.rs @@ -14,7 +14,7 @@ async fn format() { let language: Language = Language { name: "ocaml".to_owned(), - query: TopiaryQuery::new(&ocaml.clone().into(), &query_content).unwrap(), + query: TopiaryQuery::new(&ocaml.into(), &query_content).unwrap(), grammar: ocaml.into(), indent: None, }; diff --git a/topiary-core/src/tree_sitter.rs b/topiary-core/src/tree_sitter.rs index f6ed6d3f..9c6b174e 100644 --- a/topiary-core/src/tree_sitter.rs +++ b/topiary-core/src/tree_sitter.rs @@ -154,7 +154,7 @@ pub trait NodeExt { fn display_one_based(&self) -> String; } -impl<'a> NodeExt for Node<'a> { +impl NodeExt for Node<'_> { fn display_one_based(&self) -> String { format!( "{{Node {:?} {} - {}}}", @@ -166,7 +166,7 @@ impl<'a> NodeExt for Node<'a> { } #[cfg(not(target_arch = "wasm32"))] -impl<'a> NodeExt for tree_sitter::Node<'a> { +impl NodeExt for tree_sitter::Node<'_> { fn display_one_based(&self) -> String { format!( "{{Node {:?} {} - {}}}", @@ -189,7 +189,7 @@ struct LocalQueryMatch<'a> { captures: Vec>, } -impl<'a> Display for LocalQueryMatch<'a> { +impl Display for LocalQueryMatch<'_> { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!( f, diff --git a/topiary-tree-sitter-facade/src/language.rs b/topiary-tree-sitter-facade/src/language.rs index 53c824f5..83673458 100644 --- a/topiary-tree-sitter-facade/src/language.rs +++ b/topiary-tree-sitter-facade/src/language.rs @@ -6,7 +6,7 @@ mod native { pub(crate) inner: tree_sitter::LanguageRef<'a>, } - impl<'a> LanguageRef<'a> { + impl LanguageRef<'_> { pub fn field_count(&self) -> usize { self.inner.field_count() } diff --git a/topiary-tree-sitter-facade/src/node.rs b/topiary-tree-sitter-facade/src/node.rs index 84f27193..0bc21525 100644 --- a/topiary-tree-sitter-facade/src/node.rs +++ b/topiary-tree-sitter-facade/src/node.rs @@ -243,7 +243,7 @@ mod native { } } - impl<'tree> std::fmt::Debug for Node<'tree> { + impl std::fmt::Debug for Node<'_> { fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { std::fmt::Debug::fmt(&self.inner, fmt) } @@ -256,7 +256,7 @@ mod native { } } - impl<'a> Ord for Node<'a> { + impl Ord for Node<'_> { fn cmp(&self, that: &Self) -> std::cmp::Ordering { let this = self.id(); let that = that.id(); @@ -270,11 +270,11 @@ mod native { } } - impl<'a> std::panic::RefUnwindSafe for Node<'a> {} + impl std::panic::RefUnwindSafe for Node<'_> {} - impl<'a> Unpin for Node<'a> {} + impl Unpin for Node<'_> {} - impl<'a> std::panic::UnwindSafe for Node<'a> {} + impl std::panic::UnwindSafe for Node<'_> {} } #[cfg(not(target_arch = "wasm32"))] diff --git a/topiary-tree-sitter-facade/src/query_capture.rs b/topiary-tree-sitter-facade/src/query_capture.rs index 11f3c77a..d04e784d 100644 --- a/topiary-tree-sitter-facade/src/query_capture.rs +++ b/topiary-tree-sitter-facade/src/query_capture.rs @@ -8,7 +8,7 @@ mod native { pub(crate) inner: tree_sitter::QueryCapture<'a>, } - impl<'a> QueryCapture<'a> { + impl QueryCapture<'_> { #[inline] pub fn node(&self) -> Node { self.inner.node.into() @@ -21,7 +21,7 @@ mod native { } } - impl<'a> std::fmt::Debug for QueryCapture<'a> { + impl std::fmt::Debug for QueryCapture<'_> { fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { std::fmt::Debug::fmt(&self.inner, fmt) } @@ -41,11 +41,11 @@ mod native { } } - impl<'a> std::panic::RefUnwindSafe for QueryCapture<'a> {} + impl std::panic::RefUnwindSafe for QueryCapture<'_> {} - impl<'a> Unpin for QueryCapture<'a> {} + impl Unpin for QueryCapture<'_> {} - impl<'a> std::panic::UnwindSafe for QueryCapture<'a> {} + impl std::panic::UnwindSafe for QueryCapture<'_> {} } #[cfg(not(target_arch = "wasm32"))] diff --git a/topiary-tree-sitter-facade/src/query_predicate.rs b/topiary-tree-sitter-facade/src/query_predicate.rs index 415acd7b..dce059bf 100644 --- a/topiary-tree-sitter-facade/src/query_predicate.rs +++ b/topiary-tree-sitter-facade/src/query_predicate.rs @@ -6,7 +6,7 @@ mod native { pub(crate) inner: &'query tree_sitter::QueryPredicate, } - impl<'query> QueryPredicate<'query> { + impl QueryPredicate<'_> { #[inline] pub fn operator(&self) -> Cow { Cow::Borrowed(&self.inner.operator) @@ -30,7 +30,7 @@ mod native { } } - impl<'query> std::fmt::Debug for QueryPredicate<'query> { + impl std::fmt::Debug for QueryPredicate<'_> { fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { std::fmt::Debug::fmt(&self.inner, fmt) } @@ -43,11 +43,11 @@ mod native { } } - impl<'query> std::panic::RefUnwindSafe for QueryPredicate<'query> {} + impl std::panic::RefUnwindSafe for QueryPredicate<'_> {} - impl<'query> Unpin for QueryPredicate<'query> {} + impl Unpin for QueryPredicate<'_> {} - impl<'query> std::panic::UnwindSafe for QueryPredicate<'query> {} + impl std::panic::UnwindSafe for QueryPredicate<'_> {} } #[cfg(not(target_arch = "wasm32"))] diff --git a/topiary-tree-sitter-facade/src/tree_cursor.rs b/topiary-tree-sitter-facade/src/tree_cursor.rs index 4a739e0c..b2d34fe1 100644 --- a/topiary-tree-sitter-facade/src/tree_cursor.rs +++ b/topiary-tree-sitter-facade/src/tree_cursor.rs @@ -61,11 +61,11 @@ mod native { } } - impl<'a> std::panic::RefUnwindSafe for TreeCursor<'a> {} + impl std::panic::RefUnwindSafe for TreeCursor<'_> {} - impl<'a> Unpin for TreeCursor<'a> {} + impl Unpin for TreeCursor<'_> {} - impl<'a> std::panic::UnwindSafe for TreeCursor<'a> {} + impl std::panic::UnwindSafe for TreeCursor<'_> {} } #[cfg(not(target_arch = "wasm32"))] From efd2f0615f3b6d90a03b3801cef55c472db1024f Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Wed, 22 Jan 2025 16:43:00 -0600 Subject: [PATCH 38/39] updated refs to latest master of tree-sitter-openscad --- flake.lock | 6 +++--- topiary-config/languages.ncl | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/flake.lock b/flake.lock index 03d8cb00..32233044 100644 --- a/flake.lock +++ b/flake.lock @@ -118,11 +118,11 @@ ] }, "locked": { - "lastModified": 1737579220, - "narHash": "sha256-xi1LIO3VVIYlcNmvF7sqbL9ThLJG+0jhZyMQb3199Q8=", + "lastModified": 1737584789, + "narHash": "sha256-j/DordcjrrVZ9ZI2p46z4TULyf2A+4mNjcM9btowyQU=", "owner": "mkatychev", "repo": "tree-sitter-openscad", - "rev": "ebd9b1c4b6e4f3a8515cdffc49b458857918c9e2", + "rev": "270e5ff749edfacc84a6e4a434abd4e8b0f70bbe", "type": "github" }, "original": { diff --git a/topiary-config/languages.ncl b/topiary-config/languages.ncl index 7315c951..0ca74f92 100644 --- a/topiary-config/languages.ncl +++ b/topiary-config/languages.ncl @@ -77,7 +77,7 @@ extensions = ["scad"], grammar.source.git = { git = "https://github.com/mkatychev/tree-sitter-openscad.git", - rev = "ebd9b1c4b6e4f3a8515cdffc49b458857918c9e2", + rev = "270e5ff749edfacc84a6e4a434abd4e8b0f70bbe", }, }, From 4badc3e8a74441e7787b50d3e513ff8bed353980 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Fri, 24 Jan 2025 00:58:58 -0600 Subject: [PATCH 39/39] update formatting --- topiary-cli/tests/samples/input/openscad.scad | 150 +++++++----------- 1 file changed, 59 insertions(+), 91 deletions(-) diff --git a/topiary-cli/tests/samples/input/openscad.scad b/topiary-cli/tests/samples/input/openscad.scad index 54bfc562..fdf65f85 100644 --- a/topiary-cli/tests/samples/input/openscad.scad +++ b/topiary-cli/tests/samples/input/openscad.scad @@ -2,9 +2,7 @@ // Variables/Imports // ================================================================================ include ; -use ; -include -use +use ; include use // variables rr = a_vector[2]; // member of vector range1 = [-1.5:0.5:3]; // for() loop range @@ -18,11 +16,11 @@ cond_var = "is_true" ? true : false; // ================================================================================ function line(point1, point2, width = 1) = - let (angle = 90 - atan( (point2[1] - point1[1]) / (point2[0] - point1[0]) )) + let (angle = 90 - atan((point2[1] - point1[1]) / (point2[0] - point1[0]))) let (offset_x = 0.5 * width * cos(angle), offset_y = 0.5 * width * sin(angle)) - let (offset1 = [-offset_x, offset_y], offset2 = [offset_x, -offset_y]) + let (offset1 = [ -offset_x, offset_y], offset2 = [offset_x, -offset_y]) // [P1a, P2a, P2b, P1b] [point1 + offset1, point2 + offset1, point2 + offset2, point1 + offset2]; @@ -33,23 +31,18 @@ eager = (function(z) identity)(4); // Transformations // ================================================================================ cylinder(); -cylinder(d=5, h=100); +cylinder( d = 5, h=100,); rotate([90, 0, 0]) - cylinder(); +cylinder(); translate([1, 0, 0]) { - difference() { - translate([0, 1, 0]) - translate([1, 0, 0]) rotate([0, 90, 0]) - cylinder(); cube(); - } -} + difference() { translate([0, 1, 0]) + translate([1, 0, 0]) rotate([0, 90, 0]) + cylinder(); cube(); } } // ================================================================================ // Nested Items // ================================================================================ -module big_module() { - function inner_function() = undef; - module inner_module() cube(); +module big_module() { function inner_function() = undef; module inner_module() cube(); } module extern_module() include @@ -57,48 +50,25 @@ module extern_module() include // ================================================================================ // Control Flow // ================================================================================ -for (i = [10:50]) { - let (angle = i * 360 / 20, r = i * 2, distance = r * 5) { +for (i = [10:50]) { let (angle = i*360/20, r= i*2, distance = r*5) { rotate(angle, [1, 0, 0]) translate([0, distance, 0]) - sphere(r=r); - } + sphere(r = r); } } // newline indent propagates from innermost if_block -if ($preview) - if (true) - foo(); - else if (true) - if (false) - foo(false); - else - translate([2, 0, 0]) foo(); - else - bar(); +if ($preview) if(true) foo(); else if(true) if + (false) foo(false); else translate([2,0,0]) foo(); else bar(); // format propagates from first union_block if (true) { -} else if (fn(true)) { - foo(); -} else if (false) { - bar(); -} else { - baz(); -} + } else if (fn(true)) { foo();} else if (false) { bar();} else { baz(); } -for (i = [1:2:7]) { - let (x = i ^ 2, y = x - 1) { - translate([x, y, 0]) sphere(r=i); - } -} -intersection_for (i = [1, 2, 3]) { - if (i > 1) { - translate([0, i, 0]) cube(); - } else { - translate([0, i, 0]) cube(); - } -} +for(i = [1:2:7]) { let (x = i ^ 2,y = x - 1) { + translate([x,y,0]) sphere(r=i); } } + +intersection_for(i = [1,2,3]) { if (i > 1) { + translate([0,i,0]) cube(); } else { translate([0,i,0]) cube(); } } // ================================================================================ // Comments @@ -111,8 +81,7 @@ here */ my_parameter = /*inline block*/ 5; -function math(x) = - /*do math stuff*/ x + 2 // done with math +function math(x) = /*do math stuff*/ x + 2 // done with math ; module my_cylinder() { @@ -125,30 +94,31 @@ module my_cylinder() { // Modifiers // ================================================================================ !cylinder(); -*linear_extrude(4) text("Hello"); -rotate([0, 90, 0]) #cylinder(); +* linear_extrude(4) text("Hello"); +rotate([0,90,0])# cylinder(); %cube(); // multi modifier -translate(1) #!cube(); -rotate([90]) %translate() - #cube(); +translate(1) # ! cube(); +rotate([90]) % +translate() +# +cube(); // ================================================================================ // Assertions/Echoes // ================================================================================ assert(); assert(10 < 20) cube(); -for (y = [3:5]) - assert(assert() y < x, "message") +for(y = [3:5]) assert(assert() y < x, "message") cylinder(); assert(true) assert() cylinder(); -val = - assert(true, "strut must be positive") - assert(true, "frame must be nonnegative") - undef; +val = assert(true, "strut must be positive") +assert(true, "frame must be nonnegative") +undef; function foo() = - echo("this can precede an expression") true; +echo("this can precede an expression") true; + fn = function(x) echo("this is x") x; echo(fn ? "truthy" : "falsey"); @@ -157,19 +127,17 @@ echo(function(y) y ? "first" : "second"); // ================================================================================ // Lists/Ternaries // ================================================================================ -list1 = [ - 1, - 2, - 3, -]; -my_fn = fn1( - [ + list1 = [ 1, - 2, - 3, - ], - true, -); + 2, 3 + ]; + my_fn = fn1([ + 1, + 2, + 3, + ], + true + ); function affine3d_rot_from_to(from, to) = assert(is_vector(from)) @@ -177,27 +145,26 @@ function affine3d_rot_from_to(from, to) = assert(len(from) == len(to)) let ( from = unit(point3d(from)), - to = unit(point3d(to)), + to = unit(point3d(to)) ) approx(from, to) ? affine3d_identity() : from.z == 0 && to.z == 0 ? affine3d_zrot(v_theta(point2d(to)) - v_theta(point2d(from))) - : let ( - u = vector_axis(from, to), + : let (u = vector_axis(from, to), ang = vector_angle(from, to), c = cos(ang), c2 = 1 - c, - s = sin(ang), + s = sin(ang) // double indent a list preceded by list expression ) [ - [1, 0, 0, 0], - [0, 1, 0, 0], - [0, 0, 1, 0], - [0, 0, 0, 1], + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [0, 0, 0, 1], ]; + // Prettier style ternaries https://prettier.io/blog/2023/11/13/curious-ternaries -x = - foo() ? bar() +x = foo() ? bar() : baz() ? - qux() + qux() : true; // ================================================================================ @@ -208,12 +175,13 @@ conditioned = [for (x = [1:10]) if ($preview) x]; ifelse = [for (x = [1:10]) if ($preview) x else ln(x)]; if_for_ifelse = [for (x = 0) if (x < 0) for (y = 2) if (y == 2) y else x]; complex_condition = [ - for (x = [1:10]) if (x % 2 == 0) x else if (x < 5) x - 1 else 0, + for (x = [1:10]) if (x % 2 == 0) x else if (x < 5) x - 1 else 0 ]; spliced = [for (x = [1:10]) x, for (y = [1, 2, 3]) y, for (z = [4, 5, 6]) z]; nested = [for (x = [1:10]) for (y = [1, 2, 3]) for (z = [4, 5, 6]) x * y * z]; grouped = [if (x < 7) (for (y = [1:10]) if (y > x) y) else x]; -let_each = [for (i = [0:1]) let (a = 90) each arc(angle=a)]; -let_for = [let (i = [0:1]) for (i = i) let (a = 90) each arc(angle=a)]; -let_if = [for (i = [0:1]) let (a = 360) if (is_def(isect)) isect]; -fn_list = [each function() 10]; +let_each = [for(i = [0:1]) let(a=90) each arc(angle=a)]; +let_for = [let (i=[0:1]) for(i = i) let(a=90) each arc(angle=a)]; +let_if = [for(i = [0:1]) let(a=360) if (is_def(isect)) isect]; +fn_list = [each function ()10]; +