Build YAML in Gleam!

v1.0.0

+5
CHANGELOG.md
···
··· 1 + # Changelog 2 + 3 + ## v1.0.0 - 2024-02-13 4 + 5 + - Initial release
+38 -2
README.md
··· 1 # cymbal 2 3 [![Package Version](https://img.shields.io/hexpm/v/cymbal)](https://hex.pm/packages/cymbal) 4 [![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/cymbal/) 5 ··· 7 gleam add cymbal 8 ``` 9 ```gleam 10 - import cymbal 11 12 pub fn main() { 13 - // TODO: An example of the project in use 14 } 15 ``` 16
··· 1 # cymbal 2 3 + Build YAML in Gleam! 4 + 5 [![Package Version](https://img.shields.io/hexpm/v/cymbal)](https://hex.pm/packages/cymbal) 6 [![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/cymbal/) 7 ··· 9 gleam add cymbal 10 ``` 11 ```gleam 12 + import cymbal.{block, array, string, int} 13 14 pub fn main() { 15 + let document = 16 + block([ 17 + #("apiVersion", string("v1")), 18 + #("kind", string("Pod")), 19 + #("metadata", block([#("name", string("example-pod"))])), 20 + #( 21 + "spec", 22 + block([ 23 + #( 24 + "containers", 25 + array([ 26 + block([ 27 + #("name", string("example-container")), 28 + #("image", string("nginx")), 29 + #("ports", array([block([#("containerPort", int(80))])])), 30 + ]), 31 + ]), 32 + ), 33 + ]), 34 + ), 35 + ]) 36 + 37 + cymbal.encode(document) 38 + // --- 39 + // apiVersion: v1 40 + // kind: Pod 41 + // metadata: 42 + // name: example-pod 43 + // spec: 44 + // containers: 45 + // - name: example-container 46 + // image: nginx 47 + // ports: 48 + // - containerPort: 80 49 + ) 50 } 51 ``` 52
+7 -11
gleam.toml
··· 1 name = "cymbal" 2 version = "1.0.0" 3 - 4 - # Fill out these fields if you intend to generate HTML documentation or publish 5 - # your project to the Hex package manager. 6 - # 7 - # description = "" 8 - # licences = ["Apache-2.0"] 9 - # repository = { type = "github", user = "username", repo = "project" } 10 - # links = [{ title = "Website", href = "https://gleam.run" }] 11 - # 12 - # For a full reference of all the available options, you can have a look at 13 - # https://gleam.run/writing-gleam/gleam-toml/. 14 15 [dependencies] 16 gleam_stdlib = "~> 0.34 or ~> 1.0"
··· 1 name = "cymbal" 2 version = "1.0.0" 3 + description = "Build YAML in Gleam!" 4 + licences = ["Apache-2.0"] 5 + repository = { type = "github", user = "lpil", repo = "cymbal" } 6 + links = [ 7 + { title = "Website", href = "https://gleam.run" }, 8 + { title = "Sponsor", href = "https://github.com/sponsors/lpil" }, 9 + ] 10 11 [dependencies] 12 gleam_stdlib = "~> 0.34 or ~> 1.0"
+13 -3
src/cymbal.gleam
··· 7 /// 8 pub opaque type Yaml { 9 Int(Int) 10 Float(Float) 11 String(String) 12 Array(List(Yaml)) ··· 17 /// 18 pub fn encode(doc: Yaml) -> String { 19 let start = case doc { 20 - Int(_) | Float(_) | String(_) -> "---\n" 21 Array(_) | Block(_) -> "---" 22 } 23 24 en(start, 0, doc) <> "\n" 25 } 26 27 /// Create a YAML document from an int. 28 /// 29 pub fn int(i: Int) -> Yaml { ··· 56 57 fn en(acc: String, in: Int, doc: Yaml) -> String { 58 case doc { 59 Int(i) -> acc <> int.to_string(i) 60 Float(i) -> acc <> float.to_string(i) 61 String(i) -> en_string(acc, i) ··· 73 |> string.append("\n") 74 |> indent(in) 75 let acc = case doc { 76 - Int(_) | Float(_) | String(_) -> en(acc <> "- ", in + 1, doc) 77 Array(_) -> en(acc <> "-", in + 1, doc) 78 Block(docs) -> en_block(acc <> "- ", in + 1, False, docs) 79 } ··· 107 108 fn block_child(acc: String, in: Int, doc: Yaml) -> String { 109 case doc { 110 - Int(_) | Float(_) | String(_) -> en(acc <> ": ", in, doc) 111 Array(_) -> en(acc <> ":", in, doc) 112 Block(i) -> en_block(acc <> ":", in + 1, True, i) 113 } ··· 119 120 fn is_simple_string(s: String) -> Bool { 121 case s { 122 "0" <> _ 123 | "1" <> _ 124 | "2" <> _
··· 7 /// 8 pub opaque type Yaml { 9 Int(Int) 10 + Bool(Bool) 11 Float(Float) 12 String(String) 13 Array(List(Yaml)) ··· 18 /// 19 pub fn encode(doc: Yaml) -> String { 20 let start = case doc { 21 + Bool(_) | Int(_) | Float(_) | String(_) -> "---\n" 22 Array(_) | Block(_) -> "---" 23 } 24 25 en(start, 0, doc) <> "\n" 26 } 27 28 + /// Create a YAML document from a bool. 29 + /// 30 + pub fn bool(i: Bool) -> Yaml { 31 + Bool(i) 32 + } 33 + 34 /// Create a YAML document from an int. 35 /// 36 pub fn int(i: Int) -> Yaml { ··· 63 64 fn en(acc: String, in: Int, doc: Yaml) -> String { 65 case doc { 66 + Bool(True) -> acc <> "true" 67 + Bool(False) -> acc <> "false" 68 Int(i) -> acc <> int.to_string(i) 69 Float(i) -> acc <> float.to_string(i) 70 String(i) -> en_string(acc, i) ··· 82 |> string.append("\n") 83 |> indent(in) 84 let acc = case doc { 85 + Bool(_) | Int(_) | Float(_) | String(_) -> en(acc <> "- ", in + 1, doc) 86 Array(_) -> en(acc <> "-", in + 1, doc) 87 Block(docs) -> en_block(acc <> "- ", in + 1, False, docs) 88 } ··· 116 117 fn block_child(acc: String, in: Int, doc: Yaml) -> String { 118 case doc { 119 + Bool(_) | Int(_) | Float(_) | String(_) -> en(acc <> ": ", in, doc) 120 Array(_) -> en(acc <> ":", in, doc) 121 Block(i) -> en_block(acc <> ":", in + 1, True, i) 122 } ··· 128 129 fn is_simple_string(s: String) -> Bool { 130 case s { 131 + "yes" | "no" | "on" | "off" -> False 132 "0" <> _ 133 | "1" <> _ 134 | "2" <> _
+40
test/cymbal_test.gleam
··· 36 ) 37 } 38 39 pub fn encode_string_with_quote_test() { 40 string("\"") 41 |> cymbal.encode
··· 36 ) 37 } 38 39 + pub fn encode_yes_test() { 40 + string("yes") 41 + |> cymbal.encode 42 + |> should.equal( 43 + "--- 44 + \"yes\" 45 + ", 46 + ) 47 + } 48 + 49 + pub fn encode_no_test() { 50 + string("no") 51 + |> cymbal.encode 52 + |> should.equal( 53 + "--- 54 + \"no\" 55 + ", 56 + ) 57 + } 58 + 59 + pub fn encode_on_test() { 60 + string("on") 61 + |> cymbal.encode 62 + |> should.equal( 63 + "--- 64 + \"on\" 65 + ", 66 + ) 67 + } 68 + 69 + pub fn encode_off_test() { 70 + string("off") 71 + |> cymbal.encode 72 + |> should.equal( 73 + "--- 74 + \"off\" 75 + ", 76 + ) 77 + } 78 + 79 pub fn encode_string_with_quote_test() { 80 string("\"") 81 |> cymbal.encode