Skip to content

Commit 78861f9

Browse files
authored
Support indenting lists (#137)
Add `:indent-with-indicator` dumper option to support indenting of lists Closes #136
1 parent 55130d1 commit 78861f9

File tree

4 files changed

+144
-32
lines changed

4 files changed

+144
-32
lines changed

CHANGELOG.adoc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ Clj-yaml makes use of SnakeYAML, please also refer to the https://bitbucket.org/
1919
** Bump `org.flatland/ordered` to `1.15.12`
2020
(https://github.com/clj-commons/clj-yaml/issues/123[#123])
2121
(https://github.com/lread[@lread])
22+
** Add `:indent-with-indicator` dumper option to support indenting lists
23+
(https://github.com/clj-commons/clj-yaml/issues/136[#136])
24+
(https://github.com/lread[@lread])
2225

2326
== v1.0.27 - 2023-08-11 [[v1.0.27]]
2427

doc/01-user-guide.adoc

Lines changed: 99 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -223,15 +223,16 @@ SnakeYAML implementation (that clj-yaml uses for low-level encoding and decoding
223223
==== Dumper Options [[dumper-options]]
224224
Different flow styles (`:auto`, `:block`, `:flow`) allow customization of how YAML is rendered.
225225

226-
To demonstrate let's setup `some-data` to play with.
226+
To demonstrate, let's setup `some-data` to play with.
227227

228228
[source,clojure]
229229
----
230230
(def some-yaml "
231231
todo:
232-
- name: Fix issue
233-
responsible:
234-
name: Rita
232+
issues:
233+
- name: Fix all the things
234+
responsible:
235+
name: Rita
235236
")
236237
237238
(def some-data (yaml/parse-string some-yaml))
@@ -247,45 +248,120 @@ results in a string of YAML, that when printed:
247248
[source,yaml]
248249
----
249250
todo:
250-
- name: Fix issue
251-
responsible:
252-
name: Rita
251+
issues:
252+
- name: Fix all the things
253+
responsible:
254+
name: Rita
253255
----
254256

255257
The same but with the `:flow` style results in:
256258
[source,yaml]
257259
----
258-
{todo: [{name: Fix issue, responsible: {name: Rita}}]}
260+
{todo: {issues: [{name: Fix all the things, responsible: {name: Rita}}]}}
259261
----
260262

261263
And finally the `:auto` style (the default) renders:
262264
[source,yaml]
263265
----
264266
todo:
265-
- name: Fix issue
266-
responsible: {name: Rita}
267+
issues:
268+
- name: Fix all the things
269+
responsible: {name: Rita}
267270
----
268271

269-
Use the `:indent` and `:indicator-indent` options to adjust indentation:
272+
==== Controlling Indentation
273+
274+
Use `:indent` to control block indentation, to override the default block indent of `2` with `4`:
270275

271276
[source,clojure]
272277
----
273-
(yaml/generate-string some-data :dumper-options {:indent 6
274-
:indicator-indent 3
278+
(yaml/generate-string some-data :dumper-options {:indent 4
275279
:flow-style :block})
276280
----
277281

278282
results in:
279283
[source,yaml]
280284
----
281285
todo:
282-
- name: Fix issue
283-
responsible:
286+
issues:
287+
- name: Fix all the things
288+
responsible:
284289
name: Rita
285290
----
291+
Notice that each block is now indented by `4`.
286292

287-
`:indent` must always be larger than `:indicator-indent`.
288-
If it is only 1 higher, the indicator will be on a separate line:
293+
Use `:indicator-indent` to change the indentation of the `-` indicator; by default, it is `0`; let's bump it up to `2`:
294+
295+
[source,clojure]
296+
----
297+
(yaml/generate-string some-data :dumper-options {:indent 4
298+
:indicator-indent 2
299+
:flow-style :block})
300+
----
301+
302+
results in:
303+
[source,yaml]
304+
----
305+
todo:
306+
issues:
307+
- name: Fix all the things
308+
responsible:
309+
name: Rita
310+
----
311+
Notice that the blocks are still indented by 4, but the `-` indicator is now indented by `2`.
312+
313+
Indenting the `-` indicator within the block `:indent` can be limiting.
314+
Sometimes, you'll want to indent `-` blocks more than other blocks.
315+
Specifying `:indent-with-indicator true` makes block indentation for `-` indicators additive; the indicator is still indented by `:indicator-indent`, but its block is indented by `:indent` + `:indicator-indent`.
316+
317+
[source,clojure]
318+
----
319+
(yaml/generate-string some-data :dumper-options {:indent 4
320+
:indicator-indent 2
321+
:indent-with-indicator true
322+
:flow-style :block})
323+
----
324+
325+
results in:
326+
[source,yaml]
327+
----
328+
todo:
329+
issues:
330+
- name: Fix all the things
331+
responsible:
332+
name: Rita
333+
----
334+
You'll notice that the `-` indicator is indented by `2`, but its block is now indented by `6` (`4` + `2`).
335+
336+
A common usage of `indent-with-indicator true` is to indent arrays like so:
337+
338+
[source,clojure]
339+
----
340+
(yaml/generate-string some-data :dumper-options {:indent 2
341+
:indicator-indent 2
342+
:indent-with-indicator true
343+
:flow-style :block})
344+
----
345+
results in:
346+
347+
[source,yaml]
348+
----
349+
todo:
350+
issues:
351+
- name: Fix all the things
352+
responsible:
353+
name: Rita
354+
----
355+
We now have:
356+
357+
* a block indentation of `2` by default
358+
* an `-` indicator indentation of `2`
359+
* a block indentation of `4` for `-` indicator content
360+
361+
[TIP]
362+
====
363+
Unless you are using `:indent-with-indicator`, `:indicator-indent` must always be less than `:indent`.
364+
If `:ident-with-indicator` is 1 less than `:indent`, the `-` indicator will be on a separate line:
289365
290366
[source,clojure]
291367
----
@@ -297,11 +373,13 @@ results in:
297373
[source,yaml]
298374
----
299375
todo:
300-
-
301-
name: Fix issue
302-
responsible:
303-
name: Rita
376+
issues:
377+
-
378+
name: Fix all the things
379+
responsible:
380+
name: Rita
304381
----
382+
====
305383

306384
[[keyword-args]]
307385
=== Function Options as Keyword Args

src/clojure/clj_yaml/core.clj

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,16 @@
6666
6767
Returns internal SnakeYAML dumper options.
6868
See [[generate-string]] for description of options."
69-
^DumperOptions [{:keys [flow-style indent indicator-indent]}]
69+
^DumperOptions [{:keys [flow-style indent indicator-indent indent-with-indicator]}]
7070
(let [dumper (default-dumper-options)]
7171
(when flow-style
7272
(.setDefaultFlowStyle dumper (flow-styles flow-style)))
7373
(when indent
7474
(.setIndent dumper indent))
7575
(when indicator-indent
7676
(.setIndicatorIndent dumper indicator-indent))
77+
(when indent-with-indicator
78+
(.setIndentWithIndicator dumper indent-with-indicator))
7779
dumper))
7880

7981
(defn default-loader-options
@@ -258,8 +260,12 @@
258260
- default: `:auto`
259261
- `:indent` - spaces to block indent
260262
- default: `2`
261-
- `:indicator-indent` - spaces to indent after indicator
262-
- default: `0`"
263+
- `:indicator-indent` - spaces to indent `-` indicator
264+
- default: `0`
265+
- `:indent-with-indicator` -
266+
- `true` - indent blocks for `-` indicator by `:indent` + `:indicator-indent`
267+
- `false` - indent blocks for `-` indicator by `:indent`
268+
- default: `false`"
263269
[data & opts]
264270
(.dump ^Yaml (apply make-yaml opts)
265271
(encode data)))

test/clj_yaml/core_test.clj

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -372,20 +372,45 @@ lol: yolo")
372372
(parse-stream (->stream multi-doc-yaml) :load-all true))))
373373
)
374374

375-
(def indented-yaml "todo:
376-
- name: Fix issue
377-
responsible:
378-
name: Rita
375+
(def indent-yaml "todo:
376+
issues:
377+
- name: Fix all the things
378+
responsible: {name: Rita}
379379
")
380380

381381
(deftest indentation-test
382382
(testing "Can use indicator-indent and indent to achieve desired indentation"
383-
(is (not= indented-yaml (generate-string (parse-string indented-yaml)
384-
:dumper-options {:flow-style :block})))
385-
(is (= indented-yaml
386-
(generate-string (parse-string indented-yaml)
383+
(is (= (str "todo:\n"
384+
;12
385+
" issues:\n"
386+
" - name: Fix all the things\n"
387+
" responsible:\n"
388+
" name: Rita\n")
389+
(generate-string (parse-string indent-yaml)
390+
:dumper-options {:flow-style :block})))
391+
392+
(is (= (str "todo:\n"
393+
;12345
394+
" issues:\n"
395+
;; 12345
396+
" - name: Fix all the things\n"
397+
" responsible:\n"
398+
" name: Rita\n")
399+
(generate-string (parse-string indent-yaml)
400+
:dumper-options {:indent 5
401+
:indicator-indent 2
402+
:flow-style :block})))
403+
(is (= (str "todo:\n"
404+
;12345
405+
" issues:\n"
406+
; 1234567
407+
" - name: Fix all the things\n"
408+
" responsible:\n"
409+
" name: Rita\n")
410+
(generate-string (parse-string indent-yaml)
387411
:dumper-options {:indent 5
388412
:indicator-indent 2
413+
:indent-with-indicator true
389414
:flow-style :block})))))
390415

391416
(def yaml-with-unknown-tags "---

0 commit comments

Comments
 (0)