internal/third_party/yaml: improve yaml positining

- retain more of the original spacing into the conversion
- store original absolute positions

Change-Id: Id1edbefe1050e1f2dcec3ceb2f8877018b0b5876
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/2562
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/doc/tutorial/kubernetes/quick/services/frontend/bartender/kube.cue b/doc/tutorial/kubernetes/quick/services/frontend/bartender/kube.cue
index e533fcb..24164fc 100644
--- a/doc/tutorial/kubernetes/quick/services/frontend/bartender/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/frontend/bartender/kube.cue
@@ -2,5 +2,6 @@
 
 deployment bartender spec template spec containers: [{
 	image: "gcr.io/myproj/bartender:v0.1.34"
-	args: []
+	args: [
+	]
 }]
diff --git a/doc/tutorial/kubernetes/quick/services/frontend/breaddispatcher/kube.cue b/doc/tutorial/kubernetes/quick/services/frontend/breaddispatcher/kube.cue
index e0b6e2e..16af218 100644
--- a/doc/tutorial/kubernetes/quick/services/frontend/breaddispatcher/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/frontend/breaddispatcher/kube.cue
@@ -2,5 +2,8 @@
 
 deployment breaddispatcher spec template spec containers: [{
 	image: "gcr.io/myproj/breaddispatcher:v0.3.24"
-	args: ["-etcd=etcd:2379", "-event-server=events:7788"]
+	args: [
+		"-etcd=etcd:2379",
+		"-event-server=events:7788",
+	]
 }]
diff --git a/doc/tutorial/kubernetes/quick/services/frontend/host/kube.cue b/doc/tutorial/kubernetes/quick/services/frontend/host/kube.cue
index f9f8dfe..97f1fe6 100644
--- a/doc/tutorial/kubernetes/quick/services/frontend/host/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/frontend/host/kube.cue
@@ -4,6 +4,7 @@
 	replicas: 2
 	template spec containers: [{
 		image: "gcr.io/myproj/host:v0.1.10"
-		args: []
+		args: [
+		]
 	}]
 }
diff --git a/doc/tutorial/kubernetes/quick/services/frontend/maitred/kube.cue b/doc/tutorial/kubernetes/quick/services/frontend/maitred/kube.cue
index 34c9a3e..00a213c 100644
--- a/doc/tutorial/kubernetes/quick/services/frontend/maitred/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/frontend/maitred/kube.cue
@@ -2,5 +2,6 @@
 
 deployment maitred spec template spec containers: [{
 	image: "gcr.io/myproj/maitred:v0.0.4"
-	args: []
+	args: [
+	]
 }]
diff --git a/doc/tutorial/kubernetes/quick/services/frontend/valeter/kube.cue b/doc/tutorial/kubernetes/quick/services/frontend/valeter/kube.cue
index 1124b2e..da37ea9 100644
--- a/doc/tutorial/kubernetes/quick/services/frontend/valeter/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/frontend/valeter/kube.cue
@@ -8,5 +8,8 @@
 	ports: [{
 		containerPort: 8080
 	}]
-	args: ["-http=:8080", "-etcd=etcd:2379"]
+	args: [
+		"-http=:8080",
+		"-etcd=etcd:2379",
+	]
 }]
diff --git a/doc/tutorial/kubernetes/quick/services/frontend/waterdispatcher/kube.cue b/doc/tutorial/kubernetes/quick/services/frontend/waterdispatcher/kube.cue
index b9d98ab..66e9e56 100644
--- a/doc/tutorial/kubernetes/quick/services/frontend/waterdispatcher/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/frontend/waterdispatcher/kube.cue
@@ -5,5 +5,8 @@
 }]
 deployment waterdispatcher spec template spec containers: [{
 	image: "gcr.io/myproj/waterdispatcher:v0.0.48"
-	args: ["-http=:8080", "-etcd=etcd:2379"]
+	args: [
+		"-http=:8080",
+		"-etcd=etcd:2379",
+	]
 }]
diff --git a/doc/tutorial/kubernetes/quick/services/infra/download/kube.cue b/doc/tutorial/kubernetes/quick/services/infra/download/kube.cue
index 7a56c6f..2e86b4e 100644
--- a/doc/tutorial/kubernetes/quick/services/infra/download/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/infra/download/kube.cue
@@ -2,7 +2,5 @@
 
 deployment download spec template spec containers: [{
 	image: "gcr.io/myproj/download:v0.0.2"
-	ports: [{
-		containerPort: 7080
-	}]
+	ports: [{containerPort: 7080}]
 }]
diff --git a/doc/tutorial/kubernetes/quick/services/infra/etcd/kube.cue b/doc/tutorial/kubernetes/quick/services/infra/etcd/kube.cue
index 8ef181f..7a0e915 100644
--- a/doc/tutorial/kubernetes/quick/services/infra/etcd/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/infra/etcd/kube.cue
@@ -20,7 +20,9 @@
 				labelSelector matchExpressions: [{
 					key:      "app"
 					operator: "In"
-					values: ["etcd"]
+					values: [
+						"etcd",
+					]
 				}]
 				topologyKey: "kubernetes.io/hostname"
 			}]
@@ -59,12 +61,28 @@
 					valueFrom fieldRef fieldPath: "status.podIP"
 				}]
 				command: ["/usr/local/bin/etcd"]
-				args: ["-name", "$(NAME)", "-data-dir", "/data/etcd3", "-initial-advertise-peer-urls", "http://$(IP):2380", "-listen-peer-urls", "http://$(IP):2380", "-listen-client-urls", "http://$(IP):2379,http://127.0.0.1:2379", "-advertise-client-urls", "http://$(IP):2379", "-discovery", "https://discovery.etcd.io/xxxxxx"]
+				args: [
+					"-name",
+					"$(NAME)",
+					"-data-dir",
+					"/data/etcd3",
+					"-initial-advertise-peer-urls",
+					"http://$(IP):2380",
+					"-listen-peer-urls",
+					"http://$(IP):2380",
+					"-listen-client-urls",
+					"http://$(IP):2379,http://127.0.0.1:2379",
+					"-advertise-client-urls",
+					"http://$(IP):2379",
+					"-discovery",
+					"https://discovery.etcd.io/xxxxxx",
+				]
 			}]
 		}
 	}
 	// bootstrap
 	// "-initial-cluster-token", "etcd-prod-events2",
+
 	volumeClaimTemplates: [{
 		metadata: {
 			name: "etcd3"
diff --git a/doc/tutorial/kubernetes/quick/services/infra/events/kube.cue b/doc/tutorial/kubernetes/quick/services/infra/events/kube.cue
index 5350209..5bfb6a3 100644
--- a/doc/tutorial/kubernetes/quick/services/infra/events/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/infra/events/kube.cue
@@ -15,7 +15,9 @@
 				labelSelector matchExpressions: [{
 					key:      "app"
 					operator: "In"
-					values: ["events"]
+					values: [
+						"events",
+					]
 				}]
 				topologyKey: "kubernetes.io/hostname"
 			}]
@@ -30,7 +32,12 @@
 				}, {
 					containerPort: 7788
 				}]
-				args: ["-cert=/etc/ssl/server.pem", "-key=/etc/ssl/server.key", "-grpc=:7788"]
+				args: [
+					"-cert=/etc/ssl/server.pem",
+					"-key=/etc/ssl/server.key",
+					"-grpc=:7788",
+				]
+
 				volumeMounts: [{
 					mountPath: "/etc/ssl"
 					name:      "secret-volume"
diff --git a/doc/tutorial/kubernetes/quick/services/infra/tasks/service.cue b/doc/tutorial/kubernetes/quick/services/infra/tasks/service.cue
index 3909253..4cab0f4 100644
--- a/doc/tutorial/kubernetes/quick/services/infra/tasks/service.cue
+++ b/doc/tutorial/kubernetes/quick/services/infra/tasks/service.cue
@@ -2,8 +2,7 @@
 
 service tasks spec: {
 	type:           "LoadBalancer"
-	loadBalancerIP: "1.2.3.4"
-	// static ip
+	loadBalancerIP: "1.2.3.4" // static ip
 	ports: [{
 		port: 443
 		name: "http"
diff --git a/doc/tutorial/kubernetes/quick/services/infra/updater/kube.cue b/doc/tutorial/kubernetes/quick/services/infra/updater/kube.cue
index 77418ca..480d013 100644
--- a/doc/tutorial/kubernetes/quick/services/infra/updater/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/infra/updater/kube.cue
@@ -11,9 +11,12 @@
 			mountPath: "/etc/certs"
 			name:      "secret-updater"
 		}]
+
 		ports: [{
 			containerPort: 8080
 		}]
-		args: ["-key=/etc/certs/updater.pem"]
+		args: [
+			"-key=/etc/certs/updater.pem",
+		]
 	}]
 }
diff --git a/doc/tutorial/kubernetes/quick/services/infra/watcher/service.cue b/doc/tutorial/kubernetes/quick/services/infra/watcher/service.cue
index d2b2fdf..0b8b6d9 100644
--- a/doc/tutorial/kubernetes/quick/services/infra/watcher/service.cue
+++ b/doc/tutorial/kubernetes/quick/services/infra/watcher/service.cue
@@ -2,8 +2,7 @@
 
 service watcher spec: {
 	type:           "LoadBalancer"
-	loadBalancerIP: "1.2.3.4."
-	// static ip
+	loadBalancerIP: "1.2.3.4." // static ip
 	ports: [{
 		name: "http"
 	}]
diff --git a/doc/tutorial/kubernetes/quick/services/kitchen/caller/kube.cue b/doc/tutorial/kubernetes/quick/services/kitchen/caller/kube.cue
index 79a0177..6315001 100644
--- a/doc/tutorial/kubernetes/quick/services/kitchen/caller/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/kitchen/caller/kube.cue
@@ -24,7 +24,15 @@
 				name:      "secret-ssh-key"
 				readOnly:  true
 			}]
-			args: ["-env=prod", "-key=/etc/certs/client.key", "-cert=/etc/certs/client.pem", "-ca=/etc/certs/servfx.ca", "-ssh-tunnel-key=/sslcerts/tunnel-private.pem", "-logdir=/logs", "-event-server=events:7788"]
+			args: [
+				"-env=prod",
+				"-key=/etc/certs/client.key",
+				"-cert=/etc/certs/client.pem",
+				"-ca=/etc/certs/servfx.ca",
+				"-ssh-tunnel-key=/sslcerts/tunnel-private.pem",
+				"-logdir=/logs",
+				"-event-server=events:7788",
+			]
 		}]
 	}
 }
diff --git a/doc/tutorial/kubernetes/quick/services/kitchen/dishwasher/kube.cue b/doc/tutorial/kubernetes/quick/services/kitchen/dishwasher/kube.cue
index b98d0b0..fe2019d 100644
--- a/doc/tutorial/kubernetes/quick/services/kitchen/dishwasher/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/kitchen/dishwasher/kube.cue
@@ -19,7 +19,12 @@
 				name:      "secret-ssh-key"
 				readOnly:  true
 			}]
-			args: ["-env=prod", "-ssh-tunnel-key=/etc/certs/tunnel-private.pem", "-logdir=/logs", "-event-server=events:7788"]
+			args: [
+				"-env=prod",
+				"-ssh-tunnel-key=/etc/certs/tunnel-private.pem",
+				"-logdir=/logs",
+				"-event-server=events:7788",
+			]
 		}]
 	}
 }
diff --git a/doc/tutorial/kubernetes/quick/services/kitchen/expiditer/kube.cue b/doc/tutorial/kubernetes/quick/services/kitchen/expiditer/kube.cue
index f3ffe27..8370582 100644
--- a/doc/tutorial/kubernetes/quick/services/kitchen/expiditer/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/kitchen/expiditer/kube.cue
@@ -2,5 +2,10 @@
 
 deployment expiditer spec template spec containers: [{
 	image: "gcr.io/myproj/expiditer:v0.5.34"
-	args: ["-env=prod", "-ssh-tunnel-key=/etc/certs/tunnel-private.pem", "-logdir=/logs", "-event-server=events:7788"]
+	args: [
+		"-env=prod",
+		"-ssh-tunnel-key=/etc/certs/tunnel-private.pem",
+		"-logdir=/logs",
+		"-event-server=events:7788",
+	]
 }]
diff --git a/doc/tutorial/kubernetes/quick/services/kitchen/headchef/kube.cue b/doc/tutorial/kubernetes/quick/services/kitchen/headchef/kube.cue
index 4800d7a..68657ea 100644
--- a/doc/tutorial/kubernetes/quick/services/kitchen/headchef/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/kitchen/headchef/kube.cue
@@ -6,5 +6,9 @@
 	}, {
 		mountPath: "/sslcerts"
 	}]
-	args: ["-env=prod", "-logdir=/logs", "-event-server=events:7788"]
+	args: [
+		"-env=prod",
+		"-logdir=/logs",
+		"-event-server=events:7788",
+	]
 }]
diff --git a/doc/tutorial/kubernetes/quick/services/kitchen/linecook/kube.cue b/doc/tutorial/kubernetes/quick/services/kitchen/linecook/kube.cue
index c2ee42d..fbe3a2e 100644
--- a/doc/tutorial/kubernetes/quick/services/kitchen/linecook/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/kitchen/linecook/kube.cue
@@ -12,6 +12,17 @@
 		}, {
 			name: "secret-kitchen"
 		}]
-		args: ["-name=linecook", "-env=prod", "-logdir=/logs", "-event-server=events:7788", "-etcd", "etcd:2379", "-reconnect-delay", "1h", "-recovery-overlap", "100000"]
+		args: [
+			"-name=linecook",
+			"-env=prod",
+			"-logdir=/logs",
+			"-event-server=events:7788",
+			"-etcd",
+			"etcd:2379",
+			"-reconnect-delay",
+			"1h",
+			"-recovery-overlap",
+			"100000",
+		]
 	}]
 }
diff --git a/doc/tutorial/kubernetes/quick/services/kitchen/pastrychef/kube.cue b/doc/tutorial/kubernetes/quick/services/kitchen/pastrychef/kube.cue
index c117389..f8ac1a4 100644
--- a/doc/tutorial/kubernetes/quick/services/kitchen/pastrychef/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/kitchen/pastrychef/kube.cue
@@ -12,6 +12,14 @@
 		}, {
 			name: "secret-ssh-key"
 		}]
-		args: ["-env=prod", "-ssh-tunnel-key=/etc/certs/tunnel-private.pem", "-logdir=/logs", "-event-server=events:7788", "-reconnect-delay=1m", "-etcd=etcd:2379", "-recovery-overlap=10000"]
+		args: [
+			"-env=prod",
+			"-ssh-tunnel-key=/etc/certs/tunnel-private.pem",
+			"-logdir=/logs",
+			"-event-server=events:7788",
+			"-reconnect-delay=1m",
+			"-etcd=etcd:2379",
+			"-recovery-overlap=10000",
+		]
 	}]
 }
diff --git a/doc/tutorial/kubernetes/quick/services/mon/alertmanager/configmap.cue b/doc/tutorial/kubernetes/quick/services/mon/alertmanager/configmap.cue
index 2c95ab2..a8b8d62 100644
--- a/doc/tutorial/kubernetes/quick/services/mon/alertmanager/configmap.cue
+++ b/doc/tutorial/kubernetes/quick/services/mon/alertmanager/configmap.cue
@@ -21,9 +21,11 @@
 					send_resolved: true
 				}]
 			}]
+
 			// The root route on which each incoming alert enters.
 			route: {
 				receiver: "pager"
+
 				// The labels by which incoming alerts are grouped together. For example,
 				// multiple alerts coming in for cluster=A and alertname=LatencyHigh would
 				// be batched into a single group.
diff --git a/doc/tutorial/kubernetes/quick/services/mon/alertmanager/kube.cue b/doc/tutorial/kubernetes/quick/services/mon/alertmanager/kube.cue
index 4b0c245..76d2a8f 100644
--- a/doc/tutorial/kubernetes/quick/services/mon/alertmanager/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/mon/alertmanager/kube.cue
@@ -22,7 +22,11 @@
 		spec: {
 			containers: [{
 				image: "prom/alertmanager:v0.15.2"
-				args: ["--config.file=/etc/alertmanager/alerts.yaml", "--storage.path=/alertmanager", "--web.external-url=https://alertmanager.example.com"]
+				args: [
+					"--config.file=/etc/alertmanager/alerts.yaml",
+					"--storage.path=/alertmanager",
+					"--web.external-url=https://alertmanager.example.com",
+				]
 				ports: [{
 					name:          "alertmanager"
 					containerPort: 9093
@@ -40,8 +44,7 @@
 				configMap name: "alertmanager"
 			}, {
 				name: "alertmanager"
-				emptyDir: {
-				}
+				emptyDir: {}
 			}]
 		}
 	}
diff --git a/doc/tutorial/kubernetes/quick/services/mon/nodeexporter/kube.cue b/doc/tutorial/kubernetes/quick/services/mon/nodeexporter/kube.cue
index 45ec39b..8c46401 100644
--- a/doc/tutorial/kubernetes/quick/services/mon/nodeexporter/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/mon/nodeexporter/kube.cue
@@ -17,7 +17,10 @@
 		hostPID:     true
 		containers: [{
 			image: "quay.io/prometheus/node-exporter:v0.16.0"
-			args: ["--path.procfs=/host/proc", "--path.sysfs=/host/sys"]
+			args: [
+				"--path.procfs=/host/proc",
+				"--path.sysfs=/host/sys",
+			]
 			ports: [{
 				containerPort: 9100
 				hostPort:      9100
diff --git a/doc/tutorial/kubernetes/quick/services/mon/prometheus/configmap.cue b/doc/tutorial/kubernetes/quick/services/mon/prometheus/configmap.cue
index 07c78b1..4ef2755 100644
--- a/doc/tutorial/kubernetes/quick/services/mon/prometheus/configmap.cue
+++ b/doc/tutorial/kubernetes/quick/services/mon/prometheus/configmap.cue
@@ -17,7 +17,8 @@
 					labels severity: "page"
 					annotations: {
 						description: "{{$labels.app}} of job {{ $labels.job }} has been down for more than 30 seconds."
-						summary:     "Instance {{$labels.app}} down"
+
+						summary: "Instance {{$labels.app}} down"
 					}
 				}, {
 					alert: "InsufficientPeers"
@@ -46,24 +47,32 @@
 				}]
 			}]
 		}
+
 		"prometheus.yml": yaml.Marshal(_cue_prometheus_yml)
 		_cue_prometheus_yml = {
 			global scrape_interval: "15s"
-			rule_files: ["/etc/prometheus/alert.rules"]
+			rule_files: [
+				"/etc/prometheus/alert.rules",
+			]
 			alerting alertmanagers: [{
 				scheme: "http"
 				static_configs: [{
-					targets: ["alertmanager:9093"]
+					targets: [
+						"alertmanager:9093",
+					]
 				}]
 			}]
 			scrape_configs: [{
 				job_name: "kubernetes-apiservers"
+
 				kubernetes_sd_configs: [{
 					role: "endpoints"
 				}]
+
 				// Default to scraping over https. If required, just disable this or change to
 				// `http`.
 				scheme: "https"
+
 				// This TLS & bearer token file config is used to connect to the actual scrape
 				// endpoints for cluster components. This is separate to discovery auth
 				// configuration because discovery & scraping are two separate concerns in
@@ -79,6 +88,7 @@
 				//
 				// insecure_skip_verify: true
 				bearer_token_file: "/var/run/secrets/kubernetes.io/serviceaccount/token"
+
 				// Keep only the default/kubernetes service endpoints for the https port. This
 				// will add targets for each API server which Kubernetes adds an endpoint to
 				// the default/kubernetes service.
@@ -95,9 +105,11 @@
 				// cluster, or can't connect to nodes for some other reason (e.g. because of
 				// firewalling).
 				job_name: "kubernetes-nodes"
+
 				// Default to scraping over https. If required, just disable this or change to
 				// `http`.
 				scheme: "https"
+
 				// This TLS & bearer token file config is used to connect to the actual scrape
 				// endpoints for cluster components. This is separate to discovery auth
 				// configuration because discovery & scraping are two separate concerns in
@@ -106,9 +118,11 @@
 				// <kubernetes_sd_config>.
 				tls_config ca_file: "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
 				bearer_token_file: "/var/run/secrets/kubernetes.io/serviceaccount/token"
+
 				kubernetes_sd_configs: [{
 					role: "node"
 				}]
+
 				relabel_configs: [{
 					action: "labelmap"
 					regex:  "__meta_kubernetes_node_label_(.+)"
@@ -137,9 +151,11 @@
 				// This job is not necessary and should be removed in Kubernetes 1.6 and
 				// earlier versions, or it will cause the metrics to be scraped twice.
 				job_name: "kubernetes-cadvisor"
+
 				// Default to scraping over https. If required, just disable this or change to
 				// `http`.
 				scheme: "https"
+
 				// This TLS & bearer token file config is used to connect to the actual scrape
 				// endpoints for cluster components. This is separate to discovery auth
 				// configuration because discovery & scraping are two separate concerns in
@@ -148,9 +164,11 @@
 				// <kubernetes_sd_config>.
 				tls_config ca_file: "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
 				bearer_token_file: "/var/run/secrets/kubernetes.io/serviceaccount/token"
+
 				kubernetes_sd_configs: [{
 					role: "node"
 				}]
+
 				relabel_configs: [{
 					action: "labelmap"
 					regex:  "__meta_kubernetes_node_label_(.+)"
@@ -176,9 +194,11 @@
 				// * `prometheus.io/port`: If the metrics are exposed on a different port to the
 				// service then set this appropriately.
 				job_name: "kubernetes-service-endpoints"
+
 				kubernetes_sd_configs: [{
 					role: "endpoints"
 				}]
+
 				relabel_configs: [{
 					source_labels: ["__meta_kubernetes_service_annotation_prometheus_io_scrape"]
 					action: "keep"
@@ -218,12 +238,15 @@
 				// via the following annotations:
 				//
 				// * `prometheus.io/probe`: Only probe services that have a value of `true`
-				job_name:     "kubernetes-services"
+				job_name: "kubernetes-services"
+
 				metrics_path: "/probe"
 				params module: ["http_2xx"]
+
 				kubernetes_sd_configs: [{
 					role: "service"
 				}]
+
 				relabel_configs: [{
 					source_labels: ["__meta_kubernetes_service_annotation_prometheus_io_probe"]
 					action: "keep"
@@ -254,12 +277,15 @@
 				// via the following annotations:
 				//
 				// * `prometheus.io/probe`: Only probe services that have a value of `true`
-				job_name:     "kubernetes-ingresses"
+				job_name: "kubernetes-ingresses"
+
 				metrics_path: "/probe"
 				params module: ["http_2xx"]
+
 				kubernetes_sd_configs: [{
 					role: "ingress"
 				}]
+
 				relabel_configs: [{
 					source_labels: ["__meta_kubernetes_ingress_annotation_prometheus_io_probe"]
 					action: "keep"
@@ -296,9 +322,11 @@
 				// * `prometheus.io/port`: Scrape the pod on the indicated port instead of the
 				// pod's declared ports (default is a port-free target if none are declared).
 				job_name: "kubernetes-pods"
+
 				kubernetes_sd_configs: [{
 					role: "pod"
 				}]
+
 				relabel_configs: [{
 					source_labels: ["__meta_kubernetes_pod_annotation_prometheus_io_scrape"]
 					action: "keep"
diff --git a/doc/tutorial/kubernetes/quick/services/mon/prometheus/kube.cue b/doc/tutorial/kubernetes/quick/services/mon/prometheus/kube.cue
index b069ee6..c24e39c 100644
--- a/doc/tutorial/kubernetes/quick/services/mon/prometheus/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/mon/prometheus/kube.cue
@@ -30,7 +30,10 @@
 		spec: {
 			containers: [{
 				image: "prom/prometheus:v2.4.3"
-				args: ["--config.file=/etc/prometheus/prometheus.yml", "--web.external-url=https://prometheus.example.com"]
+				args: [
+					"--config.file=/etc/prometheus/prometheus.yml",
+					"--web.external-url=https://prometheus.example.com",
+				]
 				ports: [{
 					name:          "web"
 					containerPort: 9090
diff --git a/doc/tutorial/kubernetes/quick/services/proxy/authproxy/configmap.cue b/doc/tutorial/kubernetes/quick/services/proxy/authproxy/configmap.cue
index c5347a3..c38c6e3 100644
--- a/doc/tutorial/kubernetes/quick/services/proxy/authproxy/configmap.cue
+++ b/doc/tutorial/kubernetes/quick/services/proxy/authproxy/configmap.cue
@@ -5,6 +5,7 @@
 	// kubectl apply -f configmap.yaml
 	// kubectl scale --replicas=0 deployment/proxy
 	// kubectl scale --replicas=1 deployment/proxy
+
 	apiVersion: "v1"
 	kind:       "ConfigMap"
 	data "authproxy.cfg": """
diff --git a/doc/tutorial/kubernetes/quick/services/proxy/authproxy/kube.cue b/doc/tutorial/kubernetes/quick/services/proxy/authproxy/kube.cue
index af441c3..487f005 100644
--- a/doc/tutorial/kubernetes/quick/services/proxy/authproxy/kube.cue
+++ b/doc/tutorial/kubernetes/quick/services/proxy/authproxy/kube.cue
@@ -9,7 +9,10 @@
 			ports: [{
 				containerPort: 4180
 			}]
-			args: ["--config=/etc/authproxy/authproxy.cfg"]
+			args: [
+				"--config=/etc/authproxy/authproxy.cfg",
+			]
+
 			volumeMounts: [{
 				name:      "config-volume"
 				mountPath: "/etc/authproxy"
diff --git a/doc/tutorial/kubernetes/quick/services/proxy/goget/service.cue b/doc/tutorial/kubernetes/quick/services/proxy/goget/service.cue
index c50d60f..15465d2 100644
--- a/doc/tutorial/kubernetes/quick/services/proxy/goget/service.cue
+++ b/doc/tutorial/kubernetes/quick/services/proxy/goget/service.cue
@@ -2,8 +2,7 @@
 
 service goget spec: {
 	type:           "LoadBalancer"
-	loadBalancerIP: "1.3.5.7"
-	// static ip
+	loadBalancerIP: "1.3.5.7" // static ip
 	ports: [{
 		port: 443
 		name: "https"
diff --git a/internal/third_party/yaml/decode.go b/internal/third_party/yaml/decode.go
index 024794d..22a6420 100644
--- a/internal/third_party/yaml/decode.go
+++ b/internal/third_party/yaml/decode.go
@@ -80,7 +80,7 @@
 	if err != nil {
 		return nil, err
 	}
-	info := token.NewFile(filename, -1, len(b))
+	info := token.NewFile(filename, -1, len(b)+2)
 	info.SetLinesForContent(b)
 	p := parser{info: info}
 	if !yaml_parser_initialize(&p.parser, filename) {
@@ -233,6 +233,9 @@
 	for p.peek() != yaml_SEQUENCE_END_EVENT {
 		n.children = append(n.children, p.parse())
 	}
+	if len(n.children) > 0 {
+		n.endPos = n.children[len(n.children)-1].endPos
+	}
 	p.expect(yaml_SEQUENCE_END_EVENT)
 	return n
 }
@@ -244,6 +247,9 @@
 	for p.peek() != yaml_MAPPING_END_EVENT {
 		n.children = append(n.children, p.parse(), p.parse())
 	}
+	if len(n.children) > 0 {
+		n.endPos = n.children[len(n.children)-1].endPos
+	}
 	p.expect(yaml_MAPPING_END_EVENT)
 	return n
 }
@@ -252,13 +258,14 @@
 // Decoder, unmarshals a node into a provided value.
 
 type decoder struct {
-	p        *parser
-	doc      *node
-	aliases  map[*node]bool
-	mapType  reflect.Type
-	terrors  []string
-	prev     token.Pos
-	lastNode ast.Node
+	p            *parser
+	doc          *node
+	aliases      map[*node]bool
+	mapType      reflect.Type
+	terrors      []string
+	prev         token.Pos
+	lastNode     ast.Node
+	forceNewline bool
 }
 
 var (
@@ -320,10 +327,9 @@
 		if c.mark.index >= m.index {
 			break
 		}
-		// fp := d.p.info.Pos(c.mark.index, 0)
 		comments = append(comments, &ast.Comment{
-			c.pos.Pos(),
-			"//" + c.text[1:],
+			Slash: d.pos(c.mark),
+			Text:  "//" + c.text[1:],
 		})
 		d.p.parser.comments = d.p.parser.comments[1:]
 	}
@@ -343,11 +349,9 @@
 	c := d.p.parser.comments[0]
 	if c.mark.index == m.index {
 		comment := &ast.Comment{
-			c.pos.Pos(),
-			// d.p.info.Pos(m.index+1, 0),
-			"//" + c.text[1:],
+			Slash: d.pos(c.mark),
+			Text:  "//" + c.text[1:],
 		}
-		// expr.AddComment(pos, false)
 		expr.AddComment(&ast.CommentGroup{
 			Line:     true,
 			Position: pos,
@@ -357,14 +361,35 @@
 }
 
 func (d *decoder) pos(m yaml_mark_t) token.Pos {
-	return token.NoPos
-	// TODO: reenable once we have better spacing.
-	// pos := d.p.info.Pos(m.index)
-	// if pos <= d.prev+1 {
-	// 	return token.NoPos
-	// }
-	// d.prev = pos
-	// return pos
+	pos := d.p.info.Pos(m.index+1, token.NoRelPos)
+
+	if d.forceNewline {
+		d.forceNewline = false
+		pos = pos.WithRel(token.Newline)
+	} else if d.prev.IsValid() {
+		c := pos.Position()
+		p := d.prev.Position()
+		switch {
+		case c.Line-p.Line >= 2:
+			pos = pos.WithRel(token.NewSection)
+		case c.Line-p.Line == 1:
+			pos = pos.WithRel(token.Newline)
+		case c.Column-p.Column > 0:
+			pos = pos.WithRel(token.Blank)
+		default:
+			pos = pos.WithRel(token.NoSpace)
+		}
+		if pos.Before(d.prev) {
+			return token.NoPos
+		}
+	}
+
+	d.prev = pos
+	return pos
+}
+
+func (d *decoder) absPos(m yaml_mark_t) token.Pos {
+	return d.p.info.Pos(m.index+1, token.NoRelPos)
 }
 
 func (d *decoder) start(n *node) token.Pos {
@@ -373,8 +398,7 @@
 
 func (d *decoder) ident(n *node, name string) *ast.Ident {
 	return &ast.Ident{
-		// NamePos: d.pos(n.startPos),
-		NamePos: d.p.parser.relPos().Pos(),
+		NamePos: d.pos(n.startPos),
 		Name:    name,
 	}
 }
@@ -423,16 +447,14 @@
 	// TODO: use parse literal or parse expression instead.
 	case yaml_TIMESTAMP_TAG:
 		return &ast.BasicLit{
-			// ValuePos: d.start(n),
-			ValuePos: d.p.parser.relPos().Pos(),
+			ValuePos: d.start(n),
 			Kind:     token.STRING,
 			Value:    strconv.Quote(n.value),
 		}
 
 	case yaml_STR_TAG:
 		return &ast.BasicLit{
-			// ValuePos: d.start(n),
-			ValuePos: d.p.parser.relPos().Pos(),
+			ValuePos: d.start(n),
 			Kind:     token.STRING,
 			Value:    d.quoteString(n.value),
 		}
@@ -442,8 +464,7 @@
 		buf[0] = '\''
 		buf[len(buf)-1] = '\''
 		return &ast.BasicLit{
-			// ValuePos: d.start(n),
-			ValuePos: d.p.parser.relPos().Pos(),
+			ValuePos: d.start(n),
 			Kind:     token.STRING,
 			Value:    string(buf),
 		}
@@ -456,8 +477,7 @@
 			str = "true"
 		}
 		return &ast.BasicLit{
-			// ValuePos: d.start(n),
-			ValuePos: d.p.parser.relPos().Pos(),
+			ValuePos: d.start(n),
 			Kind:     tok,
 			Value:    str,
 		}
@@ -491,18 +511,16 @@
 
 	case yaml_NULL_TAG:
 		return &ast.BasicLit{
-			ValuePos: d.p.parser.relPos().Pos(),
+			ValuePos: d.start(n),
 			Kind:     token.NULL,
 			Value:    "null",
 		}
 	}
 	err := &ast.BottomLit{
-		// Bottom: d.pos(n.startPos)
-		Bottom: d.p.parser.relPos().Pos(),
+		Bottom: d.pos(n.startPos),
 	}
 	comment := &ast.Comment{
-		// Slash: d.start(n),
-		Slash: token.Blank.Pos(),
+		Slash: d.start(n),
 		Text:  "// " + d.terror(n, tag),
 	}
 	err.AddComment(&ast.CommentGroup{
@@ -533,10 +551,9 @@
 	}
 stringLabel:
 	return &ast.BasicLit{
-		ValuePos: d.p.parser.relPos().Pos(),
-		// ValuePos: d.start(n),
-		Kind:  token.STRING,
-		Value: strconv.Quote(n.value),
+		ValuePos: d.start(n),
+		Kind:     token.STRING,
+		Value:    strconv.Quote(n.value),
 	}
 }
 
@@ -546,15 +563,13 @@
 		minuses++
 	}
 	expr = &ast.BasicLit{
-		// ValuePos: d.start(n) + minuses.Pos(),
-		ValuePos: d.p.parser.relPos().Pos(),
+		ValuePos: d.start(n), //  + minuses.Pos(),
 		Kind:     kind,
 		Value:    val,
 	}
 	if minuses > 0 {
 		expr = &ast.UnaryExpr{
-			// OpPos: d.start(n),
-			OpPos: d.p.parser.relPos().Pos(),
+			OpPos: d.start(n),
 			Op:    token.SUB,
 			X:     expr,
 		}
@@ -601,22 +616,53 @@
 
 func (d *decoder) sequence(n *node) ast.Expr {
 	list := &ast.ListLit{}
-	if n.startPos.line != n.endPos.line || len(n.children) != 1 {
-		list.Lbrack = d.pos(n.startPos)
-		list.Rbrack = d.pos(n.endPos)
+	list.Lbrack = d.pos(n.startPos).WithRel(token.Blank)
+	switch ln := len(n.children); ln {
+	case 0:
+		d.prev = list.Lbrack
+	default:
+		d.prev = d.pos(n.children[ln-1].endPos)
 	}
+	list.Rbrack = d.pos(n.endPos)
+
+	noNewline := true
+	single := d.isOneLiner(n.startPos, n.endPos)
 	for _, c := range n.children {
-		list.Elts = append(list.Elts, d.unmarshal(c))
+		d.forceNewline = !single
+		elem := d.unmarshal(c)
+		list.Elts = append(list.Elts, elem)
+		_, noNewline = elem.(*ast.StructLit)
+	}
+	if !single && !noNewline {
+		list.Rbrack = list.Rbrack.WithRel(token.Newline)
 	}
 	return list
 }
 
+func (d *decoder) isOneLiner(start, end yaml_mark_t) bool {
+	s := d.absPos(start).Position()
+	e := d.absPos(end).Position()
+	return s.Line == e.Line
+}
+
 func (d *decoder) mapping(n *node) ast.Expr {
+	newline := d.forceNewline
+
 	structure := &ast.StructLit{}
 	d.insertMap(n, structure, false)
-	if len(structure.Elts) != 1 {
-		structure.Lbrace = d.pos(n.startPos)
-		structure.Rbrace = d.pos(n.endPos)
+
+	// NOTE: we currently translate YAML without curly braces to CUE with
+	// curly braces, even for single elements. Removing the following line
+	// would generate the folded form.
+	structure.Lbrace = d.absPos(n.startPos).WithRel(token.NoSpace)
+	structure.Rbrace = d.absPos(n.endPos).WithRel(token.Newline)
+	if d.isOneLiner(n.startPos, n.endPos) && !newline {
+		if len(structure.Elts) != 1 {
+			structure.Lbrace = d.absPos(n.startPos).WithRel(token.Blank)
+		}
+		if len(structure.Elts) != 1 || structure.Elts[0].Pos().RelPos() < token.Newline {
+			structure.Rbrace = structure.Rbrace.WithRel(token.Blank)
+		}
 	}
 	return structure
 }
diff --git a/internal/third_party/yaml/decode_test.go b/internal/third_party/yaml/decode_test.go
index 608fe8a..87b72f1 100644
--- a/internal/third_party/yaml/decode_test.go
+++ b/internal/third_party/yaml/decode_test.go
@@ -169,13 +169,24 @@
 	// Block sequence
 	{
 		"seq:\n - A\n - B",
-		`seq: ["A", "B"]`,
+		`seq: [
+	"A",
+	"B",
+]`,
 	}, {
 		"seq:\n - A\n - B\n - C",
-		`seq: ["A", "B", "C"]`,
+		`seq: [
+	"A",
+	"B",
+	"C",
+]`,
 	}, {
 		"seq:\n - A\n - 1\n - C",
-		`seq: ["A", 1, "C"]`,
+		`seq: [
+	"A",
+	1,
+	"C",
+]`,
 	},
 
 	// Literal block scalar
@@ -208,9 +219,7 @@
 	// Structs
 	{
 		"a: {b: c}",
-		`a: {
-	b: "c"
-}`,
+		`a: {b: "c"}`,
 	},
 	{
 		"hello: world",
@@ -232,10 +241,7 @@
 		"a: true",
 	}, {
 		"{ a: 1, b: {c: 1} }",
-		`a: 1
-b: {
-	c: 1
-}`,
+		`a: 1, b: {c: 1}`,
 	},
 
 	// Some cross type conversions
@@ -360,10 +366,13 @@
 		`"1": "\"2\""`,
 	}, {
 		"v:\n- A\n- 'B\n\n  C'\n",
-		`v: ["A", """
+		`v: [
+	"A",
+	"""
 		B
 		C
-		"""]`,
+		""",
+]`,
 	},
 
 	// Explicit tags.
@@ -400,12 +409,9 @@
 d: 2`,
 	}, {
 		"a: &a {c: 1}\nb: *a",
-		`a: {
-	c: 1
-}
+		`a: {c: 1}
 b: {
-	c: 1
-}`,
+	c: 1}`, // TODO fix this spacing. Expansions low priority though.
 	}, {
 		"a: &a [1, 2]\nb: *a",
 		"a: [1, 2]\nb: [1, 2]", // TODO: a: [1, 2], b: a
@@ -458,9 +464,7 @@
 	// issue #295 (allow scalars with colons in flow mappings and sequences)
 	{
 		"a: {b: https://github.com/go-yaml/yaml}",
-		`a: {
-	b: "https://github.com/go-yaml/yaml"
-}`,
+		`a: {b: "https://github.com/go-yaml/yaml"}`,
 	},
 	{
 		"a: [https://github.com/go-yaml/yaml]",
@@ -500,12 +504,45 @@
 	// Ordered maps.
 	{
 		"{b: 2, a: 1, d: 4, c: 3, sub: {e: 5}}",
-		`b: 2
-a: 1
-d: 4
-c: 3
-sub: {
-	e: 5
+		`b: 2, a: 1, d: 4, c: 3, sub: {e: 5}`,
+	},
+
+	// Spacing
+	{
+		`
+a: {}
+c: 1
+d: [
+]
+e: []
+`,
+		`a: {}
+c: 1
+d: [
+]
+e: []`,
+	},
+
+	{
+		`
+a:
+  - { "a": 1, "b": 2 }
+  - { "c": 1, "d": 2 }
+`,
+		`a: [{
+	a: 1, b: 2
+}, {
+	c: 1, d: 2
+}]`,
+	},
+
+	{
+		"a:\n b:\n  c: d\n  e: f\n",
+		`a: {
+	b: {
+		c: "d"
+		e: "f"
+	}
 }`,
 	},
 
diff --git a/internal/third_party/yaml/parserc.go b/internal/third_party/yaml/parserc.go
index 52d8f74..aaf7f26 100644
--- a/internal/third_party/yaml/parserc.go
+++ b/internal/third_party/yaml/parserc.go
@@ -2,8 +2,6 @@
 
 import (
 	"bytes"
-
-	"cuelang.org/go/cue/token"
 )
 
 // The parser implements the following grammar:
@@ -60,9 +58,8 @@
 	parser.tokens_head++
 }
 
-func add_comment(parser *yaml_parser_t, p token.RelPos, m yaml_mark_t, text string) {
+func add_comment(parser *yaml_parser_t, m yaml_mark_t, text string) {
 	parser.comments = append(parser.comments, yaml_comment_t{
-		pos:  p,
 		mark: m,
 		text: text,
 	})
diff --git a/internal/third_party/yaml/scannerc.go b/internal/third_party/yaml/scannerc.go
index 2229abc..94ace4b 100644
--- a/internal/third_party/yaml/scannerc.go
+++ b/internal/third_party/yaml/scannerc.go
@@ -1459,7 +1459,6 @@
 
 		// Eat a comment until a line break.
 		if parser.buffer[parser.buffer_pos] == '#' {
-			rel := parser.relPos()
 			m := parser.mark
 			parser.comment_buffer = parser.comment_buffer[:0]
 			for !is_breakz(parser.buffer, parser.buffer_pos) {
@@ -1471,7 +1470,7 @@
 					return false
 				}
 			}
-			add_comment(parser, rel, m, string(parser.comment_buffer))
+			add_comment(parser, m, string(parser.comment_buffer))
 		}
 
 		// If it is a line break, eat it.
@@ -1569,7 +1568,6 @@
 	}
 
 	if parser.buffer[parser.buffer_pos] == '#' {
-		rel := parser.relPos()
 		m := parser.mark
 		parser.comment_buffer = parser.comment_buffer[:0]
 		for !is_breakz(parser.buffer, parser.buffer_pos) {
@@ -1581,7 +1579,7 @@
 				return false
 			}
 		}
-		add_comment(parser, rel, m, string(parser.comment_buffer))
+		add_comment(parser, m, string(parser.comment_buffer))
 	}
 
 	// Check if we are at the end of the line.
@@ -2146,7 +2144,6 @@
 		}
 	}
 	if parser.buffer[parser.buffer_pos] == '#' {
-		rel := parser.relPos()
 		m := parser.mark
 		parser.comment_buffer = parser.comment_buffer[:0]
 		for !is_breakz(parser.buffer, parser.buffer_pos) {
@@ -2158,7 +2155,7 @@
 				return false
 			}
 		}
-		add_comment(parser, rel, m, string(parser.comment_buffer))
+		add_comment(parser, m, string(parser.comment_buffer))
 	}
 
 	// Check if we are at the end of the line.
diff --git a/internal/third_party/yaml/testdata/merge.out b/internal/third_party/yaml/testdata/merge.out
index b8ed7a4..ee6e6bb 100644
--- a/internal/third_party/yaml/testdata/merge.out
+++ b/internal/third_party/yaml/testdata/merge.out
@@ -2,18 +2,18 @@
 // Test
 anchors: {
 	list: [{
-		x: 1
-		y: 2
+		x: 1, y: 2
 	}, {
-		x: 0
-		y: 2
+		x: 0, y: 2
 	}, {
 		r: 10
 	}, {
 		r: 1
 	}]
 }
+
 // All the following maps are equal:
+
 plain: {
 	// Explicit keys
 	x:     1
@@ -21,47 +21,56 @@
 	r:     10
 	label: "center/big"
 }
+
 mergeOne: {
 	x: 1
 	y: 2
 	// Merge one map
+
 	r:     10
 	label: "center/big"
 }
+
 mergeMultiple: {
 	r: 10
 	x: 1
 	y: 2
 	// Merge multiple maps
+
 	label: "center/big"
 }
+
 override: {
 	r:     10
 	x:     1
 	y:     2
 	label: "center/big"
 }
+
 shortTag: {
 	r: 10
 	x: 1
 	y: 2
 	// Explicit short merge tag
+
 	label: "center/big"
 }
+
 longTag: {
 	r: 10
 	x: 1
 	y: 2
 	// Explicit merge long tag
+
 	label: "center/big"
 }
+
 inlineMap: {
 	// Inlined map
-	x:     1
-	y:     2
-	r:     10
+	x:     1, y: 2, r: 10
 	label: "center/big"
 }
+
 inlineSequenceMap: {
 	// Inlined map in sequence
 	r:     10
diff --git a/internal/third_party/yaml/yaml.go b/internal/third_party/yaml/yaml.go
index 955cd82..08821c8 100644
--- a/internal/third_party/yaml/yaml.go
+++ b/internal/third_party/yaml/yaml.go
@@ -102,11 +102,12 @@
 	return &Decoder{parser: d}, nil
 }
 
-// Decode reads the next YAML-encoded value from its input
-// and stores it in the value pointed to by v.
+// Decode reads the next YAML-encoded value from its input and stores it in the
+// value pointed to by v. It returns io.EOF if there are no more value in the
+// stream.
 //
-// See the documentation for Unmarshal for details about the
-// conversion of YAML into a Go value.
+// See the documentation for Unmarshal for details about the conversion of YAML
+// into a Go value.
 func (dec *Decoder) Decode() (expr ast.Expr, err error) {
 	d := newDecoder(dec.parser)
 	defer handleErr(&err)
diff --git a/internal/third_party/yaml/yamlh.go b/internal/third_party/yaml/yamlh.go
index 93ab268..46ce462 100644
--- a/internal/third_party/yaml/yamlh.go
+++ b/internal/third_party/yaml/yamlh.go
@@ -3,8 +3,6 @@
 import (
 	"fmt"
 	"io"
-
-	"cuelang.org/go/cue/token"
 )
 
 // The version directive data.
@@ -521,28 +519,10 @@
 }
 
 type yaml_comment_t struct {
-	pos  token.RelPos
 	mark yaml_mark_t
 	text string
 }
 
-func (p *yaml_parser_t) relPos() (pos token.RelPos) {
-	switch {
-	case p.linesSinceLast > 1:
-		pos = token.NewSection
-	case p.linesSinceLast == 1:
-		pos = token.Newline
-	case p.spacesSinceLast > 0:
-		pos = token.Blank
-	default:
-		pos = token.NoSpace
-	}
-	p.linesSinceLast = 0
-	p.spacesSinceLast = 0
-	// fmt.Println("REL", pos)
-	return token.NoRelPos
-}
-
 // The parser structure.
 //
 // All members are internal. Manage the structure using the