Skip to content

Commit 809e295

Browse files
committed
Renamed espmerge.sh to idmerge.sh
1 parent 98c92ea commit 809e295

File tree

4 files changed

+125
-62
lines changed

4 files changed

+125
-62
lines changed

README.md

+25-14
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,16 @@ dehash.sh removes '#'-style comments
3434
Usage
3535
-----
3636
```
37-
dehash.sh [-c] [-b] [-h] filename
37+
dehash.sh [-c] [-b] [-h] [-o file] filename
3838
-c|--cpp keep CPP directives
3939
-b|--blank keep blank lines
4040
-h|--help help
41-
-o|--out <file> file to write output to, else stdout
42-
filename file to dehash to stout or - for stdin
41+
-o|--out <file> file to write output else stdout
42+
filename file to dehash or - for stdin.
4343
```
4444

4545
dehash.sh was removes hash style comments from one file. Use cpphash.sh
46-
to run dehash.sh on multiple files and to run teh C-preprocessor on one of
46+
to run dehash.sh on multiple files and to run the C-preprocessor on one of
4747
them that includes one or more of the others.
4848

4949
Some possible dehash command variants are:
@@ -54,17 +54,25 @@ Some possible dehash command variants are:
5454
./dehash.sh -c -b example.txt
5555
```
5656

57-
espmerge.sh
57+
idmerge.sh
5858
===========
59-
espmerge.sh: reads esphome yaml and outputs merged esphome yaml.
59+
idmerge.sh: read yaml and output merged yaml using an id tag.
6060

6161
Usage
6262
-----
6363
```
64-
espmerge.sh <input.yaml >output.yaml
64+
Usage: idmerge.sh: [-q] [-p] [-m] [-h] [-t tag] [-o outfile] <file.yaml>
65+
-t|--tag Item tag that uniquely names what to merge. Defaults to "id".
66+
-o|--outfile File to write to, else stdout.
67+
-q|--quiet Do not output operational feedback to stdout.
68+
-p|--parseinfo Output input parser debug info to stderr
69+
-m|--mergeinfo Output merge debug info to stderr
70+
-h|--help Output this help.
71+
72+
<file.yaml>\tThe yaml file to merge, else stdin.
6573
```
6674

67-
espmerge.sh parses yaml into common blocks and merges sections that
75+
idmerge.sh parses yaml into common blocks and merges sections that
6876
are repeated *and* named.
6977

7078
Common blocks are merged backwards in the output by referencing tags
@@ -75,8 +83,8 @@ that declared "id: <tag>" first. Array elements are each treated
7583
as common blocks so it is possible to merge into an array element
7684
as long as it declares itself using "id: <tag>".
7785

78-
After running espmerge.sh, it is advised to merge remaining repeated
79-
sections that are not named with "id: <tag>" by piping the espmerge.sh
86+
After running idmerge.sh, it is advised to merge remaining repeated
87+
sections that are not named with "id: <tag>" by piping the idmerge.sh
8088
output through this pipe which sets up each section as a separate yaml
8189
document and then removes yaml comments;
8290
```
@@ -95,21 +103,24 @@ yamlmerge.sh: merge duplicate map keys in non-compliant yaml
95103

96104
Usage
97105
-----
98-
yamlmerge.sh: [-okseEqh] [-o outfile] <file.yaml>\n
106+
```
107+
yamlmerge.sh: [-o] [-k] [-s] [-e] [-E] [-q] [-h] [-o outfile] <file.yaml>\n
99108
-o|--outfile File to write to, else stdout.
100109
-k|--keep Keep yaml comments.
101110
-s|--sort Sort the map keys.
102111
-e|--esphoist Hoist the esphome: and esp32: map keys to output first.
103-
-E|--espmerge Enable esphome item merging using \"id\": references.
112+
-i|--idmerge Enable item merging using \"id\": tag references.
113+
-t|--tag Item tag that uniquely names what to merge. Defaults to "id".
104114
-q|--quiet Do not output the number of merged components.
105115
-h|--help Output this help.
106116
107117
<file.yaml> The yaml file to merge, else stdin.
118+
```
108119

109120
yamlmerge.sh processes a single yaml files using these steps:
110121
```
111122
First, yaml comments are optionally removed using yq.
112-
Then espmerge.sh is run if requested.
123+
Then idmerge.sh is run if requested.
113124
Then map keys are each put in their own yaml document, using awk.
114125
Then map keys are merged using yq.
115126
Then map keys are optionally sorted using yq.
@@ -124,7 +135,7 @@ Please refer to INSTALL.md for information relating to cpphash installation.
124135
How to use this repo
125136
====================
126137

127-
Use the cpphash.sh, dehash.sh, espmerge.sh or yamlmerge.sh scripts
138+
Use the cpphash.sh, dehash.sh, idmerge.sh or yamlmerge.sh scripts
128139
individually or optionally use the Makefile.cpphash or Makefile.esphome
129140
makefiles.
130141

idmerge.sh

+81-34
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/env bash
22

3-
# espmerge.sh: read esphome yaml and output merged esphome yaml.
3+
# idmerge.sh: read esphome yaml and output merged esphome yaml.
44

55
# Common blocks are merged backwards in the output by referencing tags
66
# specified in "id: <tag>" yaml lines. The first common block to
@@ -10,9 +10,9 @@
1010
# as common blocks so it is possible to merge into an array element
1111
# as long as it declares itself using "id: <tag>"
1212

13-
# Usage: espmerge.sh <input.yaml >output.yaml
13+
# Usage: idmerge.sh -id <idTag> <input.yaml >output.yaml
1414

15-
# After running espmerge.sh, it is advised to postprocess the yaml with
15+
# After running idmerge.sh, it is advised to postprocess the yaml with
1616
# awk '/^[[:alnum:]_]/{print "---"} | yq '... comments=""' esphome.yaml
1717
# before piping it into yq to merge sections using:
1818

@@ -21,22 +21,60 @@
2121
# Maarten's Law: "Everything is more complicated than it should be."
2222
# For proof of Maarten's Law, uncomment the next line and run this script.
2323

24-
# more espmerge.sh; exit
24+
# more idmerge.sh; exit
2525

2626
# Require all variables to be declared - to catch variable typos early.
2727

28+
declare -r me=${0##*/} # basename of this script
29+
declare -r usage="$me: read yaml and output merged yaml using an id tag.
30+
31+
Usage: $me: [-q] [-p] [-m] [-h] [-t tag] [-o outfile] <file.yaml>\n
32+
-t|--tag\tItem tag that uniquely names what to merge. Defaults to "id".
33+
-o|--outfile\tFile to write to, else stdout.
34+
-q|--quiet\tDo not output operational feedback to stdout.
35+
-p|--parseinfo\tOutput input parser debug info to stderr
36+
-m|--mergeinfo\tOutput merge debug info to stderr
37+
-h|--help\tOutput this help.
38+
39+
<file.yaml>\tThe yaml file to merge, else stdin.
40+
41+
This script is from git repo github.com/maartenSXM/cpphash.
42+
Note: This script does not vet arguments securely. Do not setuid or host it.
43+
"
44+
2845
set -e
2946
set -o nounset
3047
set -o pipefail
3148

3249
if (($BASH_VERSINFO < 4)); then
33-
echo "$0 *** bash must be at version 4 or greater. Install it. ***" >&2
50+
echo "$me: *** bash must be at version 4 or greater. Install it. ***" >&2
3451
exit -1
3552
fi
3653

37-
declare -i chatty=1 # some operational feedback to stdout
38-
declare -i dbgParse=0 # input parser debug output to stderr
39-
declare -i dbgMerge=0 # merge engine debug output to stderr
54+
declare outfile=/dev/stdout # output yaml file
55+
declare idtoken="id" # id tag for yaml item unique keys
56+
declare -i chatinfo=1 # some operational feedback to stdout
57+
declare -i parseinfo=0 # input parser debug output to stderr
58+
declare -i mergeinfo=0 # merge engine debug output to stderr
59+
60+
while [[ $# > 0 ]]
61+
do
62+
case $1 in
63+
-h|--help) printf "$usage"; exit 0;;
64+
-o|--out) outfile="$2"; shift 2;;
65+
-t|--tag) idtoken="$2"; shift 2;;
66+
-q|--quiet) chatinfo=0; shift 1;;
67+
-p|--parseinfo) parseinfo=1; shift 1;;
68+
-m|--mergeinfo) mergeinfo=1; shift 1;;
69+
*) break
70+
esac
71+
done
72+
73+
if [ -z "${infile:-}" ]; then
74+
declare -r infile=/dev/stdin
75+
else
76+
declare -r infile="$1"
77+
fi
4078

4179
# Tips for debugging:
4280

@@ -45,17 +83,16 @@ declare -i dbgMerge=0 # merge engine debug output to stderr
4583

4684
# 2. For large yaml test files, it is helpful to redirect stdout to
4785
# /dev/null and then redirect stderr to more. That is done
48-
# like this: ./espmerge.sh bigtest.yaml 2>&1 >/dev/null | more
86+
# like this: ./idmerge.sh bigtest.yaml 2>&1 >/dev/null | more
4987
# and that works because the shell does redirections from right to left.
5088

51-
# 3. dbgParse can be set to one to see how blocks are found.
52-
# dbgMerge can be set to one to see how blocks are stored and output.
89+
# 3. parseinfo can be set to one to see how blocks are found.
90+
# mergeinfo can be set to one to see how blocks are stored and output.
5391

5492
# FWIW, this script does not use any subprocesses and runs entirely in bash.
5593

5694
# Globals
5795

58-
declare -r me=${0##*/} # basename of this script
5996
declare retval # optional return value of a function
6097
declare -i nlines=0 # number of yaml lines input
6198
declare -i _nlines=0 # number of digits in nlines variable (e.g 2 for 64)
@@ -91,7 +128,7 @@ declare -a -i block_idline # block "id:" line if it has one, else zero
91128

92129
declare -r newdoc="---"
93130
declare -r is_array='^[[:blank:]]*- ([[:alnum:]: _]+)[[:blank:]]*$'
94-
declare -r is_id='^[[:blank:]]+id:[[:blank:]]+([[:alnum:]_]+)[[:blank:]]*$'
131+
declare -r is_id="^[[:blank:]]+$idtoken:[[:blank:]]+([[:alnum:]_]+)[[:blank:]]*\$"
95132
declare -r is_key='^[[:blank:]]*([[:alnum:]_]+):[[:blank:]]*$'
96133
declare -r is_mapkey='^([[:alnum:]_]+:)[[:blank:]]*$|^---$'
97134
declare -r is_comment='^[[:blank:]]*#.*$'
@@ -121,7 +158,7 @@ read_lines () {
121158
skip[$n]=1
122159
fi
123160
n=n+1
124-
done
161+
done < $infile
125162

126163
nlines=$n # number of lines of yaml
127164
_nlines=${#nlines} # number of digits in nlines
@@ -140,21 +177,31 @@ _write_lines () {
140177
declare -i b # block index
141178
declare -i p # column indentation alignment for merge comment
142179

180+
# if the line has been flagged to not be output, skip it.
181+
# This can happen when it is a merge block and the leading lines
182+
# are duplicates.ince the block being merged into has those lines also.
183+
# It can also occur for lines in the merge block itself that have
184+
# already been output since they moved earlier.
185+
143186
if ((skip[$n] == 1)); then
144187
return;
145188
fi
146189

147190
# Output line $n.
148191

192+
# oldline is 0 when the line is being simply output and not moving.
193+
149194
if ((oldline==0)); then
150-
echo "${lines[$n]}"
195+
echo "${lines[$n]}" >$outfile
151196
else
152197

153198
# Round comment column to next highest x10 after yaml line, min 40.
154199

155200
p=(${#lines[$n]}/10+1)*10
156201
((p<=40)) && p=40
157-
printf "%-*s # espmerge.sh: was line $((oldline+1))\n" $p "${lines[$n]}"
202+
printf \
203+
"%-*s # idmerge.sh: was line $((oldline+1))\n" $p "${lines[$n]}" \
204+
>$outfile
158205
fi
159206

160207
skip[$n]=1 # a line can only be output once
@@ -209,7 +256,7 @@ _record_work () {
209256
# If the key has never been seen, save it and return.
210257

211258
if [ -z "${key_block[$key]:-}" ]; then
212-
((dbgMerge)) && echo \
259+
((mergeinfo)) && echo \
213260
"*** Saved block $((block+1)) $((from+1))-$((to+1)) ($id)" >&2
214261
key_block[$key]=$block
215262
return
@@ -220,22 +267,22 @@ _record_work () {
220267
kb=${key_block[$key]}
221268
dest=${block_to[$kb]}
222269

223-
((dbgMerge)) && echo \
270+
((mergeinfo)) && echo \
224271
"*** Found block $((kb+1)) for block $((block+1)) $((from+1))-$((to+1)) ($id)" >&2
225272

226-
((chatty)) && echo \
227-
"$me: Moving lines $((from+1))-$((to+1)) to line $((dest+1)) (id: $id)" >&2
273+
((chatinfo)) && echo \
274+
"$me: Moving lines $((from+1))-$((to+1)) to line $((dest+1)) ($idtoken: $id)" >&2
228275

229276
# Skip the id: line since it is in the block being merged into.
230277

231278
skip[$idline]=1
232279

233-
((dbgMerge)) && echo "*** Skipping id line $((idline+1)) (id: $id)" >&2
280+
((mergeinfo)) && echo "*** Skipping id line $((idline+1)) ($idtoken: $id)" >&2
234281

235282
# If we are merging an array elemeny, we will skip the from line too.
236283

237284
if [[ "${lines[$from]}" =~ $is_array ]]; then
238-
((dbgMerge)) && ((skip[from]==0)) && echo \
285+
((mergeinfo)) && ((skip[from]==0)) && echo \
239286
"*** Skipping array line $((from+1))" >&2
240287
skip[$from]=1
241288
fi
@@ -250,7 +297,7 @@ _record_work () {
250297
n=from-1
251298

252299
while (( n>= 0 )); do
253-
if ((dbgMerge==1 && skip[n]==0)); then
300+
if ((mergeinfo==1 && skip[n]==0)); then
254301
if [[ "${lines[$n]}" =~ $is_key ]]; then
255302
id="${BASH_REMATCH[1]}"
256303
echo "*** Skipping key line $((n+1)) ($id)" >&2
@@ -266,7 +313,7 @@ _record_work () {
266313
done
267314
}
268315

269-
# Debug function for when dbgParse is set to 1.
316+
# Debug function for when parseinfo is set to 1.
270317

271318
dump_common_block () {
272319
declare -r -i b=$1
@@ -403,7 +450,7 @@ _find_blocks() {
403450

404451
_get_indentation "$first"; blockSpaces="$retval"
405452

406-
((dbgParse)) && echo \
453+
((parseinfo)) && echo \
407454
"*** Start _find_block $((first+1)) $((last+1)) \"$key\" \"$idTag\"" >&2
408455

409456
n=$first
@@ -422,7 +469,7 @@ _find_blocks() {
422469
# If indentation goes left, end the current block.
423470

424471
if [[ "$lineSpaces" < "$blockSpaces" ]]; then
425-
((dbgParse)) && echo "***: Indentation went left"
472+
((parseinfo)) && echo "***: Indentation went left" >&2
426473
break
427474
fi
428475

@@ -432,15 +479,15 @@ _find_blocks() {
432479
queue_first[$nqueue]=$n
433480
# if mapkey, use default tag "id: <null>". Else use the previous line
434481
if [[ "$blockSpaces" == "" ]]; then
435-
queue_idTag[$nqueue]="id: <none>"
482+
queue_idTag[$nqueue]="$idtoken: <none>"
436483
else
437484
_get_prev_non_skip $n; prev=$retval
438485
queue_idTag[$nqueue]="${lines[$prev]}"
439486
fi
440487
_get_block_to $n 1; n=$retval
441488
queue_last[$nqueue]=$n
442489

443-
((dbgParse)) && echo \
490+
((parseinfo)) && echo \
444491
"*** Indentation went right $((queue_first[$nqueue]+1)) $((n+1))" >&2
445492

446493
nqueue=nqueue+1
@@ -462,7 +509,7 @@ _find_blocks() {
462509
_get_block_to $n 0; n=$retval
463510
queue_last[$nqueue]=$n
464511

465-
((dbgParse)) && echo \
512+
((parseinfo)) && echo \
466513
"*** Queued block $((queue_first[$nqueue]+1)) $((n+1))" >&2
467514

468515
nqueue=nqueue+1
@@ -475,11 +522,11 @@ _find_blocks() {
475522

476523
if [[ "${lines[$n]}" =~ $is_id ]]; then
477524
idline=$n
478-
((dbgParse)) && echo "*** Parsed ${BASH_REMATCH[1]} id at $((n+1))" >&2
525+
((parseinfo)) && echo "*** Parsed ${BASH_REMATCH[1]} id at $((n+1))" >&2
479526
idTag="${BASH_REMATCH[1]}"
480527
fi
481528

482-
((dbgParse)) && echo "*** Queued line $((n+1))" >&2
529+
((parseinfo)) && echo "*** Queued line $((n+1))" >&2
483530

484531
_get_next_non_skip $n; n=$retval
485532
done
@@ -495,7 +542,7 @@ _find_blocks() {
495542
block_idline[$nblocks]=idline
496543
block_key[$nblocks]="$key"
497544

498-
((dbgParse)) && \
545+
((parseinfo)) && \
499546
dump_common_block $nblocks
500547

501548
nblocks=nblocks+1
@@ -508,7 +555,7 @@ _find_blocks() {
508555
"$key" "${queue_idTag[$q]}"
509556
done
510557

511-
((dbgParse)) && echo \
558+
((parseinfo)) && echo \
512559
"*** End _find_block $((first+1)) $((last+1)) \"$key\" \"${idTag}\"" >&2
513560

514561
retval=$n
@@ -530,7 +577,7 @@ find_blocks() {
530577
_find_blocks $n $((nlines-1)) "$key" ""
531578
n=$retval
532579
else
533-
echo "$me: Error: line $((n+1)) is not a map key: ${lines[$n]}"
580+
echo "$me: Error: line $((n+1)) is not a map key: ${lines[$n]}" >&2
534581
exit -1
535582
fi
536583
done

0 commit comments

Comments
 (0)