Pure OCaml Yaml 1.2 reader and writer using Bytesrw

split out cram yml

+18 -5
lib/emitter.ml
···
t.need_separator <- false;
t.state <- In_flow_mapping_value
| In_flow_mapping_value ->
-
write_anchor t anchor;
-
write_tag t ~implicit:plain_implicit tag;
-
write_scalar t ~style value;
-
t.need_separator <- true;
-
t.state <- In_flow_mapping_key
+
if t.need_separator then begin
+
(* We just finished a nested structure (array/mapping),
+
so this scalar is the next key, not a value *)
+
write t ", ";
+
write_anchor t anchor;
+
write_tag t ~implicit:plain_implicit tag;
+
write_scalar t ~style value;
+
write t ": ";
+
t.need_separator <- false;
+
t.state <- In_flow_mapping_value
+
end else begin
+
(* Normal value scalar *)
+
write_anchor t anchor;
+
write_tag t ~implicit:plain_implicit tag;
+
write_scalar t ~style value;
+
t.need_separator <- true;
+
t.state <- In_flow_mapping_key
+
end
| _ ->
if t.need_separator then write t ", ";
t.need_separator <- true;
+8 -8
tests/cram/collections.t
···
Test collections_block.yml with flow output
$ yamlcat --flow collections_block.yml
-
{simple_sequence: [apple, banana, cherry, date]simple_mapping, {name: John Doe, age: 30, city: New York, country: USA}, nested_sequences: [[alpha, beta, gamma], [one, two, three], [red, green, blue]]nested_mappings, {person: {name: Alice, contact: {email: alice@example.com, phone: 555-1234}address, {street: 123 Main St, city: Boston}}}, mapping_with_sequences: {colors: [red, green, blue]sizes, [small, medium, large], numbers: [1, 2, 3]}sequence_with_mappings, [{name: Alice, age: 25, role: developer}, {name: Bob, age: 30, role: designer}, {name: Charlie, age: 35, role: manager}], deep_nesting: {level1: {level2: {level3: {level4: [deeply, nested, values]another_key, value: }items, [item1, item2]}metadata, {created: 2024-01-01, modified: 2024-12-04}}}complex_structure, {database: {connections: [{host: db1.example.com, port: 5432, credentials: {username: admin, password: secret}}, {host: db2.example.com, port: 5432, credentials: {username: readonly, password: public}}]}services, [{name: api, endpoints: [/users, /posts, /comments]config, {timeout: 30, retries: 3}}, {name: worker, tasks: [email, reports]config, {concurrency: 10}}]}, empty_collections: {empty_sequence: []empty_mapping, {}, sequence_with_empty: [value1, [], value2]mapping_with_empty, {key1: value1, key2: {}key3, value3: }}}
+
{simple_sequence: [apple, banana, cherry, date], simple_mapping: {name: John Doe, age: 30, city: New York, country: USA}, nested_sequences: [[alpha, beta, gamma], [one, two, three], [red, green, blue]], nested_mappings: {person: {name: Alice, contact: {email: alice@example.com, phone: 555-1234}, address: {street: 123 Main St, city: Boston}}}, mapping_with_sequences: {colors: [red, green, blue], sizes: [small, medium, large], numbers: [1, 2, 3]}, sequence_with_mappings: [{name: Alice, age: 25, role: developer}, {name: Bob, age: 30, role: designer}, {name: Charlie, age: 35, role: manager}], deep_nesting: {level1: {level2: {level3: {level4: [deeply, nested, values], another_key: value}, items: [item1, item2]}, metadata: {created: 2024-01-01, modified: 2024-12-04}}}, complex_structure: {database: {connections: [{host: db1.example.com, port: 5432, credentials: {username: admin, password: secret}}, {host: db2.example.com, port: 5432, credentials: {username: readonly, password: public}}]}, services: [{name: api, endpoints: [/users, /posts, /comments], config: {timeout: 30, retries: 3}}, {name: worker, tasks: [email, reports], config: {concurrency: 10}}]}, empty_collections: {empty_sequence: [], empty_mapping: {}, sequence_with_empty: [value1, [], value2], mapping_with_empty: {key1: value1, key2: {}, key3: value3}}}
Test collections_compact.yml - Compact notation
···
Test collections_compact.yml with flow output
$ yamlcat --flow collections_compact.yml
-
{compact_sequence: [{name: Alice, age: 25, city: Boston}, {name: Bob, age: 30, city: Seattle}, {name: Charlie, age: 35, city: Portland}]compact_nested, [{id: 1, details: {type: admin, permissions: [read, write, delete]}}, {id: 2, details: {type: user, permissions: [read]}}], compact_complex: [{key1: value1, key2: value2, nested: {sub1: val1, sub2: val2}}, {key1: value3, key2: value4, nested: {sub1: val3, sub2: val4}}]users, [{username: alice, email: alice@example.com, active: true}, {username: bob, email: bob@example.com, active: false}], compact_with_flow: [{name: service1, ports: [8080, 8443]env, {DEBUG: true, MODE: production}}, {name: service2, ports: [3000]env, {DEBUG: false, MODE: development}}]deep_compact, [{category: electronics, items: [{name: laptop, specs: {cpu: Intel i7, ram: 16GB, storage: 512GB SSD}}, {name: phone, specs: {os: Android, ram: 8GB, storage: 256GB}}]}, {category: furniture, items: [{name: desk, dimensions: {width: 150cm, depth: 75cm, height: 75cm}}, {name: chair, dimensions: {width: 60cm, depth: 60cm, height: 120cm}}]}], mixed_compact: {databases: [{type: postgresql, connection: {host: localhost, port: 5432}credentials, {user: admin, password: secret}}, {type: mongodb, connection: {host: localhost, port: 27017}credentials, {user: root, password: root}}]}single_line_compact, [{name: Alice, age: 25, role: developer}, {name: Bob, age: 30, role: designer}, {name: Charlie, age: 35, role: manager}], sequences_in_compact: [{title: Project A, members: [Alice, Bob, Charlie]tags, [urgent, backend]}, {title: Project B, members: [David, Eve]tags, [frontend, design]}]compact_with_empty, [{id: 1, data: []meta, {}}, {id: 2, data: [item1]meta, {key: value}}], compact_complex_nesting: [{level: 1, children: [{level: 2a, children: [{level: 3a, value: leaf1}, {level: 3b, value: leaf2}]}, {level: 2b, children: [{level: 3c, value: leaf3}]}]}]api_endpoints, [{path: /users, method: GET, auth: required, params: [{name: page, type: integer, default: 1}, {name: limit, type: integer, default: 10}]}, {path: '/users/:id', method: GET, auth: required, params: []}, {path: /users, method: POST, auth: required, body: {username: string, email: string, password: string}}], compact_types: [{string_val: hello, number_val: 42, float_val: 3.14, bool_val: true, null_val: null}, {string_val: world, number_val: 100, float_val: 2.71, bool_val: false, null_val: null}]minimal, [{a: 1}, {b: 2}, {c: 3}]}
+
{compact_sequence: [{name: Alice, age: 25, city: Boston}, {name: Bob, age: 30, city: Seattle}, {name: Charlie, age: 35, city: Portland}], compact_nested: [{id: 1, details: {type: admin, permissions: [read, write, delete]}}, {id: 2, details: {type: user, permissions: [read]}}], compact_complex: [{key1: value1, key2: value2, nested: {sub1: val1, sub2: val2}}, {key1: value3, key2: value4, nested: {sub1: val3, sub2: val4}}], users: [{username: alice, email: alice@example.com, active: true}, {username: bob, email: bob@example.com, active: false}], compact_with_flow: [{name: service1, ports: [8080, 8443], env: {DEBUG: true, MODE: production}}, {name: service2, ports: [3000], env: {DEBUG: false, MODE: development}}], deep_compact: [{category: electronics, items: [{name: laptop, specs: {cpu: Intel i7, ram: 16GB, storage: 512GB SSD}}, {name: phone, specs: {os: Android, ram: 8GB, storage: 256GB}}]}, {category: furniture, items: [{name: desk, dimensions: {width: 150cm, depth: 75cm, height: 75cm}}, {name: chair, dimensions: {width: 60cm, depth: 60cm, height: 120cm}}]}], mixed_compact: {databases: [{type: postgresql, connection: {host: localhost, port: 5432}, credentials: {user: admin, password: secret}}, {type: mongodb, connection: {host: localhost, port: 27017}, credentials: {user: root, password: root}}]}, single_line_compact: [{name: Alice, age: 25, role: developer}, {name: Bob, age: 30, role: designer}, {name: Charlie, age: 35, role: manager}], sequences_in_compact: [{title: Project A, members: [Alice, Bob, Charlie], tags: [urgent, backend]}, {title: Project B, members: [David, Eve], tags: [frontend, design]}], compact_with_empty: [{id: 1, data: [], meta: {}}, {id: 2, data: [item1], meta: {key: value}}], compact_complex_nesting: [{level: 1, children: [{level: 2a, children: [{level: 3a, value: leaf1}, {level: 3b, value: leaf2}]}, {level: 2b, children: [{level: 3c, value: leaf3}]}]}], api_endpoints: [{path: /users, method: GET, auth: required, params: [{name: page, type: integer, default: 1}, {name: limit, type: integer, default: 10}]}, {path: '/users/:id', method: GET, auth: required, params: []}, {path: /users, method: POST, auth: required, body: {username: string, email: string, password: string}}], compact_types: [{string_val: hello, number_val: 42, float_val: 3.14, bool_val: true, null_val: null}, {string_val: world, number_val: 100, float_val: 2.71, bool_val: false, null_val: null}], minimal: [{a: 1}, {b: 2}, {c: 3}]}
Test collections_flow.yml - Flow style collections
···
Test collections_flow.yml with flow output
$ yamlcat --flow collections_flow.yml
-
{simple_flow_sequence: [apple, banana, cherry, date]simple_flow_mapping, {name: John, age: 30, city: New York}, nested_flow_sequences: [[a, b, c], [1, 2, 3], [red, green, blue]]nested_flow_mappings, {person: {name: Alice, age: 25}contact, {email: alice@example.com, phone: 555-1234}}, flow_seq_with_maps: [{name: Alice, role: dev}, {name: Bob, role: ops}, {name: Charlie, role: qa}]flow_map_with_seqs, {colors: [red, green, blue]sizes, [S, M, L], numbers: [1, 2, 3]}, deep_flow_nesting: {level1: {level2: {level3: {level4: [a, b, c]}}}}empty_flow, {empty_seq: []empty_map, {}, both: [[], {}]}, flow_in_block: {sequence: [1, 2, 3, 4, 5]mapping, {a: 1, b: 2, c: 3}, nested: {items: [x, y, z]config, {timeout: 30, retries: 3}}}block_in_flow, {users: [{name: Alice, tags: [dev, senior]}, {name: Bob, tags: [ops, junior]}]}, mixed_structure: {services: [{name: api, ports: [8080, 8443]env, {DEBUG: true, LOG_LEVEL: info}}, {name: db, ports: [5432]env, {POSTGRES_DB: mydb, POSTGRES_USER: admin}}]config, {version: 1, enabled: true}}flow_types, {strings: [hello, world, foo, bar]numbers, [1, 2, 3, 42, 100], mixed: [string, 123, true, false, null]quoted, [with spaces, 'special:chars', commas, here]}, flow_map_types: {string: value, number: 42, boolean: true, null_value: null, float: 3.14}nested_mixed, [{id: 1, data: [a, b, c]meta, {type: first}}, {id: 2, data: [d, e, f]meta, {type: second}}, {id: 3, data: [g, h, i]meta, {type: third}}], multiline_flow: {long_sequence: [item1, item2, item3, item4]long_mapping, {key1: value1, key2: value2, key3: value3}}edge_cases, {single_item_seq: [alone]single_item_map, {only: one}, nested_empty: [[], [{}], [{}, []]]all_empty, [{}, [], {a: []}, {b: {}}]}}
+
{simple_flow_sequence: [apple, banana, cherry, date], simple_flow_mapping: {name: John, age: 30, city: New York}, nested_flow_sequences: [[a, b, c], [1, 2, 3], [red, green, blue]], nested_flow_mappings: {person: {name: Alice, age: 25}, contact: {email: alice@example.com, phone: 555-1234}}, flow_seq_with_maps: [{name: Alice, role: dev}, {name: Bob, role: ops}, {name: Charlie, role: qa}], flow_map_with_seqs: {colors: [red, green, blue], sizes: [S, M, L], numbers: [1, 2, 3]}, deep_flow_nesting: {level1: {level2: {level3: {level4: [a, b, c]}}}}, empty_flow: {empty_seq: [], empty_map: {}, both: [[], {}]}, flow_in_block: {sequence: [1, 2, 3, 4, 5], mapping: {a: 1, b: 2, c: 3}, nested: {items: [x, y, z], config: {timeout: 30, retries: 3}}}, block_in_flow: {users: [{name: Alice, tags: [dev, senior]}, {name: Bob, tags: [ops, junior]}]}, mixed_structure: {services: [{name: api, ports: [8080, 8443], env: {DEBUG: true, LOG_LEVEL: info}}, {name: db, ports: [5432], env: {POSTGRES_DB: mydb, POSTGRES_USER: admin}}], config: {version: 1, enabled: true}}, flow_types: {strings: [hello, world, foo, bar], numbers: [1, 2, 3, 42, 100], mixed: [string, 123, true, false, null], quoted: [with spaces, 'special:chars', commas, here]}, flow_map_types: {string: value, number: 42, boolean: true, null_value: null, float: 3.14}, nested_mixed: [{id: 1, data: [a, b, c], meta: {type: first}}, {id: 2, data: [d, e, f], meta: {type: second}}, {id: 3, data: [g, h, i], meta: {type: third}}], multiline_flow: {long_sequence: [item1, item2, item3, item4], long_mapping: {key1: value1, key2: value2, key3: value3}}, edge_cases: {single_item_seq: [alone], single_item_map: {only: one}, nested_empty: [[], [{}], [{}, []]], all_empty: [{}, [], {a: []}, {b: {}}]}}
Inline test: Simple sequence
···
$ echo 'block_key:
> flow_seq: [1, 2, 3]
> flow_map: {a: 1, b: 2}' | yamlcat --flow
-
{block_key: {flow_seq: [1, 2, 3]flow_map, {a: 1, b: 2}}}
+
{block_key: {flow_seq: [1, 2, 3], flow_map: {a: 1, b: 2}}}
Inline test: Mixed block and flow (block in flow)
···
> tags: [x, y, z]
> config:
> enabled: false' | yamlcat --flow
-
[{id: 1, tags: [a, b, c]config, {enabled: true}}, {id: 2, tags: [x, y, z]config, {enabled: false}}]
+
[{id: 1, tags: [a, b, c], config: {enabled: true}}, {id: 2, tags: [x, y, z], config: {enabled: false}}]
Inline test: Empty collections
···
$ echo 'empty_seq: []
> empty_map: {}' | yamlcat --flow
-
{empty_seq: []empty_map, {}}
+
{empty_seq: [], empty_map: {}}
Inline test: Sequence with mapping values
···
> - banana
> config:
> mode: fast' | yamlcat --flow
-
{items: [apple, banana]config, {mode: fast}}
+
{items: [apple, banana], config: {mode: fast}}
Inline test: Complex nested structure
···
> env:
> DEBUG: false
> MODE: prod' | yamlcat --flow
-
{services: [{name: web, ports: [80, 443]env, {DEBUG: false, MODE: prod}}]}
+
{services: [{name: web, ports: [80, 443], env: {DEBUG: false, MODE: prod}}]}
Inline test: Flow sequence with various types
+2
tests/cram/scalar_bool_vs_string.yml
···
+
unquoted_true: true
+
quoted_true: "true"
+4
tests/cram/scalar_clip_folded.yml
···
+
text: >
+
Folded with one
+
trailing newline
+
+3
tests/cram/scalar_clip_literal.yml
···
+
text: |
+
One trailing newline
+
+5
tests/cram/scalar_code_sample.yml
···
+
code: |
+
def hello():
+
print("Hello")
+
if True:
+
return 42
+1
tests/cram/scalar_double_empty.yml
···
+
empty: ""
+1
tests/cram/scalar_double_quote.yml
···
+
text: "She said \"hello\""
+1
tests/cram/scalar_double_simple.yml
···
+
double: "hello world"
+1
tests/cram/scalar_empty_folded.yml
···
+
empty_folded: >
+1
tests/cram/scalar_empty_literal.yml
···
+
empty_literal: |
+4
tests/cram/scalar_folded_basic.yml
···
+
text: >
+
This is a long paragraph
+
that will be folded into
+
a single line.
+4
tests/cram/scalar_folded_comment.yml
···
+
text: >
+
Normal paragraph
+
that continues.
+
# This is part of the content
+8
tests/cram/scalar_folded_indent_preserve.yml
···
+
text: >
+
Normal paragraph
+
continues here.
+
+
Indented block
+
preserved.
+
+
Back to normal.
+6
tests/cram/scalar_folded_para.yml
···
+
text: >
+
First paragraph
+
flows together.
+
+
Second paragraph
+
also flows.
+5
tests/cram/scalar_folded_strip.yml
···
+
text: >-
+
Folded text
+
with stripped
+
trailing newlines
+
+4
tests/cram/scalar_indent2_folded.yml
···
+
text: >2
+
Text with two space
+
base indentation that
+
will be folded.
+6
tests/cram/scalar_indent2_keep.yml
···
+
text: |2+
+
Indented by 2
+
Keeps trailing newlines
+
+
+
+4
tests/cram/scalar_indent2_literal.yml
···
+
text: |2
+
Two space base
+
Second line
+
Extra indent
+4
tests/cram/scalar_indent2_strip.yml
···
+
text: |2-
+
Indented by 2
+
No trailing newlines
+
+6
tests/cram/scalar_keep_folded.yml
···
+
text: >+
+
Folded text
+
keeps trailing
+
+
+
+5
tests/cram/scalar_keep_literal.yml
···
+
text: |+
+
Keeps trailing newlines
+
+
+
+4
tests/cram/scalar_literal_basic.yml
···
+
text: |
+
line one
+
line two
+
line three
+4
tests/cram/scalar_literal_blank.yml
···
+
text: |
+
First paragraph
+
+
Second paragraph
+4
tests/cram/scalar_literal_indent.yml
···
+
text: |
+
First line
+
Indented line
+
Back to first
+8
tests/cram/scalar_nested_blocks.yml
···
+
outer:
+
inner:
+
description: >
+
This is a folded
+
description.
+
code: |
+
def test():
+
return True
+2
tests/cram/scalar_null_vs_string.yml
···
+
unquoted_null: null
+
quoted_null: "null"
+3
tests/cram/scalar_plain_multi.yml
···
+
name: Alice
+
age: 30
+
active: true
+1
tests/cram/scalar_plain_simple.yml
···
+
key: value
+5
tests/cram/scalar_plain_types.yml
···
+
null_val: null
+
bool_true: true
+
bool_false: false
+
number: 42
+
float: 3.14
+7
tests/cram/scalar_seq_blocks.yml
···
+
items:
+
- |
+
First item
+
multiline
+
- >
+
Second item
+
folded
+1
tests/cram/scalar_single_dquote.yml
···
+
quote: 'He said "hello"'
+1
tests/cram/scalar_single_empty.yml
···
+
empty: ''
+1
tests/cram/scalar_single_escaped.yml
···
+
escaped: 'It''s a test'
+3
tests/cram/scalar_single_multiline.yml
···
+
text: 'This is a
+
multi-line
+
string'
+1
tests/cram/scalar_single_simple.yml
···
+
single: 'hello world'
+4
tests/cram/scalar_special_chars.yml
···
+
code: |
+
Special: @#$%^&*()
+
Symbols: <>?/\|
+
Brackets: []{}
+3
tests/cram/scalar_strip_blank.yml
···
+
text: |-
+
Text here
+
+2
tests/cram/scalar_strip_simple.yml
···
+
text: |-
+
No trailing newline
+3
tests/cram/scalar_whitespace.yml
···
+
leading: " spaces"
+
trailing: "spaces "
+
both: " both "
+40 -136
tests/cram/scalars.t
···
Simple plain scalars
-
$ echo 'key: value' | yamlcat
+
$ yamlcat scalar_plain_simple.yml
key: value
-
$ echo 'name: Alice
-
> age: 30
-
> active: true' | yamlcat
+
$ yamlcat scalar_plain_multi.yml
name: Alice
age: 30
active: true
Plain scalars with special values
-
$ echo 'null_val: null
-
> bool_true: true
-
> bool_false: false
-
> number: 42
-
> float: 3.14' | yamlcat --json
+
$ yamlcat --json scalar_plain_types.yml
{"null_val": null, "bool_true": true, "bool_false": false, "number": 42, "float": 3.14}
================================================================================
···
Single-quoted strings preserve literal text
-
$ echo "single: 'hello world'" | yamlcat
+
$ yamlcat scalar_single_simple.yml
single: hello world
Single-quoted strings with embedded double quotes
-
$ echo "quote: 'He said \"hello\"'" | yamlcat
+
$ yamlcat scalar_single_dquote.yml
quote: "He said \"hello\""
Single-quoted strings with escaped single quotes (doubled)
-
$ echo "escaped: 'It''s a test'" | yamlcat
+
$ yamlcat scalar_single_escaped.yml
escaped: It's a test
Single-quoted multiline (newlines become spaces)
-
$ echo "text: 'This is a
-
> multi-line
-
> string'" | yamlcat --json
+
$ yamlcat --json scalar_single_multiline.yml
{"text": "This is a multi-line string"}
Empty single-quoted string
-
$ echo "empty: ''" | yamlcat
+
$ yamlcat scalar_single_empty.yml
empty: ''
================================================================================
···
Simple double-quoted strings
-
$ echo 'double: "hello world"' | yamlcat
+
$ yamlcat scalar_double_simple.yml
double: hello world
Double-quoted with escaped newline
···
Double-quoted with escaped tab
-
$ echo 'text: "Col1\tCol2\tCol3"' | yamlcat --json
+
$ yamlcat --json tab_columns.yml
{"text": "Col1\tCol2\tCol3"}
Double-quoted with backslash escape (Windows path)
···
Double-quoted with escaped quote
-
$ echo 'text: "She said \"hello\""' | yamlcat --json
+
$ yamlcat --json scalar_double_quote.yml
{"text": "She said \"hello\""}
Double-quoted with multiple escape sequences
···
Empty double-quoted string
-
$ echo 'empty: ""' | yamlcat
+
$ yamlcat scalar_double_empty.yml
empty: ''
================================================================================
···
Basic literal block scalar (preserves newlines)
-
$ echo 'text: |
-
> line one
-
> line two
-
> line three' | yamlcat --json
+
$ yamlcat --json scalar_literal_basic.yml
{"text": "line one\nline two\nline three\n"}
Literal with indentation
-
$ echo 'text: |
-
> First line
-
> Indented line
-
> Back to first' | yamlcat --json
+
$ yamlcat --json scalar_literal_indent.yml
{"text": "First line\n Indented line\nBack to first\n"}
Literal with blank lines
-
$ echo 'text: |
-
> First paragraph
-
>
-
> Second paragraph' | yamlcat --json
+
$ yamlcat --json scalar_literal_blank.yml
{"text": "First paragraph\n\nSecond paragraph\n"}
================================================================================
···
Basic folded block scalar (newlines become spaces)
-
$ echo 'text: >
-
> This is a long paragraph
-
> that will be folded into
-
> a single line.' | yamlcat --json
+
$ yamlcat --json scalar_folded_basic.yml
{"text": "This is a long paragraph that will be folded into a single line.\n"}
Folded with paragraph separation (blank line preserved)
-
$ echo 'text: >
-
> First paragraph
-
> flows together.
-
>
-
> Second paragraph
-
> also flows.' | yamlcat --json
+
$ yamlcat --json scalar_folded_para.yml
{"text": "First paragraph flows together.\nSecond paragraph also flows.\n"}
================================================================================
···
Strip chomping (-) removes trailing newlines
-
$ echo 'text: |-
-
> No trailing newline' | yamlcat --json
+
$ yamlcat --json scalar_strip_simple.yml
{"text": "No trailing newline"}
-
$ echo 'text: |-
-
> Text here
-
>
-
> ' | yamlcat --json
+
$ yamlcat --json scalar_strip_blank.yml
{"text": "Text here"}
Folded with strip
-
$ echo 'text: >-
-
> Folded text
-
> with stripped
-
> trailing newlines
-
>
-
> ' | yamlcat --json
+
$ yamlcat --json scalar_folded_strip.yml
{"text": "Folded text with stripped trailing newlines"}
Clip chomping (default) keeps single trailing newline
-
$ echo 'text: |
-
> One trailing newline
-
>
-
> ' | yamlcat --json
+
$ yamlcat --json scalar_clip_literal.yml
{"text": "One trailing newline\n"}
-
$ echo 'text: >
-
> Folded with one
-
> trailing newline
-
>
-
> ' | yamlcat --json
+
$ yamlcat --json scalar_clip_folded.yml
{"text": "Folded with one trailing newline\n"}
Keep chomping (+) preserves all trailing newlines
-
$ echo 'text: |+
-
> Keeps trailing newlines
-
>
-
>
-
> ' | yamlcat --json
+
$ yamlcat --json scalar_keep_literal.yml
{"text": "Keeps trailing newlines\n\n\n\n"}
-
$ echo 'text: >+
-
> Folded text
-
> keeps trailing
-
>
-
>
-
> ' | yamlcat --json
+
$ yamlcat --json scalar_keep_folded.yml
{"text": "Folded text keeps trailing\n\n\n\n"}
================================================================================
···
Literal with explicit 2-space indentation
-
$ echo 'text: |2
-
> Two space base
-
> Second line
-
> Extra indent' | yamlcat --json
+
$ yamlcat --json scalar_indent2_literal.yml
{"text": " Two space base\n Second line\n Extra indent\n"}
Folded with explicit indentation
-
$ echo 'text: >2
-
> Text with two space
-
> base indentation that
-
> will be folded.' | yamlcat --json
+
$ yamlcat --json scalar_indent2_folded.yml
{"text": " Text with two space\n base indentation that\n will be folded.\n"}
Combined indentation and chomping indicators
-
$ echo 'text: |2-
-
> Indented by 2
-
> No trailing newlines
-
>
-
> ' | yamlcat --json
+
$ yamlcat --json scalar_indent2_strip.yml
{"text": " Indented by 2\n No trailing newlines"}
-
$ echo 'text: |2+
-
> Indented by 2
-
> Keeps trailing newlines
-
>
-
>
-
> ' | yamlcat --json
+
$ yamlcat --json scalar_indent2_keep.yml
{"text": " Indented by 2\n Keeps trailing newlines\n\n\n\n"}
================================================================================
···
Empty block scalars
-
$ echo 'empty_literal: |' | yamlcat --json
+
$ yamlcat --json scalar_empty_literal.yml
{"empty_literal": ""}
-
$ echo 'empty_folded: >' | yamlcat --json
+
$ yamlcat --json scalar_empty_folded.yml
{"empty_folded": ""}
Block scalars with special characters (no escaping needed)
-
$ echo 'code: |
-
> Special: @#$%^&*()
-
> Quotes: "double" '"'"'single'"'"'
-
> Brackets: [array] {object}' | yamlcat --json
-
{"code": "Special: @#$%^&*()\nQuotes: \"double\" 'single'\nBrackets: [array] {object}\n"}
+
$ yamlcat --json scalar_special_chars.yml
+
{"code": "Special: @#$%^&*()\nSymbols: <>?/\\|\nBrackets: []{}\n"}
Plain scalar vs quoted string for special values
-
$ echo 'unquoted_true: true
-
> quoted_true: "true"' | yamlcat --json
+
$ yamlcat --json scalar_bool_vs_string.yml
{"unquoted_true": true, "quoted_true": "true"}
-
$ echo 'unquoted_null: null
-
> quoted_null: "null"' | yamlcat --json
+
$ yamlcat --json scalar_null_vs_string.yml
{"unquoted_null": null, "quoted_null": "null"}
Strings that need quoting to preserve leading/trailing spaces
-
$ echo 'leading: " spaces"
-
> trailing: "spaces "
-
> both: " spaces "' | yamlcat --json
-
{"leading": " spaces", "trailing": "spaces ", "both": " spaces "}
+
$ yamlcat --json scalar_whitespace.yml
+
{"leading": " spaces", "trailing": "spaces ", "both": " both "}
Block scalars in sequences
-
$ echo 'items:
-
> - |
-
> First item
-
> multiline
-
> - >
-
> Second item
-
> folded' | yamlcat --json
+
$ yamlcat --json scalar_seq_blocks.yml
{"items": ["First item\nmultiline\n", "Second item folded\n"]}
Block scalars in nested mappings
-
$ echo 'outer:
-
> inner:
-
> description: >
-
> This is a folded
-
> description.
-
> code: |
-
> def test():
-
> return True' | yamlcat --json
+
$ yamlcat --json scalar_nested_blocks.yml
{"outer": {"inner": {"description": "This is a folded description.\n", "code": "def test():\n return True\n"}}}
Preserving indentation in literal blocks
-
$ echo 'code: |
-
> def hello():
-
> print("Hello")
-
> if True:
-
> return 42' | yamlcat --json
+
$ yamlcat --json scalar_code_sample.yml
{"code": "def hello():\n print(\"Hello\")\n if True:\n return 42\n"}
Folded scalars preserve more-indented lines
-
$ echo 'text: >
-
> Normal paragraph
-
> continues here.
-
>
-
> Indented block
-
> preserved.
-
>
-
> Back to normal.' | yamlcat --json
+
$ yamlcat --json scalar_folded_indent_preserve.yml
{"text": "Normal paragraph continues here.\n\n Indented block\n preserved.\n\nBack to normal.\n"}
+1
tests/cram/tab_columns.yml
···
+
text: "Col1\tCol2\tCol3"