diff --git a/src/kicad_sexpr/token.gleam b/src/kicad_sexpr/token.gleam index 89599d7..fdf59d3 100644 --- a/src/kicad_sexpr/token.gleam +++ b/src/kicad_sexpr/token.gleam @@ -19,40 +19,40 @@ fn allowed(then next: NextFn(Bool, a)) -> Decoder(a) { decode.enum(with: [#("allowed", True), #("not_allowed", False)], then: next) } -fn optional_fill(then next: NextFn(Option(Bool), a)) -> Decoder(a) { - decode.optional( - decode.token_wrapper(named: "fill", with: yes_no, then: _), +fn fill_flag(then next: NextFn(Bool, a)) -> Decoder(a) { + decode.token_wrapper(named: "fill", with: yes_no, then: next) +} + +fn angle(then next: NextFn(Float, a)) -> Decoder(a) { + decode.token_wrapper(named: "angle", with: decode.float, then: next) +} + +fn corners(then next: NextFn(#(XY, XY, XY, XY), a)) -> Decoder(a) { + decode.token(named: "pts", then: next, with: { + use xy1 <- xy() + use xy2 <- xy() + use xy3 <- xy() + use xy4 <- xy() + decode.success(#(xy1, xy2, xy3, xy4)) + }) +} + +fn margins(then next: NextFn(#(Float, Float, Float, Float), a)) -> Decoder(a) { + decode.token( + named: "margins", + with: { + use f1 <- decode.float() + use f2 <- decode.float() + use f3 <- decode.float() + use f4 <- decode.float() + decode.success(#(f1, f2, f3, f4)) + }, then: next, ) } -fn optional_angle(then next: NextFn(Option(Float), a)) -> Decoder(a) { - decode.optional( - decode.token_wrapper(named: "angle", with: decode.float, then: _), - then: next, - ) -} - -fn optional_corners( - then next: NextFn(Option(#(XY, XY, XY, XY)), a), -) -> Decoder(a) { - decode.optional( - decode.token(named: "pts", then: _, with: { - use xy1 <- xy() - use xy2 <- xy() - use xy3 <- xy() - use xy4 <- xy() - decode.success(#(xy1, xy2, xy3, xy4)) - }), - then: next, - ) -} - -fn optional_hide(then next: NextFn(Option(Bool), a)) -> Decoder(a) { - decode.optional( - decode.token_wrapper(named: "hide", with: yes_no, then: _), - then: next, - ) +fn hide(then next: NextFn(Bool, a)) -> Decoder(a) { + decode.token_wrapper(named: "hide", with: yes_no, then: next) } fn custom_xy(named name: String, then next: NextFn(XY, a)) -> Decoder(a) { @@ -65,7 +65,7 @@ fn custom_xy(named name: String, then next: NextFn(XY, a)) -> Decoder(a) { fn layers(then next: NextFn(List(Layer), a)) -> Decoder(a) { decode.token(named: "layers", then: next, with: { - use layers <- decode.list(decode.string) + use layers <- decode.list(decode.name_or_string) let layers = list.map(layers, Layer) decode.success(layers) }) @@ -377,7 +377,7 @@ pub fn effects(then next: NextFn(Effects, a)) -> Decoder(a) { decode.token(named: "effects", then: next, with: { use font <- font() use justify <- decode.optional(justify) - use hide <- optional_hide() + use hide <- decode.optional(hide) decode.success(Effects(font:, justify:, hide:)) }) } @@ -491,13 +491,24 @@ pub fn uuid(then next: NextFn(Uuid, a)) -> Decoder(a) { }) } +pub type Timestamp { + Timestamp(ts: String) +} + +pub fn timestamp(then next: NextFn(Timestamp, a)) -> Decoder(a) { + decode.token(named: "tstamp", then: next, with: { + use ts <- decode.name_string() + decode.success(Timestamp(ts:)) + }) +} + pub type Layer { Layer(layer: String) } pub fn layer(then next: NextFn(Layer, a)) -> Decoder(a) { decode.token(named: "layer", then: next, with: { - use layer <- decode.string() + use layer <- decode.name_or_string() decode.success(Layer(layer:)) }) } @@ -565,7 +576,7 @@ pub fn footprint_property(then next: NextFn(FootprintProperty, a)) -> Decoder(a) then: _, )) use layer <- layer() - use hide <- optional_hide() + use hide <- decode.optional(hide) use uuid <- decode.optional(uuid) use effects <- effects() decode.success(FootprintProperty( @@ -653,6 +664,7 @@ pub type FootprintText { hide: Option(Bool), uuid: Option(Uuid), effects: Effects, + timestamp: Option(Timestamp), ) } @@ -667,9 +679,10 @@ pub fn footprint_text(then next: NextFn(FootprintText, a)) -> Decoder(a) { then: _, )) use layer <- layer() - use hide <- optional_hide() + use hide <- decode.optional(hide) use uuid <- decode.optional(uuid) use effects <- effects() + use timestamp <- decode.optional(timestamp) decode.success(FootprintText( type_:, text:, @@ -679,6 +692,7 @@ pub fn footprint_text(then next: NextFn(FootprintText, a)) -> Decoder(a) { hide:, uuid:, effects:, + timestamp:, )) }) } @@ -698,6 +712,7 @@ pub type FootprintTextBox { border: Option(Bool), stroke: Option(Stroke), render_cache: Option(Nil), + timestamp: Option(Timestamp), ) } @@ -707,19 +722,9 @@ pub fn footprint_text_box(then next: NextFn(FootprintTextBox, a)) -> Decoder(a) use text <- decode.string() use start <- decode.optional(custom_xy("start", then: _)) use end <- decode.optional(custom_xy("end", then: _)) - use corners <- optional_corners() - use margins <- decode.optional(decode.token( - named: "margins", - with: { - use f1 <- decode.float() - use f2 <- decode.float() - use f3 <- decode.float() - use f4 <- decode.float() - decode.success(#(f1, f2, f3, f4)) - }, - then: _, - )) - use angle <- optional_angle() + use corners <- decode.optional(corners) + use margins <- decode.optional(margins) + use angle <- decode.optional(angle) use layer <- layer() use uuid <- decode.optional(uuid) use effects <- effects() @@ -730,6 +735,7 @@ pub fn footprint_text_box(then next: NextFn(FootprintTextBox, a)) -> Decoder(a) )) use stroke <- decode.optional(stroke) let render_cache = option.None + use timestamp <- decode.optional(timestamp) decode.success(FootprintTextBox( locked:, text:, @@ -744,6 +750,7 @@ pub fn footprint_text_box(then next: NextFn(FootprintTextBox, a)) -> Decoder(a) border:, stroke:, render_cache:, + timestamp:, )) }) } @@ -752,10 +759,12 @@ pub type FootprintLine { FootprintLine( start: XY, end: XY, - stroke: Stroke, + stroke: Option(Stroke), layer: Layer, + width: Option(Float), locked: Bool, uuid: Option(Uuid), + timestamp: Option(Timestamp), ) } @@ -763,11 +772,22 @@ pub fn footprint_line(then next: NextFn(FootprintLine, a)) -> Decoder(a) { decode.token(named: "fp_line", then: next, with: { use start <- custom_xy("start") use end <- custom_xy("end") - use stroke <- stroke() + use stroke <- decode.optional(stroke) use layer <- layer() + use width <- decode.optional(width) use locked <- decode.flag("locked") use uuid <- decode.optional(uuid) - decode.success(FootprintLine(start:, end:, stroke:, layer:, locked:, uuid:)) + use timestamp <- decode.optional(timestamp) + decode.success(FootprintLine( + start:, + end:, + stroke:, + layer:, + width:, + locked:, + uuid:, + timestamp:, + )) }) } @@ -775,11 +795,12 @@ pub type FootprintRectangle { FootprintRectangle( start: XY, end: XY, - stroke: Stroke, + stroke: Option(Stroke), fill: Option(Bool), layer: Layer, locked: Bool, uuid: Option(Uuid), + timestamp: Option(Timestamp), ) } @@ -789,11 +810,12 @@ pub fn footprint_rectangle( decode.token(named: "fp_rect", then: next, with: { use start <- custom_xy("start") use end <- custom_xy("end") - use stroke <- stroke() - use fill <- optional_fill() + use stroke <- decode.optional(stroke) + use fill <- decode.optional(fill_flag) use layer <- layer() use locked <- decode.flag("locked") use uuid <- decode.optional(uuid) + use timestamp <- decode.optional(timestamp) decode.success(FootprintRectangle( start:, end:, @@ -802,6 +824,7 @@ pub fn footprint_rectangle( layer:, locked:, uuid:, + timestamp:, )) }) } @@ -810,11 +833,12 @@ pub type FootprintCircle { FootprintCircle( center: XY, end: XY, - stroke: Stroke, + stroke: Option(Stroke), fill: Option(Bool), layer: Layer, locked: Bool, uuid: Option(Uuid), + timestamp: Option(Timestamp), ) } @@ -822,11 +846,12 @@ pub fn footprint_circle(then next: NextFn(FootprintCircle, a)) -> Decoder(a) { decode.token(named: "fp_circle", then: next, with: { use center <- custom_xy("center") use end <- custom_xy("end") - use stroke <- stroke() - use fill <- optional_fill() + use stroke <- decode.optional(stroke) + use fill <- decode.optional(fill_flag) use layer <- layer() use locked <- decode.flag("locked") use uuid <- decode.optional(uuid) + use timestamp <- decode.optional(timestamp) decode.success(FootprintCircle( center:, end:, @@ -835,6 +860,7 @@ pub fn footprint_circle(then next: NextFn(FootprintCircle, a)) -> Decoder(a) { layer:, locked:, uuid:, + timestamp:, )) }) } @@ -844,10 +870,11 @@ pub type FootprintArc { start: XY, mid: XY, end: XY, - stroke: Stroke, + stroke: Option(Stroke), layer: Layer, locked: Bool, uuid: Option(Uuid), + timestamp: Option(Timestamp), ) } @@ -856,10 +883,11 @@ pub fn footprint_arc(then next: NextFn(FootprintArc, a)) -> Decoder(a) { use start <- custom_xy("start") use mid <- custom_xy("mid") use end <- custom_xy("end") - use stroke <- stroke() + use stroke <- decode.optional(stroke) use layer <- layer() use locked <- decode.flag("locked") use uuid <- decode.optional(uuid) + use timestamp <- decode.optional(timestamp) decode.success(FootprintArc( start:, mid:, @@ -868,6 +896,7 @@ pub fn footprint_arc(then next: NextFn(FootprintArc, a)) -> Decoder(a) { layer:, locked:, uuid:, + timestamp:, )) }) } @@ -875,22 +904,24 @@ pub fn footprint_arc(then next: NextFn(FootprintArc, a)) -> Decoder(a) { pub type FootprintPolygon { FootprintPolygon( points: PolyPoints, - stroke: Stroke, + stroke: Option(Stroke), fill: Option(Bool), layer: Layer, locked: Bool, uuid: Option(Uuid), + timestamp: Option(Timestamp), ) } pub fn footprint_polygon(then next: NextFn(FootprintPolygon, a)) -> Decoder(a) { decode.token(named: "fp_poly", then: next, with: { use points <- poly_points() - use stroke <- stroke() - use fill <- optional_fill() + use stroke <- decode.optional(stroke) + use fill <- decode.optional(fill_flag) use layer <- layer() use locked <- decode.flag("locked") use uuid <- decode.optional(uuid) + use timestamp <- decode.optional(timestamp) decode.success(FootprintPolygon( points:, stroke:, @@ -898,6 +929,7 @@ pub fn footprint_polygon(then next: NextFn(FootprintPolygon, a)) -> Decoder(a) { layer:, locked:, uuid:, + timestamp:, )) }) } @@ -905,21 +937,30 @@ pub fn footprint_polygon(then next: NextFn(FootprintPolygon, a)) -> Decoder(a) { pub type FootprintCurve { FootprintCurve( points: Points, - stroke: Stroke, + stroke: Option(Stroke), layer: Layer, locked: Bool, uuid: Option(Uuid), + timestamp: Option(Timestamp), ) } pub fn footprint_curve(then next: NextFn(FootprintCurve, a)) -> Decoder(a) { decode.token(named: "fp_curve", then: next, with: { use points <- points() - use stroke <- stroke() + use stroke <- decode.optional(stroke) use layer <- layer() use locked <- decode.flag("locked") use uuid <- decode.optional(uuid) - decode.success(FootprintCurve(points:, stroke:, layer:, locked:, uuid:)) + use timestamp <- decode.optional(timestamp) + decode.success(FootprintCurve( + points:, + stroke:, + layer:, + locked:, + uuid:, + timestamp:, + )) }) } @@ -1287,8 +1328,8 @@ pub fn graphical_text_box(then next: NextFn(GraphicalTextBox, a)) -> Decoder(a) use text <- decode.string() use start <- decode.optional(custom_xy("start", then: _)) use end <- decode.optional(custom_xy("end", then: _)) - use corners <- optional_corners() - use angle <- optional_angle() + use corners <- decode.optional(corners) + use angle <- decode.optional(angle) use layer <- decode.optional(layer) use uuid <- decode.optional(uuid) use effects <- effects() @@ -1325,7 +1366,7 @@ pub fn graphical_line(then next: NextFn(GraphicalLine, a)) -> Decoder(a) { decode.token(named: "gr_line", then: next, with: { use start <- custom_xy("start") use end <- custom_xy("end") - use angle <- optional_angle() + use angle <- decode.optional(angle) use layer <- decode.optional(layer) use width <- width() use uuid <- decode.optional(uuid) @@ -1352,7 +1393,7 @@ pub fn graphical_rectangle( use end <- custom_xy("end") use layer <- decode.optional(layer) use width <- width() - use fill <- optional_fill() + use fill <- decode.optional(fill_flag) use uuid <- decode.optional(uuid) decode.success(GraphicalRectangle( start:, @@ -1382,7 +1423,7 @@ pub fn graphical_circle(then next: NextFn(GraphicalCircle, a)) -> Decoder(a) { use end <- custom_xy("end") use layer <- decode.optional(layer) use width <- width() - use fill <- optional_fill() + use fill <- decode.optional(fill_flag) use uuid <- decode.optional(uuid) decode.success(GraphicalCircle(center:, end:, layer:, width:, fill:, uuid:)) }) @@ -1426,7 +1467,7 @@ pub fn graphical_polygon(then next: NextFn(GraphicalPolygon, a)) -> Decoder(a) { use points <- poly_points() use layer <- decode.optional(layer) use width <- width() - use fill <- optional_fill() + use fill <- decode.optional(fill_flag) use uuid <- decode.optional(uuid) decode.success(GraphicalPolygon(points:, layer:, width:, fill:, uuid:)) }) @@ -1526,17 +1567,7 @@ pub fn symbol_text_box(then next: NextFn(SymbolTextBox, a)) -> Decoder(a) { use text <- decode.string() use position <- position_identifier() use size <- size() - use margins <- decode.optional(decode.token( - named: "margins", - with: { - use f1 <- decode.float() - use f2 <- decode.float() - use f3 <- decode.float() - use f4 <- decode.float() - decode.success(#(f1, f2, f3, f4)) - }, - then: _, - )) + use margins <- decode.optional(margins) use stroke <- stroke() use fill <- fill() use effects <- effects() @@ -1753,7 +1784,7 @@ pub fn symbol_pin(then next: NextFn(SymbolPin, a)) -> Decoder(a) { use hide <- case hide_flag { True -> decode.of(with: decode.success(option.Some(True)), then: _) - False -> optional_hide(then: _) + False -> decode.optional(hide, then: _) } use name <- pin_name() use number <- pin_number() @@ -1974,7 +2005,7 @@ pub fn custom_pad_primitives( decode.token(named: "primitives", then: next, with: { use graphic_items <- decode.list(graphic_item) use width <- decode.optional(width) - use fill <- optional_fill() + use fill <- decode.optional(fill_flag) decode.success(CustomPadPrimitives(graphic_items:, width:, fill:)) }) } @@ -2012,6 +2043,7 @@ pub type Pad { custom_options: Option(CustomPadOptions), custom_primitives: Option(CustomPadPrimitives), uuid: Option(Uuid), + timestamp: Option(Timestamp), ) } @@ -2120,6 +2152,7 @@ pub fn pad(then next: NextFn(Pad, a)) -> Decoder(a) { use custom_options <- decode.optional(custom_pad_options) use custom_primitives <- decode.optional(custom_pad_primitives) use uuid <- decode.optional(uuid) + use timestamp <- decode.optional(timestamp) decode.success(Pad( number:, type_:, @@ -2152,6 +2185,7 @@ pub fn pad(then next: NextFn(Pad, a)) -> Decoder(a) { custom_options:, custom_primitives:, uuid:, + timestamp:, )) }) } @@ -2550,7 +2584,7 @@ pub type FootprintModel { pub fn footprint_model(then next: NextFn(FootprintModel, a)) -> Decoder(a) { decode.token(named: "model", then: next, with: { use file <- decode.string() - use hide <- optional_hide() + use hide <- decode.optional(hide) use offset <- decode.token_wrapper(named: "offset", with: xyz) use scale <- decode.token_wrapper(named: "scale", with: xyz) use rotate <- decode.token_wrapper(named: "rotate", with: xyz) @@ -2843,7 +2877,7 @@ fn base_symbol(then next: NextFn(Symbol, a)) -> Decoder(a) { let power = option.is_some(power) use hide_pin_numbers <- decode.optional(decode.token_wrapper( named: "pin_numbers", - with: optional_hide, + with: decode.optional(hide, then: _), then: _, )) let hide_pin_numbers = option.flatten(hide_pin_numbers) @@ -2855,7 +2889,7 @@ fn base_symbol(then next: NextFn(Symbol, a)) -> Decoder(a) { with: decode.float, then: _, )) - use hide <- optional_hide() + use hide <- decode.optional(hide) decode.success(#(offset, hide)) }, then: _, diff --git a/test/kicad_sexpr_test.gleam b/test/kicad_sexpr_test.gleam index fb34cdf..6bbe26a 100644 --- a/test/kicad_sexpr_test.gleam +++ b/test/kicad_sexpr_test.gleam @@ -2,7 +2,8 @@ import gleam/float import gleam/int import gleam/io import gleam/list -import gleam/pair + +// import gleam/pair import gleam/result import gleam/string import gleam/time/duration @@ -14,7 +15,6 @@ import kicad_sexpr/token import simplifile pub fn main() -> Nil { - // let file_names = list.sample(file_names, 1000) io.println("\nTesting Footprints") let assert Ok(footprint_files) = simplifile.get_files("/usr/share/kicad/footprints") @@ -23,16 +23,16 @@ pub fn main() -> Nil { // token.footprint_file, // True, // ) - test_read_parse_decode( - ["test_files/test3.kicad_mod"], - token.footprint_file, - True, - ) - // test_read_parse_decode(footprint_files, token.footprint_file, False) - // io.println("\nTesting Symbol Libraries") - // let assert Ok(symbol_libraries) = - // simplifile.get_files("/usr/share/kicad/symbols") - // test_read_parse_decode(symbol_libraries, token.symbol_library, False) + // test_read_parse_decode( + // ["test_files/test3.kicad_mod"], + // token.footprint_file, + // True, + // ) + test_read_parse_decode(footprint_files, token.footprint_file, False) + io.println("\nTesting Symbol Libraries") + let assert Ok(symbol_libraries) = + simplifile.get_files("/usr/share/kicad/symbols") + test_read_parse_decode(symbol_libraries, token.symbol_library, False) gleeunit.main() }